# Wallarm Design System > React components, tokens and AI tooling for Wallarm products ## Get Started - [Introduction](https://wallarm.github.io/design-system/get-started/introduction.md): What the Wallarm Design System is, what it is built on and where to find it. - [Installation](https://wallarm.github.io/design-system/get-started/installation.md): Install the design system and its peer dependencies, then set up Tailwind, the theme CSS and ThemeProvider. - [Theming](https://wallarm.github.io/design-system/get-started/theming.md): Light and dark themes, the frame style, and overriding design tokens with CSS variables. - [Routing](https://wallarm.github.io/design-system/get-started/routing.md): Connect links, navigation and RemoteShell to TanStack Router, React Router or Next.js. - [Migration guides](https://wallarm.github.io/design-system/get-started/migrations/index.md): Upgrade across breaking design-system releases with the @wallarm-org/migrator codemod CLI. - [Migrating to v4](https://wallarm.github.io/design-system/get-started/migrations/v4.md): Upgrade to v4.0.0, where the unused TreeBase subpath is removed. - [Migrating to v3](https://wallarm.github.io/design-system/get-started/migrations/v3.md): Upgrade to v3.0.0, where Avatar sizes are renamed and Avatar gains a user-item composition. - [Migrating to v2](https://wallarm.github.io/design-system/get-started/migrations/v2.md): Upgrade to v2.0.0, where NumericBadge type splits into type and color. - [Migrating to v1](https://wallarm.github.io/design-system/get-started/migrations/v1.md): Upgrade to v1.0.0, where Table moves to TanStack Table v9. - [Changelog](https://wallarm.github.io/design-system/get-started/changelog.md): Release notes for every @wallarm-org/design-system version. ## AI - [MCP server](https://wallarm.github.io/design-system/ai/mcp.md): Connect Claude Code, Cursor or VS Code to the design-system MCP server for component and token metadata. - [llms.txt and Markdown](https://wallarm.github.io/design-system/ai/llms.md): Machine-readable versions of this site for AI assistants and LLMs — llms.txt, Markdown pages and components.json. - [Claude Design](https://wallarm.github.io/design-system/ai/claude-design.md): Prototype with the real Wallarm components, tokens, fonts and icons in Claude Design. ## Guides - [Testing](https://wallarm.github.io/design-system/guides/testing.md): Target design-system components in Playwright and Testing Library with cascading data-testid values. - [Analytics](https://wallarm.github.io/design-system/guides/analytics.md): Attach your analytics attributes and handlers to design-system components; they land on the real interactive element. ## Foundations - [Tokens](https://wallarm.github.io/design-system/foundations/tokens.md): Wallarm design system tokens: color palettes, semantic light and dark colors, spacing, typography, radius, shadow, blur, focus and icon sizes, with their values. - [Icons](https://wallarm.github.io/design-system/foundations/icons.md): Import icons from the icons entry point, size them and give meaningful icons a title. ## Components - [Button](https://wallarm.github.io/design-system/components/button.md): Triggers an action — reach for `Link` when the control navigates somewhere instead, `ToggleButton` when it stays switched on, and `SplitButton` or `DropdownMenu` when several related actions compete for one slot. Keep one `variant='primary'` per view, and reserve `color='destructive'` for actions that are hard to undo. - [DropdownMenu](https://wallarm.github.io/design-system/components/dropdown-menu.md): A menu of actions hanging off a trigger — reach for `Select` when the reader is choosing a value for a form, since a menu runs commands rather than holding an answer. Leave the primary action visible as a `Button` and put only the secondary ones in here; past roughly ten items, group them or move them somewhere with room. - [SplitButton](https://wallarm.github.io/design-system/components/split-button.md): Pairs one action with a menu of related ones, for when a second action matters enough that burying it in a `DropdownMenu` would hide it. Both halves are ordinary `Button`s, so they must share a variant, colour and size — the group only joins their facing corners. - [ToggleButton](https://wallarm.github.io/design-system/components/toggle-button.md): A button that stays pressed — for something the reader flips in place and can see the result of, like pinning a panel or holding a filter on. Reach for `Switch` when it belongs in a settings form, and `SegmentedControl` when one of several options has to win. - [Checkbox](https://wallarm.github.io/design-system/components/checkbox.md): Collects any number of choices from a limited set, or turns a single option on or off — reach for `Radio` when only one choice is allowed, and `Switch` when the change takes effect immediately instead of on submit. Past roughly ten options, a `Select` reads better than a long column of boxes. - [Field](https://wallarm.github.io/design-system/components/field.md): The scaffolding around a control — label, description, error and the required marker — so the control itself only has to be the control. Only `Input`, `Textarea` and `Slider` read this context automatically; wrap anything else and you get the layout, but the labelling still has to be wired by hand. - [FileUpload](https://wallarm.github.io/design-system/components/file-upload.md): Attaches files to a form and checks their type, size and count before accepting them — the drop Area when attaching is the main task on the screen, the "Select file" button when space is tight. Picking never uploads: files travel with the form when it is saved, and the product marks a row `loading` while it sends one. To pick a photo by clicking an avatar, see Data Display/Avatar → Click To Upload. - [ImageCropper](https://wallarm.github.io/design-system/components/image-cropper.md): Select part of an image by moving and zooming it inside a fixed frame, then export a Blob at the exact outputSize. The frame follows the output aspect ratio and preserves the source proportions. Compose Slider for zoom, FileUpload for choosing a file, and your own Save action through ImageCropperContext. All processing runs in the browser; the consumer owns uploading. Preview rounding is visual only: the saved image is rectangular. Remote images need crossOrigin="anonymous" on ImageCropperImage and server CORS permission for canvas export; local file/object URLs also work. Size the preview with width classes; CSS scale transforms on ancestors are not supported by the underlying crop geometry. Arrow keys pan, Shift accelerates, and +/− zoom. - [InlineEdit](https://wallarm.github.io/design-system/components/inline-edit.md): Turns a displayed value into its own editor, so a reader can correct one field without opening a form — reach for a form when several values change together. Every story composes it inside an `Attribute`, because that is what keeps the read and edit states the same height and stops the row jumping on toggle. - [Input](https://wallarm.github.io/design-system/components/input.md): Short, single-line free text — reach for `Textarea` when the answer runs to sentences, and `Select` when it comes from a known set. Wrap it in `Field` for the label and description; a placeholder is an example of the answer, never a substitute for the label and never where required information lives. - [InputGroup](https://wallarm.github.io/design-system/components/input-group.md): Joins a field to whatever sits against it — an icon, a unit, a shortcut hint, a button — inside one bordered box that focuses as a single control. Reach for `Field` instead when what you need is a label and a description rather than something attached to the field itself. - [InputOTP](https://wallarm.github.io/design-system/components/input-otp.md): A short code split into one cell per character, for codes that arrive by mail or from an authenticator — reach for `Input` for anything the reader knows by heart. Six cells by default, and `groupSize` inserts separators so the reader can check what they typed against what they were sent. - [NumberInput](https://wallarm.github.io/design-system/components/number-input.md): A number the reader nudges rather than types from scratch — reach for `Input` when the figure is just data like a port or an ID, and `Slider` when the position matters more than the exact value. It starts at zero rather than empty, so pass `defaultValue` wherever a pre-filled zero would be mistaken for an answer. - [PasswordInput](https://wallarm.github.io/design-system/components/password-input.md): A password field with a reveal toggle, which is the whole point of reaching for it over an `Input` of type password. Where rules are enforced, pair it with `PasswordComplexity` so the reader watches them being met rather than discovering them on submit. - [Radio](https://wallarm.github.io/design-system/components/radio.md): Picks exactly one option from a set — reach for `Checkbox` when several answers can be true at once, and `Select` past roughly ten options. Radios cannot be cleared once chosen, so include the neutral answer as an option rather than expecting the reader to undo. - [SearchInput](https://wallarm.github.io/design-system/components/search-input.md): A search field with a magnifying-glass icon and a clear button that appears once there is a value. Controlled only — pass `value` and `onChange`, and optionally `onClear` to react to the clear button specifically. - [SegmentedControl](https://wallarm.github.io/design-system/components/segmented-control.md): Switches between renditions of the same content, with every option visible — reach for `Tabs` when the sections are distinct places rather than views of one thing, and `Radio` when the choice is an answer a form submits. It owns no panel: it reports the chosen value and you re-render the content yourself. - [Select](https://wallarm.github.io/design-system/components/select.md): Holds one answer, or several, chosen from a list — below about six options expose them instead with `Radio` or `SegmentedControl`, and reach for `DropdownMenu` when the items run commands rather than set a value. The trigger is composed rather than configured: `SelectButton` for a button-shaped trigger, `SelectInput` for one that looks like a field. - [Slider](https://wallarm.github.io/design-system/components/slider.md): Sets an approximate, bounded value by dragging along a track — reach for `NumberInput` when the exact figure matters, since a slider is faster to move than it is to land. A slider should always show its value: pair it with `SliderInput` for entry, or `SliderValue` for a readout. It implies a continuum, so a few fixed choices belong in `SegmentedControl`, `Radio` or `Select`, and on/off in `Switch`. - [Switch](https://wallarm.github.io/design-system/components/switch.md): Turns one setting on or off, and takes effect the moment it is flipped — reach for `Checkbox` when the answer is submitted with a form, and `ToggleButton` when the control belongs in a toolbar rather than a settings list. Because there is no Save to undo it, avoid a switch for anything destructive or slow. - [Textarea](https://wallarm.github.io/design-system/components/textarea.md): Multi-line free text, for answers that run to sentences — reach for `Input` when one line will do, since a tall box tells the reader to write more than you want. Like `Input`, it reads `Field` context for its label, description and error state. - [Calendar](https://wallarm.github.io/design-system/components/calendar.md): The month grid for choosing a date the reader needs to see in context — a weekday, a distance from today — where `DateInput` is for a date they already know. It is its own popover, so compose a trigger beside it rather than wrapping it in one, and take React Aria date objects rather than a JavaScript `Date`. - [DateInput](https://wallarm.github.io/design-system/components/date-input.md): A date typed segment by segment, for a date the reader knows — pair it with `Calendar` when they need to see the month to choose. It takes React Aria date objects rather than a JavaScript `Date`, and segment order and hour cycle come from `DateFormatProvider` app-wide rather than per input. - [DateRangeInput](https://wallarm.github.io/design-system/components/date-range-input.md): Two dates in one field, for a period the reader knows — pair it with `Calendar` in range mode when they need to see the months to choose. Same rules as `DateInput`: React Aria date objects, and order and hour cycle from `DateFormatProvider` rather than per input. - [TimeInput](https://wallarm.github.io/design-system/components/time-input.md): A time typed segment by segment, the companion to `DateInput` — `showTimeDropdown` adds a list of times for when the reader would rather pick than type. It takes React Aria time objects, and hour cycle comes from `DateFormatProvider` app-wide rather than per input. - [Accordion](https://wallarm.github.io/design-system/components/accordion.md): Stacks sections behind their own headers and opens each on demand — reach for `Tabs` when a few primary sections get switched between often, and leave content on the page when people read most of it anyway. `primary` and `secondary` are inline rows for grouping; `section` is the bordered panel, and the only variant with room for `AccordionActions`. - [Attribute](https://wallarm.github.io/design-system/components/attribute.md): Pairs one field's label with its value on a detail page — reach for `Table` when the same fields repeat across many objects, and `Field` when the value is being collected rather than read. The value slot takes whichever display component fits the data and hosts `InlineEdit` when the field is editable in place, while `AttributeActions` hangs a per-value menu off it. - [Avatar](https://wallarm.github.io/design-system/components/avatar.md): A person's photo on a rounded plate, falling back to initials or an icon while it loads, when it fails, or when there is none. It is decorative beside a visible name; standing alone, give it `aria-label` so it reads as an image. Add `AvatarContent` with `AvatarName` (and an optional `AvatarDescription`) for the user item: plate and name in one row. To let people change it, make the avatar the `FileUploadTrigger` (`asChild`) and give it `as='button'` — picking only previews, and your form uploads. - [Card](https://wallarm.github.io/design-system/components/card.md): Holds one self-contained thing — a metric, an integration, a saved view — in a block you can compare against its neighbours in a grid; reach for `Table` when the same fields repeat down a list, and for a `Heading` when you only mean to section a page. Passing any handler turns the whole card into the target: it becomes focusable and picks up hover and pressed overlays, while clicks on a link or button inside it stay with that control. - [CodeEditor](https://wallarm.github.io/design-system/components/code-editor.md): An editable code surface that is visually the same component as `CodeSnippet` and reuses its header, tabs, actions and show-more — reach for `CodeSnippet` whenever the code is only read, since a page that never renders `CodeEditorContent` never loads the editor engine. Colours come from the same `CodeSnippetAdapterProvider` (plain text without one), so a read-only editor matches the snippet except for a native thin scrollbar, a caret and selection drawn by the editor, and an HTTP JSON body that stays coloured when `Content-Type` has parameters or the body has blank lines. The adapter re-tokenizes the whole document after each pause in typing, which stays within a frame up to about 2 000 lines with Prism; longer documents still edit smoothly, their colours just settle a moment later. Like the snippet, the editor sits inside a `display: contents` wrapper that keeps it mounted across fullscreen, so space editors with their own `className` (for example `mt-16`) or a `gap` on the parent — not `space-*`, `divide-*` or child selectors on the parent. `lines`, `folds`, `completions` and `schema` are compared by identity, so memoise them or hoist them to module constants — a new value on every render reconfigures the editor. Autocomplete suggests language keywords and words already in the document for every language; HTTP methods and headers and JSON Schema values have their own contextual suggestions. Pass `completions` to add application-specific results. Syntax errors are best-effort: JSON reports the `JSON.parse` message, JavaScript and TypeScript use Babel, Lua uses luaparse (first error only), YAML and Python use their Lezer parsers, which still flag a few valid Python forms such as `lambda a, /, b` and parenthesised `with` items. `lines` and `folds` stay on their line numbers while typing; to keep a decoration on a piece of text, recompute it from `value` (for example `useMemo(() => linesFor(value), [value])`, or a `folds` function such as `getHttpFolds`). The editor injects `