# Plasma Design System — Full LLM Documentation Plasma is Coveo's design system built on top of Mantine. It provides a curated set of React components, a custom Mantine theme, design tokens, and icons for use in Coveo Cloud products. ## Quick Start ```bash pnpm add @coveord/plasma-mantine @mantine/core @mantine/hooks react react-dom ``` ```tsx import '@mantine/core/styles.css'; import '@mantine/notifications/styles.css'; import {Plasmantine} from '@coveord/plasma-mantine/plasmantine'; function App() { return {/* your app */}; } ``` ## Components ### Accordion Collapsible content group for progressively revealing related sections without leaving the current page. #### What problem does it solve? The `Accordion` lets users scan a set of related section headings and open the content they need without showing every detail at once. It is useful when content is secondary to the main task, grouped into clear sections, and worth keeping on the same page. #### When to use it Use `Accordion` when: - related content can be organized into short, meaningful section labels - users benefit from scanning section headings before reading details - the content is useful in context but does not need to be visible all at once - one or many sections MAY be open depending on the task Use `multiple` when users commonly compare information across several sections or need more than one section open while working. #### When not to use it Do not use `Accordion` when: - the content is required for completing the current task and should be visible without disclosure - the sections represent navigation destinations rather than expandable content - users need to compare large amounts of content side by side - there are only one or two very short details that could be shown inline - hiding the content would make errors, warnings, or required decisions easier to miss #### Decision-making guidance - Use `Accordion` for progressive disclosure inside a page, not for moving between pages or major views. - Use `Tabs` when each section is a peer view and users choose one view at a time. - Use inline helper text or an `Alert` when the information is important enough to remain visible. - Use a table, list, or cards when users need to compare many items rather than open panels one by one. - Use `Accordion.ControlDisabled` when a section heading should appear in the accordion structure but should not be interactive. #### Variants - Use `default` for the standard accordion treatment. - Use `contained` when the accordion needs a clearer boundary from surrounding page content. - Use `separated` when each item should read as an independent expandable section. - Use `filled` when the accordion needs stronger visual weight. #### States Important states include: - collapsed - expanded - multiple expanded items, when `multiple` is enabled - disabled control, through `Accordion.ControlDisabled` #### Interaction notes - Each section needs a unique, consistent identifier so the accordion can track which panels are open or closed. - Icons next to section labels can help users recognize content faster, but the label text must always be clear enough on its own. - A section heading can be made non-interactive — it appears in the accordion structure but cannot be expanded or collapsed. #### Accessibility expectations - Each control MUST have clear text that describes the panel content. - Panel content SHOULD remain logically related to its control. - Interactive content inside panels MUST remain keyboard reachable when the panel is open. #### Content guidance - Control labels SHOULD be short and specific. - Labels SHOULD describe the content inside the panel, not the action of expanding it. - Keep panel content focused on one section topic. - If every panel label needs a long sentence to be understandable, the content likely needs another structure. #### Common anti-patterns - Using accordions as primary navigation. - Hiding required form fields or critical warnings inside collapsed panels. - Creating many vague sections such as "Details" or "More information." - Using an accordion to avoid designing a clearer content hierarchy. - Nesting accordions unless the relationship between levels is unmistakable. ### API reference #### Props _No additional props beyond the Mantine base component._ #### Sub-components Plasma exposes Mantine's compound accordion API and adds a disabled control convenience wrapper. - `Accordion.Item` - `Accordion.Control` - `Accordion.Panel` - `Accordion.ControlDisabled` #### Usage ```tsx import {Accordion} from '@coveord/plasma-mantine'; function Example() { return ( Project details Configure the project name, description, and visibility settings. Always visible section This content is always visible and cannot be collapsed. ); } ``` ──────────────────────────────────────────────────────────────────────────────── ### ActionIcon Icon-only button that can trigger actions and can show a disabled-state tooltip. #### What problem does it solve? The `ActionIcon` gives users a compact way to trigger an action when the action can be represented clearly by an icon. It is useful in dense interfaces where a full text button would add visual noise, such as tables, cards, toolbars, or repeated item actions. #### When to use it Use `ActionIcon` when: - the action is short, familiar, and icon-recognizable - space is limited or the action appears in a repeated row or card - the action supplements nearby content rather than carrying the primary page task alone - disabled actions need a tooltip explaining why they are unavailable #### When not to use it Do not use `ActionIcon` when: - the action is primary, high-stakes, or unfamiliar enough to need visible text - the icon would be ambiguous without a label - several adjacent icon-only actions would be hard to scan or distinguish - the user needs to compare choices by reading command names #### Decision-making guidance - Use `Button` when the action label should remain visible. - Use `ActionIcon` for compact utility actions such as edit, remove, copy, open, or refresh. - Use destructive variants only for actions that can remove, delete, revoke, or otherwise negatively affect data. - Use lower-emphasis variants for repeated row actions so they do not compete with page-level actions. #### Variants - Ignore Mantine's `variant` values (`filled`, `light`, `outline`, `subtle`, `default`); always select emphasis through the Plasma sub-components below. - Use `Primary` for the most important compact action in a local context. - Use `Secondary`, `Tertiary`, or `Quaternary` as emphasis decreases. - Use `DestructivePrimary` for the primary destructive action in a local context (e.g. the confirming delete in a toolbar or row). - Use `DestructiveSecondary`, `DestructiveTertiary`, or `DestructiveQuaternary` as the destructive action's emphasis decreases — e.g. `DestructiveQuaternary` for a low-emphasis remove in a repeated row. - Use `ActionIcon.Group` when related icon actions need to be visually grouped. #### Accessibility expectations - Icon-only actions MUST provide an accessible name — set `aria-label` on the control (or on the icon). - Disabled icon actions SHOULD explain why they are unavailable with `disabledTooltip`. - The icon MUST NOT be the only source of meaning when the action is ambiguous. #### Common anti-patterns - Replacing important text buttons with icon-only actions just to save space. - Using destructive styling for non-destructive actions. - Placing many unlabeled icons together without enough distinction. ### API reference #### Props > Extends: `MantineActionIconProps`. Only Plasma-specific props are listed below; refer to Mantine documentation for inherited props. **`onClick`** `ClickHandler` · optional · default: `undefined` — Handler executed on click. Supports standard, async, and parameterless handlers. Async handlers MAY be provided; the button shows a loading state while the promise resolves. **`disabledTooltip`** `string` · optional · default: `undefined` — Tooltip message displayed when `disabled` is `true`. **`disabledTooltipProps`** `Omit` · optional · default: `undefined` — Additional tooltip props that MAY be set on the disabled button tooltip. #### Sub-components Plasma provides pre-configured sub-components as convenience wrappers. You SHOULD use these over setting props manually. - `ActionIcon.Group` - `ActionIcon.Primary` - `ActionIcon.Secondary` - `ActionIcon.Tertiary` - `ActionIcon.Quaternary` - `ActionIcon.DestructivePrimary` - `ActionIcon.DestructiveSecondary` - `ActionIcon.DestructiveTertiary` - `ActionIcon.DestructiveQuaternary` #### TypeScript namespace aliases These type-only aliases are available for annotations and do not add runtime static properties. - `ActionIcon.Props` - `ActionIcon.StylesNames` - `ActionIcon.CssVariables` - `ActionIcon.Factory` - `ActionIcon.{Primary, Secondary, Tertiary, Quaternary, DestructivePrimary, DestructiveSecondary, DestructiveTertiary, DestructiveQuaternary}.Props` #### Usage ```tsx import {ActionIcon} from '@coveord/plasma-mantine'; import {IconTrash} from '@coveord/plasma-react-icons'; const removeItem = () => {}; const deleteItem = async () => {}; // Common pattern: use a sub-component for the intended emphasis. ; // Async handlers automatically show a loading state while pending. ; // Disabled actions MAY explain why they are unavailable. ; ``` ──────────────────────────────────────────────────────────────────────────────── ### Alert Alert callout for contextual information, advice, warnings, critical errors, and success states. #### What problem does it solve? The `Alert` makes contextual information visible in the page layout so users can notice, read, and act on it without relying on hover or transient feedback. #### When to use it Use `Alert` when: - a message should remain visible until the user has had a chance to read it - the message affects the current page, form, or workflow - users need context, advice, warning, error, or success feedback near related content - the message is more important than helper text but does not require a modal interruption #### When not to use it Do not use `Alert` when: - feedback is lightweight and transient; use `Notification` - information is optional clarification for one field; use helper text or `Input.LabelInfo` - the user must confirm a blocking decision; use `Prompt` or `Modal` - the message is only a compact status label; use `Badge` or `StatusToken` #### Decision-making guidance - Use `Alert` over `Notification` when the message must remain visible in the page layout. - Use `Alert` over `Tooltip` when the information is important and should not depend on hover or focus. - Use `Prompt` for confirmation flows where the user must choose before continuing. #### Variants - Ignore Mantine's `color`/`variant` props for choosing intent; select the message type through the Plasma sub-components below. - Use `Alert.Information` for neutral contextual information. - Use `Alert.Advice` for recommendations or next-best-action guidance. - Use `Alert.Warning` when users can proceed but should be careful. - Use `Alert.Critical` for errors, failures, or blocking issues. - Use `Alert.Success` for persistent success states that remain relevant in context. #### Content guidance - Titles SHOULD be short and state the message purpose. - Body text SHOULD explain the impact or next step. - Critical alerts SHOULD make the consequence and recovery path clear. #### Common anti-patterns - Stacking several alerts instead of grouping related messages. - Using critical alerts for neutral information. - Putting long documentation inside an alert instead of linking to supporting content. ### API reference #### Props _No additional props beyond the Mantine base component._ #### Sub-components Plasma provides pre-configured sub-components as convenience wrappers. You SHOULD use these over setting props manually. - `Alert.Information` - `Alert.Advice` - `Alert.Warning` - `Alert.Critical` - `Alert.Success` #### TypeScript namespace aliases These type-only aliases are available for annotations and do not add runtime static properties. - `Alert.Props` - `Alert.StylesNames` - `Alert.CssVariables` - `Alert.Factory` - `Alert.{Information, Advice, Warning, Critical, Success}.Props` #### Usage ```tsx import {Alert} from '@coveord/plasma-mantine'; This is an informational message. Proceed with caution. Something went wrong. ``` ──────────────────────────────────────────────────────────────────────────────── ### Anchor Inline text link that navigates the user to another page or section. #### What problem does it solve? `Anchor` lets users navigate to another page, section, or resource directly from within text — without breaking the reading flow or pulling attention away from the content with a button. A plain `` tag would be unstyled and inconsistent; a `Button` would be too heavy for in-context navigation. `Anchor` is the right weight when the navigation action lives inside prose. #### When to use it - Navigating to an external URL or a different route within the application. - Embedding a navigation action inline within a sentence or paragraph. - Providing secondary navigation options such as "View documentation" or "See all results" beside descriptive text. #### When not to use it - When the action triggers a mutation, submission, or workflow step — use `Button` instead. - When the link stands alone as a primary call-to-action with enough prominence to warrant a button shape. - When breadcrumb-style navigation is needed — use `Header.Breadcrumbs` with `Header.BreadcrumbAnchor` rather than bare `Anchor` elements. #### Decision-making guidance - Prefer `Anchor` over a plain `` element so that Plasma theming, focus styles, and size tokens are applied consistently. - Open links in a new tab only when leaving the current context would interrupt the user's task. - Use `size="xs"` for compact contexts such as table cells or captions; use `size="sm"` for body text. - Pass `inherit` when the anchor sits inside a `Text` or other typographic container so its font size and font-weight inherit from the parent rather than resetting. #### Variants `Anchor` is a straight re-export of Mantine's `Anchor`, so the full Mantine `size` scale (`xs`–`xl`) is available. In practice, prefer: - `sm` — standard body-text links. - `xs` — compact areas such as table cells or captions. #### Accessibility expectations - Link text MUST describe the destination or action, not just "click here" or "read more". - When opening a new tab, the link SHOULD signal this to screen-reader users, either through visible text or an `aria-label`. #### Content guidance - Keep link labels short and descriptive. - Avoid punctuation at the end of a link label unless it is part of a sentence. #### Common anti-patterns - Using `Anchor` to trigger an `onClick` action with no `href` — use `Button.Tertiary` or an `ActionIcon` instead. - Wrapping large blocks of content in an `Anchor`; links SHOULD target meaningful, concise labels. - Omitting `inherit` when placing an `Anchor` inside a typographic component, causing a size mismatch. ### API reference #### Props > Extends: `AnchorProps` from `@mantine/core`. No additional Plasma-specific props beyond the Mantine base component. #### Usage ```tsx import {Alert, Anchor} from '@coveord/plasma-mantine'; // Standalone link function ExternalLink() { return ( Plasma Design System ); } // Inside an Alert description — inherit the parent font size and weight function SomeAlert() { return ( Read the{' '} setup details {' '} before continuing. ); } ``` ──────────────────────────────────────────────────────────────────────────────── ### AppShell Application layout shell with a scrollable main content area. #### What problem does it solve? The `AppShell` provides the structural frame for application pages, including persistent regions such as header, navigation, main content, aside, and footer. Plasma's `AppShell.Main` keeps main content scrolling independently so the shell structure remains stable. #### When to use it Use `AppShell` when: - building a full application or product area layout - the page needs persistent navigation, header, footer, or aside regions - main content should scroll inside a stable shell - responsive shell behavior is needed around the main content #### When not to use it Do not use `AppShell` when: - only a local panel, card, or form section needs layout - a modal or embedded preview needs its own smaller structure - the layout does not need persistent shell regions #### Decision-making guidance - Use `AppShell` at the application or page-frame level. - Use `Header` for page-level title/action structure inside a shell. - Use regular layout primitives for local section layout. - Use `BrowserPreview` when the goal is to preview content inside simulated browser chrome, not structure the application. #### Accessibility expectations - Shell regions SHOULD preserve a logical page structure. - Main content SHOULD remain reachable without trapping keyboard users in persistent regions. - Navigation and header areas SHOULD have clear landmarks or labels when appropriate. #### Common anti-patterns - Nesting multiple application shells inside each other. - Using `AppShell` for a single card or local page section. - Making both shell and inner content compete for scrolling in a way that hides actions. ### API reference #### Props _No additional props beyond the Mantine base component._ #### Sub-components Plasma provides pre-configured sub-components as convenience wrappers. You SHOULD use these over setting props manually. - `AppShell.Header` - `AppShell.Navbar` - `AppShell.Main` - `AppShell.Aside` - `AppShell.Footer` - `AppShell.Section` `AppShell.Main` wraps its children in a scrollable container that fills the available height. This ensures the main content area scrolls independently from the rest of the shell. #### Usage ```tsx import {AppShell} from '@coveord/plasma-mantine'; function Example() { return ( Header Navigation Main content scrolls independently within this area. ); } ``` ──────────────────────────────────────────────────────────────────────────────── ### Badge Status label that can display short text, counts, or metadata tags. #### What problem does it solve? The `Badge` gives users a compact text label for status, category, count, or metadata that needs to be visible near an object. #### When to use it Use `Badge` when: - a short label adds scannable metadata to an item - a state or category should be visible but not interruptive - the value is textual and needs more context than an icon alone - a list, card, or header needs compact status information #### When not to use it Do not use `Badge` when: - the message needs explanation or action; use `Alert` or inline text - only a small semantic marker is needed; use `StatusToken` - the value is interactive; use a button or link pattern - the label is too long to scan as metadata #### Decision-making guidance - Use `Badge` for readable status or metadata text. - Use `StatusToken` when an icon-like status marker is enough or space is very constrained. - Keep the default `small` size for dense lists and inline metadata; use `large` only when the badge must read as a standalone status indicator. #### Variants - Ignore Mantine's `color`/`variant` props for choosing status; select meaning through the Plasma sub-components below. - Use `Badge.Primary` for the most prominent neutral label on an item. - Use `Badge.Secondary` for lower-emphasis neutral metadata. - Use `Badge.Success` for healthy, enabled, or completed states. - Use `Badge.Warning` for cautionary states. - Use `Badge.Critical` for error or failure states. - Use `Badge.Disabled` for unavailable or inactive states. #### Content guidance - Badge text SHOULD be short, usually one to three words. - Use nouns or concise state labels rather than full sentences. - Keep wording consistent across badges in the same set. #### Common anti-patterns - Using badges as buttons. - Writing long explanatory messages inside badges. - Using semantic colors inconsistently across similar statuses. ### API reference #### Props > Extends: `BadgeProps` (sub-components use `SemanticBadgeProps`, a restricted subset). Only Plasma-specific props are listed below; inherited props MUST be referenced in Mantine documentation. **`size`** `'small' | 'large'` · optional · default: `'small'` — Controls the badge height and text size. **`on`** `'light' | 'dark'` · optional · default: current colour scheme — Forces the light or dark colour variant. #### Sub-components Plasma provides pre-configured sub-components as convenience wrappers. You SHOULD use these over setting props manually. - `Badge.Primary` - `Badge.Secondary` - `Badge.Success` - `Badge.Warning` - `Badge.Critical` - `Badge.Disabled` #### TypeScript namespace aliases These type-only aliases are available for annotations and do not add runtime static properties. - `Badge.Props` - `Badge.StylesNames` - `Badge.CssVariables` - `Badge.Factory` - `Badge.{Primary, Secondary, Success, Warning, Critical, Disabled}.Props` #### Usage ```tsx import {Badge} from '@coveord/plasma-mantine'; Active Enabled Error ``` ──────────────────────────────────────────────────────────────────────────────── ### BlankSlate Empty state container for views with no content to display. #### Props **`withBorder`** `boolean` · optional · default: `true` — Renders a border when this prop is `true` and omits it when this prop is `false`. #### Usage The most common use case is rendering a table empty state, often with an action to clear filters. ```tsx import {BlankSlate, Button, Table, Title} from '@coveord/plasma-mantine'; const NoData = ({clearFilters}: {clearFilters: () => void}) => ( No data found for those filters Clear filters ); const Example = () => ( {}} /> ); ``` You can also use `BlankSlate` for simpler empty states. ```tsx import {BlankSlate, Title} from '@coveord/plasma-mantine'; const EmptyState = () => ( No data ); ``` If the surrounding layout already has its own border, disable the `BlankSlate` border. ```tsx import {BlankSlate, Title} from '@coveord/plasma-mantine'; const EmptyState = () => ( Empty state This view has no content yet. ); ``` ──────────────────────────────────────────────────────────────────────────────── ### Breadcrumbs Horizontal trail of navigation links showing the user's position within a page hierarchy. #### What problem does it solve? `Breadcrumbs` shows users where they are within a multi-level information hierarchy and lets them navigate back to ancestor pages without using the browser back button. #### When to use it - Pages that sit two or more levels deep in a navigation tree. - Drill-down workflows such as an item detail page reached from a list. - Contexts where the user may want to jump directly to a grandparent level rather than navigating step-by-step. #### When not to use it - Flat, single-level applications where there is no meaningful hierarchy. - Inside modals or drawers where the user is expected to close rather than navigate away. #### Decision-making guidance - In Plasma products, breadcrumbs are normally placed inside a page `Header` via `Header.Breadcrumbs` / `Header.BreadcrumbAnchor`; use standalone `Breadcrumbs` only outside a `Header` context. - When there are two ancestors, use two `Anchor` links. - When there are three or more ancestors, show up to three `Anchor` links — avoid going deeper as it becomes unreadable. - Do not include the current page in the trail — the page header already shows the current page name. - All items MUST be `Anchor` elements so they are keyboard-focusable and screen-reader navigable. - Pass `inherit` on each `Anchor` child so its font size matches the `Breadcrumbs` container styling. #### Interaction notes The separator between items is rendered automatically by the component. Do not place separator characters manually between children. #### Accessibility expectations - Consider wrapping the `Breadcrumbs` in a `