# LafLabs Web Design System version: 2026.10.3 · Updated: 2026-10-07 Use this provider-neutral guide for LafLabs public websites and branded web surfaces. It does not redefine dense Admin workflows or unrelated third-party products. The active system uses Paper and Ink surfaces, Primary Blue as its sole accent, square geometry, restrained motion, and equivalent Korean and English content. Preserve factual product content and official assets; never invent claims or substitute fake product imagery. ## Core principles ### Accessibility Verify keyboard access, contrast, names, and states together. - Every action must work by keyboard and show a visible focus indicator. - Give icon controls and groups names that explain their purpose. - Keep a 44px target area on small screens. - Communicate loading, empty, and error states in text. ### Factual claims Publish only claims that can be verified. - Mention customers, metrics, product status, or hiring only when a source verifies it. - Mark unverified material unavailable or omit it. - Never fill an empty surface with invented numbers or examples. ### Color Use Paper and Ink by default, with Primary Blue as the sole accent. - Reserve blue for key actions, selected states, and direction. - Route-era colors are legacy references, not defaults for new surfaces. - Never communicate state or meaning with color alone. ### Iconography Use the Phosphor family consistently for new interface icons. - Choose a meaningful Phosphor icon instead of drawing decorative SVGs. - Give icon-only controls an accessible name. - Use the current 15px icon size inside a 34px compact control. ### Brand identity Keep the official logo shape and proportions intact. - Use the official PNG asset; do not crop or redraw it. - Give the logo clear space and strong contrast against its surface. - Do not add shadows, outlines, or color effects to the logo. ### Motion Motion explains entry, progress, and state changes only. - The Segmented Control uses the shared spring at stiffness 520 and damping 38. - Do not move layout position or padding on hover. - Under prefers-reduced-motion, show the final state immediately. ### Shape Use zero-radius corners and one-pixel rules to reveal structure. - Keep controls, surfaces, and indicators square. - Prefer surface contrast and rules to card shadows. - Use circles only when the product meaning requires one. ### Spacing and layout A 1280px shell and responsive gutter establish horizontal rhythm. - The current shell is min(1280px, calc(100% - 64px)). - Use --gutter for full-width sections instead of adding ad hoc inline space. - Stack complex layouts at 1080px and move to a one-column flow at 720px. - Keep generous vertical section space between 80px and 150px. ### Typography Sans carries meaning; Mono carries compact system information. - Pair Geist Sans with Pretendard to balance Korean and Latin text. - Keep large headings short and body measures easy to scan. - Do not introduce 9px text in new UI. - Check Korean line breaks so phrases remain intact. ### Voice Write briefly and concretely while preserving technical terms. - Do not expand an explanation when one sentence is enough. - Keep technical terms such as API and token, and preserve English identifiers. - Keep Korean and English equivalent without forcing identical word order. ## Design tokens The production shell is `min(1280px, calc(100% - 64px))`. Treat tokens marked legacy as reference values, not defaults for new surfaces. | Token | Group | Value | Status | Purpose | | --- | --- | --- | --- | --- | | `color.blue-grey` | color | `#8ba7d9` | Legacy reference | Legacy supporting copy and unavailable-state color. | | `color.blue-light` | color | `#60a5fa` | Current | Short highlights inside dark contrast bands. | | `color.blue-pale` | color | `#dbeafe` | Current | Large passive marks and supporting text on blue surfaces. | | `color.border-blue` | color | `#263d68` | Legacy reference | Legacy one-pixel rule color from the route-era interface. | | `color.border-blue-strong` | color | `#385a91` | Legacy reference | Legacy emphasized rule and outline-action border color. | | `color.button-ink` | color | `#0a0e18` | Legacy reference | Legacy text color for the light contact action. | | `color.error` | color | `#ef4444` | Current | Reserved for error and danger status. | | `color.error-deep` | color | `#b91c1c` | Current | High-contrast background for destructive actions with a white foreground. | | `color.info` | color | `#0ea5e9` | Current | Reserved for informational status. | | `color.ink` | color | `#0f172a` | Current | The default text, rule, and dark contrast-band color. | | `color.inverse-navy` | color | `#071022` | Legacy reference | Legacy contact-section surface from the route-era interface. | | `color.line` | color | `#cbd5e1` | Current | Quiet dividers and inactive outlines. | | `color.mask-black` | color | `#000` | Legacy reference | Legacy opaque mask stop, not a visible surface color. | | `color.muted` | color | `#64748b` | Current | Supporting copy and lower-priority metadata. | | `color.off-white` | color | `#f4f7fb` | Legacy reference | Legacy text and light-control color from the route-era interface. | | `color.page-navy` | color | `#0b1328` | Legacy reference | Legacy default page surface from the route-era interface. | | `color.paper` | color | `#f8fafc` | Current | The default page and control surface. | | `color.primary` | color | `#2563eb` | Current | The primary accent for key actions, selected states, and structure. | | `color.primary-deep` | color | `#1e40af` | Current | The hover and pressed color for Primary Blue actions. | | `color.pure-white` | color | `#fff` | Current | Foreground color on Ink, Primary Blue, and Error Deep surfaces. | | `color.raised-navy` | color | `#101c35` | Legacy reference | Legacy raised dark detail from the route-era interface. | | `color.route-blue` | color | `#165dff` | Legacy reference | Legacy fill and structural accent from the route-era interface. | | `color.route-blue-deep` | color | `#0f4bd8` | Legacy reference | Legacy primary-button hover color from the route-era interface. | | `color.route-blue-soft` | color | `#112b5d` | Legacy reference | Legacy quiet active surface from the route-era interface. | | `color.route-endpoint` | color | `#5e8fe8` | Legacy reference | Legacy route-endpoint stroke color. | | `color.route-line` | color | `#8fb6ff` | Legacy reference | Legacy route, metadata, and focus color. | | `color.slate-detail` | color | `#475569` | Current | Compact editorial detail on light surfaces. | | `color.slate-soft` | color | `#94a3b8` | Current | Metadata on dark contrast bands. | | `color.subtle-navy` | color | `#0e1931` | Legacy reference | Legacy alternating section surface from the route-era interface. | | `color.success` | color | `#10b981` | Current | Reserved for successful status. | | `color.warning` | color | `#f59e0b` | Current | Reserved for warning status. | | `layout.breakpoint-mobile` | layout | `720px` | Current | The small-screen breakpoint for collapsed navigation and one-column layout. | | `layout.breakpoint-stack` | layout | `1080px` | Current | The breakpoint where complex desktop arrangements begin to stack. | | `layout.compact-control` | layout | `34px` | Current | The desktop visual size for language and icon controls. | | `layout.gutter` | layout | `max(32px, calc((100vw - 1280px) / 2))` | Current | Responsive inline space for full-width sections. | | `layout.shell` | layout | `min(1280px, calc(100% - 64px))` | Current | The current public-shell maximum width and inline space. | | `motion.reduced` | motion | `0ms` | Current | State transitions complete immediately when reduced motion is requested. | | `motion.segmented-control` | motion | `spring(stiffness: 520, damping: 38)` | Current | The shared spring for the Segmented Control selection surface. | | `shape.radius` | shape | `0px` | Current | The default corner radius for controls, surfaces, and indicators. | | `shape.rule` | shape | `1px` | Current | The default rule width for sections, rows, and controls. | | `spacing.section-vertical` | spacing | `80px–150px` | Current | Responsive vertical section space, adjusted to content and viewport width. | | `typography.body-default` | typography | `16px` | Current | Default body size, with contextual sizes ranging from 14px to 17px. | | `typography.compact-title` | typography | `22px` | Current | Compact list and repository titles at weight 700. | | `typography.company-statement` | typography | `clamp(52px, 5.6vw, 72px)` | Current | Dark-band company statement at weight 700, line-height 1.04, and -0.04em tracking. | | `typography.family-mono` | typography | `Geist Mono, monospace` | Current | Reserved for status, indices, and technical metadata. | | `typography.family-sans` | typography | `Geist Sans, Pretendard, sans-serif` | Current | The default family stack for headings and body copy. | | `typography.hero-field-mark` | typography | `clamp(116px, 14vw, 210px)` | Current | The large homepage hero field mark only, at weight 850 and line-height 0.75. | | `typography.homepage-hero` | typography | `clamp(64px, 6.2vw, 80px)` | Current | Homepage proposition at weight 780, line-height 0.98, and -0.04em tracking. | | `typography.method-mark` | typography | `clamp(88px, 10.5vw, 154px)` | Current | Graphic ASK, BUILD, and RUN marks only, at weight 850 and line-height 0.75. | | `typography.mobile-company` | typography | `clamp(36px, 10.8vw, 44px)` | Current | Company statements on small screens. | | `typography.mobile-homepage-hero` | typography | `clamp(40px, 11.6vw, 48px)` | Current | The homepage proposition on small screens. | | `typography.mobile-method-mark` | typography | `clamp(94px, 33vw, 136px)` | Current | ASK, BUILD, and RUN marks on small screens. | | `typography.mobile-search-input` | typography | `clamp(30px, 9vw, 38px)` | Current | Search input on small screens. | | `typography.mobile-search-result` | typography | `clamp(18px, 5.6vw, 22px)` | Current | Search-result headings on small screens. | | `typography.mobile-section` | typography | `clamp(32px, 9.6vw, 40px)` | Current | Major section headings on small screens. | | `typography.mono-label` | typography | `10–11px` | Current | Indices, metadata, states, and compact navigation labels. | | `typography.panel-title` | typography | `clamp(27px, 2.5vw, 36px)` | Current | Titles inside bounded modules at weight 710 and line-height 1.08. | | `typography.search-input` | typography | `clamp(42px, 4.5vw, 64px)` | Current | Search-overlay input at weight 760 and line-height 1. | | `typography.search-result` | typography | `clamp(20px, 1.8vw, 26px)` | Current | Search-result headings at weight 720 and line-height 1.12. | | `typography.section-heading` | typography | `clamp(44px, 4.5vw, 60px)` | Current | Major section headings at weight 720, line-height 1.06, and -0.04em tracking. | | `typography.work-title` | typography | `clamp(32px, 3.4vw, 44px)` | Current | Selected-work titles at weight 720 and line-height 1. | ## Components ### Accordion (`accordion`) Maturity: **candidate** · Category: **disclosure** Expands and collapses longer content by heading. - Use: Use it for FAQs or supporting detail that need not be visible at once. - Avoid: Do not hide essential information or short primary copy by default. - Accessibility: Preserves real headings, buttons, aria-expanded, and arrow-key movement. - States: `closed` (fixture), `open` (fixture), `disabled` (fixture) - Related components: `tabs`, `separator` - Dependencies: `@phosphor-icons/react`, `radix-ui` ### Alert (`alert`) Maturity: **candidate** · Category: **feedback** Explains a persistent inline state and its next action. - Use: Use it when information, success, warning, or error must remain with the task. - Avoid: Use Toast for brief outcomes and Alert Dialog for decisions. - Accessibility: Labels the region from a visible title and reserves live for new urgent errors. - States: `info` (fixture), `warning` (fixture), `error` (fixture), `live` (fixture) - Related components: `toast`, `alert-dialog`, `button` - Dependencies: `@phosphor-icons/react` ### Alert Dialog (`alert-dialog`) Maturity: **candidate** · Category: **overlay** Requests an explicit decision before a consequential action. - Use: Use it for immediate actions such as deletion or permission changes. - Avoid: Use Dialog or Alert for general information or reversible actions. - Accessibility: Requires cancel or action, ignores outside dismissal, and restores focus. - States: `closed` (fixture), `open` (interactive), `destructive` (interactive) - Related components: `dialog`, `alert`, `button` - Dependencies: `radix-ui` ### Breadcrumb (`breadcrumb`) Maturity: **candidate** · Category: **navigation** Shows where the current page sits in the information hierarchy. - Use: Use it in documents or admin views more than one level deep. - Avoid: Do not use it on a single-level page or as a progress indicator. - Accessibility: Uses a named nav, ordered list, current-page state, and hidden separators. - States: `default` (fixture), `collapsed` (fixture) - Related components: `text-link`, `dropdown-menu` - Dependencies: `@phosphor-icons/react` ### Button (`button`) Maturity: **stable** · Category: **action** Runs an action in the current interface. - Use: Use it for immediate actions such as save, submit, and confirm. - Avoid: Use Button Link or Text Link for navigation. - Accessibility: Keep an action-specific name, expose busy and disabled states, and name icon buttons with aria-label. - States: `primary` (fixture), `secondary` (fixture), `outline` (fixture), `inverse` (fixture), `ghost` (fixture), `icon` (fixture), `disabled` (fixture), `loading` (fixture), `danger` (fixture) - Related components: `button-link`, `button-group` ### Button Group (`button-group`) Maturity: **candidate** · Category: **action** Composes related actions and supporting parts in one connected frame. - Use: Use it for related actions, split actions, or an input paired with its action. - Avoid: Do not force unrelated actions or long explanations into one row. - Accessibility: Name the group while preserving a specific name for every control. - States: `horizontal` (fixture), `vertical` (fixture), `split` (fixture), `input` (fixture) - Related components: `button`, `button-link`, `dropdown-menu`, `input-group` ### Button Link (`button-link`) Maturity: **stable** · Category: **action** Uses Button's appearance while preserving a native anchor for navigation. - Use: Use it only when a prominent CTA navigates to another page or address. - Avoid: Use Button for in-place actions such as save, submit, or opening a dialog. - Accessibility: Do not replace it with Button; preserve native anchor semantics and a destination-specific name. - States: `primary` (fixture), `secondary` (fixture), `outline` (fixture), `inverse` (fixture), `ghost` (fixture), `icon` (fixture) - Related components: `button`, `text-link` ### Checkbox (`checkbox`) Maturity: **candidate** · Category: **selection** Turns an independent selection on or off. - Use: Use it for independent consent, list, or multi-select values. - Avoid: Use Switch for a single setting that changes immediately. - Accessibility: Preserve the native checkbox and expose mixed state through aria-checked. - States: `unchecked` (fixture), `checked` (fixture), `indeterminate` (fixture), `disabled` (fixture) - Related components: `radio-group`, `switch` ### Code Block (`code-block`) Maturity: **stable** · Category: **content** A readable code region with a language label and copy action. - Use: Use it to present multiline code or commands verbatim in documentation. - Avoid: Do not use it for short inline identifiers or as an executable editor. - Accessibility: The copy button names the language, and the source remains selectable after a copy failure. - States: `idle` (fixture), `copied` (interactive), `error` (environment) - Related components: `button` ### Combobox (`combobox`) Maturity: **candidate** · Category: **form** Selects one value from a searchable list. - Use: Use it when the option list is long or labels may be unfamiliar. - Avoid: Use Native Select or Select for short, fixed option lists. - Accessibility: Exposes combobox/listbox relationships, active option, selection, and arrow-key operation. - States: `closed` (fixture), `open` (interactive), `empty` (interactive) - Related components: `field`, `select`, `input` - Dependencies: `@phosphor-icons/react`, `radix-ui` ### Data Table (`data-table`) Maturity: **candidate** · Category: **content** Displays structured data with sorting and an explicit empty state. - Use: Use it for operational lists that people need to reorder by column. - Avoid: Use Table for static comparison and Item for editorial browsing. - Accessibility: Connects sort buttons with aria-sort while preserving real Table semantics. - States: `default` (fixture), `sorted` (interactive), `empty` (fixture) - Related components: `table`, `pagination`, `empty-state` - Dependencies: `@phosphor-icons/react` ### Dialog (`dialog`) Maturity: **candidate** · Category: **overlay** Opens a focused, short task above the current flow. - Use: Use it for settings or a short form without leaving context. - Avoid: Do not use it for long documents or consequential decisions. - Accessibility: Preserves naming, focus trapping, Escape dismissal, and trigger focus restoration. - States: `closed` (fixture), `open` (interactive), `body-scroll` (interactive) - Related components: `alert-dialog`, `button`, `field` - Dependencies: `@phosphor-icons/react`, `radix-ui` ### Dropdown Menu (`dropdown-menu`) Maturity: **candidate** · Category: **navigation** Opens related commands and settings from one trigger. - Use: Use it to group related, secondary commands in one place. - Avoid: Do not hide primary actions or replace straightforward page navigation. - Accessibility: Preserves arrow keys, typeahead, Escape, submenus, and trigger focus restoration. - States: `default` (fixture), `open` (interactive), `disabled` (fixture) - Related components: `button`, `select`, `dialog` - Dependencies: `@phosphor-icons/react`, `radix-ui` ### Empty State (`empty-state`) Maturity: **candidate** · Category: **feedback** Explains why no content is present and what can happen next. - Use: Use it for a genuinely empty result, document, or collection. - Avoid: Do not invent example data or use it as a promotional card. - Accessibility: Make the state understandable from title and description, with recovery when available. - States: `default` (fixture), `action` (fixture) - Related components: `button`, `text-link`, `skeleton` ### Field (`field`) Maturity: **candidate** · Category: **form** Composes labels, controls, descriptions, and errors into complete form sections with FieldGroup and FieldSet. - Use: Use Field for one control and FieldGroup with FieldSet for related form sections. - Avoid: Do not group read-only content or unrelated controls under one label. - Accessibility: Links nested FieldContent descriptions and errors to the control and names groups with FieldLegend. - States: `default` (fixture), `required` (fixture), `invalid` (fixture) - Related components: `label`, `input`, `textarea`, `native-select` ### Input (`input`) Maturity: **candidate** · Category: **form** A native input for single-line values. - Use: Use it for single-line values such as email, title, or search. - Avoid: Use Textarea for multiline copy and Native Select for fixed choices. - Accessibility: Provide a name through Field or Label and choose the correct native type. - States: `default` (fixture), `focus-visible` (interactive), `invalid` (fixture), `disabled` (fixture) - Related components: `field`, `label`, `textarea`, `native-select` ### Input Group (`input-group`) Maturity: **candidate** · Category: **form** Groups an input with a unit, prefix, or compact action. - Use: Use it for prefixes, units, or actions directly tied to an input. - Avoid: Do not place independent fields or several primary actions inside one boundary. - Accessibility: Keeps one native control in DOM order; the start and end aliases normalize to inline placements. - States: `default` (fixture), `focus-visible` (interactive), `invalid` (fixture) - Related components: `field`, `input`, `button` ### Item (`item`) Maturity: **candidate** · Category: **structure** Composes media, copy, metadata, and actions into one row. - Use: Use it for repeated entities such as repositories, documents, or people without card grids. - Avoid: Use Table for column comparison and Panel for a standalone region. - Accessibility: Chooses article, div, or li for the surrounding structure and labels the item from its title. - States: `default` (fixture), `subtle` (fixture), `inverse` (fixture) - Related components: `panel`, `table`, `status-label` ### Label (`label`) Maturity: **candidate** · Category: **form** Provides a concise name for a form control. - Use: Use it to explicitly name a native control outside Field. - Avoid: Do not use a label element for help text or decoration. - Accessibility: Keep htmlFor equal to the target control ID. - States: `default` (fixture), `required` (fixture) - Related components: `field`, `input`, `textarea`, `native-select` ### Logo (`logo`) Maturity: **stable** · Category: **brand** Displays the official symbol with the LafLabs wordmark. - Use: Use it where the LafLabs identity must be explicit, such as the site header and footer. - Avoid: Do not use it as a decorative background or repeating motif. - Accessibility: The component exposes the LafLabs name; check that an enclosing link does not create a redundant label. - States: `default` (fixture), `compact` (fixture) - Dependencies: `next` ### Native Select (`native-select`) Maturity: **candidate** · Category: **form** A select that preserves native browser selection behavior. - Use: Use it to choose one value from a short, fixed list. - Avoid: Do not use it for long searchable lists or multi-selection. - Accessibility: Keep the native select as the only interactive element and hide its decorative icon. - States: `default` (fixture), `focus-visible` (interactive), `disabled` (fixture) - Related components: `field`, `label`, `input` - Dependencies: `@phosphor-icons/react` ### Pagination (`pagination`) Maturity: **candidate** · Category: **navigation** Navigates a collection from one connected page rail. - Use: Use it when a collection has multiple URL-addressable pages. - Avoid: Do not use it for slides or in-page tabs. - Accessibility: Uses a named nav, real links, aria-current, and disabled boundaries. - States: `default` (fixture), `current` (fixture), `boundary` (fixture), `collapsed` (fixture) - Related components: `data-table`, `breadcrumb`, `text-link` - Dependencies: `@phosphor-icons/react` ### Panel (`panel`) Maturity: **candidate** · Category: **structure** Structures related information and actions within one clear boundary. - Use: Use it when a settings group or summary module needs a genuine independent boundary. - Avoid: Do not wrap every section or list row, and do not nest Panels inside Panels. - Accessibility: Name independent regions with aria-label or aria-labelledby and keep heading levels consistent with the document. - States: `default` (fixture), `subtle` (fixture), `inverse` (fixture), `action` (fixture) - Related components: `separator`, `button`, `status-label` ### Popover (`popover`) Maturity: **candidate** · Category: **overlay** Opens compact information or controls beside the current context. - Use: Use it for supporting tasks such as filters or compact settings. - Avoid: Use Dialog, Alert Dialog, or Dropdown Menu for long forms, confirmations, or command lists. - Accessibility: Names the supporting surface and preserves Escape dismissal and focus restoration. - States: `closed` (fixture), `open` (interactive) - Related components: `dropdown-menu`, `dialog`, `tooltip` - Dependencies: `radix-ui` ### Progress (`progress`) Maturity: **candidate** · Category: **feedback** Shows measurable completion or an indeterminate connection state. - Use: Use it for uploads, processing, or synchronization that takes time. - Avoid: Do not use it for instant actions or final success status. - Accessibility: Connects native progress with a visible label and never invents a numeric value. - States: `determinate` (fixture), `indeterminate` (fixture), `reduced-motion` (environment) - Related components: `spinner`, `skeleton`, `status-label` ### Radio Group (`radio-group`) Maturity: **candidate** · Category: **selection** Selects exactly one value from a named group. - Use: Use it when a short list of options should stay visible for comparison. - Avoid: Use Native Select when space is tight or the list is long. - Accessibility: Keeps a named native radio set and communicates selection with square outer and inner indicators. - States: `default` (fixture), `selected` (fixture), `controlled` (interactive), `disabled` (fixture) - Related components: `checkbox`, `native-select` ### Segmented Control (`segmented-control`) Maturity: **candidate** · Category: **selection** Selects one value from two or more short options. - Use: Use it to switch short peer values such as locale, view, or status. - Avoid: Use Radio Group or Select for verbose or numerous options. - Accessibility: Provides radiogroup and radio semantics, aria-checked, and arrow-key roving focus. - States: `default` (fixture), `three-options` (fixture), `focus-visible` (interactive), `selected` (fixture), `disabled` (fixture), `reduced-motion` (environment) - Related components: `radio-group`, `tabs` - Dependencies: `motion` ### Select (`select`) Maturity: **candidate** · Category: **form** Navigates a longer option list by keyboard or pointer. - Use: Use it when options need richer states and controlled popup placement. - Avoid: Use Native Select for short lists or when the platform picker is preferable. - Accessibility: Provide a label and preserve arrow selection, disabled options, Escape dismissal, and focus return. - States: `default` (fixture), `open` (interactive), `disabled` (fixture) - Related components: `field`, `native-select`, `dropdown-menu` - Dependencies: `@phosphor-icons/react`, `radix-ui` ### Separator (`separator`) Maturity: **candidate** · Category: **structure** Creates a visual or semantic boundary between content. - Use: Use it when spacing alone cannot distinguish rows or sections. - Avoid: Do not box every element or repeat rules as decoration. - Accessibility: Hide it by default and expose a separator only when the boundary carries meaning. - States: `decorative` (fixture), `horizontal` (fixture), `vertical` (fixture) - Related components: `empty-state` ### Side Panel (`side-panel`) Maturity: **candidate** · Category: **overlay** Opens a larger workspace from a viewport edge without leaving the page. - Use: Use it for settings, details, or editing that need more room than a Popover. - Avoid: Do not confine a primary page flow or complex multi-step task to a panel. - Accessibility: Preserves Dialog title, description, focus trap, Escape dismissal, and focus restoration. - States: `closed` (fixture), `open` (interactive) - Related components: `dialog`, `popover`, `panel` - Dependencies: `@phosphor-icons/react`, `radix-ui` ### Skeleton (`skeleton`) Maturity: **candidate** · Category: **feedback** Reserves content structure while data is loading. - Use: Use it for brief loading when the final layout shape is known. - Avoid: Do not replace progress feedback or an empty state with a skeleton. - Accessibility: Always hide it from assistive technology and announce loading separately. - States: `loading` (fixture), `reduced-motion` (environment) - Related components: `empty-state` ### Spinner (`spinner`) Maturity: **candidate** · Category: **feedback** Signals indeterminate progress as one gap travels around a stationary square perimeter. - Use: Use it inside a button or compact inline task. - Avoid: Use Progress for measurable work and Skeleton for page loading. - Accessibility: Provides a named status and hides the stationary square track as presentation. - States: `compact` (fixture), `default` (fixture), `reduced-motion` (environment) - Related components: `button`, `progress`, `skeleton` ### Status Label (`status-label`) Maturity: **candidate** · Category: **feedback** Shows a real entity state with a small color square and concise text. - Use: Use it for static document or media lifecycle metadata. - Avoid: Do not use it as an action, filter, long explanation, or live error. - Accessibility: Always provide explicit status text that remains clear without color. - States: `neutral` (fixture), `info` (fixture), `success` (fixture), `warning` (fixture), `error` (fixture) - Related components: `alert`, `panel`, `toast` ### Switch (`switch`) Maturity: **candidate** · Category: **selection** Turns one immediately applied setting on or off. - Use: Use it for a binary setting that takes effect immediately. - Avoid: Use Checkbox when consent is only committed on form submission. - Accessibility: Preserves native checkbox behavior and a stable label; tone applies only to the checked surface. - States: `off` (fixture), `on` (fixture), `focus-visible` (interactive), `disabled` (fixture) - Related components: `checkbox`, `segmented-control` ### Table (`table`) Maturity: **candidate** · Category: **content** Presents information that must be compared across native table rows and columns. - Use: Use it to compare the same attributes, such as status, name, or date, across records. - Avoid: Use Item for one record's details or a list whose sequence matters more than column comparison. - Accessibility: Preserves native caption, thead, tbody, and scoped header semantics. - States: `default` (fixture), `overflow` (environment) - Related components: `data-table`, `item`, `separator` ### Tabs (`tabs`) Maturity: **candidate** · Category: **disclosure** Switches between peer panels within one context. - Use: Use it for quickly switching between a few peer views. - Avoid: Do not use it for sequential steps or independent page navigation. - Accessibility: Preserves tablist, tab, tabpanel relationships and arrow-key roving focus. - States: `default` (fixture), `selected` (fixture), `disabled` (fixture) - Related components: `segmented-control`, `accordion` - Dependencies: `radix-ui` ### Text Link (`text-link`) Maturity: **stable** · Category: **navigation** A reusable link that pairs text with an arrow toward the next destination. - Use: Use it at the end of a section or row for lightweight onward navigation. - Avoid: Do not use it for primary submission actions or icon-only controls. - Accessibility: The link text must identify its destination; treat the arrow as decorative. - States: `default` (fixture), `hover` (interactive), `focus-visible` (interactive), `visited` (interactive) - Related components: `button-link` - Dependencies: `@phosphor-icons/react` ### Textarea (`textarea`) Maturity: **candidate** · Category: **form** Accepts longer multiline text. - Use: Use it for values that need line breaks, such as inquiries or summaries. - Avoid: Do not use it as a code editor or for single-line values. - Accessibility: Associate a visible label and expose length guidance as a description when needed. - States: `default` (fixture), `focus-visible` (interactive), `invalid` (fixture) - Related components: `field`, `label`, `input` ### Toast (`toast`) Maturity: **candidate** · Category: **feedback** Reports a brief result through one application-wide queue. - Use: Use it for brief save, upload, or undo outcomes. - Avoid: Use Alert or Alert Dialog for persistent errors or required decisions. - Accessibility: Announces routine results as status, errors as alert, and localizes dismissal. - States: `success` (interactive), `error` (interactive), `action` (interactive), `queued` (interactive), `persistent` (interactive) - Related components: `alert`, `status-label`, `spinner` - Dependencies: `radix-ui` ### Tooltip (`tooltip`) Maturity: **candidate** · Category: **overlay** Provides a short supporting description on hover and focus. - Use: Use it to clarify controls whose visible name, such as an icon, is insufficient. - Avoid: Do not rely on it for essential information, long copy, or touch-only actions. - Accessibility: Opens on keyboard focus as well as hover and is associated as the trigger description. - States: `closed` (fixture), `open` (interactive) - Related components: `button` - Dependencies: `radix-ui` ## Recipes ### Collection state surface (`collection-state-surface`) Category: **system-state** Explains loading, results, empty, and error states consistently in one collection surface. - Use: Use when a table or list waits for asynchronous data and has multiple outcomes. - Avoid: Do not use for immediate static content or one form-submission result. - Accessibility: Name the state and next action in text without announcing loading or errors twice. - Components: `panel`, `table`, `item`, `pagination`, `skeleton`, `empty-state`, `alert`, `status-label`, `button` - Related Patterns: `collection-row`, `system-states`, `responsive-collapse` - States: `loading` (fixture), `populated` (fixture), `empty` (fixture), `error` (fixture) - Responsive behavior: - On small screens, keep essential comparisons and reflow the rest into Item rows. - Never hide the state title or retry action behind horizontal overflow. ```tsx import { Item, ItemActions, ItemContent, ItemTitle, } from "@/components/ui/item" import { Pagination, PaginationContent, PaginationItem, PaginationLink, } from "@/components/ui/pagination" import { Panel, PanelContent, PanelHeader, PanelTitle } from "@/components/ui/panel" import { StatusLabel } from "@/components/ui/status-label" import { Table, TableBody, TableCell, TableRow } from "@/components/ui/table" Documents Operations policy Published
Operations policy Published 1
``` ### Document publishing toolbar (`document-publishing-toolbar`) Category: **action** Combines document status, saving, and publishing into one predictable workflow. - Use: Use for document work with a clear order and priority, such as saving and publishing. - Avoid: Do not use for unrelated actions or a form with one simple submit action. - Accessibility: Expose status in text and preserve keyboard order across save, publish, and more options. - Components: `button-group`, `button`, `dropdown-menu`, `status-label` - Related Patterns: `document-surface`, `responsive-collapse` - States: `draft` (fixture), `publish-options` (interactive), `publishing` (fixture) - Responsive behavior: - On small screens, place status above a full-width action group. - Keep save, publish, and more-options order at every viewport size. ```tsx import { Button } from "@/components/ui/button" import { ButtonGroup, ButtonGroupSeparator } from "@/components/ui/button-group" import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu" import { StatusLabel } from "@/components/ui/status-label"
Draft Schedule publication Copy preview link
``` ### Document settings form (`document-settings-form`) Category: **form** Connects document metadata and publishing settings in one meaningful form structure. - Use: Use when editing related fields and immediately applied settings as one task. - Avoid: Do not group unrelated settings or use it as a read-only summary. - Accessibility: Name the task with fieldset and legend, and connect all guidance and errors to their fields. - Components: `field`, `input`, `native-select`, `checkbox`, `switch`, `alert` - Related Patterns: `document-surface`, `responsive-collapse` - States: `default` (fixture), `invalid` (fixture), `disabled` (fixture), `saving` (fixture) - Responsive behavior: - On small screens, collapse horizontal fields into one label-then-input column. - Keep descriptions and errors immediately below their related input. ```tsx import { Checkbox } from "@/components/ui/checkbox" import { Field, FieldGroup, FieldLabel, FieldLegend, FieldSet, } from "@/components/ui/field" import { Input } from "@/components/ui/input" import { NativeSelect } from "@/components/ui/native-select" import { Switch } from "@/components/ui/switch"
Document settings Title Category
``` ### Search and filter field (`search-filter-field`) Category: **form** Combines a query and structured filters into one named discovery task. - Use: Use to search a document or record collection and narrow it with a small filter set. - Avoid: Do not use for a form field that selects one fixed value without search. - Accessibility: Connect label, description, and error to the query while preserving popup keyboard navigation. - Components: `field`, `input-group`, `combobox`, `alert`, `button` - Related Patterns: `collection-row`, `responsive-collapse` - States: `default` (fixture), `filters-open` (interactive), `empty` (fixture), `invalid` (fixture) - Responsive behavior: - On small screens, move filters below the query as a full-width row. - Keep the label and error associated with the same input after reflow. ```tsx import { Alert, AlertAction } from "@/components/ui/alert" import { Button } from "@/components/ui/button" import { Combobox } from "@/components/ui/combobox" import { Field, FieldDescription, FieldLabel } from "@/components/ui/field" import { InputGroup, InputGroupInput } from "@/components/ui/input-group" const statusOptions = [ { value: "all", label: "All statuses" }, { value: "draft", label: "Draft" }, { value: "published", label: "Published" }, ]
Search documents Search titles and content. Filter by document status Clear the query or adjust the status filter.
``` ## Composition and responsive patterns ### Collection row (`collection-row`) A full-width row separated by space and one-pixel rules. - Keep rules and spacing between items instead of wrapping each item in a card. - Align name, description, and status or action to shared columns. - Do not animate padding on hover. - Related components: `button`, `separator`, `status-label`, `text-link` ### Contrast band (`contrast-band`) A restrained Ink surface divides the flow of the light public theme. - Use a dark band only for a clear content shift, such as the company statement. - Use white for primary text and Blue Light for short highlights. - Do not restore legacy Page Navy as the default surface for new public pages. - Related components: `logo`, `button-link`, `text-link` ### Document surface (`document-surface`) A shared shell and reading rhythm connect document indices and detail pages. - Keep body measure, heading levels, dates, and metadata placement consistent. - Use Code Block for multiline code and distinguish it from inline identifiers. - Use direct links between document indices and reading surfaces. - Related components: `field`, `code-block`, `panel`, `separator`, `text-link` ### Editorial heading (`editorial-heading`) A short heading and only the necessary copy establish a section's purpose. - Do not stack an eyebrow, number, and subtitle by default. - Constrain heading and description measures separately to clarify hierarchy. - Add a Text Link only when the section needs an onward destination. - Related components: `text-link` ### Responsive collapse (`responsive-collapse`) Desktop relationships become a one-column reading order on small screens. - Stack complex grids at 1080px and simplify navigation and actions at 720px. - Reorder the same content for reading instead of shrinking a desktop diagram. - Keep a 44px target area on small screens. - Related components: `button`, `button-group`, `field`, `segmented-control` ### Selected work (`selected-work`) An editorial module pairing a real image with verified project copy. - Use real images from public and never fabricate a product screen. - Show product status and destinations only when current data provides them. - Provide previous and next actions as named, keyboard-operable buttons. - Related components: `button`, `segmented-control`, `text-link` ### Site chrome (`site-chrome`) The existing Site Header and Footer frame every public surface. - Do not add a second fixed navbar inside a page. - Keep logo, locale, search, and document navigation in their established chrome positions. - Place page-local navigation inside the content shell. - Related components: `logo`, `segmented-control`, `button`, `text-link` ### System states (`system-states`) Loading, empty, and error states share one visual and verbal grammar. - Name the state and the next available action in short copy. - Provide a retry action for errors when recovery is available. - Do not fill empty states with invented example data. - Related components: `alert`, `button`, `empty-state`, `panel`, `skeleton`, `status-label`, `text-link` ## Public machine resources - AI context bundle: https://www.laflabs.co/design/context.json - Provider-neutral guide: https://www.laflabs.co/design/guide.md - Versioned tokens: https://www.laflabs.co/design/tokens.json - Skill entry point: https://www.laflabs.co/design/skill/SKILL.md - Skill foundations: https://www.laflabs.co/design/skill/references/foundations.md - Skill components: https://www.laflabs.co/design/skill/references/components.md - Skill patterns: https://www.laflabs.co/design/skill/references/patterns.md - Skill tokens: https://www.laflabs.co/design/skill/references/tokens.json - Skill archive: https://www.laflabs.co/design/skill.zip - Source repository: https://github.com/laflabs-inc/homepage