Appearance
@carrot/design-components-core
Shared component primitives (field wrapper, close button, panel, link, label, divider, sr-only, shortcut) for the Carrot Design System.
Installation
bash
npm install @carrot/design-components-corecss
@import "@carrot/design-components-core";ts
import {
CloseBtnSizes, PanelVariants, PanelSizes,
LinkVariants, LabelSizes, DividerOrientations
} from "@carrot/design-components-core/types";
import type {
FieldStyleProps, CloseBtnStyleProps, PanelStyleProps,
LinkStyleProps, LabelStyleProps, DividerStyleProps
} from "@carrot/design-components-core/types";Contents
Tokens
CSS custom properties defined in @layer kapish.tokens (file: core.css).
Field Wrapper
| Token | Default | Description |
|---|---|---|
--field-gap | --space-1 | Gap between label, control, and help/error |
--field-label-font-size | --text-sm | Label font size |
--field-label-font-weight | --font-semibold | Label font weight |
--field-label-color | --text-primary | Label color |
--field-help-font-size | --text-xs | Help text font size |
--field-help-color | --text-muted | Help text color |
--field-error-font-size | --text-xs | Error/success message font size |
--field-required-color | --color-danger | Required indicator color |
Close Button
| Token | Default | Description |
|---|---|---|
--close-btn-color | --text-muted | Default icon color |
--close-btn-hover-color | --text-primary | Hover icon color |
--close-btn-hover-bg | --surface-hover-overlay | Hover background |
--close-btn-radius | --radius-sm | Border radius |
--close-btn-size-sm | 1.25rem | Small size |
--close-btn-size-md | 1.75rem | Medium size (default) |
--close-btn-size-lg | 2rem | Large size |
Panel
| Token | Default | Description |
|---|---|---|
--panel-bg | --surface-primary | Panel background |
--panel-border-color | --border-default | Border color (outlined) |
--panel-border-width | 1px | Border width |
--panel-radius | --radius-lg | Border radius |
--panel-padding-sm | --space-3 | Small padding |
--panel-padding-md | --space-4 | Medium padding (default) |
--panel-padding-lg | --space-6 | Large padding |
--panel-padding-xl | --space-8 | Extra-large padding |
--panel-raised-shadow | --shadow-md | Raised variant shadow |
Link
| Token | Default | Description |
|---|---|---|
--link-muted-color | --text-muted | Muted variant color |
--link-muted-hover-color | --text-primary | Muted variant hover |
--link-decoration | none | Default text-decoration |
--link-hover-decoration | underline | Hover text-decoration |
--link-disabled-opacity | 0.5 | Disabled opacity |
Label
| Token | Default | Description |
|---|---|---|
--label-color | --text-primary | Label text color |
--label-font-weight | --font-semibold | Label font weight |
--label-size-sm | --text-xs | Small font size |
--label-size-md | --text-sm | Medium font size |
--label-size-lg | --text-base | Large font size |
--label-disabled-opacity | 0.5 | Disabled opacity |
Divider
| Token | Default | Description |
|---|---|---|
--divider-color | --border-default | Divider line color |
--divider-width | 1px | Line width |
--divider-style | solid | Line style |
--divider-spacing | --space-4 | Margin around divider |
--divider-label-color | --text-muted | Label text color |
--divider-label-font-size | --text-xs | Label font size |
--divider-label-gap | --space-3 | Gap around label |
Generated Styles
Component classes generated into @layer kapish.components (file: core.g.css).
Field Wrapper
| Class | Description |
|---|---|
.field | Vertical flex column -- label -> control -> help/error |
.field-label | Styled label text |
.field-required | Danger-colored required indicator (*) |
.field-help | Muted help text below control |
.field-error | Error message (danger color) |
.field-success | Success message (success color) |
Modifier: .field[data-horizontal] -- switches to row layout with fixed-width label (8rem min).
Close Button
| Class | Description |
|---|---|
.close-btn | Inline-flex centered button with hover/focus states |
Sizes: data-size="sm" · data-size="md" (default) · data-size="lg"
Focus-visible ring is applied via box-shadow.
Panel
| Class | Description |
|---|---|
.panel | Container with background, border-radius, and default md padding |
Variants: data-variant="outlined" (border) · data-variant="raised" (shadow) · data-variant="ghost" (transparent bg)
Sizes: data-size="sm" · data-size="md" · data-size="lg" · data-size="xl" (controls padding)
Modifier: .panel[data-flush] -- removes all padding.
Link
| Class | Description |
|---|---|
.link | Accent-colored link with hover underline and focus-visible ring |
Variants: data-variant="muted" (muted color) · data-variant="inherit" (inherits parent color)
Modifiers: .link[data-active] (semibold) · .link[data-disabled] (reduced opacity, no pointer events)
Label
| Class | Description |
|---|---|
.label | Inline-flex label with default md font size |
.label-required | Danger-colored bold required indicator |
Sizes: data-size="sm" · data-size="md" · data-size="lg"
Modifier: .label[data-disabled] -- reduced opacity, default cursor.
Divider
| Class | Description |
|---|---|
.divider | Horizontal rule (border-top) with spacing |
.divider-label | Centered label text with pseudo-element lines on sides |
Orientation: data-orientation="vertical" -- switches to vertical rule (border-left, self-stretching).
Screen Reader Only
| Class | Description |
|---|---|
.sr-only | Visually hidden but accessible to screen readers |
.sr-only-focusable | Hidden until focused (for skip links) |
Shortcut
| Class | Description |
|---|---|
.shortcut-key | Inline-flex keyboard shortcut with border styling |
.shortcut-key[data-active] | Accent-colored active state |
.shortcut-key[data-size="md"] | Larger size variant (1.5rem height) |
.shortcut-sep | Separator between keys (reduced opacity) |
TypeScript Types
ts
CloseBtnSizes // ["sm", "md", "lg"]
type CloseBtnSize
PanelVariants // ["default", "outlined", "raised", "ghost"]
type PanelVariant
PanelSizes // ["sm", "md", "lg", "xl"]
type PanelSize
LinkVariants // ["accent", "muted", "inherit"]
type LinkVariant
LabelSizes // ["sm", "md", "lg"]
type LabelSize
DividerOrientations // ["horizontal", "vertical"]
type DividerOrientation
interface FieldStyleProps { horizontal?: boolean }
interface FieldLabelStyleProps {}
interface FieldRequiredStyleProps {}
interface FieldHelpStyleProps {}
interface FieldErrorStyleProps {}
interface FieldSuccessStyleProps {}
interface CloseBtnStyleProps { size?: CloseBtnSize }
interface PanelStyleProps { variant?: PanelVariant; size?: PanelSize; flush?: boolean }
interface LinkStyleProps { variant?: LinkVariant; active?: boolean; disabled?: boolean }
interface LabelStyleProps { size?: LabelSize; disabled?: boolean }
interface DividerStyleProps { orientation?: DividerOrientation }Dist Structure
| File | Description |
|---|---|
index.css | Barrel -- imports tokens + generated styles |
core.css | Token definitions |
core.g.css | Generated component styles |
index.js / index.d.ts | TypeScript types + runtime constants |
Dependencies
Requires tokens from @carrot/design (typography, spacing, colors, surfaces, transitions, elevation).
Build
bash
npm run buildUsage Guide
Import
css
@import "@carrot/design-components-core";ts
import type {
FieldStyleProps, CloseBtnStyleProps, PanelStyleProps,
LinkStyleProps, LabelStyleProps, DividerStyleProps
} from "@carrot/design-components-core/types";Variants
Field Wrapper
The field wrapper uses data-horizontal for layout switching. No data-variant -- the field is structural only.
Close Button
Close button uses data-size for three size options: sm, md (default), lg.
Panel
Panel uses data-variant for appearance: outlined (border), raised (shadow), ghost (transparent). Use data-size for padding: sm, md, lg, xl. Add data-flush to remove padding entirely.
Link
Link defaults to accent color. Use data-variant="muted" for muted styling or data-variant="inherit" to inherit the parent color. Add data-active for bold weight or data-disabled to disable.
Label
Label defaults to medium size. Use data-size for sm, md, lg. Add data-disabled to dim. Use .label-required for the required indicator.
Divider
Divider is horizontal by default. Use data-orientation="vertical" for a vertical rule. Nest a .divider-label element for a labelled divider with lines on either side.
Screen Reader Only
Use .sr-only to visually hide content while keeping it accessible. Use .sr-only-focusable for skip links that appear on focus.
Shortcut
Use .shortcut-key for keyboard shortcut indicators. Add data-active for the active/pressed state. Use data-size="md" for a larger variant. Use .shortcut-sep between keys.
Examples
Basic vertical field
html
<!-- Standard vertical field with label, input, and help text -->
<div class="field">
<label class="field-label">
Email address
<span class="field-required">*</span>
</label>
<input type="email" class="input" placeholder="you@example.com" />
<span class="field-help">We'll never share your email.</span>
</div>Field with error state
html
<!-- Field displaying a validation error -->
<div class="field">
<label class="field-label">Username</label>
<input type="text" class="input" data-state="error" value="x" />
<span class="field-error">Username must be at least 3 characters.</span>
</div>Field with success state
html
<!-- Field displaying a success confirmation -->
<div class="field">
<label class="field-label">Password</label>
<input type="password" class="input" data-state="success" />
<span class="field-success">Password meets requirements.</span>
</div>Horizontal layout
html
<!-- Horizontal field: label sits to the left of the control -->
<div class="field" data-horizontal>
<label class="field-label">Display name</label>
<input type="text" class="input" />
</div>Close button sizes
html
<!-- Small close button (e.g. inside a badge) -->
<button class="close-btn" data-size="sm" aria-label="Remove">
<svg><!-- x icon --></svg>
</button>
<!-- Default medium close button (e.g. inside a toast) -->
<button class="close-btn" aria-label="Dismiss">
<svg><!-- x icon --></svg>
</button>
<!-- Large close button (e.g. inside a modal header) -->
<button class="close-btn" data-size="lg" aria-label="Close dialog">
<svg><!-- x icon --></svg>
</button>Panel variants
html
<!-- Default panel -->
<div class="panel">Default panel content</div>
<!-- Outlined panel -->
<div class="panel" data-variant="outlined">Outlined with border</div>
<!-- Raised panel with large padding -->
<div class="panel" data-variant="raised" data-size="lg">Raised with shadow</div>
<!-- Ghost panel (transparent background) -->
<div class="panel" data-variant="ghost">Ghost panel</div>
<!-- Flush panel (no padding) -->
<div class="panel" data-variant="outlined" data-flush>No padding</div>Link variants
html
<!-- Default accent link -->
<a class="link" href="/about">About us</a>
<!-- Muted link -->
<a class="link" data-variant="muted" href="/terms">Terms</a>
<!-- Inherit-color link -->
<a class="link" data-variant="inherit" href="/help">Help</a>
<!-- Active link -->
<a class="link" data-active href="/dashboard">Dashboard</a>
<!-- Disabled link -->
<a class="link" data-disabled>Unavailable</a>Label
html
<!-- Standard label -->
<label class="label">First name</label>
<!-- Label with required indicator -->
<label class="label">
Email
<span class="label-required">*</span>
</label>
<!-- Small label -->
<label class="label" data-size="sm">Optional hint</label>
<!-- Disabled label -->
<label class="label" data-disabled>Locked field</label>Divider
html
<!-- Horizontal divider -->
<hr class="divider" />
<!-- Vertical divider (e.g. in a flex row) -->
<div class="divider" data-orientation="vertical"></div>
<!-- Labelled divider -->
<div class="divider">
<span class="divider-label">Or continue with</span>
</div>Screen reader only
html
<!-- Visually hidden label for accessibility -->
<span class="sr-only">Navigation menu</span>
<!-- Skip-to-content link (visible on focus) -->
<a class="sr-only-focusable" href="#main">Skip to main content</a>Shortcut keys
html
<!-- Single key -->
<kbd class="shortcut-key">K</kbd>
<!-- Key combo with separator -->
<kbd class="shortcut-key">Ctrl</kbd>
<span class="shortcut-sep">+</span>
<kbd class="shortcut-key">K</kbd>
<!-- Active state -->
<kbd class="shortcut-key" data-active>Enter</kbd>
<!-- Medium size -->
<kbd class="shortcut-key" data-size="md">Space</kbd>With Vue
Use @carrot/design-vue-core for <SbField>, <SbFieldLabel>, <SbFieldHelp>, <SbFieldError>, <SbCloseBtn>, <SbPanel>, <SbLink>, <SbLabel>, <SbDivider>, and <SbShortcut> components that accept the typed props.