This guide is for AI agents (Claude, Cursor, Copilot, Codex, ...) building interfaces with GNexus UI Kit — in Vue projects, plain HTML pages, or inside this repository.
It answers the two most common failure modes:
Before writing ANY markup, check the component selection table (or
docs/catalog.json). If a component exists for the need, use it. Do not hand-roll buttons, modals, tabs, toasts, forms, badges or tables.
Raw markup is acceptable only for layout wrappers and content with no adapter component yet.
import "gnexus-ui-kit/dist/css/kit.css"; import "gnexus-ui-kit/dist/assets/fonts/phosphor-icons/src/css/icons.css";
Vue: use the adapter (gnexus-ui-kit/vue) — see docs/vue/ai-usage-guide.md for the full Vue contract. Vanilla JS: the bundle publishes GNexusUIKit.* on window — see docs/javascript.md.
Every mapping below is generated from docs/catalog.json — the single source of truth. If your need is not in this table, search docs/catalog.json before inventing markup.
| Need | Use | When |
|---|---|---|
| Button | GnButton |
Any clickable command or submit action |
| Icon-only button | GnIconButton |
Action that shows only an icon (always pass label for accessibility) |
| Copy button | GnCopyButton |
Copy-to-clipboard action with built-in success feedback |
| Status label | GnBadge |
Small colored status text (active, pending, failed) — never a hand-styled span |
| Message block | GnAlert |
Inline info/warning/error message inside page content |
| Card / panel | GnCard |
Framed content block with optional title and footer |
| Horizontal card | GnHorizontalCard |
Media-left preview card (image + linked title) |
| Login card | GnLoginCard |
Username/password sign-in form |
| User card | GnUserCard |
Person or account profile block with avatar, email and role |
| Page title bar | GnPageHeader |
Screen-level title with kicker, subtitle, meta and action buttons |
| Text field | GnInput |
Single-line text input with label, icon and validation state |
| Textarea | GnTextarea |
Multiline text input |
| Select dropdown | GnSelect |
Choose one option from a short list via native dropdown |
| Checkbox | GnCheckbox |
Boolean opt-in/opt-out choice |
| Toggle switch | GnSwitch |
Instant on/off setting toggle |
| Radio | GnRadio / GnRadioGroup |
Single choice from a small, fully visible option set |
| Range slider | GnRange |
Numeric value picked on a min–max scale |
| File upload | GnFileUpload |
File picker with previews; it owns preview object URLs |
| Searchable select | GnCombobox |
Choose one option from a large or filterable list |
| Tag / multi-value input | GnTagInput |
Enter multiple free-form values as chips |
| Tabs | GnTabs |
Switch between views within one page |
| Router tabs | GnRouterTabs |
Tabs mapped to vue-router routes |
| Accordion | GnAccordion |
Collapsible disclosure groups |
| Modal dialog | GnModal |
Blocking dialog; Escape, focus trap and focus return are handled for you |
| Side drawer | GnDrawer |
Slide-in panel for details, quick edit or secondary flows |
| Toasts | GnToastProvider + useToast |
Transient global notification; one toast at a time by design |
| Confirm dialog | GnConfirmDialog |
Yes/no confirmation before a destructive or important action |
| Table | GnTable |
Structured data rows with per-cell customization slots |
| Toolbar | GnToolbar |
Title/meta + action buttons row above content |
| Input group | GnInputGroup |
Input with prefix/suffix addon or embedded action button |
| Search field | GnSearchField |
Search input with clear button |
| Pagination | GnPagination |
Page switcher for tables and lists |
| Empty state | GnEmptyState |
No-data placeholder with icon, text and actions |
| Skeleton loader | GnSkeleton |
Loading placeholder blocks while content loads |
| Key-value list | GnDescriptionList |
Read-only key-value metadata pairs |
| Progress bar | GnProgress |
Determinate progress from 0 to max |
| Usage meter card | GnUsageMeter |
Limit/quota usage card with progress bar |
| Staged progress | GnProgressStages |
Segmented progress across named stages |
| Wizard steps | GnSteps |
Step-by-step wizard flow indicator (horizontal or vertical) |
| Chip / tag | GnChip |
Small label that can be selectable or removable |
| Chip group | GnChipGroup |
Row/wrap container for a group of chips |
| Avatar | GnAvatar |
User/entity avatar from image, initials or icon, with optional status |
| Identity row | GnIdentity |
Compact avatar + title + meta row |
| Avatar stack | GnAvatarStack |
Overlapping group of avatars |
| Timeline | GnTimeline |
Vertical event history with state markers |
| Activity log | GnActivityLog |
Compact audit or job log rows |
| Basic list | GnList |
Simple item list |
| Definition list | GnDefinitionList |
Term/description pairs |
| Action list | GnActionList |
List of clickable actions |
| Loader / spinner | GnLoader |
Indeterminate loading spinner |
| Status card | GnStatusCard |
Card communicating a state (success/warning/error/info) |
| Metric card | GnMetricCard |
KPI number with delta and meta |
| Action card | GnActionCard |
Card with text and action buttons |
| Dropdown menu | GnDropdown |
Menu of actions revealed from a trigger button |
| Popover panel | GnPopover |
Small anchored panel with title and text |
| Tooltip | GnTooltip |
Short hover hint |
| Navigation list | GnNavList |
Vertical navigation links list (router-aware) |
| App shell | GnNavigationShell |
Whole-app topbar/drawer/footer navigation frame |
primary, secondary, accent, success, warning, danger, error, info. Never invent a variant name (danger and error render the same in most components).ph class. Vue props: icon="ph-house" (prefix required). Raw HTML: <i class="ph ph-house"></i>.$surface-panel-muted, $color-text-light, $color-primary, $color-secondary, $color-success/warning/error/info. In plain CSS (no build step): the tokens are exposed as custom properties in kit.css — var(--gn-color-secondary), var(--gn-surface-panel-muted), var(--gn-border-width-accent), var(--gn-space-4), var(--gn-motion-base), ... — plus the kit's component and utility classes (p-*, m-*, g-*, row, d-flex, text-*) instead of restyling.$space-1 … $space-12 scale, never arbitrary pixel values.@include focus_ring in SCSS).@include hover_touch so touch devices fall back to :active.$motion-fast (0.15s) / $motion-base (0.2s) / $motion-slow (0.28s) with ease. No decorative animation.If — and only if — the catalog has no component for the need, build one, but it must look native. Checklist:
@include hard_panel — $surface-panel-muted background, 2px solid border ($border-width-base), light border-radius ($border-radius-md, 6px).@include hard_panel($border-color-muted, $border-width-accent) (6px left border).$font-size-sm, $font-weight-bold, text-transform: uppercase). No hero-size headings inside panels.$color-text-light for primary text, $color-text-medium for secondary/meta. Meta text uses $font-size-xs/$font-size-sm.font-family.@include focus_ring on :focus-visible, @include hover_touch for hover affordances, transitions on $motion-fast/$motion-base.<i class="ph ph-name"></i>, sizes from $icon-size-xs … $icon-size-xl.$color-success, $color-warning, $color-error, $color-info — the same four the kit's badges/alerts/status cards use.Do (matches the kit's own panels):
.my-widget {
@include hard_panel($border-color-muted, $border-width-accent);
padding: $space-4;
transition-duration: $motion-base;
transition-property: border-color;
transition-timing-function: $motion-ease;
@include hover_touch {
border-color: $color-secondary;
}
&:focus-visible {
@include focus_ring;
}
}
.my-widget-title {
font-size: $font-size-sm;
font-weight: $font-weight-bold;
text-transform: uppercase;
}
Don't (the classic drift):
// WRONG: invented palette, oversized rounding, random spacing, no focus ring
.my-widget {
background: #1a1b26;
border: 1px solid #333;
border-radius: 14px;
padding: 13px;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
}
Full token reference: docs/style-guide.md. In plain CSS (no SCSS build) the same tokens are available as var(--gn-*) custom properties — see CSS custom properties below; the mapping is 1:1 ($color-secondary → --gn-color-secondary, $space-4 → --gn-space-4).
Add this block to the consuming project's CLAUDE.md / AGENTS.md (whichever your agent reads), so the agent knows the kit exists:
## GNexus UI Kit
This project uses GNexus UI Kit (npm: `gnexus-ui-kit`). Rules:
- Before writing ANY UI markup, check the component catalog in
`node_modules/gnexus-ui-kit/docs/catalog.json` (columns: need, component,
props, useWhen). If a component exists for the need, use it.
- In Vue: import components from `gnexus-ui-kit/vue` (GnButton, GnModal, ...).
In vanilla HTML: use the kit's documented classes, not custom lookalikes.
- Icons: Phosphor only — `icon="ph-house"` in Vue, `<i class="ph ph-house"></i>` in HTML.
- Variants: only `primary, secondary, accent, success, warning, danger, error, info`.
- Custom components must follow the GNexus recipe:
`node_modules/gnexus-ui-kit/docs/ai-guide.md` ("Building a custom component").
- Full agent guide: `node_modules/gnexus-ui-kit/docs/ai-guide.md`
kit.css publishes the design tokens on :root as --gn-* custom properties, so plain-CSS consumers (no SCSS build) style on-palette without hex values:
.my-widget {
background: var(--gn-surface-panel-muted);
border: var(--gn-border-width-base) var(--gn-border-style-base) var(--gn-border-color-muted);
border-left-width: var(--gn-border-width-accent);
padding: var(--gn-space-4);
transition-duration: var(--gn-motion-base);
}
Available groups: colors (--gn-color-*, 14), surfaces (--gn-surface-*), borders (--gn-border-*), focus (--gn-focus-*), motion (--gn-motion-*), typography (--gn-font-*, --gn-line-height-*), spacing (--gn-space-0 … --gn-space-12). The SCSS tokens remain the source of truth.
When working inside this repo, follow CLAUDE.md — it carries the repo workflow rules (demo sync, build verification, screenshot policy) on top of everything above.