Appearance
@vibe-labs/design-components-core
Shared component primitives (field wrapper, close button) for the Vibe Design System.
Installation
bash
npm install @vibe-labs/design-components-corecss
@import "@vibe-labs/design-components-core";ts
import { CloseBtnSizes } from "@vibe-labs/design-components-core/types";
import type { FieldStyleProps, CloseBtnStyleProps } from "@vibe-labs/design-components-core/types";Contents
Tokens
CSS custom properties defined in @layer vibe.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 |
Generated Styles
Component classes generated into @layer vibe.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.
TypeScript Types
ts
CloseBtnSizes // ["sm", "md", "lg"]
type CloseBtnSize
interface FieldStyleProps { horizontal?: boolean }
interface FieldLabelStyleProps {}
interface FieldRequiredStyleProps {}
interface FieldHelpStyleProps {}
interface FieldErrorStyleProps {}
interface FieldSuccessStyleProps {}
interface CloseBtnStyleProps { size?: CloseBtnSize }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 @vibe-labs/design (typography, spacing, colors, surfaces, transitions, elevation).
Build
bash
npm run buildUsage Guide
Import
css
@import "@vibe-labs/design-components-core";ts
import type { FieldStyleProps, CloseBtnStyleProps } from "@vibe-labs/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.
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><!-- × icon --></svg>
</button>
<!-- Default medium close button (e.g. inside a toast) -->
<button class="close-btn" aria-label="Dismiss">
<svg><!-- × icon --></svg>
</button>
<!-- Large close button (e.g. inside a modal header) -->
<button class="close-btn" data-size="lg" aria-label="Close dialog">
<svg><!-- × icon --></svg>
</button>With Vue
Use @vibe-labs/design-vue-core for <SbField>, <SbFieldLabel>, <SbFieldHelp>, <SbFieldError>, and <SbCloseBtn> components that accept the typed props from FieldStyleProps and CloseBtnStyleProps.