--- title: "Introduction" description: "Clinia UI is Clinia's design system: brand tokens, shadcn components and the rules for using them." url: https://ui.clinia.dev/docs/getting-started --- # Introduction ## What is Clinia UI? Clinia UI is a design system built on [Tailwind CSS](https://tailwindcss.com), [shadcn](https://ui.shadcn.com) and [Base UI](https://base-ui.com). It turns Clinia's brand guidelines (colour, typography and motion) into design tokens and components, so teams ship consistent, accessible interfaces without starting over on every project. Clinia feels calm, clear and human: precise without turning cold. Infinite, a deep near-black, anchors the system on a white page; Remedy, a warm cream, sets apart a hero or a highlighted section; Trust, a soft brown, carries emphasis sparingly. Let space and one emphasis do the work. Components ship as source files from a **shadcn-compatible registry** at `https://ui.clinia.dev/r`. Adding one creates a tracked file in your repository. You own that file: edit it like any other component, and it keeps Clinia's tokens. ## Key features - **24 brand swatches** across four colour families. _Live example: see the web page._ - **Two surfaces, one base**: product apps run shadcn's [Luma style](https://ui.clinia.dev/docs/app/getting-started), marketing sites run [Sera style](https://ui.clinia.dev/docs/marketing/getting-started). Both leverage the same Clinia tokens. - **shadcn-compatible registry**: install components with the standard `pnpm dlx shadcn@latest add` workflow. Components pick up Clinia's tokens from the theme. - **Material Symbols icons**: one module per icon, so a page only loads the icons it uses. Every component comes wired with them instead of the default shadcn icons. - **WCAG AA contrast**: every text pairing meets AA in both themes, and borders, focus rings and icons meet 3:1. See [Accessibility](https://ui.clinia.dev/docs/accessibility) for more details. ## Where to start Setup differs by surface. Pick yours: - **Building a product app**, such as the console or a studio: [App getting started](https://ui.clinia.dev/docs/app/getting-started). - **Building a marketing site**, such as clinia.com: [Marketing getting started](https://ui.clinia.dev/docs/marketing/getting-started). - **Adding Clinia to an app that already runs shadcn**: [Installation](https://ui.clinia.dev/docs/installation). --- title: "Installation" description: "Set up Clinia UI in a new or existing Next.js project." url: https://ui.clinia.dev/docs/installation --- # Installation ## Prerequisites Before you begin, make sure your project meets the following requirements: - **Node.js 20.9 or later** - **Next.js 15+ with the App Router** (pages router is not supported) - **pnpm** is recommended, though npm and yarn also work - **Tailwind CSS v4**. Clinia UI does not support Tailwind v3 ## Pick your path Clinia ships one shadcn style per surface (App or Marketing), each with its own base registry item. Select the one that best suits your application. ### A new product app For the console, a [studio](https://github.com/clinia/context-engine-studio) or any other product surface. This installs the `base` item and shadcn's Luma style. ```bash pnpm dlx shadcn@latest init https://ui.clinia.dev/r/base.json pnpm dlx shadcn@latest add @clinia/theme pnpm dlx shadcn@latest add @clinia/button ``` [App getting started](https://ui.clinia.dev/docs/app/getting-started) explains each step. ### A new marketing site For [clinia.com](https://clinia.com) or any other marketing site. This installs the `marketing` item and shadcn's Sera style, with the rounded `--radius` override. ```bash pnpm dlx shadcn@latest init https://ui.clinia.dev/r/marketing.json pnpm dlx shadcn@latest add @clinia/theme-marketing pnpm dlx shadcn@latest add @clinia/brand-logo @clinia/infinity-band ``` [Marketing getting started](https://ui.clinia.dev/docs/marketing/getting-started) explains each step. ### An existing app that already runs shadcn Follow the [migration guide](https://ui.clinia.dev/docs/migration). ### An existing app without shadcn Write a `components.json` by hand, as [the migration guide shows](https://ui.clinia.dev/docs/migration#an-app-without-shadcn), then follow the rest of the guide. --- title: "Using AI tools" description: "How to set up Claude Code and Claude Design so the apps and sites they build follow Clinia's conventions." url: https://ui.clinia.dev/docs/ai-tools --- # Using AI tools AI agents can be leveraged to build with Clinia's conventions. This page shows what to give them, and how to set them up in Claude Code and Claude Design. ## What your agent needs | Source | What it holds | Use it for | |---|---|---| | [`DESIGN.md`](https://ui.clinia.dev/DESIGN.md) | Every page and convention from this site in one file, with the tokens and each component's rules. It's compiled from the content of this website, so it never drifts from it. It opens with the tokens as YAML, which tools that check code against `DESIGN.md` read | Context on every task, and checking code against the tokens | | [`/llms.txt`](https://ui.clinia.dev/llms.txt) | The index of every page on this site as Markdown | Details on one topic | | [`/llms-full.txt`](https://ui.clinia.dev/llms-full.txt) | Every page, docs and components, in full | Agents that want everything at once | | `/docs/.md`, `/components/.md` | One page as Markdown, like [`/docs/typography.md`](https://ui.clinia.dev/docs/typography.md) | Reading a page without the site | | The `@clinia` registry | Every component as source, already on Clinia's tokens | Building the interface | ## Claude Code ### 1. Set up the project Once the installation is completed from following either the [App getting started](https://ui.clinia.dev/docs/app/getting-started) or the [Marketing getting started](https://ui.clinia.dev/docs/marketing/getting-started), the project has access to all the components and styles it needs to render accurately. ### 2. Add DESIGN.md This file tells any agent working in your project what Clinia's brand guidelines are and how to leverage the installed components. Save it at the root of your repository: ```bash curl -o DESIGN.md https://ui.clinia.dev/DESIGN.md ``` Run the same command again when you update Clinia UI, so the agent reads the current rules. Keep DESIGN.md out of your formatter, such as in `.prettierignore`: a reformatted copy no longer matches the published file. ### 3. Describe the product in PRODUCT.md DESIGN.md is the same in every repository: it says how Clinia looks. PRODUCT.md says what this product is, so the agent designs for the user who will actually use it. Save it at the root, next to DESIGN.md, and fill it in once: ```md # Product ## Users Who uses it, and what they already know. ## What they do here The main tasks, in the user's words, most frequent first. ## Where and when Device, setting and pace: a clinician between patients, an analyst at a desk. ## Constraints Languages (English, French), compliance, data the screens must never show, browsers to support. ## Evidence What the agent may cite: real metrics, customers, approved claims. Anything else stays out of the interface. ``` The surface, App or Marketing, isn't in the file: the `style` in `components.json` already says it. Update PRODUCT.md when the product changes, not with each feature. ### 4. Point CLAUDE.md to it Add this section to your `CLAUDE.md` to guide Claude to the design principles, and uncomment the line for your surface: ```md ## Design system - Read DESIGN.md before you build or change any interface, and PRODUCT.md for who uses it and why. - For one topic in detail, read its page as Markdown. https://ui.clinia.dev/llms.txt lists them all. - Add components from the Clinia registry (`pnpm dlx shadcn@latest add @clinia/`), never from upstream shadcn. - Style with semantic tokens (`bg-primary`, `text-muted-foreground`), never raw hex values. - Write interface copy with the clinia-brand-voice skill. ``` The `clinia-brand-voice` skill is one of Clinia's enterprise skills, available to everyone by default. ### 5. Check every edit DESIGN.md tells the agent the rules. The lint rules catch it when it breaks one. Install them with [`@clinia/eslint`](https://ui.clinia.dev/docs/migration#8-add-the-lint-rules), then add this hook to `.claude/settings.json`. After each edit, it lints the file the agent changed and hands any error back, so the agent fixes it in the same turn: ```json { "hooks": { "PostToolUse": [ { "matcher": "Edit|MultiEdit|Write", "hooks": [ { "type": "command", "command": "f=$(jq -r '.tool_input.file_path // empty'); case \"$f\" in *.js|*.jsx|*.ts|*.tsx|*.mjs) npx eslint --no-warn-ignored \"$f\" >&2 || exit 2 ;; esac" } ] } ] } } ``` The hook needs `jq` (`brew install jq`). Commit the file, so everyone working in the repository gets the same checks. ### 6. Add the clinia-ui skill The skill gives the agent four jobs to run on request: set up a repository, build or change a screen, audit one, and migrate an app. It reads the rules from DESIGN.md and this site, so it stays current with them. Install it in the repository: ```bash npx skills add clinia/ui --skill clinia-ui ``` The command needs access to the `clinia/ui` repository on GitHub. Without it, download the skill from this site: ```bash curl --create-dirs -o .claude/skills/clinia-ui/SKILL.md https://ui.clinia.dev/skills/clinia-ui/SKILL.md ``` Then ask in plain words, such as "audit the settings screen" or "set this repository up for Clinia UI". ## Migrate an existing app An agent can move an app that doesn't follow Clinia UI yet onto it, without changing what the app does. It audits the app, proposes a plan as a series of small pull requests (or one pull request with a commit per step), then makes one change at a time and proves each one: same tests, same screens, same keyboard behaviour. It stops for your approval after the audit, after the plan, and before opening any pull request. Have these ready before you start: - **The repository where changes are made.** Not a mirror or an export of another repository: changes there are overwritten. - **What it takes to run the app and reach every screen:** credentials, environment variables, and seed data. A static site needs none of these. The agent asks for them in the audit, and stops rather than guessing. - **Whether the repository is public.** Clinia's brand fonts are licensed and can't be committed to a public repository. Open Claude Code in the app's repository and give it this prompt. With the clinia-ui skill installed, "migrate this app to Clinia UI" runs the same prompt: ```text Migrate this app to Clinia UI, Clinia's design system, without changing what the app does. ## Sources - https://ui.clinia.dev/DESIGN.md is the whole design system for agents. Every docs page also has a Markdown version: add `.md` to its URL. Read DESIGN.md first, then /docs/migration.md, /docs/installation.md, and the Breaking sections of /docs/changelog.md. - Read this repo's AGENTS.md, CLAUDE.md, README, CONTRIBUTING, and convention docs before planning. Where they disagree with Clinia UI, list the disagreement; don't pick a side. That includes rules that keep a host such as `ui.clinia.dev` out of a public tree, which the setup files name. A DESIGN.md already in the repo is an older copy: it's replaced in the first PR, so never read it as a source or list its rules as disagreements. - Before Phase 1, check what the install needs and ask for everything missing in one list: the seven font files (/docs/migration.md, step 4), and where this repo keeps its environment variables. ## The rule Behaviour doesn't change. Same routes, data and API calls, states, validation, form values, keyboard and focus behaviour, screen-reader names, copy, analytics events, and test ids. Only how the app looks, and which components render it, change. When the two conflict, take Clinia's visuals and keep the app's behaviour. Put every conflict in a decision table (what, current, Clinia, your proposal) and wait for my answer. Never resolve one silently. DESIGN.md conventions that change behaviour are conflicts too, such as an Alert Dialog for destructive actions, a row menu in place of a button on every row, or verb-first labels: put each in the decision table. So is a Clinia component that brings behaviour the app doesn't have, such as Sidebar collapsing to icons; adopting only its look is not a conflict. Defects you find are the exception that proves the rule: accessibility defects, analytics events that never fire, broken links. Fixing one changes behaviour on purpose. List them, and fix each only as its own flagged change once I've approved it. ## Scope The app's UI code only. Leave out email templates, server code, scripts, a docs site beside the app, and anything else that isn't the app's interface, and confirm that boundary with me in Phase 1. When the docs site is the app, migrate it: /docs/migration.md covers sites on Fumadocs. Don't upgrade, refactor, or tidy anything the migration doesn't need; the `@clinia/tailwindcss` version the theme requires is part of the migration. The migration includes the logo, the favicon and the app icons, and replacing hand-built patterns (in an app: navigation, list rows, loading and empty states, form fields, status pills; on a marketing site: the header, CTAs, logo rows, compliance badges, line accents and the product lockup) with the Clinia components that do the same job (/docs/migration.md, steps 10 and 11). That isn't tidying. Don't rewrite copy. Clinia's content guidelines don't apply to app copy. If the repository is public or open source, don't commit Clinia's licensed fonts or brand files to it. Ask me how the public build should handle them. ## Phase 1: audit (read only) First, confirm this repository is where changes are made. Check the README, CONTRIBUTING, commit authors, and any "generated" or "exported" headers. If it's a mirror or an export of another repository, stop and ask me for the source. Then report what the plan depends on, with counts and file paths (put long lists in an appendix): - Where the app starts: Tailwind version, the `@clinia/tailwindcss` version if any, the shadcn style and primitives (Radix or Base UI), component and icon libraries, fonts and weights (every font file outside the seven in /docs/migration.md, step 4, is deleted), and the themes a user can actually reach (a `dark:` class nothing switches on doesn't count). If the app is live, request each font URL its CSS declares: a font that returns 404 renders in a fallback nobody notices. - If the primitives are Radix: every Radix-specific API you'll have to convert (`asChild`, data attributes, portals, controlled open state), with counts. Clinia's components are built on Base UI, and this conversion is where behaviour is most at risk. If they're already Base UI, report the drift from Clinia's style instead: local variants, sizes, and overrides. - Every UI component and pattern, mapped to its `@clinia` registry item (https://ui.clinia.dev/r/registry.json) as an equivalent, a replacement that behaves differently (put the differences in the decision table), or none. - Every pattern the app builds by hand, per screen: navigation, list rows, loading and empty states, form fields, status pills, `div` or `span` elements with `role="button"`, and logo images; on a marketing site, the header, hero and section CTAs, logo rows, compliance blocks, closing CTA bands, line accents and the lockup. Name the Clinia component that replaces each (/docs/migration.md, step 11, has a table for each surface). A hand-built pattern with a Clinia equivalent is not "none". - The brand assets: every logo use, the favicon, and the app and manifest icons. On a marketing site, the compliance badges and their captions too, compared with the files and approved lines on /docs/marketing/compliance.md. - Values that aren't Clinia tokens (raw colours, arbitrary sizes, radii, shadows, or font weights), with the token each becomes. A Clinia swatch used without its token counts too: `#cb6a3d` is Peach-4, a chart colour, and passing a palette check doesn't make it an accent. Count live and dead selectors apart: only selectors and classes the code renders are migration work, and dead ones go in cleanup. Search the code for them: the `@clinia/eslint` rules (/docs/migration.md, step 8) aren't installed yet, and once they are, they catch arbitrary text sizes, radii, hex colours in classes, font weights, and `--clinia-*` in JavaScript and TypeScript, but not arbitrary `leading` or `tracking`, `rgba()` in classes, or anything in CSS files. - Product app (`base-luma`) or marketing site (`base-sera`). A help or support site uses `base-sera` with App conventions. With no `components.json`, propose one and put it in the decision table. - How behaviour is protected today: unit, DOM, and end-to-end tests, test ids, and visual checks. - Analytics: the tool, every event the app sends, and where each fires. With Vercel Analytics, an event tracked in an effect on page load is dropped unless the page starts Vercel's queue first (/docs/marketing/seo.md): list an event that never fires as a defect. - What it takes to run the app and reach every screen: credentials, environment variables, services, and seed data. List what you need from me now. - Accessibility defects: run axe (`@axe-core/playwright`) on every screen you can reach, and add any you see on the way. Triage axe's `incomplete` results by hand too: a contrast failure can show up only there. If the app's Content-Security-Policy blocks axe, open the page with `bypassCSP: true`. A cookie banner built on vanilla-cookieconsent hides itself from automated browsers: launch Chromium with `--disable-blink-features=AutomationControlled`, or axe and the screenshots never see it. List defects in a third-party library (a docs framework, a playground) on their own, as upstream issues. ## Phase 2: plan A sequence of small PRs, each leaving the app working. If I want one PR, plan one commit per step instead, each leaving the app working: lint, typecheck, build, and tests pass on every commit. As a starting point, not a template: DESIGN.md and PRODUCT.md first if the repo lacks them (/docs/ai-tools.md, Claude Code steps 2 and 3), then registry, theme and the `icons` item (`sonner`, `dialog` and other components install `icons` as a dependency), then the style switch with the simplest components (`components.json` style is global, so it can't be split per component), then one component family per PR, then the icon swap in the app's own code, then the brand assets, then one PR per hand-built pattern or screen to align it with App or Marketing conventions, by surface, then cleanup (add the `@clinia/eslint` rules, remove unused libraries, and update the repo's own docs and agent files that describe the UI stack). For each PR: what changes, what could break, how you'll prove it didn't. Ask me which branch the PRs target, `main` or an integration branch, and how far `main` may move while they're open. Components Clinia doesn't have in its registry stay as they are, restyled with Clinia tokens, and go on a list for https://ui.clinia.dev/docs/request-a-component. Stop and wait for my OK on the audit, the decision table, and the plan. ## Phase 3: one PR at a time In one-PR mode, read each PR below as a commit: the baseline is the previous commit, and every commit gets the same proof. 1. Capture the baseline, from the head of the previous PR: the test results, and screenshots of every screen the PR touches, at 1440, 1024, 800, and 390 pixels wide, in every theme a user can reach. A Playwright script for those screenshots is in scope; keep it in the repo so later PRs reuse it, and keep the images out of git. Make it deterministic: if the app is static, build once and serve it; otherwise the same seed data, seeded so a second run doesn't fail; dates, times and live values replaced with fixed placeholders once the page has settled; external services blanked; animations waited out. Give it its own port and database, keep it out of the default test run, and keep one screenshot folder per PR head. Run it twice and confirm the images match before you rely on it; in ARIA snapshots, mask names that change from run to run, such as a progress value. Capture the cookie banner too, with the launch flag from the axe step in Phase 1. If the app is live, compare the first baseline with it once: when they match, later PRs compare with the previous PR's head only. List any state you can't capture reliably. 2. Make the change. Install with `CI=1 pnpm dlx shadcn@latest add @clinia/ --yes --overwrite`, or with the repo's own package manager's runner (`CI=1 npx shadcn@latest add …` with npm): without `CI=1` and `--overwrite`, the CLI waits for an answer. Then check that the lockfile is still the repo's own, with no `pnpm-lock.yaml` appearing beside `package-lock.json`. Adding `@clinia/theme` replaces `globals.css`, so put back anything else the app had there. 3. Prove behaviour didn't change: lint, typecheck, and build pass, the existing tests pass, tests are added where a changed component had none, a Clinia component that replaces a custom one gets a test that passes on both versions, `cn()` keeps the type scale's sizes (/docs/migration.md, step 6), the screenshots are compared with the baseline and read, not only diffed, against the screen's App or Marketing conventions page, a script checks at each width that no text is clipped or overflows its box (an element whose `scrollWidth` or `scrollHeight` exceeds its client size), because a screenshot diff misses a label that wraps or a chip that clips, the affected flows are walked with the keyboard, and the same analytics events fire with the same payloads. Check that last one on every link moved under a `render` prop: a wrapper that spreads its props after its own `onClick` loses that handler. With Vercel Analytics, read `window.vaq` locally, where the script returns 404 and events only queue, or intercept and abort the beacons on a deployment with a desktop Chrome user agent: the live script ignores HeadlessChrome. When the app has no tests, the screenshots and the keyboard walk are the proof: say so in the PR. 4. Prepare the branch and a PR description with the before and after screenshots and what you checked. Push and open the PR only when I say so. If you can't install a package, authenticate, seed data, or reach a screen, stop and tell me what you need. Never invent a screenshot or a test result. ``` The steps it follows are on [Migration](https://ui.clinia.dev/docs/migration), including what changes when an app [comes from Radix](https://ui.clinia.dev/docs/migration#coming-from-radix). ## Claude Design [Clinia's design system](https://claude.ai/artifact/8KqGvgAPLAJ9UxT8vRzFT2) in Claude Design is built from Clinia UI's components and `DESIGN.md`. Start your project from it, and say in your prompt which surface you're designing for: a product app (Luma) or a marketing site (Sera). For Figma files, FigJam boards and artifacts made outside Claude Design and outside a repository, the `clinia-design-system` skill applies the same rules. It's one of Clinia's enterprise skills, available to everyone by default; to add it yourself, [download it](https://ui.clinia.dev/skills/clinia-design-system.zip) and upload it under Skills in Claude Desktop's settings. It reads `DESIGN.md` live and hands decks, documents and code to the skill made for them. ## Scenes, Animations and Illustrations The skills that make illustrated scenes, `composing-scenes` and `authoring-rive-scenes`, ship in this repository. Open it in Claude Code to make a scene, then copy the approved result into your site. See [Scenes](https://ui.clinia.dev/docs/marketing/scenes) and [Rive scenes](https://ui.clinia.dev/docs/marketing/rive-scenes). ## Do and Don't ### Do - Refresh `DESIGN.md` with the `curl` command above when there is an update to Clinia UI guidelines. - Get anything an agent makes reviewed and approved before you publish it. Scenes, animations and illustrations need the marketing lead's approval. - Say which surface (App or Marketing) you're building for. ### Don't - Edit `DESIGN.md` directly. It's compiled from this site: to change a rule, [request a change](https://ui.clinia.dev/docs/request-a-component). - Let an agent edit a component's colours or states to make a design fit. [Request a component change](https://ui.clinia.dev/docs/request-a-component) instead. - Publish a scene, an animation or an illustration before it's approved. - Use real patient data in prompts or mock-ups. Use a fictional persona, such as one picked from our synthetic patient list. --- title: "Migration" description: "Move an existing app to Clinia UI." url: https://ui.clinia.dev/docs/migration --- # Migration This page showcases how to migrate an app that already runs shadcn to Clinia UI's version: the registry, the style, the theme, the components and the icons. An app without shadcn starts with [its own `components.json`](#an-app-without-shadcn). Don't run `shadcn init` again. It would overwrite your `components.json`. In an app with a `src/` folder, the CLI writes every file item under `src/` too: `eslint.clinia.mjs`, `icons.manifest.ts`, the icon scripts, and the SVGs from `brand-logo` and `infinity-band`. Move anything that lands in `src/public/` to `public/`, where Next.js serves it, and import `eslint.clinia.mjs` from where it lands. To have an agent do the migration, use the prompt in [Using AI tools](https://ui.clinia.dev/docs/ai-tools#migrate-an-existing-app). It follows these steps and stops for your approval. The commands use pnpm. In an npm repository, run `npx shadcn@latest add` where a step says `pnpm dlx shadcn@latest add`, and `npm install --package-lock-only` where it says `pnpm install --lockfile-only`. After each `shadcn add`, check that the lockfile is still your package manager's own: no `pnpm-lock.yaml` beside a `package-lock.json`. ## An app without shadcn An app that doesn't run shadcn yet needs a `components.json` before step 1. Write it by hand rather than running `shadcn init`, which rewrites `globals.css` and adds files that Clinia's items replace. For an app with a `src/` folder: ```json { "$schema": "https://ui.shadcn.com/schema.json", "style": "base-luma", "rsc": true, "tsx": true, "tailwind": { "config": "", "css": "src/app/globals.css", "baseColor": "neutral", "cssVariables": true }, "aliases": { "components": "@/components", "utils": "@/lib/utils", "ui": "@/components/ui", "lib": "@/lib", "hooks": "@/hooks" }, "registries": { "@clinia": { "url": "https://ui.clinia.dev/r/{style}/{name}.json" } } } ``` - `style` is the surface: `base-luma` for a product app, `base-sera` for a marketing site (step 2). - `tailwind.css` is the file that imports Tailwind. The theme replaces it in step 3. Without a `src/` folder, it's `app/globals.css`. - The aliases need `"@/*"` in the `paths` of `tsconfig.json`, pointing to `./src/*`, or to `./*` without a `src/` folder. The file already holds steps 1 and 2: continue from step 3. ## 1. Add the Clinia registry Add `@clinia` to the `registries` block of your `components.json`: ```json { "registries": { "@clinia": { "url": "https://ui.clinia.dev/r/{style}/{name}.json" } } } ``` ## 2. Set the shadcn style Set `"style"` in `components.json`. It decides which version of each `@clinia` component you get, Luma or Sera, and the shape of anything you add from upstream. **Product app**: shadcn's Luma style. ```json { "style": "base-luma" } ``` **Marketing site**: shadcn's Sera style. ```json { "style": "base-sera" } ``` Leave `iconLibrary` as it is. Clinia's components import their icons from `components/ui/icons/`, so the value changes nothing. ## 3. Install the theme **Product app**: ```bash pnpm dlx shadcn@latest add @clinia/theme ``` **Marketing site**: ```bash pnpm dlx shadcn@latest add @clinia/theme-marketing ``` The theme replaces `app/globals.css`. Copy anything your app added there before you run it, and put it back after. The theme imports the font declarations itself. From a script or an agent, set `CI=1` and add `--yes --overwrite`, or the command waits for an answer: ```bash CI=1 pnpm dlx shadcn@latest add @clinia/theme --yes --overwrite ``` The theme installs `@clinia/tailwindcss` 2. If your `.npmrc` maps `@clinia` to GitHub Packages, for `@clinia/web-cookiebot` for one, it installs from there: GitHub Packages carries every release from 2.0.1 on. It doesn't carry 2.0.0 or the release candidates, so if your app pins one, move it to `^2.0.1`. If the app keeps its old tokens in a hand-written CSS file that also styles elements (`body`, `h1` to `h4`, `p`) or holds classes the pages use, split it. Delete the tokens now, and keep the element rules and classes in their own file until step 11, so the type change doesn't land with the theme. The theme sets `font-synthesis: none`, so the browser stops faking bold and italic as soon as it lands, before any font changes: an `` in a face with no italic turns upright. Expect that change in this step's screenshots. ## 4. Host the brand fonts `@clinia/tailwindcss` declares the fonts but does not include font files. Get the seven licensed `.woff2` files from the [brand drive](https://drive.google.com/drive/folders/1FsfV5tf6NICyoeq5qW4_Q67m7VDohpnL?usp=drive_link), put them in `public/fonts/`. With access to `clinia/ui`, you can fetch them instead: ```bash mkdir -p public/fonts for f in CircularXXWeb-Book CircularXXWeb-BookItalic CircularXXWeb-Regular CircularXXWeb-Medium CircularXXWeb-MediumItalic CircularXXMonoWeb-Regular NaNSerfBText-Book; do gh api "repos/clinia/ui/contents/apps/web/public/fonts/$f.woff2" -H "Accept: application/vnd.github.raw" > "public/fonts/$f.woff2" done ``` The fonts are licensed: don't commit them to a public repository. | File | Family | Weight | Style | | --- | --- | --- | --- | | `CircularXXWeb-Book.woff2` | CircularXX | Book 400 | Normal | | `CircularXXWeb-BookItalic.woff2` | CircularXX | Book 400 | Italic | | `CircularXXWeb-Regular.woff2` | CircularXX | Regular 450 | Normal | | `CircularXXWeb-Medium.woff2` | CircularXX | Medium 500 | Normal | | `CircularXXWeb-MediumItalic.woff2` | CircularXX | Medium 500 | Italic | | `CircularXXMonoWeb-Regular.woff2` | CircularXX Mono | Regular 400 | Normal | | `NaNSerfBText-Book.woff2` | NaN Serf B | Book 400 | Normal | The file names must match exactly: `@clinia/tailwindcss/fonts` points at `/fonts/`, which the theme from step 3 imports. Clinia UI uses these seven files and no others. Delete every other brand font file and its declaration, such as CircularXX Bold 700 or Gothia Serif, along with any `font-bold` or `font-semibold` that used them (step 8 rejects both). An app that loads its fonts with `next/font/local` keeps doing so, with the same seven files. Remove the `@import "@clinia/tailwindcss/fonts"` line the theme adds, so no face is declared twice (and again each time you add the theme), and point the font tokens at the `next/font` variables after the theme imports: ```css :root { --clinia-font-sans: var(--font-circular), "Inter", sans-serif; --clinia-font-mono: var(--font-circular-mono), ui-monospace, monospace; --clinia-font-display: var(--font-nan-serf), Georgia, serif; } ``` The variable names are the ones your `localFont()` calls set, on an element that wraps the app such as ``. `next/font` keeps preloading the faces and adjusting the fallback's size. ## 5. Install the icon modules Clinia UI uses **Google Material Symbols** in the Rounded, weight 300 flavour. The [Iconography](https://ui.clinia.dev/docs/iconography) page covers the set and how to use it. **Product app**: ```bash pnpm dlx shadcn@latest add @clinia/icons ``` **Marketing site**: add the [marketing icons](https://ui.clinia.dev/docs/marketing/icons) too. ```bash pnpm dlx shadcn@latest add @clinia/icons @clinia/marketing-icons ``` This writes one module per icon under `components/ui/icons/`, plus `icons.manifest.ts`, `scripts/gen-icons.mjs` and `scripts/codemod-icons.mjs`. ## 6. Reinstall your components Reinstall the components your app uses from `@clinia`, with `--overwrite`. The same command works on both surfaces: the style you set in step 2 decides whether you get the Luma or the Sera version. The icons are already wired. ```bash pnpm dlx shadcn@latest add @clinia/button @clinia/select --overwrite ``` This replaces your current copies, so review the diff first if you edited them. Then install Clinia's `cn()`, which knows the type scale. Without it, `tailwind-merge` reads `text-body-s` as a colour and keeps the component's own `text-sm` beside it, so the size never changes: ```bash pnpm dlx shadcn@latest add @clinia/utils --overwrite ``` It replaces `lib/utils.ts`: move any other helpers your app keeps there to their own file first. The CLI installs dependencies with its own copy of pnpm, which can be newer than the one your repository pins. After each `shadcn add`, run `pnpm install --lockfile-only` with your repository's pnpm (`npm install --package-lock-only` with npm) and check the lockfile diff. A stylesheet of the app's own, imported after the theme, is unlayered, so it beats every utility in the components. A reset such as `a { color: inherit }` overrides `text-primary-foreground` and can leave a button's label dark on dark, which axe may not report. When the components arrive, move the app's element resets (`a`, `button`, headings) into `@layer base`. Don't move the whole file into a layer: a class that shares a utility's name, such as `.container`, then loses to the utility and the layout changes without a warning. A site on `@clinia/web-cookiebot` moves to [Cookie Consent](https://ui.clinia.dev/components/cookie-consent): add `@clinia/cookie-consent`, mount it once in the root layout with the site's categories, then uninstall the package and remove its `@clinia` entry from `.npmrc` if nothing else needs GitHub Packages. It reads the same `cc_cookie`, so users keep their earlier choice. Cookie Consent has no banner title and no free-text sections in its preferences, so web-cookiebot's title and info copy are dropped: put what users need to know in `message` and in each category's `description`. A site with only necessary cookies removes the banner instead, and says so in its privacy policy. Keep the files the registry writes out of your formatter: `components/ui/`, `lib/utils.ts`, `icons.manifest.ts`, the icon scripts and `eslint.clinia.mjs`. Add them to `.prettierignore` or its equivalent, so the next reinstall shows only Clinia's changes. ## 7. Import selected icons ```tsx import { CheckIcon } from "@/components/ui/icons/check" ``` - Icons are 20px by default. The standard sizes are 16, 20 and 24. - Icons draw in the `currentColor` of the surrounding text or section. - An interactive icon needs a `label` for accessibility. Leave the `label` off only for decorative icons. - Import each icon from its own file, as above. Don't wrap icons in a component that picks one by name: it loads every icon into the page. ## 8. Add the lint rules The lint rules keep the migration in place. Without them, the next `shadcn add` quietly brings back a second icon set, and raw values creep back into the app's own code. ```bash pnpm dlx shadcn@latest add @clinia/eslint ``` This writes `eslint.clinia.mjs`. Spread it last in your `eslint.config.mjs`: ```js import clinia from "./eslint.clinia.mjs" export default [...yourConfig, ...clinia] ``` Outside `components/ui/`, the rules reject other icon libraries, raw `--clinia-*` swatches, arbitrary text sizes such as `text-[13px]`, `font-semibold` and `font-bold`, `rounded-none`, corners above `rounded-lg` and arbitrary radii, hex colours in classes such as `bg-[#fcf8ef]` or in a `style` prop, `role="button"` on an element that isn't a button, and a logo drawn with ``. They read JavaScript and TypeScript only. They don't catch arbitrary `leading-[…]` or `tracking-[…]`, `rgba()` in classes, or anything in a CSS file: search for those by hand. Once the rules are installed, `pnpm lint` counts what they do catch. In a monorepo with one flat config at the root, scope Clinia's rules to the app. Its blocks match `**/*`, so imported as they are, they lint every package. Prefix each block's `files` and `ignores` with the app's folder. If the root config sets `no-restricted-imports` for the same files, merge its options into Clinia's block: a later block replaces the rule's options rather than adding to them. Then uninstall any other icon library your app still lists in `package.json`, such as `lucide-react` or `@hugeicons/react`. ## 9. Components Clinia doesn't ship Don't install them straight from shadcn: [request them](https://ui.clinia.dev/docs/request-a-component). The page also covers what to do if you can't wait. ## 10. Replace the brand assets The logo, the favicon and the app icons don't change with the components. Replace them, or the migrated app keeps showing the old ones. ```bash pnpm dlx shadcn@latest add @clinia/logo curl -LO https://ui.clinia.dev/favicon/favicon.zip unzip favicon.zip -d public/favicon cp public/favicon/light/favicon.ico public/favicon.ico ``` - Replace each logo `` with the inline `Logo` or `Logomark`, coloured with `text-foreground`. An `` can't follow the theme. See [Logo](https://ui.clinia.dev/docs/logo). - Replace the favicon, the app icons and the manifest icons with the files from `favicon.zip`, set the `` tags as [Favicon](https://ui.clinia.dev/docs/favicon) shows, and delete the old files. - On a marketing site, replace any copies of the compliance badges with the files on [Security & compliance](https://ui.clinia.dev/docs/marketing/compliance), and their captions with its approved titles and lines. A site's own copies drift in size and wording. ## 11. Align each screen with its conventions New tokens and components don't make a screen look like Clinia on their own. Go through each screen, list the patterns the app built by hand, and replace each with the Clinia component that does the job. In a product app: | Built by hand | Clinia component | |---|---| | Sidebar navigation, with links made of `div role="button"` | [Sidebar](https://ui.clinia.dev/components/sidebar) | | List rows with an icon, a title and actions | [Item](https://ui.clinia.dev/components/item) | | "Loading…" text | [Skeleton](https://ui.clinia.dev/components/skeleton) shaped like the content, or [Spinner](https://ui.clinia.dev/components/spinner) inside the button that started the action | | "No results" or "Nothing here yet" text | [Empty](https://ui.clinia.dev/components/empty) | | A logo `` | [Logo](https://ui.clinia.dev/components/logo), from step 10 | | A label, an input, its hint and its error | [Field](https://ui.clinia.dev/components/field) | | Status pills | [Badge](https://ui.clinia.dev/components/badge) | Then check each screen against the App conventions: [Empty states](https://ui.clinia.dev/docs/app/empty-states), [Loading](https://ui.clinia.dev/docs/app/loading), [Forms and validation](https://ui.clinia.dev/docs/app/forms) and [Destructive actions](https://ui.clinia.dev/docs/app/destructive-actions). On a marketing site: | Built by hand | Clinia component | |---|---| | A header bar | [Site header](https://ui.clinia.dev/docs/site-header): transparent over the home page's hero, solid on inner pages | | A hero or section CTA pair, or any link styled as a button | [CTA](https://ui.clinia.dev/components/cta) | | A row of customer logos | [Logo Strip](https://ui.clinia.dev/components/logo-strip) | | Compliance badges and their captions | The files and lines on [Security & compliance](https://ui.clinia.dev/docs/marketing/compliance), from step 10 | | A decorative background behind a hero or a closing CTA band | [Brand Background](https://ui.clinia.dev/components/brand-background) | | Hand-drawn line loops | The Infinity Band lines on [Line & shape](https://ui.clinia.dev/docs/marketing/line-and-shape) | | A product name beside the logo, or a "powered by Clinia" line | The [product lockup](https://ui.clinia.dev/docs/logo#product-lockup) | Then check each page against the Marketing conventions: [Getting started](https://ui.clinia.dev/docs/marketing/getting-started), [Line & shape](https://ui.clinia.dev/docs/marketing/line-and-shape), [Imagery](https://ui.clinia.dev/docs/marketing/imagery) and [Motion](https://ui.clinia.dev/docs/marketing/motion). A hand-built card that already matches Card through tokens (the `border` hairline, `bg-card` and 8px corners) needs no swap. Keep its element, such as an `
`. A component can bring behaviour the app doesn't have, such as Sidebar's collapse to icons and its mobile drawer. Decide on that before adopting it. Matching its look, such as the active item's tint and spacing, needs no decision. Two layout traps when you swap hand-built cards and links: - `buttonVariants()` returns the variant's classes without merging them. On a ``, wrap it in `cn()`, or the outline variant keeps `border-transparent` and loses its border. Don't use ` // Base UI, in Clinia's components Edit profile} /> ``` Walk every dialog, menu, and popover with the keyboard after the switch: focus moves in on open, Escape closes, and focus returns to the trigger. ## From Clinia UI 1.x An app on `@clinia/tailwindcss` 0.x is partly on Clinia UI already. The site and the package number their versions differently: Clinia UI 1.x shipped `@clinia/tailwindcss` 0.x, and Clinia UI 2.0 ships `@clinia/tailwindcss` 2.0. Version 2.0 changes the foundations under it, so check each of these on top of the steps above. The [changelog](https://ui.clinia.dev/docs/changelog) has the full Breaking list. | In a 1.x app | In 2.0 | What to do | |---|---|---| | `@clinia/tailwindcss` 0.x | 2.0 | Upgrade the package: `pnpm add @clinia/tailwindcss@2`. If `@clinia` maps to GitHub Packages, see step 3. If pnpm adds the package to `minimumReleaseAgeExclude`, keep that line. | | `@clinia/tailwindcss/style-luma` or `style-sera` imports, `data-style` on an element | Removed | Delete them. Shape comes from the shadcn style in `components.json`. | | Another shadcn style, such as `base-maia` | `base-luma` for product apps, `base-sera` for marketing sites | Set the style, then reinstall every component (step 6). Product screens use Luma, even admin areas that used Sera. | | Vital as the accent | Trust | Reinstalled components follow on their own. In the app's own code, move `--clinia-vital` and accent uses to semantic tokens, and keep small text off Trust. | | Gothia Serif | NaN Serf B, Book 400 only | Replace the font files and drop any weight above 400 on display text. | | `font-semibold`, `font-bold` | Not shipped: CircularXX goes up to 500 | Use `font-medium`. | | No animation imports | The theme imports `tw-animate-css` and `shadcn/tailwind.css` | Add the theme item again (step 3), so overlays and accordions animate. | | HugeIcons, Lucide or inlined icons | Material Symbols modules | Steps 5 and 7. | ## Documentation sites on Fumadocs A docs site built on `fumadocs-ui` keeps Fumadocs' layout, search, table of contents and API reference, and takes Clinia's colours, states and type. Developer documentation is an App surface: set `base-luma`. 1. Replace the Fumadocs colour preset (`fumadocs-ui/css/neutral.css` and its siblings) with `@clinia/tailwindcss/fumadocs`. The preset sets its own dark sidebar colours, which override any mapping you add. Keep `fumadocs-ui/css/preset.css`: it holds the layout, not colours. 2. Import Clinia after Fumadocs. Both declare a `dark` variant, and the later one wins: ```css @import "tailwindcss"; @import "fumadocs-ui/css/preset.css"; @import "@clinia/tailwindcss/fonts"; @import "@clinia/tailwindcss"; @import "tw-animate-css"; @import "shadcn/tailwind.css"; @import "@clinia/tailwindcss/fumadocs"; ``` 3. Map the MDX components onto Clinia's in the page's `components`, so no `.mdx` file changes: `Callout` to Alert and `Card` to Item, with Fumadocs' props. Alert is a live region (`role="alert"`): pass `role={undefined}` for a static callout. Keep a card's title a heading. 4. If the site uses `fumadocs-openapi`, check its method labels and status colours. They use Tailwind's palette directly, and `text-green-600` fails AA on white. 5. Give highlighted code a dark theme that passes on your dark card. Shiki's GitHub dark theme draws comments at 3.25:1. Clinia's theme ships in `@clinia/code-block` as `lib/code-theme.ts`. ## Before you ship Quality gates to make sure all guidelines are followed: **In the code** - `pnpm lint` passes. This makes sure conventions are followed, and that the rules from step 8 catch any icon import, hand-built button or logo image that slipped through, and the raw values they cover. **On each screen** - It uses the components from step 11, not hand-built versions of them, and follows its App or Marketing conventions page. - The logo is the inline `Logo`, and the tab shows Clinia's favicon in both themes. --- title: "Request a component" description: "How to get a component added to @clinia, and what to use until it ships." url: https://ui.clinia.dev/docs/request-a-component --- # Request a component ## General guideline Always install from `@clinia`. When the component you need isn't in [Components](https://ui.clinia.dev/components), ask for it instead of installing it straight from shadcn. ## Why ask for new components instead of installing from shadcn? A component installed straight from shadcn will miss the overrides the Clinia design guidelines add: - **Colour fixes**: to align the selected colours with specific component parts. - **Icons**: it imports Lucide, which Clinia's lint rules reject once you add them ([Migration](https://ui.clinia.dev/docs/migration), step 8). - **Both styles**: a `@clinia` component ships in Luma and Sera, and the `style` in your `components.json` picks the right one. - **Testing**: every `@clinia` component passes an automated accessibility check in both styles and both themes before it ships. ## How to ask [Open a component request](https://github.com/clinia/ui/issues/new?template=component-request.yml) on the `clinia/ui` repository. You will need access to the private Clinia repository and have the following information on hand: - The shadcn component name, or a link to its page on [ui.shadcn.com](https://ui.shadcn.com). - The surface: product app, marketing site or both. - Where you'll use it: the app or site, and the screen or section. - When you need it. - Anything that differs from upstream: a variant, a size, a state or a behaviour. ## Icons The same form covers a utility icon the set doesn't have. Name the glyph from [Material Symbols](https://fonts.google.com/icons) and where you'll use it. The icon generator runs in `clinia/ui` only, so an app can't add an icon to the set itself. ## What happens next A maintainer will add the component to the registry in a reasonable amount of time. The component will then appear in the theme after review and sign-off. --- title: "Changelog" description: "What changed in Clinia UI, release by release." url: https://ui.clinia.dev/docs/changelog --- # Changelog {/* Entry template: every release follows it, newest release first. ## vX.Y.Z (feeds the timeline beside the page) One line: what the release is, when it shipped, and the @clinia/tailwindcss version. ### Breaking what changes and what to do about it; link the page that explains it ### Added ### Changed ### Fixed Leave out a group with nothing in it. One change per bullet, written for the reader who installs from @clinia, compared with the previous release. Link the docs page, not the commit. */} Every change to what ships is listed here: tokens, components, registry items and the rules on this site. Each release opens with its breaking changes and what to do about them. The [migration guide](https://ui.clinia.dev/docs/migration) walks through the upgrade step by step. ## Unreleased Changes merged since v2.0.2, released with the next version. ### Added - Six slide layouts in the External deck template: four steps with an example, a problem with its evidence, three equal results, seven points and their impact, the layer diagram beside three benefits, and two theses. - Two deck figures: `access`, each agent getting only its scoped view of one record with what it was refused, and `schema`, sources resolved to one coded fact each. Both build in, with a GIF for a deck presented live. - Two deck figures: `fanout`, the Context Engine feeding the reader's own workflows, and `pipeline`, the engine end to end from sources to an agent. Both build in, with a GIF for a deck presented live. Connectors in deck figures are now curves, `wiring` included. - A deck figure, `answer`: the same question put to an agent without and with the Context Engine, side by side, with the context each had and the sources the answer cites. It builds in, and the clinia-deck-figures export gives it a GIF for a deck presented live. - The LinkedIn company, LinkedIn personal and social media banners carry the descriptor "Patient Context for Healthcare AI". Download them again from [Social media](https://ui.clinia.dev/docs/marketing/social-media). - One-pagers, a page under Document conventions: when to send a one-pager instead of a deck, what makes a good one, and who approves it. Sales one-pagers are single US Letter PDFs built from this site's type, colours and line art by the `clinia-one-pagers` skill in the repository. See [One-pagers](https://ui.clinia.dev/docs/documents/one-pagers). - Fifteen utility icons for the Console: `home`, `group`, `person-add`, `credit-card`, `cloud-off`, `school`, `redeem`, `speed`, `stacks`, `code`, `smart-toy`, `done-all`, `block`, `verified-user` and `report`. Reinstall `@clinia/icons`. See [Iconography](https://ui.clinia.dev/docs/iconography). - Documents, a page under Document conventions: the Clinia document template in Google Docs, which pages a document has, the rules that make it good, and the `clinia-docs` skill, which builds a document from the template or brings an older one onto it without adding content. See [Documents](https://ui.clinia.dev/docs/documents/google-docs). - Presentations, a page under Document conventions: three deck templates in Google Slides (External, Client, and Internal), which deck needs marketing's approval, how to make one by hand or with Claude, and the frame and building blocks every slide uses, shown on the template's own slides. See [Presentations](https://ui.clinia.dev/docs/documents/presentations). - Scene: source records (`SceneSource`, the `source` plan node), an ambient dot field (`SceneField`, the plan's `field`) and a larger display card with the name in the serif (`display`), for a scattered-record scene: one patient's data as each source wrote it, before it is linked. See [Scenes](https://ui.clinia.dev/docs/marketing/scenes). - [Patient personas](https://ui.clinia.dev/docs/marketing/personas), a page under Marketing conventions: eight fictional patients, including the five clinia.com shows, each with a fixed name, date of birth and approved photo, used the same way in scenes, deck figures and post images. A scene card takes one with `"avatar": "avatar:"`. ### Changed - The `clinia-decks` skill runs a storyline pass on the outline and again on the built deck. It fails a deck whose titles, read alone, don't tell the argument, whose parts don't answer the question the part before raised, whose numbers or names disagree between slides, that has no closing slide with the ask, or whose slides carry two claims or a claim with no source in the notes. The report goes out with the deck. See [Presentations](https://ui.clinia.dev/docs/documents/presentations). - [Presentations](https://ui.clinia.dev/docs/documents/presentations) adds a rule, readable by everyone. The deck check in the clinia-decks skill now also reviews layout and accessibility before a deck is handed back. - The product is the Clinia Context Engine, described as "Patient Context for Healthcare AI". The press boilerplate on [Brand exposure](https://ui.clinia.dev/docs/marketing/brand-exposure) and the `clinia-writing` and `clinia-one-pagers` skills drop "for Health AI" from the product name, and `clinia-writing` flags the old line. - The `clinia-one-pagers` skill can be [downloaded](https://ui.clinia.dev/skills/clinia-one-pagers.zip) for Claude Desktop: it writes a one-pager's copy as a plan, rendered to PDF in the repository. See [One-pagers](https://ui.clinia.dev/docs/documents/one-pagers). - A Document conventions group in the sidebar holds [Presentations](https://ui.clinia.dev/docs/documents/presentations), [Documents](https://ui.clinia.dev/docs/documents/google-docs) and [One-pagers](https://ui.clinia.dev/docs/documents/one-pagers), under `/docs/documents/`. The old addresses redirect. - [Presentations](https://ui.clinia.dev/docs/documents/presentations): decks end on the closing slide, pick the slide made for their number of points, keep the approved compliance titles and lines, and never show a placeholder slide. The `clinia-decks` check now flags topic titles, titles out of line with the rest of the deck, reworded compliance text and slides left half empty, flags headings side by side that wrap differently and labels that wrap, and the skill has a customer-facing cloud marketplace recipe. - The `clinia-design-system` skill reads `DESIGN.md` live instead of keeping its own summary, and hands decks, documents and code to `clinia-decks`, `clinia-docs` and `clinia-ui`. [Download it](https://ui.clinia.dev/skills/clinia-design-system.zip) from [Using AI tools](https://ui.clinia.dev/docs/ai-tools#claude-design). - The `clinia-decks` skill can be [downloaded](https://ui.clinia.dev/skills/clinia-decks.zip) for Claude Desktop, and the `clinia-writing` download now matches the skill in the repository. See [Presentations](https://ui.clinia.dev/docs/documents/presentations). - Section headings on every docs page are links to themselves: click one, or copy it, to share a link to that section. - [Brand exposure](https://ui.clinia.dev/docs/marketing/brand-exposure) links the help centre, now live at help.clinia.com, and the new status page at status.clinia.dev, which replaces cliniastatus.com. - The HIPAA, GDPR, SOC 2 and PIPEDA badges on [Security & compliance](https://ui.clinia.dev/docs/marketing/compliance) are SVG files, so they stay sharp at any size, and the download includes them. The old PNG links redirect to the SVGs. - Help and support sites use `base-sera` with App conventions. The migration prompt on [Using AI tools](https://ui.clinia.dev/docs/ai-tools#migrate-an-existing-app) and the `clinia-ui` skill name it. - Using AI tools links Clinia UI, Clinia's design system in Claude Design: the 2.0.2 tokens, fonts and logos, and all 118 components with Luma and Sera side by side, each with its page's rules and a live preview. See [Using AI tools](https://ui.clinia.dev/docs/ai-tools#claude-design). ### Fixed - The deck check in the clinia-decks skill reads a space set as its own text run, so a title such as "Global security & compliance" no longer reads as "security &compliance". - The deck check in the clinia-decks skill no longer fails a meeting agenda's title for naming the meeting, or a mono label broken onto several lines on purpose. ## v2.0.2 Patch release with `@clinia/tailwindcss` 2.0.2 on npm `latest` and GitHub Packages. The tokens are unchanged from 2.0.1; the fixes and rules below ship with the site and the registry. ### Added - Twenty utility icons: `layers`, `scan-delete` and `trending-down` for Concord; `rocket-launch`, `database`, `shield`, `key`, `troubleshoot`, `support-agent`, `list` and `arrow-right-alt` for the help centre; and `play-arrow`, `science`, `lock`, `light-mode`, `dark-mode`, `arrow-downward`, `flag`, `pause` and `not-equal` for the CCE benchmark dashboard. Reinstall `@clinia/icons`. See [Iconography](https://ui.clinia.dev/docs/iconography). - Charts, a Draft page under App conventions: gauge, radar, range plot, bullet, trend line, ranked bars, sparkbars and heatmap examples, with guidance on status marks, hand-built SVG charts, band opacity, entry motion and when a gauge beats a stat. See [Charts](https://ui.clinia.dev/docs/app/charts). - Logo Strip takes `still`, which holds the logos still, as under reduced motion, whatever the user's motion setting. A still row that overflows also scrolls with a mouse drag. Reinstall `@clinia/logo-strip`. See [Logo Strip](https://ui.clinia.dev/components/logo-strip). - The Button, Card and Item pages preview the Sera version and its states beside Luma's, so a marketing reviewer sees what a marketing site installs. See [Button](https://ui.clinia.dev/components/button). - Field, Select, Tooltip, Table, Code Block and Command pages show the states their rules depend on: the invalid field with its error, an open Select list, open tooltips, resting, hover and selected rows, the Code Block copy button, and the Command no-results state. See [Select](https://ui.clinia.dev/components/select). ### Changed - Icon modules inline their Rounded 300 SVG, so `@clinia/icons` no longer installs `@material-symbols-svg/react`, and a client route ships one weight per icon instead of sixteen (`check` drops from 2.9 kB to 0.6 kB minified). The props and the rendered `` are the same. Reinstall `@clinia/icons`, then remove `@material-symbols-svg/react` from your dependencies. `@clinia/eslint` now flags any import of it, or of `@material-symbols/svg-300`, outside the icon generator. See [Iconography](https://ui.clinia.dev/docs/iconography). - The registry items are MIT, like `@clinia/tailwindcss`. The repository's LICENSE carries the notices for the shadcn/ui, Material Symbols and Carbon code they include, and keeps the Clinia name, logo and brand assets out of the grant. See the [LICENSE](https://github.com/clinia/ui/blob/main/LICENSE). - Marketing getting started warns that Sera's uppercase controls widen labels and show user input in capitals, and links full-width sections in Containers. See [Marketing getting started](https://ui.clinia.dev/docs/marketing/getting-started). - Item: the Sera `ItemTitle` is an uppercase label for a few words. See [Item](https://ui.clinia.dev/components/item). - Rive scenes drops the "Home: start building" agency scene, which never played its typewriter. The generated rebuild still plays under the prompt example. See [Rive scenes](https://ui.clinia.dev/docs/marketing/rive-scenes). ### Fixed - Logo Strip keeps its logos on one line under reduced motion. A row wider than the strip scrolls sideways and, only then, takes keyboard focus as a region named like the list. Its scrollbar stays clear until the pointer is over the row or it has focus. Reinstall `@clinia/logo-strip`. See [Logo Strip](https://ui.clinia.dev/components/logo-strip). - Cookie Consent passes eslint-config-next 16's React Compiler rules (`react-hooks/refs`, `react-hooks/set-state-in-effect`) with no disables, and no longer leaves an empty dialog from vanilla-cookieconsent in the accessibility tree. Reinstall `@clinia/cookie-consent`. See [Cookie Consent](https://ui.clinia.dev/components/cookie-consent). - Command no longer leaves an empty listbox when a search matches nothing: the input reports collapsed and screen readers announce the no-results text. Reinstall `@clinia/command`. See [Command](https://ui.clinia.dev/components/command). - Alert takes `role="note"` for a static note in content, so screen readers read it in place instead of announcing it on load. See [Alert](https://ui.clinia.dev/components/alert). - `EmptyTitle` takes `render`, so `render={

}` makes it a heading. Reinstall `@clinia/empty`. See [Empty](https://ui.clinia.dev/components/empty). - Table: while a table is wider than its container, the scroll container is a tab stop and a region named by the table's `aria-label` or its `TableCaption`, so keyboard users can scroll it. Reinstall `@clinia/table`. See [Table](https://ui.clinia.dev/components/table). - A long `ItemTitle` truncates to one line with an ellipsis in Luma and Sera. A title that holds an icon or a badge now lays out inline; add `flex items-center gap-2` through `className` to space them, which turns the clamp off. Reinstall `@clinia/item`. See [Item](https://ui.clinia.dev/components/item). - Code Block's copy button drops its shadow, in product and marketing. Code Block and File Upload keep one file for both styles. Reinstall `@clinia/code-block`. See [Code Block](https://ui.clinia.dev/components/code-block). - Typography says that 17 to 19px sizes move down to `body-m`, as its table shows. See [Typography](https://ui.clinia.dev/docs/typography#sizes-off-the-scale). - Migration step 3 says GitHub Packages carries `@clinia/tailwindcss` from 2.0.1, and drops the npm tarball workaround. See [Migration](https://ui.clinia.dev/docs/migration). ## v2.0.1 Patch release with `@clinia/tailwindcss` 2.0.1 on npm `latest` and GitHub Packages. The tokens are unchanged from 2.0.0; the release brings v2 to GitHub Packages, and the fixes and rules below ship with the site and the registry. ### Added - Marketing Forms: how contact, demo and newsletter forms ask, validate and confirm on a marketing site, with the Sera fields, Button for the submit, the privacy line and unticked consent. See [Forms](https://ui.clinia.dev/docs/marketing/forms). - Card takes `render`, in Luma and Sera, so a card can render as an `
` or as its own link. See [Card](https://ui.clinia.dev/components/card). - Scenes can show provider data. New parts: the panel, a titled box of rows, and fields on the card. A plan can set its layout `width` and each box its `w`, and a line can meet a panel at one of its rows. A scene without pills has no emphasized entity, and chips can also stand for the systems that receive data. Reinstall `@clinia/scene`. See [Scenes](https://ui.clinia.dev/docs/marketing/scenes). - A sharing image for each Clinia site's home page: the light Article card with the site's name as the eyebrow, for ui.clinia.dev, docs.clinia.com, help.clinia.com (English and French) and Concord. ui.clinia.dev now sets its own. See [Sharing images](https://ui.clinia.dev/docs/marketing/sharing-images#site-home-pages). ### Changed - Marketing (Sera) form fields now match the forms on clinia.com: Input, Textarea, Select, Native Select, Combobox, Input Group and Input OTP are boxed controls with an `input` border and 8px corners instead of an underline, with a 16px value, and Field sets its label above the control in 16px sentence case. Focus takes the `ring` border and halo. Reinstall these components on a marketing site. See [Field](https://ui.clinia.dev/components/field). - Migration covers marketing sites: a table of marketing patterns and their Clinia components in step 11, the compliance badges in step 10, npm commands beside the pnpm ones, the tarball fallback when `@clinia` maps to GitHub Packages, and layering a site's own CSS so it doesn't beat the components. The migration prompt audits the same, plus dead CSS, swatches used outside a token, analytics, and the cookie banner. See [Migration](https://ui.clinia.dev/docs/migration). - Typography: display headlines carry no emphasis on a single word, since NaN Serf B has no italic or bold. See [Typography](https://ui.clinia.dev/docs/typography#italic). - Colour: a swatch with no semantic token or `brand-*` utility, such as Peach-4, is for charts and illustrations only. See [Colour](https://ui.clinia.dev/docs/color#palette). - Logo and Favicon: a named Clinia product site uses the product lockup, with no "powered by Clinia" line, and Clinia's favicon. See [Logo](https://ui.clinia.dev/docs/logo#product-lockup). - Marketing motion: SVG animated with SMIL is out, since reduced motion can't stop it. See [Motion](https://ui.clinia.dev/docs/marketing/motion). - Brand Background: a hero with no Rive scene can take a blurred band, cropped away from the copy, and then drops its line accent. See [Brand Background](https://ui.clinia.dev/components/brand-background). - SEO: with Vercel Analytics, start the `window.va` queue before tracking an event on page load, or the event is dropped. See [SEO](https://ui.clinia.dev/docs/marketing/seo#in-nextjs). - Site header: a transparent home header needs the hero to run up under it. Marketing getting started links Site header for the scroll behaviour. See [Site header](https://ui.clinia.dev/docs/site-header#the-home-page). - Cookie Consent replaces `@clinia/web-cookiebot`: Migration step 6 says how to move, and users keep their choice through the shared `cc_cookie`. See [Cookie Consent](https://ui.clinia.dev/components/cookie-consent). - Logo Strip drops its Pause button. The loop still pauses on hover and off screen, and stops under reduced motion. Reinstall `@clinia/logo-strip`. See [Logo Strip](https://ui.clinia.dev/components/logo-strip). ### Fixed - The `theme` and `theme-marketing` items install `@clinia/tailwindcss@^2`. With no version, a project that maps `@clinia` to GitHub Packages got 0.3.0 without a warning. See [Migration](https://ui.clinia.dev/docs/migration). - CTA takes an `href`, and a CTA with an `href` or a `render` link such as `` renders a plain link. Screen readers announce it as a link, not a button, and Space no longer follows it. Drop `nativeButton={false}`. See [CTA](https://ui.clinia.dev/components/cta). - Scene: a card with fields no longer calls a hook on one branch only, and a scene hidden by CSS waits until it shows to place its lines, instead of drawing them at NaN. Reinstall `@clinia/scene`. See [Scene](https://ui.clinia.dev/components/scene). - Marketing (Sera) Input Group pads its addons like Luma, so an icon or a button inside the boxed field no longer touches its border. Reinstall `@clinia/input-group` on a marketing site. See [Input Group](https://ui.clinia.dev/components/input-group). ## v2.0.0 Design system v2, released on October 21, 2026, with `@clinia/tailwindcss` 2.0.0 on npm `latest`. Every entry below compares with v1.0.0. ### Breaking - **Trust replaces Vital as the accent.** `--accent`, `--sidebar-accent` and `--ring` move from Vital `#ff5c00` to Trust `#95795c`. Trust is a 3:1 colour: borders, icons, selected states and text from 24px up, never label-size text or a fill behind it. Any component that puts small text on `accent` fails WCAG AA after the upgrade. Vital leaves product UI and the chart palette. See [Colour](https://ui.clinia.dev/docs/color). - **NaN Serf B replaces Gothia Serif** as the display face, Book 400 only. Self-hosted apps swap the font files. See [Typography](https://ui.clinia.dev/docs/typography). - **`--input` becomes a boundary colour**: `#8c8c8c` light, `#777777` dark, so field edges clear 3:1. - **The Sera and Luma CSS shape layers are removed.** Shape now comes from the shadcn style in `components.json`: `base-luma` for product, `base-sera` for marketing. - **Utility icons move to Material Symbols**, Rounded, weight 300, one module per icon in `@clinia/icons`. See [Iconography](https://ui.clinia.dev/docs/iconography). - **Table rows hover only when they're `interactive`.** A row of static data no longer tints on hover. Set `interactive` on a `TableRow` that opens, selects or links to something, and it takes the `bg-foreground/4` hover tint. `TableHeader` and `TableFooter` sit on `bg-foreground/3`. Reinstall `@clinia/table`, then add `interactive` to clickable rows and drop any `hover:bg-transparent` you added to static ones. See [Table](https://ui.clinia.dev/components/table). ### Added - Every component also ships in a Sera version for marketing sites, with the same colour fixes and icons. Point `@clinia` at `https://ui.clinia.dev/r/{style}/{name}.json` and the `style` in `components.json` picks Luma or Sera. The old `/r/{name}.json` URL keeps serving Luma. - New components: app shell, form and data components, File Upload, date and time pickers, Code Block and Logo. New variants: emphasis and interactive Card, success and warning Badge. - Cookie Consent: one banner and preferences panel for every app and site, opt-in by default, honouring Global Privacy Control, with a cookie inventory per category. It keeps the `cc_cookie` of `@clinia/web-cookiebot`, so visitors' choices carry over. See [Cookie Consent](https://ui.clinia.dev/components/cookie-consent). - `@clinia/utils`: a `cn()` that knows the type scale, so `text-body-s` replaces a component's `text-sm` instead of sitting beside it. New apps get it with `base` or `marketing`; existing apps add it. See [Migration](https://ui.clinia.dev/docs/migration#6-reinstall-your-components). - `@clinia/eslint`: lint rules for an app's own code. They reject other icon libraries, raw `--clinia-*` swatches, raw hex colours, arbitrary text sizes, `font-semibold` and `font-bold`, `rounded-none`, corners above `rounded-lg`, `role="button"` on an element that isn't a button, and a logo drawn with ``. See [Migration](https://ui.clinia.dev/docs/migration#8-add-the-lint-rules). - New tokens: `border-emphasis` for selected outlines and the one emphasis moment per view, and `.light`, which pins a subtree to the light theme, the counterpart to `.dark`. - `@clinia/tailwindcss/marketing`: marketing-only illustration roles `scene-condition`, `scene-lab` and `scene-medication`, on existing swatches. The `theme-marketing` item imports it. - `@clinia/tailwindcss/fumadocs`: Fumadocs' colour tokens and states from Clinia's theme, for documentation sites built on fumadocs-ui. Import it after the theme, in place of a Fumadocs colour preset. See [Migration](https://ui.clinia.dev/docs/migration#documentation-sites-on-fumadocs). - Marketing components, for marketing surfaces only. CTA, the clinia.com call to action: a mono uppercase label beside a square arrow tile, in `primary`, `default` and `ghost`. Brand Background: `BandBackground` sets the twist or ring band behind a section, and `LineBackground` sets a line shape behind a card, with `keepAspect` for wide, short banners. Logo Strip: a row of customer logos scrolling in a loop, with a Pause button, still under reduced motion and paused off screen. See [Custom components](https://ui.clinia.dev/docs/marketing/custom-components) and [Backgrounds](https://ui.clinia.dev/docs/marketing/backgrounds). - Scene: a marketing kit to compose clinia.com-style patient graphs in code (card, pills, relation tags, lines, source chips) that build in when scrolled into view, and the Rive scenes, with the skills that build both and the marketing lead's approval. See [Scenes](https://ui.clinia.dev/docs/marketing/scenes) and [Rive scenes](https://ui.clinia.dev/docs/marketing/rive-scenes). - Marketing icons, with the 25 IBM Carbon icons clinia.com uses as overrides, approved for marketing surfaces only. They ship in `@clinia/marketing-icons`, so a site installs no Carbon package. See [Marketing icons](https://ui.clinia.dev/docs/marketing/icons#carbon-overrides). - Brand downloads: transparent PNGs of the mark and the wordmark in Infinite and Serene, a social profile set, profile banners for LinkedIn, YouTube, the B Corp listing, the Trust Center and other platforms, a status page banner, and sharing images, each in a light and a dark version, at 1×, 2× or 3× the platform size. See [Logo](https://ui.clinia.dev/docs/logo#source-files), [Social media](https://ui.clinia.dev/docs/marketing/social-media) and [Sharing images](https://ui.clinia.dev/docs/marketing/sharing-images). - A product lockup for a Clinia site that names itself beside the logo, such as the developer documentation. See [Logo](https://ui.clinia.dev/docs/logo#product-lockup). - Conventions shared by app and marketing: [Colour](https://ui.clinia.dev/docs/color), [Typography](https://ui.clinia.dev/docs/typography), [Containers](https://ui.clinia.dev/docs/containers), including full-width sections, [Iconography](https://ui.clinia.dev/docs/iconography), [Motion](https://ui.clinia.dev/docs/motion), [Accessibility](https://ui.clinia.dev/docs/accessibility) with a live contrast matrix, and the [Site header](https://ui.clinia.dev/docs/site-header) shared by the developer documentation and the help centre. - App patterns: [Empty states](https://ui.clinia.dev/docs/app/empty-states), [Loading](https://ui.clinia.dev/docs/app/loading), [Forms and validation](https://ui.clinia.dev/docs/app/forms), [Destructive actions](https://ui.clinia.dev/docs/app/destructive-actions). - Marketing guidance: [Motion](https://ui.clinia.dev/docs/marketing/motion), [Icons](https://ui.clinia.dev/docs/marketing/icons), [Imagery](https://ui.clinia.dev/docs/marketing/imagery), [Line & shape](https://ui.clinia.dev/docs/marketing/line-and-shape), [Co-branding](https://ui.clinia.dev/docs/marketing/co-branding), [Social media](https://ui.clinia.dev/docs/marketing/social-media), [Security & compliance](https://ui.clinia.dev/docs/marketing/compliance) and [SEO](https://ui.clinia.dev/docs/marketing/seo). - Content guidelines for public content: the voice, a house style for English and French, and how it's written with the `clinia-writing` skill and approved by marketing in #content-review. Product apps follow each component's copy rules instead. See [Content guidelines](https://ui.clinia.dev/docs/content). - A [migration guide](https://ui.clinia.dev/docs/migration) from v1.0.0 and from Radix, for apps with or without shadcn, monorepos, documentation sites on Fumadocs, and apps that keep `next/font/local`, with the steps to replace the logo and favicon and align each screen with App conventions. - AI tools: a Markdown version of every page (`/docs/color.md`, `/components/button.md`), an [`/llms.txt`](https://ui.clinia.dev/llms.txt) index and [`/llms-full.txt`](https://ui.clinia.dev/llms-full.txt) with every page in one file. [`DESIGN.md`](https://ui.clinia.dev/DESIGN.md) is compiled from this site and opens with Clinia's tokens as YAML, so a checker can flag a colour, font, size or corner Clinia UI doesn't ship. See [Using AI tools](https://ui.clinia.dev/docs/ai-tools#what-your-agent-needs). - For agents in consuming repositories: the `clinia-ui` skill, a Claude Code hook that lints each file an agent edits and hands the errors back, a PRODUCT.md template, and a prompt that migrates an existing app one proven pull request at a time. See [Using AI tools](https://ui.clinia.dev/docs/ai-tools#migrate-an-existing-app). - An accessibility check in CI: axe tests every component demo and state against WCAG 2.2 AA, in Luma and Sera, light and dark. - Every component page follows one order: when to use, anatomy, Clinia rules, Do and Don't, states, accessibility in three parts, and an API table generated from the component file, with a size table where it has sizes. See [Components](https://ui.clinia.dev/components/button). - Every page shows its status: Draft, Ready or Deprecated. ### Changed - The page background is white, as on clinia.com. `--background` moves from Serene `#fffdf9` to `#ffffff`. Heroes and highlighted sections take Remedy, the warm cream, through `bg-muted`. See [Backgrounds](https://ui.clinia.dev/docs/marketing/backgrounds#how-to-choose-a-background). - App and marketing components share 8px corners. `--radius` is `0.5rem`, and components use `rounded-lg` for controls and containers, `rounded-md` for items inside them and `rounded-sm` for small parts. Badges and tabs are no longer pills. Reinstall your components to get the new corners. See [Containers](https://ui.clinia.dev/docs/containers#radius). - Every component ships from the `@clinia` registry, carrying Clinia's colour fixes. An upstream `shadcn add` no longer undoes them. - Hover and keyboard highlight take a light ink tint, `bg-foreground/4`, across buttons, menus, list items and navigation. Selected and current items take Trust: `bg-accent/15`, plus `border-emphasis` where the element has a border. Remedy is a surface, never a state. See [Colour](https://ui.clinia.dev/docs/color#states). - The chart palette leads with Trust, without Vital. The light `--chart-2` is Infinite-5 `#333333`, 12.63:1 on white, where Thistle measured 1.35:1. See [Chart](https://ui.clinia.dev/components/chart). - `@clinia/theme` and `@clinia/theme-marketing` import the font declarations, `tw-animate-css` and `shadcn/tailwind.css`, so dialogs, sheets, popovers, menus, tooltips and accordions animate. Run `add @clinia/theme` (or `@clinia/theme-marketing`) again: it replaces `globals.css`, so put back anything else your app added. See [App getting started](https://ui.clinia.dev/docs/app/getting-started). - The brand fonts are self-hosted: seven licensed files, nothing synthesized. See [App getting started](https://ui.clinia.dev/docs/app/getting-started#3-host-the-brand-fonts). - Typography maps the sizes an app already uses to the scale, allows `text-xs`, `text-sm` and `text-base` alongside it, and sets the link rule. See [Typography](https://ui.clinia.dev/docs/typography#sizes-off-the-scale). - A highlighted destructive menu item takes a `bg-destructive/10` tint, so its red text clears 4.5:1 in both themes. See [Dropdown Menu](https://ui.clinia.dev/components/dropdown-menu). - Sonner's toast description takes `text-muted-foreground`, and toasts in an app without a `next-themes` `ThemeProvider` use the light theme. See [Sonner](https://ui.clinia.dev/components/sonner). - Skeleton blocks take `bg-foreground/8`, an ink tint that follows the theme. See [Skeleton](https://ui.clinia.dev/components/skeleton). - An indeterminate Progress slides a segment across the track. With reduced motion it shows a still, faint full-width bar. See [Progress](https://ui.clinia.dev/components/progress). - A read-only Input takes the Remedy surface, `bg-muted`, with a border that clears 3:1 on it, so it reads as set rather than editable. See [Input](https://ui.clinia.dev/components/input). - An open Accordion item loses its Remedy tint: the chevron shows the state. See [Accordion](https://ui.clinia.dev/components/accordion). - One Docs section with four groups: Getting started, Conventions, App conventions, Marketing conventions. Design guidelines becomes [Using AI tools](https://ui.clinia.dev/docs/ai-tools), and `/docs/design` redirects there. The `/theme` preview page redirects to [Theming](https://ui.clinia.dev/docs/theming). - Downloadable brand assets sit in one folder per category: `/logo/`, `/favicon/`, `/social/`, `/bands/`, `/backgrounds/`, `/imagery/`, `/compliance/`, each with its zip inside. Old URLs such as `/logomark.svg` and `/brand/...` redirect to the new ones. The `infinity-band` item no longer includes the Closing the Loop SVGs. - The site, DESIGN.md and the comments shipped in components and in `@clinia/tailwindcss` are written in Canadian English: colour, behaviour, centre. Class names, tokens, props and the `/docs/color` URL keep their spelling, so nothing changes in code. ### Fixed - Disabled Checkbox and Radio Group controls fade to half opacity, and so does a Label beside them. They looked enabled. See [Checkbox](https://ui.clinia.dev/components/checkbox). - Keyboard focus shows a solid Trust ring on every control, including the Slider thumb and the Accordion trigger, which had a faint halo or nothing. See [Accessibility](https://ui.clinia.dev/docs/accessibility). - Card no longer has a shadow: it stands apart by its border. See [Card](https://ui.clinia.dev/components/card). - Button `link` is underlined at rest, so a link in a sentence doesn't rely on colour alone. See [Button](https://ui.clinia.dev/components/button). - Slider's `aria-label` reaches each thumb, so screen readers name the control. - Avatar Group overlaps its avatars by 4px, so the second initial stays readable. See [Avatar](https://ui.clinia.dev/components/avatar). - `tracking-display` and `tracking-eyebrow` set their letter spacing. Tailwind never generated the two classes, so display headlines and eyebrows had none. See [Typography](https://ui.clinia.dev/docs/typography). - Reduced motion also zeroes animation and transition delays, so a staggered entrance appears complete at once. ## v1.0.0 The first ui.clinia.dev, from May to October 2026, with `@clinia/tailwindcss` 0.2 and 0.3 on npm. ### Added - `@clinia/tailwindcss`: Clinia's brand colours, type and radius as Tailwind v4 tokens, with a light and a dark theme and the sidebar tokens. - The `@clinia` shadcn registry, with `base`, `theme`, `brand-logo` and `infinity-band`, and 23 components: Accordion, Alert, Avatar, Badge, Button, Card, Checkbox, Dialog, Dropdown Menu, Input, Label, Progress, Radio Group, Select, Separator, Skeleton, Slider, Sonner, Switch, Table, Tabs, Textarea and Tooltip. - Guidelines for the logo and favicon, with the favicon set and a BIMI logomark, and for the Infinity Band, Clinia's line and shape language. - `DESIGN.md`: the brand, colour, type and shape for AI agents and engineers. --- title: "Colour" description: "The Clinia palette, where each colour is allowed, and the semantic tokens components use." url: https://ui.clinia.dev/docs/color --- # Colour ## Palette Twenty-four swatches across four families are defined in `@clinia/tailwindcss/tokens.css` to describe the colours allowed in Clinia's brand guidelines. **Infinite**: Brand black and the neutral ramp under it. Carries text, surfaces, borders and hairlines in both themes. `#1a1a1e Infinite` · `#333333 Infinite-5` · `#666666 Infinite-4` · `#999999 Infinite-3` · `#cdcdcd Infinite-2` · `#e2e2e2 Infinite-1` **Beige / Tan**: The warm neutrals. Remedy is the cream for heroes and highlighted sections on the white page, and the rest are editorial surfaces. Noble is a fill only (warning surfaces, charts), never text: it measures 2.34:1 on white. `#fffdf9 Serene` · `#fcf8ef Remedy` · `#f1e3cb Beige-3` · `#ecd9b9 Remedy-dark` · `#dbbe87 Beige-5` · `#cca44f Noble` **Purple**: The decorative family. Used in backgrounds and illustration, never as text or icon colour. `#faf7ff Purple-1` · `#f8f1ff Aura` · `#ede5f6 Purple-3` · `#e3daed Thistle` · `#cabbdb Purple-5` · `#b3a0ae Purple-6` **Peach / Orange**: The warm family. Trust is the accent, a 3:1 colour: borders, icons, selected states, chart fills and text from 24px up, never body, label, button or link text. Vital has no product-UI use: it appears only as a marketing line accent (see [Line & shape](https://ui.clinia.dev/docs/marketing/line-and-shape)). `#ffccaf Mend` · `#fd945f Peach-2` · `#ff5c00 Vital` · `#cb6a3d Peach-4` · `#b3724c Peach-5` · `#95795c Trust` A swatch reaches the page through its token, never as a hex value. The swatches with no semantic token and no `brand-*` utility, such as Peach-4 (`#cb6a3d`), appear only in charts and illustrations, through the `chart-*` and `scene-*` tokens. Being in the palette doesn't make a swatch a second accent: the accent is Trust. [Accessibility](https://ui.clinia.dev/docs/accessibility) measures every pairing from the shipped tokens and lists the surfaces Trust may appear on. ## Semantic tokens Semantic tokens are used in stylesheets to represent how the swatches above land in the light and dark themes. | Token | Job | Light | Dark | |---|---|---|---| | `background` | Page ground. | `#ffffff Derived` | `#1a1a1e Infinite` | | `foreground` | Body text and icons on the page. | `#1a1a1e Infinite` | `#fffdf9 Serene` | | `card` | Raised surfaces: cards, panels. | `#ffffff Derived` | `#232327 Derived` | | `popover` | Menus, popovers, dialogs. | `#ffffff Derived` | `#232327 Derived` | | `primary` | The one main action. | `#1a1a1e Infinite` | `#fffdf9 Serene` | | `primary-foreground` | Label on a primary fill. | `#fffdf9 Serene` | `#1a1a1e Infinite` | | `secondary` | Low-emphasis actions and surfaces. | `#fcf8ef Remedy` | `#333333 Infinite-5` | | `muted` | Quiet surfaces. | `#fcf8ef Remedy` | `#333333 Infinite-5` | | `muted-foreground` | Secondary text. | `#666666 Infinite-4` | `#cdcdcd Infinite-2` | | `accent` | Emphasis: borders, icons, selected states, text from 24px. | `#95795c Trust` | `#95795c Trust` | | `accent-foreground` | Text on an accent fill, 24px and up only. | `#1a1a1e Infinite` | `#1a1a1e Infinite` | | `border` | Decorative hairlines. | `#e2e2e2 Infinite-1` | `#333333 Infinite-5` | | `input` | Form field boundaries, 3:1. | `#8c8c8c Derived` | `#777777 Derived` | | `ring` | Focus indicator. | `#95795c Trust` | `#95795c Trust` | | `border-emphasis` | Selected outlines, the one emphasis moment per view. | `#95795c Trust` | `#95795c Trust` | | `destructive` | Errors and destructive actions. | `#b91c1c Derived` | `#ef6b5c Derived` | | `success` | Success states. | `#2d7d5e Derived` | `#4ea985 Derived` | | `warning` | Warning surfaces. A fill, never text. | `#cca44f Noble` | `#dbbe87 Beige-5` | See [Theming](https://ui.clinia.dev/docs/theming) for more details on how the tokens switch between light and dark. ## States Each colour has one job. Remedy is a surface, never a state. - **Hover and keyboard highlight:** a light ink tint. It carries no meaning, so it never competes with a selection, and it looks the same on white and on Remedy. - **Selected or current:** Trust, as a tint with a Trust border where the element has one. The current page, a selected row, a pressed toggle. - **Surface:** Remedy sets apart a hero, a highlighted section or a panel. It never marks a hovered or highlighted item: on the white page, a Remedy row reads as highlighted. _Live example: see the web page._ ## Build reference ### State recipes | State | Class | Where | |---|---|---| | Hover, keyboard highlight, open trigger | `bg-foreground/4` (`bg-sidebar-foreground/4` in Sidebar) | Button `outline` and `ghost`, CTA `ghost`, Item link rows, Table rows set `interactive`, Toggle, menu, listbox and command items, Navigation Menu and Menubar triggers, Sidebar items, File Upload, Field choice cards | | Selected, current, pressed | `bg-accent/15`, plus `border-emphasis` on an element with a border | Sidebar and Navigation Menu active item, selected Table row, Toggle pressed, Calendar range, checked Field choice card | | Surface | `bg-muted` | Heroes, highlighted sections, panels, the Tabs track, Kbd | | Table header and footer | `bg-foreground/3` | `TableHeader`, `TableFooter` | - `foreground` flips with the theme, so the tint follows it. Measured on white, the tint is `#f6f6f6` (1.08:1); on the dark page `#232327` (1.11:1); on Remedy `#f3efe7`. `foreground` and `muted-foreground` keep AA on every tinted surface. - A destructive menu item keeps its `bg-destructive/10` highlight. - Never use `hover:bg-muted`, `hover:bg-secondary` or `hover:bg-accent/15` for a transient state. --- title: "Typography" description: "The three type families, the sixteen-step scale, and the rules for using them." url: https://ui.clinia.dev/docs/typography --- # Typography ## Type families Three licensed families are available in the Clinia design: | Utility | Family | Use | |---|---|---| | `font-display` | NaN Serf B | Headlines, display text | | `font-sans` | CircularXX | UI, body text | | `font-mono` | CircularXX Mono | Code, tokens | - **Display** (`font-display`, NaN Serf B) - Used by default for headlines, hero copy, and every step in the Display and Title scale. - **Sans** (`font-sans`, CircularXX) - The default for the rest of the text sections, including body copy, labels, buttons, form fields, navigation. - **Mono** (`font-mono`, CircularXX Mono) - The default for eyebrow labels and code. ex: Eyebrow label ## Scale Sixteen font sizes covering hero text, down to a 10px eyebrow. Each group (Display, Title, Body and Eyebrow) has its own job and family, so sizes overlap between groups. **Display** (`font-display`): Marketing heroes and campaign headlines. | Step | Class | Size | |---|---|---| | Display XL | `text-display-xl` | 6rem | | Display L | `text-display-l` | 5.5rem | | Display M | `text-display-m` | 4.5rem | | Display S | `text-display-s` | 3.5rem | **Title** (`font-display`): Headings, H1 to H4: page, section, subsection, card. | Step | Class | Size | |---|---|---| | Title XL | `text-title-xl` | 5rem | | Title L | `text-title-l` | 4rem | | Title M | `text-title-m` | 2.5rem | | Title S | `text-title-s` | 2rem | | Title XS | `text-title-xs` | 1.5rem | **Body** (`font-sans`): Running text and UI: paragraphs, labels, buttons, fields. | Step | Class | Size | |---|---|---| | Body XL | `text-body-xl` | 2rem | | Body L | `text-body-l` | 1.5rem | | Body M | `text-body-m` | 1rem | | Body S | `text-body-s` | 0.875rem | | Body XS | `text-body-xs` | 0.75rem | **Eyebrow** (`font-mono uppercase tracking-widest`): Section labels above a heading. | Step | Class | Size | |---|---|---| | Eyebrow L | `text-eyebrow-l` | 1rem | | Eyebrow S | `text-eyebrow-s` | 0.625rem | ## Sizes off the scale An app moving to Clinia UI maps each size it uses to a step, as in the table. Sizes under 16px move up a pixel or two, which makes those screens less dense. Sizes from 17 to 19px move down to `body-m` (16px), and headings from 20 to 28px land on `title-xs` (24px) from either side. Compare each screen before and after. | Size in the app | Step | |---|---| | 9 to 10px | `eyebrow-s` for an eyebrow label (mono, uppercase), otherwise `body-xs` | | 11 to 12px | `body-xs` | | 13 to 14px | `body-s` | | 15 to 19px | `body-m` | | 20 to 28px, headings | `title-xs` | | Larger headings | The nearest Title step | Tailwind's `text-xs`, `text-sm` and `text-base` are allowed. They're the same sizes as `body-xs`, `body-s` and `body-m`, and the components use them. They also set Tailwind's line height, which the scale steps leave to the surrounding text. ## Headings Showcases how headings (H1 to H6) map onto the allowed size scale. H1 to H4 use NaN Serf B, H5 and H6 use CircularXX Medium. | Heading | Classes | Size | |---|---|---| | H1 | `font-display text-title-l tracking-tight` | 4rem | | H2 | `font-display text-title-m tracking-tight` | 2.5rem | | H3 | `font-display text-title-s tracking-tight` | 2rem | | H4 | `font-display text-title-xs` | 1.5rem | | H5 | `font-sans text-body-m font-medium` | 1rem | | H6 | `font-sans text-body-s font-medium` | 0.875rem | ## Weights Five weights across the three families, to keep the range tight: CircularXX has three, CircularXX Mono and NaN Serf B have one each. | Family | Weight | Class | |---|---|---| | CircularXX | Book 400 | `font-sans font-normal` | | CircularXX | Regular 450 | `font-sans font-[450]` | | CircularXX | Medium 500 | `font-sans font-medium` | | CircularXX Mono | Regular 400 | `font-mono font-normal` | | NaN Serf B | Book 400 | `font-display font-normal` | ## Italic Only CircularXX has italics, in Book 400 and Medium 500. NaN Serf B and CircularXX Mono have none, so `italic` on them does not render. _Live example: see the web page._ Headlines carry no emphasis on a single word. NaN Serf B has one weight and no italic, so an `` or a `` in a display line renders like the rest of it, with no warning. Write the line so it doesn't need one, and drop the tag. ## Links Links keep the text colour, in Medium, and carry a thin `accent` underline (Trust, `#95795C`) set a little below the text. Trust sits on the underline only. A hovered link dims slightly, and a focused one shows the focus ring. - Keep the underline at the font's own thickness. A thicker or text-coloured underline makes a paragraph of links read as bold. - Never set link text in Trust: at body size it measures 4.06:1 on white, under AA. - A heading's anchor link stays plain: the heading is already the link. _Live example: see the web page._ For the container widths and rhythm that type sits inside, see [Containers](https://ui.clinia.dev/docs/containers). For type space and case per surface, see [App getting started](https://ui.clinia.dev/docs/app/getting-started) and [Marketing getting started](https://ui.clinia.dev/docs/marketing/getting-started). ## Build reference ### Link styles On an element, the classes Clinia's docs use: ```tsx ``` In CSS, for prose a framework styles, such as Fumadocs' typography plugin: | Property | Value | |---|---| | `color` | `var(--foreground)` | | `font-weight` | `500` | | `text-decoration-line` | `underline` | | `text-decoration-color` | `var(--accent)` | | `text-decoration-thickness` | `auto` | | `text-underline-offset` | `4px` | | `opacity` on hover | `0.8` | Exclude links inside headings, which frameworks use as section anchors. --- title: "Iconography" description: "Google Material Symbols, Rounded weight 300, shipped one module per icon." url: https://ui.clinia.dev/docs/iconography --- # Iconography ## The set Clinia's utility icons are **Google Material Symbols** in Rounded style and with a weight of 300 (thinner than default). `check` · `close` · `content-copy` · `keyboard-arrow-down` · `keyboard-arrow-up` · `chevron-right` · `unfold-more` · `check-circle` · `info` · `warning` · `cancel` · `progress-activity` · `search` · `menu` · `add` · `edit` · `delete` · `more-vert` · `remove` · `filter-list` · `settings` · `person` · `calendar-month` · `arrow-back` · `arrow-forward` · `chevron-left` · `arrow-upward` · `arrow-outward` · `more-horiz` · `description` · `folder` · `help` · `error` · `wand-stars` · `psychology` · `cloud-upload` · `upload` · `download` · `refresh` · `star` · `link` · `add-comment` · `forum` · `left-panel-open` · `stop` · `view-list` · `grid-view` Import one as `@/components/ui/icons/`. Each cell renders the same icon at 24px, 20px and 16px for comparison. These are the icons Clinia ships today. Any glyph in the [Material Symbols catalogue](https://fonts.google.com/icons) can join them, so browse it to search for a currently unsupported icon and ask for it using the [current process](https://ui.clinia.dev/docs/request-a-component). Material Symbols is the only icon set in apps. Marketing surfaces may also use a fixed list of IBM Carbon icons, approved on [Marketing icons](https://ui.clinia.dev/docs/marketing/icons#carbon-overrides). Those overrides never ship to an app. ### Requested (Alarm System) `monitoring` · `sensors` · `sensors-off` · `pin` · `timer` · `receipt-long` · `videocam` · `videocam-off` · `logout` · `fullscreen` Import one as `@/components/ui/icons/`. ### Requested (Developer docs) `devices` · `terminal` · `menu-book` · `data-object` · `package-2` · `web-asset` Import one as `@/components/ui/icons/`. ### Requested (Concord) `layers` · `scan-delete` · `trending-down` Import one as `@/components/ui/icons/`. ### Requested (Help centre) `rocket-launch` · `database` · `shield` · `key` · `troubleshoot` · `support-agent` · `list` · `arrow-right-alt` Import one as `@/components/ui/icons/`. ### Requested (CCE benchmarks) `play-arrow` · `science` · `lock` · `light-mode` · `dark-mode` · `arrow-downward` · `flag` · `pause` · `not-equal` Import one as `@/components/ui/icons/`. ### Requested (Console) `home` · `group` · `person-add` · `credit-card` · `cloud-off` · `school` · `redeem` · `speed` · `stacks` · `code` · `smart-toy` · `done-all` · `block` · `verified-user` · `report` Import one as `@/components/ui/icons/`. ## Using an icon Import the module for the icon you need: ```tsx import { CheckIcon } from "@/components/ui/icons/check" ``` Sizes are 16, 20 and 24. The default is 20. Set another with `size`, or with a Tailwind size utility when the surrounding layout already speaks in classes: ```tsx ``` An icon with no `label` is decorative and stays out of the accessibility tree. That is the right default: most icons sit next to text that already names the thing. Pass `label` only when the icon carries the meaning on its own, such as an icon-only button. ```tsx ``` ## Colour Every icon draws in `currentColor`, so it inherits from whatever it sits in. Colour it by colouring the text. An icon is a non-text element: it needs 3:1 against its background, not 4.5:1. That makes Trust allowed on icons through `text-accent`, where it is not allowed on label-size text. Leave icons in the text colour by default, and keep Trust for the selected or emphasized state. [Accessibility](https://ui.clinia.dev/docs/accessibility) lists the surfaces Trust clears 3:1 on. --- title: "Theming" description: "How the token-based theme works, and how to switch between light and dark." url: https://ui.clinia.dev/docs/theming --- # Theming ## What is a theme Clinia UI's theme is built entirely on CSS custom properties. The `@clinia/tailwindcss` package defines every design token as a CSS variable, such as `--primary`, `--background` or `--radius`, and then bridges them into Tailwind v4 utility classes through an `@theme inline` block: ```css @theme inline { --color-primary: var(--primary); --color-background: var(--background); --color-foreground: var(--foreground); --radius-md: var(--radius); /* ... */ } ``` Tailwind utility classes like `bg-primary`, `text-foreground`, and `rounded-md` resolve to these live CSS variables at runtime. Switching themes changes one class on the `` element, with no JavaScript re-rendering and no class toggling on individual components. For the tokens themselves and what each one carries, see [Colour](https://ui.clinia.dev/docs/color). ## Light and dark Clinia UI uses a class-based dark mode strategy. Add `class="dark"` to the `` element to activate the dark theme: ```html ``` All colour tokens have dark-mode overrides defined inside a `.dark` selector in the theme CSS, so the switch is automatic for every component, including the ones rendered across this design guide. ### Light sections inside dark Add `class="light"` to any element to keep it in the light theme on a dark page. Tokens inherit, so the nearest `.light` or `.dark` ancestor wins: ```html
…
``` ### With next-themes The recommended approach for Next.js apps is to use [`next-themes`](https://github.com/pacocoursey/next-themes), which handles system preference detection, persistence, and hydration: ```bash pnpm add next-themes ``` Wrap your root layout with the `ThemeProvider`: ```tsx // app/layout.tsx import { ThemeProvider } from "next-themes" export default function RootLayout({ children }: { children: React.ReactNode }) { return ( {children} ) } ``` The `suppressHydrationWarning` prop on `` prevents React from warning about the mismatch between server-rendered and client-resolved theme classes. Keep `disableTransitionOnChange`: it turns CSS transitions off while the theme class swaps, so every colour changes at once instead of fading unevenly. --- title: "Accessibility" description: "Live WCAG contrast matrix for every semantic colour pairing, computed from the shipped tokens." url: https://ui.clinia.dev/docs/accessibility --- # Accessibility ## Contrast matrix Clinia UI measures every colour pairing against WCAG, the web's accessibility standard. Every ratio on this page is computed in your browser at render time, for both the light and dark themes, from the semantic tokens in `@clinia/tailwindcss/theme.css`, so the page shows what actually ships. The same pair list runs in CI as `pnpm check:contrast`, and a token below its threshold fails the build. | Pair | Tokens | Needs | Light | Dark | Note | |---|---|---|---|---|---| | Page | `foreground` on `background` | 4.5:1 | 17.35 (AAA) | 17.08 (AAA) | | | Card | `card-foreground` on `card` | 4.5:1 | 17.35 (AAA) | 15.41 (AAA) | | | Popover | `popover-foreground` on `popover` | 4.5:1 | 17.35 (AAA) | 15.41 (AAA) | | | Primary | `primary-foreground` on `primary` | 4.5:1 | 17.08 (AAA) | 17.08 (AAA) | | | Secondary | `secondary-foreground` on `secondary` | 4.5:1 | 16.37 (AAA) | 12.44 (AAA) | | | Muted | `muted-foreground` on `muted` | 4.5:1 | 5.42 (AA) | 7.95 (AAA) | | | Muted on page | `muted-foreground` on `background` | 4.5:1 | 5.74 (AA) | 10.91 (AAA) | | | Destructive | `destructive-foreground` on `destructive` | 4.5:1 | 6.37 (AA) | 5.72 (AA) | | | Destructive text | `destructive` on `background` | 4.5:1 | 6.47 (AA) | 5.72 (AA) | | | Success | `success-foreground` on `success` | 4.5:1 | 4.91 (AA) | 6.06 (AA) | | | Warning | `warning-foreground` on `warning` | 4.5:1 | 7.43 (AAA) | 9.69 (AAA) | | | Sidebar | `sidebar-foreground` on `sidebar` | 4.5:1 | 17.35 (AAA) | 17.08 (AAA) | | | Sidebar primary | `sidebar-primary-foreground` on `sidebar-primary` | 4.5:1 | 17.08 (AAA) | 17.08 (AAA) | | | Accent | `accent-foreground` on `accent` | 3:1 | 4.27 (AA-large) | 4.27 (AA-large) | large text only | | Sidebar accent | `sidebar-accent-foreground` on `sidebar-accent` | 3:1 | 4.27 (AA-large) | 4.27 (AA-large) | large text only | | Accent text on page | `accent` on `background` | 3:1 | 4.06 (AA-large) | 4.27 (AA-large) | large text only | | Focus ring on page | `ring` on `background` | 3:1 | 4.06 (AA-large) | 4.27 (AA-large) | | | Focus ring on card | `ring` on `card` | 3:1 | 4.06 (AA-large) | 3.85 (AA-large) | | | Input edge on page | `input` on `background` | 3:1 | 3.36 (AA-large) | 3.87 (AA-large) | | | Input edge on card | `input` on `card` | 3:1 | 3.36 (AA-large) | 3.50 (AA-large) | | | Emphasis border on page | `border-emphasis` on `background` | 3:1 | 4.06 (AA-large) | 4.27 (AA-large) | | | Emphasis border on card | `border-emphasis` on `card` | 3:1 | 4.06 (AA-large) | 3.85 (AA-large) | | | Border on page | `border` on `background` | informational | 1.30 (fail) | 1.37 (fail) | decorative hairline | | Border on card | `border` on `card` | informational | 1.30 (fail) | 1.24 (fail) | decorative hairline | | Sidebar border | `sidebar-border` on `sidebar` | informational | 1.30 (fail) | 1.37 (fail) | decorative hairline | ## Where Trust accent may appear Trust (`#95795c`) is measured against every brand swatch and both card surfaces. A surface at 3:1 or above can carry Trust as a border, an icon or a headline from 24px up. Body text stays in `foreground` on all of them. | Surface | Trust ratio | Verdict | |---|---|---| | Infinite | 4.27 | allowed | | Card (light) | 4.06 | allowed | | Serene | 4.00 | allowed | | Card (dark) | 3.85 | allowed | | Purple 1 | 3.83 | allowed | | Remedy | 3.83 | allowed | | Aura | 3.68 | allowed | | Purple 3 | 3.32 | allowed | | Beige 3 | 3.21 | allowed | | Infinite 1 | 3.14 | allowed | | Infinite 5 | 3.11 | allowed | | Thistle | 3.00 | borderline | | Remedy dark | 2.94 | disallowed | | Mend | 2.81 | disallowed | | Infinite 2 | 2.56 | disallowed | | Beige 5 | 2.27 | disallowed | | Purple 5 | 2.25 | disallowed | | Peach 2 | 1.85 | disallowed | | Noble | 1.74 | disallowed | | Purple 6 | 1.66 | disallowed | | Infinite 3 | 1.43 | disallowed | | Infinite 4 | 1.41 | disallowed | | Vital | 1.31 | disallowed | | Peach 4 | 1.10 | disallowed | | Peach 5 | 1.05 | disallowed | ## Using Trust Don't use Vital (`#ff5c00`) as an accent. Trust replaced it in design system v2, and Vital has no use in product UI. Its only approved use is the line accents on [Line & shape](https://ui.clinia.dev/docs/marketing/line-and-shape). Do: - A Trust outline with `foreground` text (Badge `accent`). - A Trust headline from 24px up: 3:1 is enough. Don't: - 12px text on a Trust fill: 4.27:1 is under 4.5:1. - A body-size link in Trust: 4.06:1 is under 4.5:1. - Vital as the accent: Trust replaces it. --- title: "Content guidelines" description: "How Clinia writes: the voice, the house style in English and French, and how public content gets approved." url: https://ui.clinia.dev/docs/content --- # Content guidelines Every word Clinia publishes sounds like one company, whether it sits in a help article, the developer documentation, or a LinkedIn post. This page sets the voice, the house style in English and French, and how public content is written and approved. Product apps aren't held to this page. They show little text, and their copy follows each component's rules, such as a [Button](https://ui.clinia.dev/components/button)'s verb-first label. ## Voice Clinia's voice is C.A.R.E. Confident and Efficient lead; Real and Accessible come in depending on the reader. - **Confident:** expert and declarative, never arrogant. - **Accessible:** the reader's language. Technical for developers, plain for everyone else. - **Real:** specific and human, without hollow enthusiasm. - **Efficient:** short sentences, with a longer one now and then for rhythm. The `clinia-brand-voice` skill applies the voice, Clinia's approved messaging, and its product names. It's one of Clinia's enterprise skills, available to everyone by default. ## Public content Help articles, the developer documentation, blog posts, LinkedIn posts, release notes, and web copy all go through marketing before they're published. Nina, in marketing, owns the process. ### Write it with the skill The `clinia-writing` skill writes or rewrites a piece and prepares it for review, on top of `clinia-brand-voice`: 1. **Brief:** who reads it, what they came for, and a source for every fact. 2. **Draft:** in English, French, or both. The French is written from the brief, not translated word for word. 3. **Checks:** a gate flags spelling, punctuation, and patterns that read as machine-written. Two reviews follow: one for the voice, one for whether the reader gets what they came for. 4. **Fact check:** every claim is traced to its source, or listed for someone to confirm. 5. **Review packet:** the text, the changes made, and the facts to confirm, ready for marketing. The skill is in Claude Desktop for everyone at Clinia. To add it yourself, [download the skill](https://ui.clinia.dev/skills/clinia-writing.zip) and upload it under Skills in Claude Desktop's settings, or open the [clinia/ui](https://github.com/clinia/ui) repository in Claude Code, where it ships in [`.claude/skills/clinia-writing`](https://github.com/clinia/ui/tree/main/.claude/skills/clinia-writing). ### Get it approved Post the draft and its review packet in [#content-review](https://clinia.slack.com/archives/C0C7218SY1Z). Marketing approves there, and only an approved piece is published. A piece written without the skill goes through the same channel. ## House style | | English | French | |---|---|---| | Spelling | Canadian: colour, centre, behaviour, organize | OQLF usage | | Lists | A comma before the last "and" or "or": search, generation, and action | No comma before « et » | | Headings | Sentence case | A capital on the first word only | | Punctuation | No em dashes, no exclamation marks | No space before ; ! ?, a non-breaking space before : and inside « » | | Numbers | Zero to nine in words, 10 and up in numerals | 10 000, 3,5, 50 % | | Dates and times | October 6, 2026, 2:30 p.m. | le 6 octobre 2026, 14 h 30 | | Terms | healthcare, Montreal, email | soins de santé, Montréal, courriel | | The reader | you | vous | | UI labels | In bold, exactly as on screen | In bold, in English, as the Console shows them | ## Interface copy Words in Clinia products follow the same voice. The copy rules for each pattern live with the pattern: - [Forms and validation](https://ui.clinia.dev/docs/app/forms): labels, optional fields, and error messages. - [Empty states](https://ui.clinia.dev/docs/app/empty-states): what to say when there's nothing yet. - [Loading](https://ui.clinia.dev/docs/app/loading): what to say while the user waits. - [Destructive actions](https://ui.clinia.dev/docs/app/destructive-actions): confirmations that name what is lost. ## Do and Don't ### Do - Lead with what the reader came for. - Give the specific: the number, the name, the step. - Name a source for every claim. A claim without one goes to marketing as a question. ### Don't - Use em dashes, "not just X, but Y", or superlatives such as "the leading". - Fill a gap with a detail that sounds right. - Publish before marketing approves it in [#content-review](https://clinia.slack.com/archives/C0C7218SY1Z). ## Build reference ### The skill files The skill lives in `.claude/skills/clinia-writing/`. Its files hold the full rules; this page summarizes them. - `SKILL.md`: the six steps and the approval notice the skill adds to every draft. - `references/house-style.md`: the full English and French house style, with the OQLF spacing table. - `references/tells.md`: the patterns that read as machine-written or off-brand, in hard and advisory tiers. The script reads its patterns from this file. - `references/claims.md`: what needs a source, and the health and compliance limits. - `references/examples.md`: before and after pairs, and the approved pieces per channel. - `references/channels/`: one file per channel (help centre, developer documentation). ### Check a file ```bash python3 .claude/skills/clinia-writing/scripts/lint.py article.en-ca.md article.fr-ca.md python3 .claude/skills/clinia-writing/scripts/lint.py --diff before.md after.md ``` The script checks prose only and exits 1 on a hard finding. It treats a file name containing `.fr.` or `.fr-ca.` as French. Run `--self-test` after changing `tells.md`. ### Regenerate the download After a change to the skill, run `pnpm --filter web skills:zip`. It rewrites `public/skills/clinia-writing.zip` with the skill folder at its root, the shape Claude Desktop expects. --- title: "Containers" description: "Spacing, widths, radius and elevation for the surfaces content sits in, and how they respond to screen size." url: https://ui.clinia.dev/docs/containers --- # Containers ## Spacing Spacing follows Tailwind's 4px scale. Whitespace is a feature. When a view feels crowded, add space before adding a border, and keep one clear focal point per view. ## Widths | Content | Max width | |---|---| | Reading column | `max-w-3xl` | | Full layout | `max-w-7xl` | Keep grids simple: `grid gap-6 sm:grid-cols-2 md:grid-cols-3`. Avoid nesting cards inside cards. ### Full-width sections A hero, and any section with its own background (Remedy, a band, an image), runs edge to edge at every screen width. Only its content stops at the widths above, centred. A background that stops short of the screen's edges reads as a card floating on the page. - Check it on a screen wider than the layout, such as 1920px: a hero can look full-width at 1440px and stop short above it. - Inside a docs framework or app shell that caps the page's width, paint the background past the cap rather than leaving it boxed. ## Radius Every radius step derives from a single `--radius` base (`0.5rem`, 8px): `sm` is 0.6 times the base, `md` 0.8, `lg` the base itself, `xl` 1.4, up through `4xl` at 2.6, the same multipliers shadcn ships. App and marketing components share the same corners: `rounded-lg` (8px) for controls and containers, `rounded-md` for items inside them, such as menu items, and `rounded-sm` for small parts. Only circles and thin bars stay fully round: avatars, radio buttons, switches, sliders, progress bars and scrollbars. | Class | Value | |---|---| | `--radius` | `0.5rem` (8px) | | `rounded-sm` | `calc(var(--radius) * 0.6)` (4.8px) | | `rounded-md` | `calc(var(--radius) * 0.8)` (6.4px) | | `rounded-lg` | `var(--radius)` (8px) | | `rounded-xl` | `calc(var(--radius) * 1.4)` (11.2px) | | `rounded-2xl` | `calc(var(--radius) * 1.8)` (14.4px) | | `rounded-3xl` | `calc(var(--radius) * 2.2)` (17.6px) | | `rounded-4xl` | `calc(var(--radius) * 2.6)` (20.8px) | A surface that needs other corners overrides `--radius` locally; see [Marketing getting started](https://ui.clinia.dev/docs/marketing/getting-started). ## Elevation `@clinia/tailwindcss` ships one neutral elevation (shadows) set. How far a surface leans on it depends on the shadcn style it installed, not on a Clinia CSS layer. | Class | Light | Dark | |---|---|---| | `shadow-sm` | `0 1px 2px 0 rgb(0 0 0 / 0.04)` | `0 1px 2px 0 rgb(0 0 0 / 0.04)` | | `shadow-md` | `0 1px 3px 0 rgb(0 0 0 / 0.06), 0 1px 2px -1px rgb(0 0 0 / 0.04)` | `0 1px 3px 0 rgb(0 0 0 / 0.06), 0 1px 2px -1px rgb(0 0 0 / 0.04)` | | `shadow-lg` | `0 8px 24px -8px rgb(0 0 0 / 0.10)` | `0 8px 24px -8px rgb(0 0 0 / 0.10)` | In dark mode, surfaces lift by lightening: `background` (`#1a1a1e`), then `card` (`#232327`). Shadow opacity rises so the lift still reads. ## Responsiveness Responsiveness is a requirement, not a design choice: every surface works on every screen size, from phone to desktop. - **Breakpoints** are Tailwind's defaults: `sm 640` · `md 768` · `lg 1024` · `xl 1280` · `2xl 1536`. - **Headlines grow with the screen.** A hero headline starts smaller on phones and steps up on tablets and desktops. Body text stays the same size everywhere. - **Design for phones first.** Start with one column, then add columns and sidebars as the screen gets wider. - **Keep everything easy to tap.** Anything a finger can tap needs at least 24px. On touch-first screens, use the large button size. ## Build reference ### Full-width sections Put the background on a full-width wrapper and cap the content inside it: ```tsx
{/* content */}
``` When a parent caps the width (Fumadocs' layout, an app shell), paint the background out to the viewport with a border-image outset. It adds no horizontal scroll, where `w-screen` or `calc(50% - 50vw)` margins count the scrollbar and overflow: ```tsx
``` --- title: "Logo" description: "The Logo component, source files, colour usage, minimum sizes and clear space." url: https://ui.clinia.dev/docs/logo --- # Logo ## Logo React component The Clinia UI library has defined a [Logo component](https://ui.clinia.dev/components/logo). It renders the wordmark or the mark inline, takes the surrounding text colour, and is announced as "Clinia" to screen readers. ```bash pnpm dlx shadcn@latest add @clinia/logo ``` ```tsx import { Logo, Logomark } from "@/components/ui/logo"; ``` Pass `decorative` when visible text beside the logo already says Clinia, so it isn't announced twice. ## Source files For everything else (email signatures, slides, a CMS, an `` tag), use the SVG files. Both are available below and leverage `currentColor`, so they inherit the surrounding text colour. | Asset | File | Native size | Use | |---|---|---|---| | **Mark** (logomark) | [`public/logomark.svg`](https://ui.clinia.dev/logo/logomark.svg) | 339 × 350 | The "C" alone. Square/tight contexts, avatars, favicon. | | **Wordmark** (logotype) | [`public/logotype.svg`](https://ui.clinia.dev/logo/logotype.svg) | 748 × 228 | Full "Clinia" wordmark. The **primary** logo, the default for most uses. | To copy both into your app's `public/` folder, run: ```bash pnpm dlx shadcn@latest add @clinia/brand-logo ``` Where SVG doesn't work (most email clients, and some slide tools and upload forms), use the transparent PNGs. They're cropped tight to the logo, in Infinite for light backgrounds and Serene for dark ones. | Asset | On light backgrounds | On dark backgrounds | Size | |---|---|---|---| | **Mark** | [`logomark-light.png`](https://ui.clinia.dev/logo/logomark-light.png) | [`logomark-dark.png`](https://ui.clinia.dev/logo/logomark-dark.png) | 992 × 1024 | | **Wordmark** | [`logotype-light.png`](https://ui.clinia.dev/logo/logotype-light.png) | [`logotype-dark.png`](https://ui.clinia.dev/logo/logotype-dark.png) | 2048 × 624 | ## Colour usage The mark and the wordmark follow the same rule: Infinite on light backgrounds, Serene on dark ones, one colour at a time. ### Do - Use the dark logo (**Infinite** `#1a1a1e`) on light backgrounds: **Serene** `#fffdf9` and **Remedy** `#fcf8ef`. - Use the light logo (**Serene** `#fffdf9`) on dark backgrounds: **Infinite** `#1a1a1e`. - Render the logo **inline**, with the Logo component or the SVG, and set its colour with a `text-*` utility. `text-foreground` switches with the theme on its own. - An `` can't inherit colour. Use the inline Logo component when the logo must switch with the theme. _Live example: see the web page._ ### Don't - Recolour to anything outside the single-colour Infinite/Serene rule: no multi-colour, no gradient, no brand-family tints. - Place it on Vital, on busy imagery, or on a low-contrast background. _Live example: see the web page._ ## Minimum sizes and conventions - Mark: 16px minimum width. - Wordmark: 80px minimum width. ### Do - Keep the **mark** at **16px** minimum width. - Keep the **wordmark** at **80px** minimum width. - Keep clear space on every side at least the height of the "C" opening. Never crowd the logo with other elements. ### Don't - Stretch, skew or rotate the logo. - Add shadows, outlines or other effects. - Redraw or reconstruct the mark. - Scale it below the minimum sizes above. ## Product lockup A Clinia site or product that names itself beside the logo, such as the developer documentation, sets the name in the eyebrow style: mono, uppercase, tracked and muted, to the right of the wordmark. A named Clinia product's own site, such as a product marketing site, uses the same lockup: the Clinia wordmark, then the product name. It carries no "powered by Clinia" line, since the wordmark already says so. The wordmark at its 80px minimum or larger, with the product name to its right in the eyebrow style: mono, uppercase, tracked, muted. ### Do - Keep the wordmark at its **80px** minimum or larger, and the name smaller than the wordmark. - Leave at least the clear space between the wordmark and the name. - Use the name the site is known by, in one or two words. ### Don't - Set the name in the wordmark's weight or size, so it reads as part of the logo. - Shrink the wordmark to make room for the name. - Add a divider: that's the lockup for a partner brand, on [Co-branding](https://ui.clinia.dev/docs/marketing/co-branding). - Replace the wordmark with a "powered by Clinia" line in text, or add one beside the lockup. ## Build reference ### Product lockup ```tsx import { Logo } from "@/components/ui/logo"; Developers ``` - `h-6.5` is the wordmark's 80px minimum; go larger, never smaller. - `gap-3` (12px) clears the wordmark's clear space at that height. - `translate-y-0.5` sets the name on the wordmark's optical baseline. - Inside a link, the accessible name reads "Clinia" then the product name: don't pass `decorative`. --- title: "Site header" description: "What the header of a Clinia site holds, how it behaves on the home page, inner pages and phones, and what to keep out of it." url: https://ui.clinia.dev/docs/site-header --- # Site header ## What the header does The header tells users which Clinia site they're on. It lets them search the site, move between its sections and reach its main action. The developer documentation and the help centre share one header, so a user crossing from one to the other keeps their bearings. _Live example: see the web page._ ## Anatomy On a wide screen the header has two rows. 1. **Site row:** the product lockup on the left, search in the centre, and the utilities on the right. 2. **Section tabs:** one tab per top-level section of the site, with the current one marked. _Live example: see the web page._ | Part | What it holds | Rule | |---|---|---| | Product lockup | The wordmark and the site's name | Links to the site's home page. See [Logo](https://ui.clinia.dev/docs/logo#product-lockup). | | Search | A field-shaped button that opens the site's search | Centred, with its keyboard shortcut shown. | | Utilities | Links to other Clinia sites, then a link to a page of this site that users need from anywhere, then the language, the theme and the main action | Right-aligned. Only what the site needs: a site without a dark theme has no theme switch. The help centre's page link is Submit a request. | | Section tabs | The site's top-level sections, in its own order | Pages on this site only. | ## Home page and inner pages ### Inner pages Inner pages set the header on a solid panel in the page's background colour, edge to edge. No line sits under it: once the page scrolls, a soft shadow fades in and separates it from the content. _Live example: see the web page._ ### The home page The home page header starts transparent, over its hero. When the page scrolls, the panel slides down behind the header. The hero runs up under the header: pull it up by the header's height, or a strip of page colour shows above the hero. The home page can drop the search when its hero holds a search field, and the tabs when the page lists the sections itself. _Live example: see the web page._ _Live example: see the web page._ ## Phones and tablets Below 1024px the tabs move into a menu. The site row keeps the lockup, a search button, the language and a menu button. Links to other sites and the page link move into the menu with the tabs. _Live example: see the web page._ ## Do and don't _Live example: see the web page._ Also: - Keep the header identical on every inner page of a site. Only the current tab changes. - Keep tab labels to one to three words. If the tabs don't fit at 1024px, cut a tab rather than shrink the text. - Open links to other sites in a new tab. - Keep the header the same height as the page scrolls: never shrink or hide it, and never use Vital in it. ## Accessibility - The header is a `header` landmark, and the tabs a `nav` with its own label. - The current tab carries `aria-current="page"`, so screen readers announce it too. - Every control is at least 24px tall and shows the focus ring. - The search button names its shortcut. Closing the search returns focus to the button that opened it. - With reduced motion, the home page's panel appears without sliding. ## Build reference ### Site row - Height `h-14` (56px). Side padding matches the layout below it: `px-4 md:px-6` in a full-width docs layout, the page gutter in a layout capped at `max-w-7xl`. - Lockup: as on [Logo](https://ui.clinia.dev/docs/logo#product-lockup), the wordmark at `h-6.5`, the name in `font-mono text-xs uppercase tracking-widest text-muted-foreground`, `gap-3`, no divider. - Search button, centred in the row: ```tsx ``` It opens the site's search dialog, as does ⌘K (Ctrl+K on Windows and Linux). - Utilities, in this order, `gap-4 md:gap-6`: links to other sites (`text-sm font-medium text-muted-foreground hover:text-foreground`, with `ArrowOutwardIcon`, `target="_blank"`), the page link (the same classes plus `text-nowrap`, no arrow, same tab), the language switch, the theme switch, then the main action as `Button size="sm"` (default variant). - At 1024px the row must still fit: the lockup's site name is `text-nowrap`, and the search button takes `min-w-0` and truncates its label. ### Section tabs - A `nav` with an `aria-label`, `h-10`, `gap-6`, the same side padding as the site row. Shown from `lg` (1024px). - Each tab: ```tsx ``` ### Panel and shadow - The header is `sticky top-0`. Inner pages paint a `bg-background` panel behind it, edge to edge: with a border-image outset inside a capped layout (see [Containers](https://ui.clinia.dev/docs/containers#full-width-sections)). - No `border-b`. The shadow is a 16px gradient below the header, `rgb(0 0 0 / 0.05)` to transparent, faded in over 200ms once the page scrolls. - Home page: no panel at rest. On scroll the panel, shadow included, slides down with `translateY` over 450ms `cubic-bezier(0.16, 1, 0.3, 1)`, and back up over 150ms `cubic-bezier(0.25, 0.46, 0.45, 0.94)`. Under `prefers-reduced-motion: reduce`, no transition. ### Below 1024px - The tab row is hidden. The site row shows the lockup, then on the right a search icon button and a menu icon button (`Button variant="ghost" size="icon"`, each with an `aria-label`), plus the language switch. - The menu opens a sheet with the tabs, the current one marked, then the page link and the links to other sites. Focus moves into the sheet and returns to the menu button when it closes. --- title: "Favicon" description: "The favicon package: a light and a dark tile of the mark, and how to add it to your site." url: https://ui.clinia.dev/docs/favicon --- # Favicon The favicon is Clinia's mark on a square tile, in two versions: **Infinite `#1a1a1e` on Remedy `#fcf8ef`** for light browsers and **Remedy on Infinite** for dark ones. A Clinia product's own site uses the same favicon: the tab shows Clinia's mark, and the product's name goes in the page title. _Live example: see the web page._ _Live example: see the web page._ ## The package Each version is the same six files, in `public/favicon/light/` and `public/favicon/dark/`. The package also builds icons for installed web apps (PWA), Apple home screens and the web manifest, which tells browsers the site's name, icons and colours. | File | Purpose | |---|---| | `favicon.ico` | Legacy icon, 16 / 32 / 48. The light one is also copied to `public/favicon.ico`, for browsers that ask for it directly. | | `favicon-16x16.png` | Browser tab. | | `favicon-32x32.png` | Browser tab on high-density screens. | | `apple-touch-icon.png` | 180 × 180 home-screen icon on iOS. | | `android-chrome-192x192.png` | Android home screen and web manifest. | | `android-chrome-512x512.png` | Android splash screen and web manifest. | ## Light and dark The tab icon follows the browser's colour scheme (`prefers-color-scheme`), not the site's theme toggle, since the favicon lives in the browser's tabs, tied to the browser, and not on the page. To see the dark tile, switch your operating system or browser to dark mode and reload. Support for `media` on icon links varies. Browsers that ignore it show the light icon everywhere, which stays legible on a dark tab bar because the tile carries its own Remedy background. The Apple touch icon and `site.webmanifest` use the light version, since neither can switch with the theme. The manifest sets `theme_color` and `background_color` to Remedy `#fcf8ef`, the light tile's background. The mark fills 61% of the tile's height, so it stays clear of the rounded corners and circle crops that home screens apply. ## Use it in your app Download the package above, then unzip it into `public/favicon/` and copy the light `.ico` to the root, where browsers look for it, or fetch it from your project root with a simple command: ```bash curl -LO https://ui.clinia.dev/favicon/favicon.zip unzip favicon.zip -d public/favicon cp public/favicon/light/favicon.ico public/favicon.ico ``` Then add the manifest and the icon declarations. `public/site.webmanifest`: ```json { "name": "Clinia", "short_name": "Clinia", "icons": [ { "src": "/favicon/light/android-chrome-192x192.png", "sizes": "192x192", "type": "image/png" }, { "src": "/favicon/light/android-chrome-512x512.png", "sizes": "512x512", "type": "image/png" } ], "theme_color": "#fcf8ef", "background_color": "#fcf8ef", "display": "standalone" } ``` ### Next.js (App Router) In `app/layout.tsx`: ```tsx import type { Metadata } from "next"; export const metadata: Metadata = { manifest: "/site.webmanifest", icons: { icon: [ { url: "/favicon.ico", sizes: "48x48" }, ...(["light", "dark"] as const).flatMap((theme) => [16, 32].map((size) => ({ url: `/favicon/${theme}/favicon-${size}x${size}.png`, type: "image/png", sizes: `${size}x${size}`, media: `(prefers-color-scheme: ${theme})`, })), ), ], apple: { url: "/favicon/light/apple-touch-icon.png", sizes: "180x180" }, }, }; ``` ### Any other site In the page ``: ```html ``` --- title: "Motion" description: "The timing, easing and reduced-motion rules every Clinia surface shares." url: https://ui.clinia.dev/docs/motion --- # Motion ## Principles Motion explains a change: where something came from, where it went, or what just responded. If an animation doesn't help someone follow the change, leave it out. ## Timing and easing | Motion | Duration | Easing | |---|---|---| | Hover, press, colour changes | 100 to 250ms | `linear` for colour and opacity, ease-out for movement | | Menus, popovers, dialogs | 100 to 200ms | The shadcn style's own defaults | Keep motion quick so it never slows down repeat work. A surface can allow longer motion where it's for display purposes. For display animation, see [Marketing motion](https://ui.clinia.dev/docs/marketing/motion). ## Reduced motion When someone turns on reduced motion in their system settings, every animation and transition in Clinia components (CSS or JS) skips straight to its end state. No extra configuration or setting is required. Animations you write in JavaScript check the browser setting themselves before rendering in the correct format: ```ts window.matchMedia("(prefers-reduced-motion: reduce)").matches ``` ### Do - Test each page with reduced motion turned on. - Make sure content is complete and readable without the animation. ### Don't - Hide content until an animation reveals it. - Animate from JavaScript (canvas, Rive, scroll libraries) without checking the setting: the global rule only reaches CSS. --- title: "App getting started" description: "Why Clinia product apps run the Luma style, and how to set one up." url: https://ui.clinia.dev/docs/app/getting-started --- # App getting started [Installation](https://ui.clinia.dev/docs/installation) lists what a web project needs before it starts. This page covers how product apps differ in configuration once the project base has been configured. For a marketing site, see [Marketing getting started](https://ui.clinia.dev/docs/marketing/getting-started). ## Luma, for product All product apps run [shadcn's Luma style](https://ui.shadcn.com/docs/changelog/2026-03-luma). Clinia's app is where users create workspaces, monitor usage and subscribe to paid product tiers: configuration screens, usage views and dashboards used every day. This selected style is optimized for this use with: - **Soft elevation over loud shadows, calm motion over flourish**: keeps attention on the data, not the chrome. - **Sentence-case controls, efficient spacing**: scans fast on dense, repeat-use screens. - **Rounded geometry**: reads as approachable and calm, right for a tool users return to daily. ## 1. Initialize with the Clinia base Run `shadcn init` pointing directly at the Clinia base registry item: ```bash pnpm dlx shadcn@latest init https://ui.clinia.dev/r/base.json ``` This creates a `components.json` at the root of your project configured with: - `style` set to the shadcn style for the surface, `base-luma` for product apps - `@clinia` namespace pre-registered so you can install Clinia registry items by name It also installs the `icons` item that the `base` depends on. That lands Clinia's utility icons under `components/ui/icons/` (one module per icon). See [Iconography](https://ui.clinia.dev/docs/iconography) for the convention. Your `components.json` will look similar to this after initialization: ```json { "$schema": "https://ui.shadcn.com/schema.json", "style": "base-luma", "rsc": true, "tsx": true, "tailwind": { "css": "app/globals.css", "baseColor": "neutral", "cssVariables": true }, "iconLibrary": "lucide", "aliases": { "components": "@/components", "utils": "@/lib/utils", "ui": "@/components/ui", "lib": "@/lib", "hooks": "@/hooks" }, "registries": { "@clinia": { "url": "https://ui.clinia.dev/r/{style}/{name}.json" } } } ``` ## 2. Install the Clinia theme The theme registry item installs the `@clinia/tailwindcss` package and writes the necessary imports into your `globals.css`: ```bash pnpm dlx shadcn@latest add @clinia/theme ``` After running this, your `globals.css` will contain: ```css @import "@clinia/tailwindcss/fonts"; @import "@clinia/tailwindcss"; @import "tw-animate-css"; @import "shadcn/tailwind.css"; ``` The first import declares the brand fonts (step 3). The second brings in all design tokens (colours, typography, spacing, ...). The last two bring the animations the components use: dialogs, popovers and menus that fade in, and accordions that slide open. ## 3. Host the brand fonts `@clinia/tailwindcss` declares the fonts but ships no font files: the CircularXX and NaN Serf B licenses don't allow redistribution. The theme already imports the declarations. Get the seven licensed `.woff2` files from the [brand drive](https://drive.google.com/drive/folders/1FsfV5tf6NICyoeq5qW4_Q67m7VDohpnL?usp=drive_link) and put them in `public/fonts/`. Until they're there, text falls back to the system fonts. ## 4. Add the brand assets Run the following command to import the required logos: ```bash pnpm dlx shadcn@latest add @clinia/brand-logo curl -LO https://ui.clinia.dev/favicon/favicon.zip unzip favicon.zip -d public/favicon cp public/favicon/light/favicon.ico public/favicon.ico ``` - `brand-logo`: the logomark and logotype, as SVGs in `public/`. See [Logo](https://ui.clinia.dev/docs/logo). - `favicon.zip`: the light and dark tab icons, plus the app and manifest icons. See [Favicon](https://ui.clinia.dev/docs/favicon) for the `` tags. ## 5. Add components Add shadcn components, based on what your app needs. They will inherit Clinia tokens automatically from the configuration run above: ```bash pnpm dlx shadcn@latest add @clinia/button @clinia/card @clinia/input ``` This lands the component source code in `components/ui/`. To prevent style drift, keep Clinia's colour and accessibility branding choices in these files as shipped when adding. If a component needs to change, [request it](https://ui.clinia.dev/docs/request-a-component). Every component in [Components](https://ui.clinia.dev/components) ships from `@clinia`: Luma, wired to the icon modules, with Clinia's contrast fixes (solid input borders, visible selected states, no Trust fill behind small text). A component Clinia doesn't list isn't installed from shadcn: [request it](https://ui.clinia.dev/docs/request-a-component). --- title: "Empty states" description: "What a list, table or page shows when there is nothing in it yet, and how it leads to the next step." url: https://ui.clinia.dev/docs/app/empty-states --- # Empty states An empty state helps visualize content that isn't there yet. It says what's missing and promotes the user action that fills it. ## How to compose an empty state section - [Empty](https://ui.clinia.dev/components/empty): leverage the existing component and add one action in `EmptyContent`. - A [Button](https://ui.clinia.dev/components/button): guide the user to the next step to fill in the condition. - A utility icon from [Iconography](https://ui.clinia.dev/docs/iconography): tied to the action type the user is asked to perform. ## Example - Do: say what's missing and offer the next step. - Don't: leave a bare label with nowhere to go. ## Do and Don't - Do: name the way to resolve the empty state. - Don't: blame the user or use generic labels. ### Do - Align the copy to the wanted outcome. - Start the action in the button with a verb that names what it fills. - Render it where the content would be, at the same size, so the filters and the header stay where the user left them. - Announce an empty result after a search or a filter: put it in a `role="status"` region, so a screen reader reads it. ### Don't - Open with "Oops", or write it as an error. This isn't taking the place of an error: it's a next step for the user. - Blame the user: "You haven't added anything". - Use a generic button label, such as `OK` or `Get started`, that doesn't say what happens next. ## Where it should not be used - Content that's still loading: show a [Skeleton](https://ui.clinia.dev/components/skeleton). See [Loading](https://ui.clinia.dev/docs/app/loading). - Something that failed: show an [Alert](https://ui.clinia.dev/components/alert) that says what to fix. --- title: "Loading" description: "Which indicator to show while something loads, and when to show none at all." url: https://ui.clinia.dev/docs/app/loading --- # Loading Loading feedback tells a user the app is currently working for them. The right choice of indicator depends on what's loading and for how long. ## How to choose a loading indicator | Situation | Use | |---|---| | Content whose shape is known | [Skeleton](https://ui.clinia.dev/components/skeleton), shaped like the content | | An action started from a button | [Spinner](https://ui.clinia.dev/components/spinner) inside the [Button](https://ui.clinia.dev/components/button), which is `disabled` with a present-tense label | | A job with a known length | [Progress](https://ui.clinia.dev/components/progress) with the percentage beside it | | Work that outlasts the screen | [Sonner](https://ui.clinia.dev/components/sonner) with `toast.promise`, so the user keeps working | The expected completion time and the situation set the choice. ## Example - Do: shape the skeleton like the content it replaces. - Don't: swap a whole section for a spinner. ## Do and Don't - Do: keep a label that says what's in progress. - Don't: replace the button label with a spinner. ### Do - If an action is expected to complete in under about 300ms, don't show any loading indicator. - Shape the skeleton like the content it replaces, so nothing jumps when the content arrives. - Keep a label in the button that says what's in progress, such as `Saving` or `Ingesting`. - Let the words carry the state, such as `Saving` or `Uploading`. Note: under reduced motion, spinners stop turning and skeletons stop pulsing (see [Motion](https://ui.clinia.dev/docs/motion)). ### Don't - Let an animation be the only sign that something is happening. - Replace a button's label with a spinner. ## Where it should not be used - There's nothing to load: show an [Empty](https://ui.clinia.dev/components/empty) state. See [Empty states](https://ui.clinia.dev/docs/app/empty-states). - Something failed: show an [Alert](https://ui.clinia.dev/components/alert) that says what to fix. --- title: "Charts" description: "Which chart to use for a score, a range or a ranking, and the colour, size, motion and accessibility rules that apply to every chart." url: https://ui.clinia.dev/docs/app/charts --- # Charts The [Chart](https://ui.clinia.dev/components/chart) component covers series charts such as bars, lines and areas. This page covers the charts a dashboard adds around them, and the rules every chart follows. ## Choose a chart | Question | Chart | |---|---| | How far is this one score from pass or fail? | [Gauge](#gauge), or [bullet](#bullet) in a table or a list | | How did a value move over time, against a target? | [Trend line](#trend-line) | | How do the parts of one run compare? | [Radar](#radar) | | Where did a value land against a target, across runs? | [Range plot](#range-plot) | | Which area is best or worst? | [Ranked bars](#ranked-bars) | | How did a value move run by run, with a link to each run? | [Sparkbars](#sparkbars) | | Where and when did something break, across areas and runs? | [Heatmap](#heatmap) | Each chart is followed by its takeaway in text. If a chart has more than a handful of marks and users need exact values, show a [Table](https://ui.clinia.dev/components/table) too. ## Gauge _Live example: see the web page._ A gauge shows one score from 0 to 100% against thresholds. A [Card](https://ui.clinia.dev/components/card) with the number as text is often enough: use a gauge only when where the score sits between pass and fail matters as much as the number. The value always appears inside the gauge as text, with its status word. ## Radar _Live example: see the web page._ A radar compares the dimensions of one run on a shared scale. Use it for up to eight dimensions and one series. To compare runs or sort dimensions, use [ranked bars](#ranked-bars): the eye can't read values off a polygon. ## Range plot _Live example: see the web page._ A range plot sits in a card and shows the band a value stayed in across runs, one dot per run, against a dashed target and a safe zone. The latest run is the large dot, and its value is the number in the card header. ## Bullet _Live example: see the web page._ A bullet shows one value against a target line and the fail, warn and pass ranges, in the height of a table row. Use it where a gauge would repeat down a list. The ranges are neutral greys, so the status colour stays on the value bar. ## Trend line _Live example: see the web page._ A trend line shows a value over runs or time, with the target as a dashed line and the safe zone shaded behind it. A line chart may crop its value axis, unlike a bar chart, as long as the axis labels show where it starts. ## Ranked bars _Live example: see the web page._ Ranked bars sort areas by value, one bar each, with the value and the status word at the end of the bar. ## Sparkbars _Live example: see the web page._ Sparkbars show one small bar per run, oldest first, and each bar links to its run. They are a trend, not a measurement: show the latest value in text beside them. ## Heatmap _Live example: see the web page._ A heatmap shows one value per area and run, so a failure that repeats or spreads stands out. Each cell shows its value in text, so colour is never the only cue. ## Do and Don't ### Do - Pick the chart from the question it answers, using [Choose a chart](#choose-a-chart). - Write what the chart shows in one sentence beside it, so the point lands before anyone reads the marks. - Show each value on or next to its mark, and say pass, warn or fail in words. - Keep the pass, warn and fail colours for outcomes. - Look at the chart in the light and dark themes before you approve it. ### Don't - Let colour alone tell series or outcomes apart. - Mix outcome colours and series colours in one chart. - Use a gauge for a number that needs no context: write the number. - Crop a bar chart's axis so a small difference looks large. - Replay a chart's animation every time its data refreshes. ## Build reference ### Colour - **Series** come from `chart-1` to `chart-5`, as on the [Chart](https://ui.clinia.dev/components/chart) page. - **Status** marks may use `success`, `warning` and `destructive`, only when the mark says an outcome: pass, warn or fail. Colour a bar by status, not a series by status. - **Never mix the two in one chart.** A chart either compares series (`chart-*`) or reports outcomes (status colours). - **Never rely on colour.** Each status mark also carries its value and a status word, or a label, or its position. Warning is Noble, which is 2.34:1 on a white card, so a warning mark takes a 1px `foreground` outline. - **Bands and envelopes** are fills with a line at their edge. Fill them at 15% in the light theme and 25% in the dark theme (`fill-chart-1/15 dark:fill-chart-1/25` in SVG, or `fillOpacity` from the theme in Recharts). The fill is decoration: the edge line holds the 3:1. ### Motion Marks may enter once, when the chart first appears: 400ms, ease-out, with no more than 30ms between marks and 600ms in total. Never loop, never replay on a data refresh, and never animate the axes or the text. Under reduced motion, the chart appears complete. Recharts animates in JavaScript, so set `isAnimationActive` from the `prefers-reduced-motion` setting, as the examples do. ### Charts you draw yourself A chart drawn as SVG meets the same rules as one from Recharts. - **Colour:** fill and stroke through token classes (`fill-foreground`, `stroke-chart-1`) or `currentColor`. Never a raw hex. - **Text:** 12px (`text-xs`) at the smallest, in `foreground` or `muted-foreground`. - **Name:** give the `` `role="img"` and an `aria-label` that states the value and its status. For a chart of many marks, use `role="group"` and name each mark instead. - **Takeaway:** write it in text beside the chart. - **Heatmap:** a `` with a caption and row and column headers, each cell holding its value as text on its status fill with the matching `*-foreground` text. - **Links:** make each mark an `` with its own accessible name, in reading order, with a target of at least 24 by 24px and a visible focus outline. ### Values | Item | Value | |---|---| | Status mark fills | `var(--success)`, `var(--warning)`, `var(--destructive)` | | Light contrast on the white card | success 4.99, warning 2.34, destructive 6.47 | | Dark contrast on the `#232327` card | success 5.47, warning 8.74, destructive 5.17 | | Warning mark outline | `stroke="var(--foreground)"`, 1px | | Band fill opacity | 15% light, 25% dark | | Mark entry | 400ms ease-out, 30ms stagger, 600ms total, once | | Smallest chart text | 12px | | Smallest link target | 24 by 24px | | Example thresholds | pass at 90% and above, warn at 70% and above, fail below | The examples are in `components/chart-examples.tsx`. The radar sets `fillOpacity` from the resolved theme: 0.15 light, 0.25 dark. --- title: "Forms and validation" description: "How Clinia forms label fields, validate input and report errors." url: https://ui.clinia.dev/docs/app/forms --- # Forms and validation ## How to compose a form - [Field](https://ui.clinia.dev/components/field): wraps every control, with its `FieldLabel`, a `FieldDescription` when the field needs a hint, and a `FieldError` for validation. - Supported controls: [Input](https://ui.clinia.dev/components/input), [Textarea](https://ui.clinia.dev/components/textarea), [Select](https://ui.clinia.dev/components/select), [Native Select](https://ui.clinia.dev/components/native-select), [Combobox](https://ui.clinia.dev/components/combobox), [Checkbox](https://ui.clinia.dev/components/checkbox), [Radio Group](https://ui.clinia.dev/components/radio-group), [Switch](https://ui.clinia.dev/components/switch), [Slider](https://ui.clinia.dev/components/slider), [Input Group](https://ui.clinia.dev/components/input-group), [Input OTP](https://ui.clinia.dev/components/input-otp), [Date Picker](https://ui.clinia.dev/components/date-picker) and [File Upload](https://ui.clinia.dev/components/file-upload). - `FieldSet` with a `FieldLegend`: ties related fields together, visually and for screen readers, and describes them as one group. ## Example - Do: put the label above and the hint below it. - Don't: put the hint in the placeholder. ### Grouping fields with `FieldSet` _Live example: see the web page._ ## Do and Don't - Do: mark the optional field, in words. - Don't: mark required fields with an asterisk. ### Do - Put the label above the field, in sentence case, with no colon. - If there is a field error, write the problem and the way out, in one sentence. It goes under the field and replaces the description, if one exists. - Check a field's validity when focus leaves it, and every field in the form on submit. Once a field shows an error, check it on every change, so the error clears the moment it's fixed. - Add "(optional)" after the label of an optional field, and leave required fields' labels unchanged. - Set `required` on every required control in the code, so screen readers announce it. - Label the form submit button with a verb that names the result: `Create source` vs `Submit`. - If a submit triggers errors, show every error and move focus to the first invalid field. - While the form saves, disable the submit button and switch its label to what's in progress, such as `Saving`. See [Loading](https://ui.clinia.dev/docs/app/loading). ### Don't - Put a hint as the field placeholder. It vanishes as soon as the user types. - Validate on the first keystroke. - Mark required fields with an asterisk. - Disable the submit button until the form is valid. The user can't tell what's missing. --- title: "Destructive actions" description: "How much friction to put in front of deleting, revoking or archiving, based on what a mistake would cost." url: https://ui.clinia.dev/docs/app/destructive-actions --- # Destructive actions A destructive action removes something important that a user may want back, or should confirm first so a misclick does no harm. The friction added for the action should match the cost of a mistake: none for what's easy to undo, a clear stop for what isn't. ## How to choose the friction | If the action is… | Use | |---|---| | Reversible, such as archive or hide | Do it at once, then offer Undo in a [Sonner](https://ui.clinia.dev/components/sonner) toast | | Hard to reverse, on one item | An [Alert Dialog](https://ui.clinia.dev/components/alert-dialog) that names the item and the consequence | | Irreversible, with wide impact | An Alert Dialog that also asks the user to type a validation, such as the item's name, before the action enables | ## Example - Do: archive at once, then offer Undo. - Don't: confirm something users can restore. ## Do and Don't - Do: name the item and repeat the verb. - Don't: ask yes or no with generic buttons. ### Do - Do a reversible action at once, then offer Undo in a toast that stays at least 10 seconds (`duration: 10_000`), so the user can notice it, read it and act on it. Sonner's 4-second default is too short for an Undo. - Name the item in the dialog title, such as `Delete "Montréal clinic"?`. - Say in the description what goes with the item and whether it comes back. - Repeat the verb on the action button: `Delete workspace`, not `Yes`. - For an irreversible action with wide impact, ask the user to type a validation, such as the item's name, before the action enables. - Use the `destructive` Button variant on the final action of every hard-to-reverse or irreversible action, with no exception. Cancel stays `outline`. - Make the trigger `destructive` when it's a standalone button, such as `Delete workspace` in settings. On a table row, put it in the row's menu as a `destructive` item instead of a red button on every row. ### Don't - Ask for confirmation on something users can restore. - Ask a yes-or-no question with generic buttons, such as `Yes`, `No` or `OK`. - Make a reversible action red, such as `Archive` or `Hide`. Nothing is lost, and Undo covers it. - Use the destructive colour anywhere else on the page. --- title: "Marketing getting started" description: "Why Clinia marketing sites run the Sera style, and how to set one up." url: https://ui.clinia.dev/docs/marketing/getting-started --- # Marketing getting started [Installation](https://ui.clinia.dev/docs/installation) lists what a web project needs before it starts. This page covers how marketing sites differ in configuration once the project base has been configured. For a product app, see [App getting started](https://ui.clinia.dev/docs/app/getting-started). ## Sera, for marketing All marketing sites run [shadcn's Sera style](https://ui.shadcn.com/docs/changelog/2026-04-sera). A marketing page earns a visitor's attention once, then has to convert it: landing pages, product stories and campaign pages read in one visit. This selected style is optimized for this use with: - **Typography carries the page**: NaN Serf B for display, CircularXX for body and mono for eyebrows, instead of chrome. - **Hairline borders, no shadows**: flat surfaces keep focus on the words and the story, not on depth cues. - **Tracked uppercase controls, generous rhythm**: a print-inspired hierarchy. Uppercase widens text. Sera sets controls in tracked capitals, so a label takes about a third more room than in sentence case, and anything a user typed shows in capitals too. Size chips and labels on the uppercase text, and never pass user input, such as a name or a search term, through an uppercase control. ## 1. Initialize with the marketing base ```bash pnpm dlx shadcn@latest init https://ui.clinia.dev/r/marketing.json ``` This writes a `components.json` with `"style": "base-sera"` and the `@clinia` registry, and installs Clinia's icons: the Material Symbols utility set and the marketing icons. From here, every `shadcn add` generates the Sera version of a component. See [Iconography](https://ui.clinia.dev/docs/iconography) and [Icons](https://ui.clinia.dev/docs/marketing/icons) for the conventions. ## 2. Install the marketing theme ```bash pnpm dlx shadcn@latest add @clinia/theme-marketing ``` It writes the imports into your `app/globals.css`: the brand fonts, the design tokens (colours, typography, spacing, ...), the animations the components use, and the marketing illustration roles. It also sets one override: `--radius`, back to the brand's value. Shadcn's Sera ships square corners, and Clinia's brand is rounded. ```css @import "@clinia/tailwindcss/fonts"; @import "@clinia/tailwindcss"; @import "tw-animate-css"; @import "shadcn/tailwind.css"; @import "@clinia/tailwindcss/marketing"; :root { --radius: 0.5rem; } ``` This is the only sanctioned local override. Hairline borders, no shadows and tracked uppercase controls stay exactly as Sera ships them; changing more than radius makes a different style, not an override. The override rounds the `@clinia` Sera components, which use radius tokens. An upstream Sera component hard-codes square corners, so the override can't reach it. ## 3. Host the brand fonts `@clinia/tailwindcss` declares the fonts but ships no font files: the CircularXX and NaN Serf B licenses don't allow redistribution. The theme already imports the declarations. Get the seven licensed `.woff2` files from the [brand drive](https://drive.google.com/drive/folders/1FsfV5tf6NICyoeq5qW4_Q67m7VDohpnL?usp=drive_link) and put them in `public/fonts/`. Until they're there, text falls back to the system fonts. The theme turns off faked bold and italic (`font-synthesis: none`), so a missing file falls back cleanly instead of being imitated. ## 4. Add the brand assets Run the following command to import the required logos, band and favicon: ```bash pnpm dlx shadcn@latest add @clinia/brand-logo @clinia/infinity-band curl -LO https://ui.clinia.dev/favicon/favicon.zip unzip favicon.zip -d public/favicon cp public/favicon/light/favicon.ico public/favicon.ico ``` - `brand-logo`: the logomark and logotype, as SVGs in `public/`. See [Logo](https://ui.clinia.dev/docs/logo). - `infinity-band`: the line language and the twist and ring bands, as SVGs in `public/`. See [Line & shape](https://ui.clinia.dev/docs/marketing/line-and-shape). - `favicon.zip`: the light and dark tab icons, plus the app and manifest icons. See [Favicon](https://ui.clinia.dev/docs/favicon) for the `` tags. ## 5. Add components Add shadcn components, based on what your site needs. They will inherit Clinia tokens automatically from the configuration run above: ```bash pnpm dlx shadcn@latest add @clinia/button @clinia/card ``` This lands the component source code in `components/ui/`. To prevent style drift, keep Clinia's colour and accessibility branding choices in these files as shipped when adding. If a component needs to change, [request it](https://ui.clinia.dev/docs/request-a-component). Every component in [Components](https://ui.clinia.dev/components) ships from `@clinia` in two versions, Luma and Sera. Your `components.json` says `base-sera`, so you get the Sera one: wired to the icon modules, with Clinia's colour fixes, and rounded by the `--radius` override. A component Clinia doesn't list isn't installed from shadcn: [request it](https://ui.clinia.dev/docs/request-a-component). A hero, or any section with its own background, runs edge to edge while its content stays in a capped width: see Full-width sections in [Containers](https://ui.clinia.dev/docs/containers#widths). The header follows [Site header](https://ui.clinia.dev/docs/site-header): transparent over the home page's hero with a panel that slides in on scroll, and a solid panel on inner pages. --- title: "Marketing icons" description: "The custom icon set that extends Clinia's icons for marketing use." url: https://ui.clinia.dev/docs/marketing/icons --- # Marketing icons Marketing adds a custom icon set to Clinia's utility icons ([Google Material Symbols](https://ui.clinia.dev/docs/iconography)). Both sets draw in `currentColor` and follow the same [contrast rules](https://ui.clinia.dev/docs/accessibility). They differ in job and in size. Functional icons on marketing pages are [Material Symbols](https://ui.clinia.dev/docs/iconography), the same modules apps use. ## The set `book` · `clipboard` · `search` · `sparkle` Import one as `@/components/ui/icons/marketing/`. Each cell renders the same icon at 24px, 20px and 16px for comparison. ## Carbon overrides A marketing page may also use an [IBM Carbon](https://carbondesignsystem.com/elements/icons/library/) icon when no alternative exists in the Google Material Symbols library. The approved list is below: _Live example: see the web page._ They ship in `@clinia/marketing-icons` with the marketing set, so the site needs no Carbon package. They take the same props as the [utility icons](https://ui.clinia.dev/docs/iconography) and default to 20, the size of the Material icons beside them: ```tsx import { CarbonCompareIcon } from "@/components/ui/icons/marketing/carbon/compare" import { CarbonLogoLinkedinIcon } from "@/components/ui/icons/marketing/carbon/logo-linkedin" ``` Any other icon comes from Material Symbols. One that Clinia doesn't ship yet joins the set through the [current process](https://ui.clinia.dev/docs/request-a-component). A new Carbon override goes through the same process, and only once Material has no icon for the idea. ## Using an icon The marketing base installs the set, one module per icon in `components/ui/icons/marketing/`, with the [Carbon overrides](#carbon-overrides) in `carbon/` beside it. To add it to a site that was set up another way: ```bash pnpm dlx shadcn@latest add @clinia/marketing-icons ``` Import the module for the icon you need: ```tsx import { MarketingSearchIcon } from "@/components/ui/icons/marketing/search" ``` The default size is 64. Set another with `size`, or with a Tailwind size utility: ```tsx ``` Every icon draws in `currentColor`, so it inherits from whatever it sits in. Colour it by colouring the text: `text-foreground` by default, or `text-accent` for emphasis. The props are the same as the [utility icons](https://ui.clinia.dev/docs/iconography): an icon with no `label` is decorative and stays out of the accessibility tree. Marketing icons sit beside a heading that already names the idea, so they rarely need one. ## Don't - Use a Carbon icon that isn't in the [Carbon overrides](#carbon-overrides), or install a Carbon package. A new override joins the set here first. - Use a Carbon override in an app. - Redraw an icon, add fills or change the stroke weight. A new icon comes from the brand file. --- title: "Imagery" description: "Which photo to use on Clinia marketing, how to place it and how to put text on it." url: https://ui.clinia.dev/docs/marketing/imagery --- # Imagery Which photo to use, where it comes from and how to set it on a page. ## Approved images Use only images from the two approved folders in the internal brand drive. | Folder | What's in it | Where to use it | |---|---|---| | [09 Stock Images](https://drive.google.com/drive/folders/1Pzl9XQp9NleGLiHV2Dlmoqwy523GW7RT) | Purchased stock photos, free to use | All Clinia marketing material | | [10 Lifestyle photos](https://drive.google.com/drive/folders/1mriPYc7PPBi_xstQFIpz5_rdbcf3Tqzj) | Real Clinia employees | With caution: see Photos of employees | The marketing lead owns the selection criteria beyond art direction, such as licensing, diversity and fit for French and English audiences. ## How to choose a photo | If the section is… | Use | |---|---| | About a person: the team, a testimonial, a byline | A **portrait**, in the format the space needs (see Portrait) | | About a scene or a mood: a hero, a section opener, a promo band | A **lifestyle** photo | | A product or use-case page that no employee photo fits | A **stock** photo from 09 Stock Images | ## Portrait Portraits show the people behind Clinia. Choose the format by the space it fills, and never mix in older or self-supplied photos. | Format | Crop | Use it for | |---|---|---| | Studio, half body | 4:5 | Team grids, speaker and author bios | | Studio, headshot | 1:1 | Avatars, bylines and short lists | | Environmental | 1:1 | Careers, Culture, testimonials and social posts | The studio shots share one warm taupe backdrop and soft light, so a grid of them reads as one team. The environmental shots are taken at the office, with the background kept soft behind the person. **Studio, half body** _Live example: see the web page._ **Studio, headshot** _Live example: see the web page._ **Environmental** _Live example: see the web page._ ### Photos of employees The people in Clinia's photos are colleagues, not models. Their consent decides where a photo can go, and they can withdraw it. #### Do - Use an employee photo only where the person has agreed to the specific use, such as the website, social posts or sales decks. If you're not sure, ask the marketing lead. - Show employees as who they are: Clinia's team, culture, careers and events. #### Don't - Present an employee as a customer, a clinician or a patient. - Put an employee photo in a paid ad or in partner material, unless approval has been granted for that use. - Use the photo of someone who left Clinia or withdrew consent. Leave it out of new material, and take it off live pages at the next update. - Alter an employee's likeness: no AI edits, no background swaps that change the context, no composites. ## Lifestyle A lifestyle photo focuses on a scene and sets the brand's mood. It blends the **seriousness of mission-critical work** with the **ambition for better human health**: dramatic lighting, real environments and people interacting. Lifestyle photos mix everyday employee photos and purchased stock images. An employee photo follows the same rules as above. _Live example: see the web page._ ## Layouts Every photo is a rectangle with `rounded-lg` corners, the marketing `--radius`, set on a light brand surface (see [Colour](https://ui.clinia.dev/docs/color)). The line language goes beside a photo, never on or around it (see [Line & shape](https://ui.clinia.dev/docs/marketing/line-and-shape)). These are the layouts all marketing surfaces should repeat: each one shows its template and crop beside the section rebuilt live, with the site's own photos and copy. _Live example: see the web page._ _The examples are [clinia.com](https://clinia.com) sections rebuilt at their real desktop size, a 1425px row, then scaled down as a whole: every photo, type size and gap keeps its true proportion. Open the site for the full-size version._ ## Example - Do: put text over a photo inside a card. - Don't: set small text straight on the photo. **Accessibility:** write real `alt` text for every informative image: for a portrait, the person's name. A decorative photo takes `alt=""` to prevent overloading screen readers with decorative information. --- title: "Backgrounds" description: "Which background to set behind a marketing hero, section or card, and how to render it at any size." url: https://ui.clinia.dev/docs/marketing/backgrounds --- # Backgrounds A background gives a section its mood without competing with its copy. Every Clinia background comes from the Infinity Band (see [Line & shape](https://ui.clinia.dev/docs/marketing/line-and-shape)), rendered by a component so it stays sharp at any size. Each one follows the site theme: in dark, a band keeps its colours on an Infinite ground, and a line card turns to a dark tint of its ground. _Live example: see the web page._ ## How to choose a background | If the section is… | Use | |---|---| | A hero | An animated [Rive scene](https://ui.clinia.dev/docs/marketing/rive-scenes), which carries the dot field | | A large panel behind cards | A [Brand Background](https://ui.clinia.dev/components/brand-background) band, blurred into a sweep | | A closing call to action | A band, sharp, with its glow | | A newsletter or sign-up strip | A band, blurred, across the strip | | A card | A line, scaled past the card | | Any other section | The white page. To set one apart without a band, use Remedy, the warm cream (`bg-muted`) | ## Hero The hero's background usually uses a [scene](https://ui.clinia.dev/docs/marketing/scenes), mostly reserved for the home page: the dot field and the line work move as part of the Rive file, so there is no separate background to place. See [Rive scenes](https://ui.clinia.dev/docs/marketing/rive-scenes) for the files and the contract. _Live example: see the web page._ ## Band background The shape language as a background: the brand's twist or ring vector, scaled past its container, cropped by it and softened. `blur` sets the look, from a sharp band with its glow to a soft sweep. Any copy on top of it goes on the flat part of the ground. ```bash pnpm dlx shadcn@latest add @clinia/brand-background ``` **Large panel, blurred sweep** _Live example: see the web page._ ```tsx import { BandBackground } from "@/components/ui/brand-background"; {/* eyebrow, headline and cards */} ``` **Closing call to action, sharp band with its glow** _Live example: see the web page._ ```tsx {/* headline and CTA on the left */} ``` **Newsletter strip, blurred band** _Live example: see the web page._ ```tsx {/* headline and body on the left, the email field on the right */} ``` ## Line background The line language as a card background: one line shape scaled well past the card and cropped by it, with its crossing in the open area under the text. The line keeps its width at any scale. Any copy on top of it goes in the upper part of the card, clear of the line. _Live example: see the web page._ ```tsx import { LineBackground } from "@/components/ui/brand-background"; {/* title and body */} {/* title and body */} {/* title and body */} ``` **Wide, short banner card** On a card much wider than it is tall, such as a help banner, the line is sized from the card's width and cropped by it, so it stays as large as on a regular card instead of shrinking to the card's height. _Live example: see the web page._ Set `keepAspect` on a wide, short card: `scale` then sets the line's width only, and its height follows the line's own proportions. ```tsx {/* headline and body on the left */} ``` _The section examples are [clinia.com](https://clinia.com) sections rebuilt at their real desktop size, then scaled down as a whole, so every proportion stays true._ _The dark line-card grounds (`#2f2f34` for Remedy, `#44403d` for Remedy-dark, `#665e6f` for Aura) and their line colours come from clinia.com's dark theme. They are approved for backgrounds only: they are not brand swatches, so don't use them anywhere else._ ## Example - Do: put copy on the flat ground, beside the band. - Don't: run copy across the band. ## Do and Don't ### Do - Crop the band or the line on at least two sides. A whole band behind copy competes with it. - Use one band per section. Cards and panels below a hero can carry their own. - Pick the ground from the brand surfaces. The component sets the copy colour to match: Infinite on light grounds, Serene on Infinite. ### Don't - Stretch, recolour, tile or flip the art. - Stack a background behind every section. It loses its effect after the first. - Set a background image file. Use the component, so the band stays sharp at any size. --- title: "Security & compliance" description: "The four compliance badges marketing uses, and how to show them." url: https://ui.clinia.dev/docs/marketing/compliance --- # Security & compliance Clinia's marketing surfaces should show security and compliance with the same four badges, approved titles and lines everywhere: **HIPAA**, **GDPR**, **SOC 2** and **PIPEDA**. The footer adds the **Certified B Corporation** logo. ## The files | Badge | Type | File | |---|---|---| | HIPAA | Security & compliance | [`hipaa.svg`](https://ui.clinia.dev/compliance/hipaa.svg) | | GDPR | Security & compliance | [`gdpr.svg`](https://ui.clinia.dev/compliance/gdpr.svg) | | SOC 2 | Security & compliance | [`soc2.svg`](https://ui.clinia.dev/compliance/soc2.svg) | | PIPEDA | Security & compliance | [`pipeda.svg`](https://ui.clinia.dev/compliance/pipeda.svg) | | B Corp | Social & environmental impact | [`b-corp.svg`](https://ui.clinia.dev/compliance/b-corp.svg) | All five files can be downloaded below and used on approved surfaces. _Live example: see the web page._ ## Using security badges The badges usually sit in a **Global security & compliance** section, with the Trust Center link beside them. Display each badge at **72px**, with its title and line under it. _Live example: see the web page._ _The section is the [clinia.com](https://clinia.com) section rebuilt at its real desktop size, then scaled down as a whole, so every proportion stays true._ ### Do - Keep the approved title and line under each badge in the block. - Leave `alt` empty on a badge in the block: the title under it already names the standard. - Give a badge that stands alone, as in the footer, `alt` text that names the standard. - Link to the [Trust Center](https://trust.clinia.com/) whenever possible to direct users to the source of truth for anyone requesting a compliance report. - Link the footer row to the Trust Center as one link, not one link per badge, with a visible focus ring. ### Don't - Recolour, crop, redraw or add effects to a badge. - Show a standard Clinia no longer meets. If a certification changes, the badge and its line change everywhere at once. ## Using B Corp The footer shows the **Certified B Corporation** logo on its own, 34px wide in `foreground` at 40%. It is a separate link to Clinia's [B Corp listing](https://www.bcorporation.net/en-us/find-a-b-corp/company/clinia-sant/), outside the Trust Center row. The SVG draws in `currentColor`: inline it or mask it so it takes the text colour. ### Do - Link the B Corp logo to Clinia's [B Corp listing](https://www.bcorporation.net/en-us/find-a-b-corp/company/clinia-sant/), with `Certified B Corporation` as its accessible name. - Keep it distinct from the security badges: it certifies social and environmental impact, not security. ### Don't - Crop, redraw or add effects to the logo, or colour it outside the text colour. ## The footer The footer shows the four badges in one row after the word **Certified**, at **34px**, with no title or line. The order changes there: SOC 2, GDPR, PIPEDA, HIPAA. The whole row is one link to the [Trust Center](https://trust.clinia.com/), so anyone who wants a report is one click from it. The **Certified B Corporation** logo sits beside the row as its own link: see [Using B Corp](#using-b-corp). _Live example: see the web page._ --- title: "Co-branding" description: "How to show the Clinia logo next to a partner's." url: https://ui.clinia.dev/docs/marketing/co-branding --- # Co-branding The Clinia logo can appear beside other brands in two ways: a side-by-side lockup with one partner, or within a row of customer logos under a claim. ## Lockups - Default to the **primary wordmark** beside the partner logo, separated by a thin vertical divider. - For mark-only contexts, pair the **mark** with the partner mark across the same divider. - Unless a partner brand specifies otherwise, size each logo to be **optically equal** as a collection of shapes, rather than to equal bounding-box height. Spacing, with h as the height of the Clinia logo: - Wordmark lockup: h/2 of space on each side of the divider, and a divider 1.5h tall. - Mark lockup: h/3 of space on each side, and a divider as tall as the mark. - The divider is 1px, in the logo colour at 15%. _The partner logo is a placeholder from [Logoipsum](https://logoipsum.com/)._ ## Colour The Clinia logo is Infinite on light grounds and Serene on dark ones, as on [Logo](https://ui.clinia.dev/docs/logo). The partner logo keeps its own colours; on a dark ground, use the partner's reversed version. ## Do and Don't - Do: separate the logos with the divider. - Don't: join the logos with a symbol. ### Do - Use the partner's official logo files, and follow their co-branding rules when they set them. - Put Clinia first, on the left, in material Clinia leads. ### Don't - Put a `+`, `×` or `&` between the logos. The divider is the only separator. - Recolour a partner logo to Clinia's colours, or redraw or retype its wordmark. ## Customer logos _Live example: see the web page._ _The logos above are placeholders from [Logoipsum](https://logoipsum.com/)._ ### Do - Show a customer's logo only with their written approval, confirmed by the marketing lead. - Use each customer's one-colour logo, sized by eye so every logo carries the same weight. - Name every logo with the company name. ### Don't - Give every logo the same height. A wide wordmark then looks larger than the others. - Show a logo in its brand colours in the strip. Every logo takes the same one colour. --- title: "Social media" description: "The official profile images and banners for LinkedIn, B Corp, YouTube, GitHub and other social media platforms." url: https://ui.clinia.dev/docs/marketing/social-media --- # Social media These are the official profile images for Clinia's public accounts: LinkedIn, B Corp, YouTube, GitHub, job boards and other social media platforms. _Live example: see the web page._ ## Mark The default profile image. Use it wherever the platform shows the company name beside the avatar. _Live example: see the web page._ ## Wordmark For platforms that show the image alone, with no name beside it: a directory tile, a partner's customer grid, a sponsor wall. _Live example: see the web page._ ## Which background - **Remedy `#fcf8ef`** (prioritize), with the logo in Infinite: the default for profile avatars, matched to the light banner. - **Infinite `#1a1a1e`**, with the logo in Serene: with the dark banner, or where a dark avatar fits the page better. - **Transparent**, with the logo in Infinite: only where the file sits on a light background you control, such as a partner page or a sponsor wall. Never upload it as an avatar: platforms fill the empty background with their own colour, often dark. The logo colour follows the [Logo](https://ui.clinia.dev/docs/logo) rule: Infinite on light backgrounds, Serene on dark ones. ## Banners A banner is the cover image across the top of a profile. The profile image covers the bottom left on most platforms, so nothing sits there. Each file is cut to its platform's exact size, with the wordmark inside the area that platform never crops. The LinkedIn and social media banners also carry the descriptor, "Patient Context for Healthcare AI", at the top left. Each banner comes in two versions. Use the light one by default and leverage the dark one when otherwise more fitting. _Live example: see the web page._ | Where | File | Upload size | |---|---|---| | LinkedIn company page | `linkedin-company.png`, `linkedin-company-dark.png` | 2256 × 382 | | LinkedIn event cover | `linkedin-event.png`, `linkedin-event-dark.png` | 2560 × 1440 | | LinkedIn personal profile | `linkedin-personal.png`, `linkedin-personal-dark.png` | 3168 × 792 | | Other social media platforms | `social-media.png`, `social-media-dark.png` | 3000 × 1000 | | YouTube | `youtube.png`, `youtube-dark.png` | 2560 × 1440 | | B Corp listing | `b-corp-listing.png`, `b-corp-listing-dark.png` | 1984 × 768 | | Trust Center | `trust-center.png` | 2496 × 832 | | Status page | `status-page.png`, `status-page-dark.png` | 1700 × 630 | _Live example: see the web page._ ## Regenerate the set The profile PNGs are rendered from `public/logo/logomark.svg` and `public/logo/logotype.svg`, so the logo is never redrawn. After a logo change, run `pnpm --filter web brand:social`. It rewrites `public/social/` at 1×, 2× and 3× (`@2x`, `@3x`), `public/social/social.zip` with the 1× files, and the favicon package. The banners and the sharing images are screenshots of the cards drawn on this page and on [Sharing images](https://ui.clinia.dev/docs/marketing/sharing-images): after a change to `components/og-cards.tsx`, run `pnpm --filter web brand:cards` with the dev server on port 3005 (or `BASE_URL`). It rewrites every size in `public/banners/` and `public/sharing/`, and their .zip files. The plain file is the size the table names (2×, 1× for YouTube); the others carry `@x`. --- title: "Brand exposure" description: "Every public surface Clinia runs or appears on, and when to link to each from marketing material." url: https://ui.clinia.dev/docs/marketing/brand-exposure --- # Brand exposure These are the public places Clinia runs or appears on. Link to them from the website, blog posts, emails, decks and event pages, so every surface points users to the right one. For the avatars and banners these profiles use, see [Social media](https://ui.clinia.dev/docs/marketing/social-media). ## Owned sites | Surface | Link | When to link to it | |---|---|---| | Website | [clinia.com](https://clinia.com) | The default link wherever Clinia is named. | | Documentation | [docs.clinia.com](https://docs.clinia.com/) | Developer content and any page that shows how to build with the Clinia Context Engine. | | Changelog | [docs.clinia.com/changelog](https://docs.clinia.com/changelog) | Release notes and "what's new" mentions. | | Trust Center | [trust.clinia.com](https://trust.clinia.com/) | Wherever security or compliance comes up, and for any compliance report request. | | Help centre | [help.clinia.com](https://help.clinia.com/) | How-to and support content, and every "Need help?" link. French readers go to [help.clinia.com/fr-ca](https://help.clinia.com/fr-ca). | | Status page | [status.clinia.dev](https://status.clinia.dev/) | Support pages, product footers and any mention of uptime or an incident. | | Design system | [ui.clinia.dev](https://ui.clinia.dev) | Briefs for agencies, partners and anyone building a Clinia surface. | ## Profiles | Surface | Link | When to link to it | |---|---|---| | LinkedIn | [linkedin.com/company/clinia](https://www.linkedin.com/company/clinia/) | Company news and hiring, and every social footer. | | GitHub | [github.com/clinia](https://github.com/clinia) | Developer content, open-source releases and engineering posts. | | YouTube | [youtube.com/@CliniaAI](https://www.youtube.com/@CliniaAI) | Product demos, talks and video embeds. | | Hugging Face | [huggingface.co/clinia](https://huggingface.co/clinia) | Research, datasets and benchmark posts, such as CURE. | | Crunchbase | [crunchbase.com/organization/clinia](https://www.crunchbase.com/organization/clinia) | Press kits and investor material. | | B Corp listing | [bcorporation.net](https://www.bcorporation.net/en-us/find-a-b-corp/company/clinia-sant/) | Beside the B Corp logo, and any mention of Clinia's social and environmental impact. | ## Careers | Surface | Link | When to link to it | |---|---|---| | Careers board | [cliniahealth.applytojobs.ca](https://cliniahealth.applytojobs.ca/) | Every job post and every "we're hiring" mention. | ## Product | Surface | Link | When to link to it | |---|---|---| | Product sign-in | [console.clinia.cloud](https://console.clinia.cloud/auth/sign-in) | The Login link for the Clinia Context Engine. | ## Linking between Clinia surfaces A link from one Clinia surface to another adds `utm_source` with the site it comes from and `utm_medium=referral`, so the visit is credited to its source. clinia.com already does this. Links to the profiles above (LinkedIn, GitHub, YouTube, Hugging Face, Crunchbase and the B Corp listing) stay plain: those sites don't report the parameters back. ## Press kit (to validate) Send this section to journalists, event organizers and partners who ask for Clinia's assets. ### Boilerplate Use one as written, at the end of a press release or in an event program. **Short (50 words)** > Clinia builds the Clinia Context Engine: patient context for healthcare AI. It is a health-specific context layer between patient data and the AI agents built on it. Founded in 2016 in Montréal, Clinia helps health organizations turn fragmented data into a patient story their AI can trust. Clinia is a Certified B Corporation. **Long (100 words)** > Clinia builds the Clinia Context Engine: patient context for healthcare AI. It is a health-specific context layer that sits between patient data and the AI agents built on top of it. It deduplicates and reconciles records, connects them in a Patient Context Graph, and gives every agent the right context, securely and in line with HIPAA, GDPR, SOC 2 and PIPEDA. Health organizations use it to turn fragmented data into a patient story their AI can act on. Founded in 2016 and headquartered in Montréal, Clinia's mission is to power health decisions and systems with the right context. Clinia is a Certified B Corporation. ### Assets - **Logos**: [Logo](https://ui.clinia.dev/docs/logo) - **Profile images and banners**: [Social media](https://ui.clinia.dev/docs/marketing/social-media) - **Founder portraits**: [Imagery](https://ui.clinia.dev/docs/marketing/imagery) - **Certification badges**: [Security & compliance](https://ui.clinia.dev/docs/marketing/compliance) --- title: "Sharing images" description: "The image a link shows when it is shared on LinkedIn, X, Slack or in a message (og:image)." url: https://ui.clinia.dev/docs/marketing/sharing-images --- # Sharing images When a user shares a Clinia link, the platform shows the page's sharing image beside its title. It is often the first thing anyone sees of a page, so every page sets one. ## Size and format - **1200 × 630px**, a 1.91:1 ratio. LinkedIn, X, Facebook and Slack all show it uncropped. - **PNG or JPG, under 5MB.** X and LinkedIn reject larger files. - **Keep the logo and copy in the centre 630 × 630px.** WhatsApp and iMessage crop the image to a square. ## How to choose a layout | If the page is… | Use | |---|---| | A site's home page, such as help.clinia.com or docs.clinia.com | **Article**, with the site's name as the eyebrow: see [Site home pages](#site-home-pages) | | Any other page without its own image | **Default**: the wordmark, centred | | A blog post, case study or announcement | **Article**: an eyebrow, the title in NaN Serf B and the wordmark | | A partnership, integration or certification | **Co-branded**: Clinia and the partner across the divider, as on [Co-branding](https://ui.clinia.dev/docs/marketing/co-branding) | ## Layouts Each layout comes in two versions, like the [profile banners](https://ui.clinia.dev/docs/marketing/social-media#banners): light, on Remedy, by default, and dark, on Infinite. The Vital line from [Line & shape](https://ui.clinia.dev/docs/marketing/line-and-shape) is cropped at the top right, clear of the logo and copy. _Live example: see the web page._ _Live example: see the web page._ Keep an Article title to two lines, about 30 characters. On French pages, use an Article image with the French title. Default and Co-branded carry no copy, so one file serves both languages. _Live example: see the web page._ _The partner above is a placeholder from [Logoipsum](https://logoipsum.com/)._ _Live example: see the web page._ ## Site home pages Each Clinia site's home page uses the light Article card, with the site's name as the eyebrow and a title of two lines at most, about 20 characters. When several sites are shared in one thread, the cards match and each one names its site. A new site adds its card here before it goes live. _Live example: see the web page._ ## Do and Don't - Do: keep the logo and copy in the centre square. - Don't: set copy at the edge, where a square crop cuts it. ### Do - Check a new image in each platform's preview tool before the page goes live. ### Don't - Export at another size, such as 1024 × 522. Platforms crop or letterbox it. - Put small text on the image. It shrinks to a thumbnail in most feeds. ## Tags Set the image, its size and its `alt` text with the other Open Graph tags: see [SEO](https://ui.clinia.dev/docs/marketing/seo#open-graph). --- title: "SEO" description: "The tags every Clinia marketing page sets in its head: title, description, languages, sharing image and structured data." url: https://ui.clinia.dev/docs/marketing/seo --- # SEO Every marketing page sets the same tags in its ``, so search engines, agents and social platforms describe Clinia the same way everywhere. The examples below come from clinia.com. Marketing sites live under clinia.com or on their own subdomain. In the examples, replace `https://clinia.com` with the address the site is served from: in page URLs, canonical and `hreflang` links, `og:url`, `WebSite`, the sitemap and `robots.txt`. The `Organization` values stay on clinia.com on every site, since they describe the company. | Tag | What it does | Set it on | |---|---|---| | Title and description | The blue link and the text under it in search results | Every page | | Canonical and `hreflang` | Which URL counts, and which page is its French or English twin | Every page | | Open Graph | The card a shared link shows on LinkedIn, Slack and in messages | Every page | | Favicon | The icon in the tab, in bookmarks and beside the result in search | Once, in the root layout | | Structured data | Facts about Clinia and the page, as JSON-LD | Once for the site, and on every blog post | | Robots and sitemap | Which pages search engines index, and where to find them | Once for the site, and on pages kept out of search | | `llms.txt` | A short map of the site for agents | Once, at the site root | ## Title and description - **Title:** the page's subject, then ` | Clinia`, under 60 characters in all. Search results cut it past that. The home page leads with what Clinia does: "Context Engine for Healthcare AI Agents | Clinia". - **Description:** one or two sentences, 120 to 155 characters, that say what the reader gets from the page. Write it for the reader, not as a list of keywords. - **One of each per page.** Two pages with the same title compete with each other in search. ```html heMTEB: Open-Source Benchmark for Health Retrieval | Clinia ``` ## Canonical and languages Each page names its own URL as canonical, absolute and with the trailing slash the site uses. Each English page and its French twin list both versions, and `x-default` points to the English one for every other language. ```html ``` Only list a twin that exists. An `hreflang` link to a page that returns 404 tells search engines the pair is broken. ## Open Graph The sharing image, its size and its `alt` text, with the title and description repeated for the card. See [Sharing images](https://ui.clinia.dev/docs/marketing/sharing-images) for the image itself. Use `og:type` `website` on the home page and landing pages, and `article` on blog posts and case studies. **Home and landing pages** ```html ``` **Blog posts and case studies** ```html ``` ## Favicon The icon tags and the web manifest are set once, in the root layout. See [Favicon](https://ui.clinia.dev/docs/favicon#use-it-in-your-app) for the files and the tags. ## Structured data Structured data tells search engines and agents who published the page. Add it as JSON-LD, in a `