@usevyre/ai-context 1.0.1 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/anti-patterns.json +106 -1
- package/dist/cheat-sheets/buttongroup.md +42 -0
- package/dist/cheat-sheets/combobox.md +37 -0
- package/dist/cheat-sheets/datagrid.md +44 -0
- package/dist/cheat-sheets/index.md +6 -0
- package/dist/cheat-sheets/tag.md +46 -0
- package/dist/cheat-sheets/taggroup.md +33 -0
- package/dist/cheat-sheets/tagsinput.md +35 -0
- package/dist/claude-context.md +198 -1
- package/dist/copilot-instructions.md +198 -1
- package/dist/cursor-rules.md +72 -1
- package/dist/full-context.md +197 -0
- package/dist/index.js +1493 -113
- package/dist/schema.json +368 -5
- package/dist/version-info.json +112 -65
- package/dist/windsurf-rules.md +198 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
// @usevyre/ai-context v1.
|
|
1
|
+
// @usevyre/ai-context v1.1.0
|
|
2
2
|
// Auto-generated — do not edit directly. Edit src/schema/components.json instead.
|
|
3
3
|
|
|
4
|
-
export const version = "1.
|
|
4
|
+
export const version = "1.1.0";
|
|
5
5
|
|
|
6
6
|
export const fullContext = `# useVyre Design System — AI Context
|
|
7
7
|
# Version: 0.2.0
|
|
@@ -886,6 +886,188 @@ import { Text, Heading, Lead, Code, Blockquote } from "@usevyre/react"
|
|
|
886
886
|
|
|
887
887
|
---
|
|
888
888
|
|
|
889
|
+
### ButtonGroup
|
|
890
|
+
|
|
891
|
+
Groups multiple Button components into one visual unit (toolbar, segmented control). Pure layout — no internal state.
|
|
892
|
+
|
|
893
|
+
\`\`\`tsx
|
|
894
|
+
import { ButtonGroup, Button } from "@usevyre/react"
|
|
895
|
+
|
|
896
|
+
// Props:
|
|
897
|
+
// orientation = "horizontal" | "vertical" (default: horizontal)
|
|
898
|
+
// attached = boolean (default: false)
|
|
899
|
+
// size = "sm" | "md" | "lg" | "icon"
|
|
900
|
+
|
|
901
|
+
// Examples:
|
|
902
|
+
<ButtonGroup attached>
|
|
903
|
+
<Button variant="secondary">Day</Button>
|
|
904
|
+
<Button variant="secondary">Week</Button>
|
|
905
|
+
<Button variant="secondary">Month</Button>
|
|
906
|
+
</ButtonGroup>
|
|
907
|
+
<ButtonGroup orientation="vertical" attached>
|
|
908
|
+
<Button variant="secondary">Top</Button>
|
|
909
|
+
<Button variant="secondary">Bottom</Button>
|
|
910
|
+
</ButtonGroup>
|
|
911
|
+
\`\`\`
|
|
912
|
+
|
|
913
|
+
**Common mistakes:**
|
|
914
|
+
- ❌ \`ButtonGroup variant="..."\` → Set variant on each <Button> inside the group
|
|
915
|
+
- ❌ \`ButtonGroup without Button children\` → Place <Button> elements as direct children
|
|
916
|
+
|
|
917
|
+
---
|
|
918
|
+
|
|
919
|
+
### TagsInput
|
|
920
|
+
|
|
921
|
+
Multi-tag input. Type and press Enter or comma to add a tag, click x to remove, Backspace on empty input removes the last tag. Controlled.
|
|
922
|
+
|
|
923
|
+
\`\`\`tsx
|
|
924
|
+
import { TagsInput } from "@usevyre/react"
|
|
925
|
+
|
|
926
|
+
// Props:
|
|
927
|
+
// value = string[]
|
|
928
|
+
// onChange = (tags: string[]) => void
|
|
929
|
+
// placeholder = string
|
|
930
|
+
// disabled = boolean (default: false)
|
|
931
|
+
// max = number
|
|
932
|
+
// size = "sm" | "md" | "lg" (default: md)
|
|
933
|
+
|
|
934
|
+
// Examples:
|
|
935
|
+
const [tags, setTags] = useState<string[]>([]);
|
|
936
|
+
<TagsInput value={tags} onChange={setTags} placeholder="Add a tag…" />
|
|
937
|
+
<TagsInput value={tags} onChange={setTags} max={5} />
|
|
938
|
+
\`\`\`
|
|
939
|
+
|
|
940
|
+
**Common mistakes:**
|
|
941
|
+
- ❌ \`TagsInput value={string}\` → Pass an array: value={['react','vue']}
|
|
942
|
+
- ❌ \`TagsInput without onChange\` → Provide value and onChange (React) or v-model (Vue)
|
|
943
|
+
|
|
944
|
+
---
|
|
945
|
+
|
|
946
|
+
### Combobox
|
|
947
|
+
|
|
948
|
+
Searchable single-select dropdown with typeahead filtering and keyboard navigation. Use when the list is long enough to need search. Differs from Select (no search) and Command (palette).
|
|
949
|
+
|
|
950
|
+
\`\`\`tsx
|
|
951
|
+
import { Combobox } from "@usevyre/react"
|
|
952
|
+
|
|
953
|
+
// Props:
|
|
954
|
+
// options = { value: string; label: string; disabled?: boolean }[]
|
|
955
|
+
// value = string | null
|
|
956
|
+
// onChange = (value: string | null) => void
|
|
957
|
+
// placeholder = string (default: "Search…")
|
|
958
|
+
// disabled = boolean (default: false)
|
|
959
|
+
// size = "sm" | "md" | "lg" (default: md)
|
|
960
|
+
// emptyText = string (default: "No results")
|
|
961
|
+
|
|
962
|
+
// Examples:
|
|
963
|
+
const [lang, setLang] = useState<string | null>(null);
|
|
964
|
+
<Combobox
|
|
965
|
+
options={[{ value: "ts", label: "TypeScript" }, { value: "go", label: "Go" }]}
|
|
966
|
+
value={lang}
|
|
967
|
+
onChange={setLang}
|
|
968
|
+
placeholder="Search language…"
|
|
969
|
+
/>
|
|
970
|
+
\`\`\`
|
|
971
|
+
|
|
972
|
+
**Common mistakes:**
|
|
973
|
+
- ❌ \`Combobox value=""\` → Use value={null} for no selection
|
|
974
|
+
- ❌ \`Combobox options={string[]}\` → Use [{ value: 'ts', label: 'TypeScript' }]
|
|
975
|
+
- ❌ \`Using Combobox for command palette\` → Use Command for command palettes
|
|
976
|
+
|
|
977
|
+
---
|
|
978
|
+
|
|
979
|
+
### DataGrid
|
|
980
|
+
|
|
981
|
+
Table with built-in column sorting, loading skeletons, and empty state. Filtering and pagination are out of scope — compose with the Pagination component.
|
|
982
|
+
|
|
983
|
+
\`\`\`tsx
|
|
984
|
+
import { DataGrid } from "@usevyre/react"
|
|
985
|
+
|
|
986
|
+
// Props:
|
|
987
|
+
// columns = { key: string; label: string; sortable?: boolean; width?: string }[]
|
|
988
|
+
// rows = Record<string, unknown>[]
|
|
989
|
+
// sortKey = string
|
|
990
|
+
// sortDir = "asc" | "desc"
|
|
991
|
+
// onSort = (key: string, dir: 'asc' | 'desc') => void
|
|
992
|
+
// loading = boolean (default: false)
|
|
993
|
+
// emptyText = string (default: "No data")
|
|
994
|
+
// stickyHeader = boolean (default: false)
|
|
995
|
+
|
|
996
|
+
// Examples:
|
|
997
|
+
const cols = [{ key: "name", label: "Name", sortable: true }];
|
|
998
|
+
<DataGrid
|
|
999
|
+
columns={cols}
|
|
1000
|
+
rows={people}
|
|
1001
|
+
sortKey={sortKey}
|
|
1002
|
+
sortDir={sortDir}
|
|
1003
|
+
onSort={(k, d) => { setSortKey(k); setSortDir(d); }}
|
|
1004
|
+
/>
|
|
1005
|
+
<DataGrid columns={cols} rows={[]} loading />
|
|
1006
|
+
\`\`\`
|
|
1007
|
+
|
|
1008
|
+
**Common mistakes:**
|
|
1009
|
+
- ❌ \`DataGrid expecting built-in pagination\` → Slice rows yourself and use the Pagination component
|
|
1010
|
+
- ❌ \`DataGrid expecting built-in filtering\` → Filter the rows array before passing it in
|
|
1011
|
+
- ❌ \`sortable without onSort\` → Handle onSort and sort the rows array in your state
|
|
1012
|
+
|
|
1013
|
+
---
|
|
1014
|
+
|
|
1015
|
+
### Tag
|
|
1016
|
+
|
|
1017
|
+
Standalone display tag/chip for categories, labels, or filter chips. NOT an input — for tag input use TagsInput. Group multiple with TagGroup.
|
|
1018
|
+
|
|
1019
|
+
\`\`\`tsx
|
|
1020
|
+
import { Tag } from "@usevyre/react"
|
|
1021
|
+
|
|
1022
|
+
// Props:
|
|
1023
|
+
// variant = "default" | "accent" | "danger" (default: default)
|
|
1024
|
+
// size = "sm" | "md" | "lg" (default: md)
|
|
1025
|
+
// onRemove = () => void
|
|
1026
|
+
// onClick = () => void
|
|
1027
|
+
// disabled = boolean (default: false)
|
|
1028
|
+
|
|
1029
|
+
// Examples:
|
|
1030
|
+
<TagGroup>
|
|
1031
|
+
<Tag>Design</Tag>
|
|
1032
|
+
<Tag variant="accent">Featured</Tag>
|
|
1033
|
+
<Tag>Engineering</Tag>
|
|
1034
|
+
</TagGroup>
|
|
1035
|
+
<Tag onRemove={() => removeFilter("react")}>react</Tag>
|
|
1036
|
+
<Tag onClick={() => toggleFilter("vue")}>vue</Tag>
|
|
1037
|
+
\`\`\`
|
|
1038
|
+
|
|
1039
|
+
**Common mistakes:**
|
|
1040
|
+
- ❌ \`Tag variant="success"\` → Use Badge for success/warning/teal status colors; Tag is for categories/filters
|
|
1041
|
+
- ❌ \`Using Tag for tag input\` → Use TagsInput for adding/removing tags via keyboard
|
|
1042
|
+
- ❌ \`Tag size="xl"\` → Use size="lg"
|
|
1043
|
+
|
|
1044
|
+
---
|
|
1045
|
+
|
|
1046
|
+
### TagGroup
|
|
1047
|
+
|
|
1048
|
+
Read-only container that lays out multiple Tag elements with automatic wrapping and consistent spacing. For tag input use TagsInput.
|
|
1049
|
+
|
|
1050
|
+
\`\`\`tsx
|
|
1051
|
+
import { TagGroup, Tag } from "@usevyre/react"
|
|
1052
|
+
|
|
1053
|
+
// Props:
|
|
1054
|
+
// gap = "sm" | "md" | "lg" (default: md)
|
|
1055
|
+
// wrap = boolean (default: true)
|
|
1056
|
+
|
|
1057
|
+
// Examples:
|
|
1058
|
+
<TagGroup gap="sm">
|
|
1059
|
+
<Tag>React</Tag>
|
|
1060
|
+
<Tag>Vue</Tag>
|
|
1061
|
+
<Tag variant="accent">TypeScript</Tag>
|
|
1062
|
+
</TagGroup>
|
|
1063
|
+
\`\`\`
|
|
1064
|
+
|
|
1065
|
+
**Common mistakes:**
|
|
1066
|
+
- ❌ \`TagGroup without Tag children\` → Place <Tag> elements as direct children
|
|
1067
|
+
- ❌ \`Using TagGroup for tag input\` → Use TagsInput for an editable tag field
|
|
1068
|
+
|
|
1069
|
+
---
|
|
1070
|
+
|
|
889
1071
|
## Hallucination Guard — Common AI Mistakes
|
|
890
1072
|
|
|
891
1073
|
The following prop values and patterns do NOT exist in useVyre.
|
|
@@ -922,6 +1104,21 @@ If you generate these, you are hallucinating.
|
|
|
922
1104
|
- ❌ \`<Toast variant="info">\` → Use variant="default"
|
|
923
1105
|
- ❌ \`<Tooltip Using Tooltip for rich content (forms, buttons, etc.)>\` → Use Popover for rich interactive content
|
|
924
1106
|
- ❌ \`<Typography Using raw <h1>, <p> tags instead of Typography components>\` → Use <Heading>, <Text>, <Lead> from @usevyre/react
|
|
1107
|
+
- ❌ \`<ButtonGroup ButtonGroup variant="...">\` → Set variant on each <Button> inside the group
|
|
1108
|
+
- ❌ \`<ButtonGroup ButtonGroup without Button children>\` → Place <Button> elements as direct children
|
|
1109
|
+
- ❌ \`<TagsInput TagsInput value={string}>\` → Pass an array: value={['react','vue']}
|
|
1110
|
+
- ❌ \`<TagsInput TagsInput without onChange>\` → Provide value and onChange (React) or v-model (Vue)
|
|
1111
|
+
- ❌ \`<Combobox Combobox value="">\` → Use value={null} for no selection
|
|
1112
|
+
- ❌ \`<Combobox Combobox options={string[]}>\` → Use [{ value: 'ts', label: 'TypeScript' }]
|
|
1113
|
+
- ❌ \`<Combobox Using Combobox for command palette>\` → Use Command for command palettes
|
|
1114
|
+
- ❌ \`<DataGrid DataGrid expecting built-in pagination>\` → Slice rows yourself and use the Pagination component
|
|
1115
|
+
- ❌ \`<DataGrid DataGrid expecting built-in filtering>\` → Filter the rows array before passing it in
|
|
1116
|
+
- ❌ \`<DataGrid sortable without onSort>\` → Handle onSort and sort the rows array in your state
|
|
1117
|
+
- ❌ \`<Tag Tag variant="success">\` → Use Badge for success/warning/teal status colors; Tag is for categories/filters
|
|
1118
|
+
- ❌ \`<Tag Using Tag for tag input>\` → Use TagsInput for adding/removing tags via keyboard
|
|
1119
|
+
- ❌ \`<Tag Tag size="xl">\` → Use size="lg"
|
|
1120
|
+
- ❌ \`<TagGroup TagGroup without Tag children>\` → Place <Tag> elements as direct children
|
|
1121
|
+
- ❌ \`<TagGroup Using TagGroup for tag input>\` → Use TagsInput for an editable tag field
|
|
925
1122
|
|
|
926
1123
|
---
|
|
927
1124
|
|
|
@@ -976,7 +1173,7 @@ alwaysApply: true
|
|
|
976
1173
|
---
|
|
977
1174
|
|
|
978
1175
|
# useVyre Design System — Cursor Rules
|
|
979
|
-
# Version: 1.
|
|
1176
|
+
# Version: 1.1.0
|
|
980
1177
|
|
|
981
1178
|
You are working in a project using the useVyre design system (@usevyre/react).
|
|
982
1179
|
Follow these rules strictly when generating any UI code.
|
|
@@ -1255,13 +1452,84 @@ Import: \`import { Text, Heading, Lead, Code, Blockquote } from "@usevyre/react"
|
|
|
1255
1452
|
Never do:
|
|
1256
1453
|
- ❌ Using raw <h1>, <p> tags instead of Typography components → ✅ Use <Heading>, <Text>, <Lead> from @usevyre/react
|
|
1257
1454
|
|
|
1455
|
+
## ButtonGroup
|
|
1456
|
+
Groups multiple Button components into one visual unit (toolbar, segmented control). Pure layout — no internal state.
|
|
1457
|
+
Import: \`import { ButtonGroup, Button } from "@usevyre/react"\`
|
|
1458
|
+
|
|
1459
|
+
Valid props:
|
|
1460
|
+
- orientation: "horizontal" | "vertical" [default: horizontal]
|
|
1461
|
+
- size: "sm" | "md" | "lg" | "icon"
|
|
1462
|
+
|
|
1463
|
+
Never do:
|
|
1464
|
+
- ❌ ButtonGroup variant="..." → ✅ Set variant on each <Button> inside the group
|
|
1465
|
+
- ❌ ButtonGroup without Button children → ✅ Place <Button> elements as direct children
|
|
1466
|
+
|
|
1467
|
+
## TagsInput
|
|
1468
|
+
Multi-tag input. Type and press Enter or comma to add a tag, click x to remove, Backspace on empty input removes the last tag. Controlled.
|
|
1469
|
+
Import: \`import { TagsInput } from "@usevyre/react"\`
|
|
1470
|
+
|
|
1471
|
+
Valid props:
|
|
1472
|
+
- size: "sm" | "md" | "lg" [default: md]
|
|
1473
|
+
|
|
1474
|
+
Never do:
|
|
1475
|
+
- ❌ TagsInput value={string} → ✅ Pass an array: value={['react','vue']}
|
|
1476
|
+
- ❌ TagsInput without onChange → ✅ Provide value and onChange (React) or v-model (Vue)
|
|
1477
|
+
|
|
1478
|
+
## Combobox
|
|
1479
|
+
Searchable single-select dropdown with typeahead filtering and keyboard navigation. Use when the list is long enough to need search. Differs from Select (no search) and Command (palette).
|
|
1480
|
+
Import: \`import { Combobox } from "@usevyre/react"\`
|
|
1481
|
+
|
|
1482
|
+
Valid props:
|
|
1483
|
+
- size: "sm" | "md" | "lg" [default: md]
|
|
1484
|
+
|
|
1485
|
+
Never do:
|
|
1486
|
+
- ❌ Combobox value="" → ✅ Use value={null} for no selection
|
|
1487
|
+
- ❌ Combobox options={string[]} → ✅ Use [{ value: 'ts', label: 'TypeScript' }]
|
|
1488
|
+
- ❌ Using Combobox for command palette → ✅ Use Command for command palettes
|
|
1489
|
+
|
|
1490
|
+
## DataGrid
|
|
1491
|
+
Table with built-in column sorting, loading skeletons, and empty state. Filtering and pagination are out of scope — compose with the Pagination component.
|
|
1492
|
+
Import: \`import { DataGrid } from "@usevyre/react"\`
|
|
1493
|
+
|
|
1494
|
+
Valid props:
|
|
1495
|
+
- sortDir: "asc" | "desc"
|
|
1496
|
+
|
|
1497
|
+
Never do:
|
|
1498
|
+
- ❌ DataGrid expecting built-in pagination → ✅ Slice rows yourself and use the Pagination component
|
|
1499
|
+
- ❌ DataGrid expecting built-in filtering → ✅ Filter the rows array before passing it in
|
|
1500
|
+
- ❌ sortable without onSort → ✅ Handle onSort and sort the rows array in your state
|
|
1501
|
+
|
|
1502
|
+
## Tag
|
|
1503
|
+
Standalone display tag/chip for categories, labels, or filter chips. NOT an input — for tag input use TagsInput. Group multiple with TagGroup.
|
|
1504
|
+
Import: \`import { Tag } from "@usevyre/react"\`
|
|
1505
|
+
|
|
1506
|
+
Valid props:
|
|
1507
|
+
- variant: "default" | "accent" | "danger" [default: default]
|
|
1508
|
+
- size: "sm" | "md" | "lg" [default: md]
|
|
1509
|
+
|
|
1510
|
+
Never do:
|
|
1511
|
+
- ❌ Tag variant="success" → ✅ Use Badge for success/warning/teal status colors; Tag is for categories/filters
|
|
1512
|
+
- ❌ Using Tag for tag input → ✅ Use TagsInput for adding/removing tags via keyboard
|
|
1513
|
+
- ❌ Tag size="xl" → ✅ Use size="lg"
|
|
1514
|
+
|
|
1515
|
+
## TagGroup
|
|
1516
|
+
Read-only container that lays out multiple Tag elements with automatic wrapping and consistent spacing. For tag input use TagsInput.
|
|
1517
|
+
Import: \`import { TagGroup, Tag } from "@usevyre/react"\`
|
|
1518
|
+
|
|
1519
|
+
Valid props:
|
|
1520
|
+
- gap: "sm" | "md" | "lg" [default: md]
|
|
1521
|
+
|
|
1522
|
+
Never do:
|
|
1523
|
+
- ❌ TagGroup without Tag children → ✅ Place <Tag> elements as direct children
|
|
1524
|
+
- ❌ Using TagGroup for tag input → ✅ Use TagsInput for an editable tag field
|
|
1525
|
+
|
|
1258
1526
|
## Token Rules
|
|
1259
1527
|
|
|
1260
1528
|
Use --vyre-color-semantic-* for all colors. Never use primitive tokens.
|
|
1261
1529
|
Use --vyre-spacing-* for all spacing. Never use raw px in component code.
|
|
1262
1530
|
Use --vyre-border-radius-* for border radius.`;
|
|
1263
1531
|
export const claudeContext = `# useVyre Design System Context
|
|
1264
|
-
# Version: 1.
|
|
1532
|
+
# Version: 1.1.0
|
|
1265
1533
|
|
|
1266
1534
|
You are working in a codebase that uses the useVyre design system.
|
|
1267
1535
|
Follow the rules below strictly when writing any UI code.
|
|
@@ -2149,6 +2417,188 @@ import { Text, Heading, Lead, Code, Blockquote } from "@usevyre/react"
|
|
|
2149
2417
|
|
|
2150
2418
|
---
|
|
2151
2419
|
|
|
2420
|
+
### ButtonGroup
|
|
2421
|
+
|
|
2422
|
+
Groups multiple Button components into one visual unit (toolbar, segmented control). Pure layout — no internal state.
|
|
2423
|
+
|
|
2424
|
+
\`\`\`tsx
|
|
2425
|
+
import { ButtonGroup, Button } from "@usevyre/react"
|
|
2426
|
+
|
|
2427
|
+
// Props:
|
|
2428
|
+
// orientation = "horizontal" | "vertical" (default: horizontal)
|
|
2429
|
+
// attached = boolean (default: false)
|
|
2430
|
+
// size = "sm" | "md" | "lg" | "icon"
|
|
2431
|
+
|
|
2432
|
+
// Examples:
|
|
2433
|
+
<ButtonGroup attached>
|
|
2434
|
+
<Button variant="secondary">Day</Button>
|
|
2435
|
+
<Button variant="secondary">Week</Button>
|
|
2436
|
+
<Button variant="secondary">Month</Button>
|
|
2437
|
+
</ButtonGroup>
|
|
2438
|
+
<ButtonGroup orientation="vertical" attached>
|
|
2439
|
+
<Button variant="secondary">Top</Button>
|
|
2440
|
+
<Button variant="secondary">Bottom</Button>
|
|
2441
|
+
</ButtonGroup>
|
|
2442
|
+
\`\`\`
|
|
2443
|
+
|
|
2444
|
+
**Common mistakes:**
|
|
2445
|
+
- ❌ \`ButtonGroup variant="..."\` → Set variant on each <Button> inside the group
|
|
2446
|
+
- ❌ \`ButtonGroup without Button children\` → Place <Button> elements as direct children
|
|
2447
|
+
|
|
2448
|
+
---
|
|
2449
|
+
|
|
2450
|
+
### TagsInput
|
|
2451
|
+
|
|
2452
|
+
Multi-tag input. Type and press Enter or comma to add a tag, click x to remove, Backspace on empty input removes the last tag. Controlled.
|
|
2453
|
+
|
|
2454
|
+
\`\`\`tsx
|
|
2455
|
+
import { TagsInput } from "@usevyre/react"
|
|
2456
|
+
|
|
2457
|
+
// Props:
|
|
2458
|
+
// value = string[]
|
|
2459
|
+
// onChange = (tags: string[]) => void
|
|
2460
|
+
// placeholder = string
|
|
2461
|
+
// disabled = boolean (default: false)
|
|
2462
|
+
// max = number
|
|
2463
|
+
// size = "sm" | "md" | "lg" (default: md)
|
|
2464
|
+
|
|
2465
|
+
// Examples:
|
|
2466
|
+
const [tags, setTags] = useState<string[]>([]);
|
|
2467
|
+
<TagsInput value={tags} onChange={setTags} placeholder="Add a tag…" />
|
|
2468
|
+
<TagsInput value={tags} onChange={setTags} max={5} />
|
|
2469
|
+
\`\`\`
|
|
2470
|
+
|
|
2471
|
+
**Common mistakes:**
|
|
2472
|
+
- ❌ \`TagsInput value={string}\` → Pass an array: value={['react','vue']}
|
|
2473
|
+
- ❌ \`TagsInput without onChange\` → Provide value and onChange (React) or v-model (Vue)
|
|
2474
|
+
|
|
2475
|
+
---
|
|
2476
|
+
|
|
2477
|
+
### Combobox
|
|
2478
|
+
|
|
2479
|
+
Searchable single-select dropdown with typeahead filtering and keyboard navigation. Use when the list is long enough to need search. Differs from Select (no search) and Command (palette).
|
|
2480
|
+
|
|
2481
|
+
\`\`\`tsx
|
|
2482
|
+
import { Combobox } from "@usevyre/react"
|
|
2483
|
+
|
|
2484
|
+
// Props:
|
|
2485
|
+
// options = { value: string; label: string; disabled?: boolean }[]
|
|
2486
|
+
// value = string | null
|
|
2487
|
+
// onChange = (value: string | null) => void
|
|
2488
|
+
// placeholder = string (default: "Search…")
|
|
2489
|
+
// disabled = boolean (default: false)
|
|
2490
|
+
// size = "sm" | "md" | "lg" (default: md)
|
|
2491
|
+
// emptyText = string (default: "No results")
|
|
2492
|
+
|
|
2493
|
+
// Examples:
|
|
2494
|
+
const [lang, setLang] = useState<string | null>(null);
|
|
2495
|
+
<Combobox
|
|
2496
|
+
options={[{ value: "ts", label: "TypeScript" }, { value: "go", label: "Go" }]}
|
|
2497
|
+
value={lang}
|
|
2498
|
+
onChange={setLang}
|
|
2499
|
+
placeholder="Search language…"
|
|
2500
|
+
/>
|
|
2501
|
+
\`\`\`
|
|
2502
|
+
|
|
2503
|
+
**Common mistakes:**
|
|
2504
|
+
- ❌ \`Combobox value=""\` → Use value={null} for no selection
|
|
2505
|
+
- ❌ \`Combobox options={string[]}\` → Use [{ value: 'ts', label: 'TypeScript' }]
|
|
2506
|
+
- ❌ \`Using Combobox for command palette\` → Use Command for command palettes
|
|
2507
|
+
|
|
2508
|
+
---
|
|
2509
|
+
|
|
2510
|
+
### DataGrid
|
|
2511
|
+
|
|
2512
|
+
Table with built-in column sorting, loading skeletons, and empty state. Filtering and pagination are out of scope — compose with the Pagination component.
|
|
2513
|
+
|
|
2514
|
+
\`\`\`tsx
|
|
2515
|
+
import { DataGrid } from "@usevyre/react"
|
|
2516
|
+
|
|
2517
|
+
// Props:
|
|
2518
|
+
// columns = { key: string; label: string; sortable?: boolean; width?: string }[]
|
|
2519
|
+
// rows = Record<string, unknown>[]
|
|
2520
|
+
// sortKey = string
|
|
2521
|
+
// sortDir = "asc" | "desc"
|
|
2522
|
+
// onSort = (key: string, dir: 'asc' | 'desc') => void
|
|
2523
|
+
// loading = boolean (default: false)
|
|
2524
|
+
// emptyText = string (default: "No data")
|
|
2525
|
+
// stickyHeader = boolean (default: false)
|
|
2526
|
+
|
|
2527
|
+
// Examples:
|
|
2528
|
+
const cols = [{ key: "name", label: "Name", sortable: true }];
|
|
2529
|
+
<DataGrid
|
|
2530
|
+
columns={cols}
|
|
2531
|
+
rows={people}
|
|
2532
|
+
sortKey={sortKey}
|
|
2533
|
+
sortDir={sortDir}
|
|
2534
|
+
onSort={(k, d) => { setSortKey(k); setSortDir(d); }}
|
|
2535
|
+
/>
|
|
2536
|
+
<DataGrid columns={cols} rows={[]} loading />
|
|
2537
|
+
\`\`\`
|
|
2538
|
+
|
|
2539
|
+
**Common mistakes:**
|
|
2540
|
+
- ❌ \`DataGrid expecting built-in pagination\` → Slice rows yourself and use the Pagination component
|
|
2541
|
+
- ❌ \`DataGrid expecting built-in filtering\` → Filter the rows array before passing it in
|
|
2542
|
+
- ❌ \`sortable without onSort\` → Handle onSort and sort the rows array in your state
|
|
2543
|
+
|
|
2544
|
+
---
|
|
2545
|
+
|
|
2546
|
+
### Tag
|
|
2547
|
+
|
|
2548
|
+
Standalone display tag/chip for categories, labels, or filter chips. NOT an input — for tag input use TagsInput. Group multiple with TagGroup.
|
|
2549
|
+
|
|
2550
|
+
\`\`\`tsx
|
|
2551
|
+
import { Tag } from "@usevyre/react"
|
|
2552
|
+
|
|
2553
|
+
// Props:
|
|
2554
|
+
// variant = "default" | "accent" | "danger" (default: default)
|
|
2555
|
+
// size = "sm" | "md" | "lg" (default: md)
|
|
2556
|
+
// onRemove = () => void
|
|
2557
|
+
// onClick = () => void
|
|
2558
|
+
// disabled = boolean (default: false)
|
|
2559
|
+
|
|
2560
|
+
// Examples:
|
|
2561
|
+
<TagGroup>
|
|
2562
|
+
<Tag>Design</Tag>
|
|
2563
|
+
<Tag variant="accent">Featured</Tag>
|
|
2564
|
+
<Tag>Engineering</Tag>
|
|
2565
|
+
</TagGroup>
|
|
2566
|
+
<Tag onRemove={() => removeFilter("react")}>react</Tag>
|
|
2567
|
+
<Tag onClick={() => toggleFilter("vue")}>vue</Tag>
|
|
2568
|
+
\`\`\`
|
|
2569
|
+
|
|
2570
|
+
**Common mistakes:**
|
|
2571
|
+
- ❌ \`Tag variant="success"\` → Use Badge for success/warning/teal status colors; Tag is for categories/filters
|
|
2572
|
+
- ❌ \`Using Tag for tag input\` → Use TagsInput for adding/removing tags via keyboard
|
|
2573
|
+
- ❌ \`Tag size="xl"\` → Use size="lg"
|
|
2574
|
+
|
|
2575
|
+
---
|
|
2576
|
+
|
|
2577
|
+
### TagGroup
|
|
2578
|
+
|
|
2579
|
+
Read-only container that lays out multiple Tag elements with automatic wrapping and consistent spacing. For tag input use TagsInput.
|
|
2580
|
+
|
|
2581
|
+
\`\`\`tsx
|
|
2582
|
+
import { TagGroup, Tag } from "@usevyre/react"
|
|
2583
|
+
|
|
2584
|
+
// Props:
|
|
2585
|
+
// gap = "sm" | "md" | "lg" (default: md)
|
|
2586
|
+
// wrap = boolean (default: true)
|
|
2587
|
+
|
|
2588
|
+
// Examples:
|
|
2589
|
+
<TagGroup gap="sm">
|
|
2590
|
+
<Tag>React</Tag>
|
|
2591
|
+
<Tag>Vue</Tag>
|
|
2592
|
+
<Tag variant="accent">TypeScript</Tag>
|
|
2593
|
+
</TagGroup>
|
|
2594
|
+
\`\`\`
|
|
2595
|
+
|
|
2596
|
+
**Common mistakes:**
|
|
2597
|
+
- ❌ \`TagGroup without Tag children\` → Place <Tag> elements as direct children
|
|
2598
|
+
- ❌ \`Using TagGroup for tag input\` → Use TagsInput for an editable tag field
|
|
2599
|
+
|
|
2600
|
+
---
|
|
2601
|
+
|
|
2152
2602
|
## Hallucination Guard — Common AI Mistakes
|
|
2153
2603
|
|
|
2154
2604
|
The following prop values and patterns do NOT exist in useVyre.
|
|
@@ -2185,6 +2635,21 @@ If you generate these, you are hallucinating.
|
|
|
2185
2635
|
- ❌ \`<Toast variant="info">\` → Use variant="default"
|
|
2186
2636
|
- ❌ \`<Tooltip Using Tooltip for rich content (forms, buttons, etc.)>\` → Use Popover for rich interactive content
|
|
2187
2637
|
- ❌ \`<Typography Using raw <h1>, <p> tags instead of Typography components>\` → Use <Heading>, <Text>, <Lead> from @usevyre/react
|
|
2638
|
+
- ❌ \`<ButtonGroup ButtonGroup variant="...">\` → Set variant on each <Button> inside the group
|
|
2639
|
+
- ❌ \`<ButtonGroup ButtonGroup without Button children>\` → Place <Button> elements as direct children
|
|
2640
|
+
- ❌ \`<TagsInput TagsInput value={string}>\` → Pass an array: value={['react','vue']}
|
|
2641
|
+
- ❌ \`<TagsInput TagsInput without onChange>\` → Provide value and onChange (React) or v-model (Vue)
|
|
2642
|
+
- ❌ \`<Combobox Combobox value="">\` → Use value={null} for no selection
|
|
2643
|
+
- ❌ \`<Combobox Combobox options={string[]}>\` → Use [{ value: 'ts', label: 'TypeScript' }]
|
|
2644
|
+
- ❌ \`<Combobox Using Combobox for command palette>\` → Use Command for command palettes
|
|
2645
|
+
- ❌ \`<DataGrid DataGrid expecting built-in pagination>\` → Slice rows yourself and use the Pagination component
|
|
2646
|
+
- ❌ \`<DataGrid DataGrid expecting built-in filtering>\` → Filter the rows array before passing it in
|
|
2647
|
+
- ❌ \`<DataGrid sortable without onSort>\` → Handle onSort and sort the rows array in your state
|
|
2648
|
+
- ❌ \`<Tag Tag variant="success">\` → Use Badge for success/warning/teal status colors; Tag is for categories/filters
|
|
2649
|
+
- ❌ \`<Tag Using Tag for tag input>\` → Use TagsInput for adding/removing tags via keyboard
|
|
2650
|
+
- ❌ \`<Tag Tag size="xl">\` → Use size="lg"
|
|
2651
|
+
- ❌ \`<TagGroup TagGroup without Tag children>\` → Place <Tag> elements as direct children
|
|
2652
|
+
- ❌ \`<TagGroup Using TagGroup for tag input>\` → Use TagsInput for an editable tag field
|
|
2188
2653
|
|
|
2189
2654
|
---
|
|
2190
2655
|
|
|
@@ -2234,7 +2699,7 @@ If you generate these, you are hallucinating.
|
|
|
2234
2699
|
\`\`\`
|
|
2235
2700
|
`;
|
|
2236
2701
|
export const windsurfRules = `# useVyre Rules for Windsurf
|
|
2237
|
-
# Version: 1.
|
|
2702
|
+
# Version: 1.1.0
|
|
2238
2703
|
|
|
2239
2704
|
# useVyre Design System — AI Context
|
|
2240
2705
|
# Version: 0.2.0
|
|
@@ -3119,46 +3584,243 @@ import { Text, Heading, Lead, Code, Blockquote } from "@usevyre/react"
|
|
|
3119
3584
|
|
|
3120
3585
|
---
|
|
3121
3586
|
|
|
3122
|
-
|
|
3587
|
+
### ButtonGroup
|
|
3123
3588
|
|
|
3124
|
-
|
|
3125
|
-
If you generate these, you are hallucinating.
|
|
3589
|
+
Groups multiple Button components into one visual unit (toolbar, segmented control). Pure layout — no internal state.
|
|
3126
3590
|
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
|
|
3135
|
-
|
|
3136
|
-
|
|
3137
|
-
|
|
3138
|
-
|
|
3139
|
-
|
|
3140
|
-
|
|
3141
|
-
|
|
3142
|
-
|
|
3143
|
-
|
|
3144
|
-
|
|
3145
|
-
|
|
3146
|
-
|
|
3147
|
-
|
|
3148
|
-
- ❌
|
|
3149
|
-
- ❌
|
|
3150
|
-
- ❌ \`<Popover placement="top-center">\` → Use placement="top" for centered placement
|
|
3151
|
-
- ❌ \`<Progress value > 100>\` → Normalize your value to 0–100 range before passing
|
|
3152
|
-
- ❌ \`<Select Passing strings directly as children>\` → Pass options={[{ value: 'a', label: 'Option A' }]}
|
|
3153
|
-
- ❌ \`<Toast Rendering <Toast> directly in JSX>\` → Use: const { toast } = useToast(); then toast({ title, variant })
|
|
3154
|
-
- ❌ \`<Toast variant="error">\` → Use variant="danger"
|
|
3155
|
-
- ❌ \`<Toast variant="info">\` → Use variant="default"
|
|
3156
|
-
- ❌ \`<Tooltip Using Tooltip for rich content (forms, buttons, etc.)>\` → Use Popover for rich interactive content
|
|
3157
|
-
- ❌ \`<Typography Using raw <h1>, <p> tags instead of Typography components>\` → Use <Heading>, <Text>, <Lead> from @usevyre/react
|
|
3591
|
+
\`\`\`tsx
|
|
3592
|
+
import { ButtonGroup, Button } from "@usevyre/react"
|
|
3593
|
+
|
|
3594
|
+
// Props:
|
|
3595
|
+
// orientation = "horizontal" | "vertical" (default: horizontal)
|
|
3596
|
+
// attached = boolean (default: false)
|
|
3597
|
+
// size = "sm" | "md" | "lg" | "icon"
|
|
3598
|
+
|
|
3599
|
+
// Examples:
|
|
3600
|
+
<ButtonGroup attached>
|
|
3601
|
+
<Button variant="secondary">Day</Button>
|
|
3602
|
+
<Button variant="secondary">Week</Button>
|
|
3603
|
+
<Button variant="secondary">Month</Button>
|
|
3604
|
+
</ButtonGroup>
|
|
3605
|
+
<ButtonGroup orientation="vertical" attached>
|
|
3606
|
+
<Button variant="secondary">Top</Button>
|
|
3607
|
+
<Button variant="secondary">Bottom</Button>
|
|
3608
|
+
</ButtonGroup>
|
|
3609
|
+
\`\`\`
|
|
3610
|
+
|
|
3611
|
+
**Common mistakes:**
|
|
3612
|
+
- ❌ \`ButtonGroup variant="..."\` → Set variant on each <Button> inside the group
|
|
3613
|
+
- ❌ \`ButtonGroup without Button children\` → Place <Button> elements as direct children
|
|
3158
3614
|
|
|
3159
3615
|
---
|
|
3160
3616
|
|
|
3161
|
-
|
|
3617
|
+
### TagsInput
|
|
3618
|
+
|
|
3619
|
+
Multi-tag input. Type and press Enter or comma to add a tag, click x to remove, Backspace on empty input removes the last tag. Controlled.
|
|
3620
|
+
|
|
3621
|
+
\`\`\`tsx
|
|
3622
|
+
import { TagsInput } from "@usevyre/react"
|
|
3623
|
+
|
|
3624
|
+
// Props:
|
|
3625
|
+
// value = string[]
|
|
3626
|
+
// onChange = (tags: string[]) => void
|
|
3627
|
+
// placeholder = string
|
|
3628
|
+
// disabled = boolean (default: false)
|
|
3629
|
+
// max = number
|
|
3630
|
+
// size = "sm" | "md" | "lg" (default: md)
|
|
3631
|
+
|
|
3632
|
+
// Examples:
|
|
3633
|
+
const [tags, setTags] = useState<string[]>([]);
|
|
3634
|
+
<TagsInput value={tags} onChange={setTags} placeholder="Add a tag…" />
|
|
3635
|
+
<TagsInput value={tags} onChange={setTags} max={5} />
|
|
3636
|
+
\`\`\`
|
|
3637
|
+
|
|
3638
|
+
**Common mistakes:**
|
|
3639
|
+
- ❌ \`TagsInput value={string}\` → Pass an array: value={['react','vue']}
|
|
3640
|
+
- ❌ \`TagsInput without onChange\` → Provide value and onChange (React) or v-model (Vue)
|
|
3641
|
+
|
|
3642
|
+
---
|
|
3643
|
+
|
|
3644
|
+
### Combobox
|
|
3645
|
+
|
|
3646
|
+
Searchable single-select dropdown with typeahead filtering and keyboard navigation. Use when the list is long enough to need search. Differs from Select (no search) and Command (palette).
|
|
3647
|
+
|
|
3648
|
+
\`\`\`tsx
|
|
3649
|
+
import { Combobox } from "@usevyre/react"
|
|
3650
|
+
|
|
3651
|
+
// Props:
|
|
3652
|
+
// options = { value: string; label: string; disabled?: boolean }[]
|
|
3653
|
+
// value = string | null
|
|
3654
|
+
// onChange = (value: string | null) => void
|
|
3655
|
+
// placeholder = string (default: "Search…")
|
|
3656
|
+
// disabled = boolean (default: false)
|
|
3657
|
+
// size = "sm" | "md" | "lg" (default: md)
|
|
3658
|
+
// emptyText = string (default: "No results")
|
|
3659
|
+
|
|
3660
|
+
// Examples:
|
|
3661
|
+
const [lang, setLang] = useState<string | null>(null);
|
|
3662
|
+
<Combobox
|
|
3663
|
+
options={[{ value: "ts", label: "TypeScript" }, { value: "go", label: "Go" }]}
|
|
3664
|
+
value={lang}
|
|
3665
|
+
onChange={setLang}
|
|
3666
|
+
placeholder="Search language…"
|
|
3667
|
+
/>
|
|
3668
|
+
\`\`\`
|
|
3669
|
+
|
|
3670
|
+
**Common mistakes:**
|
|
3671
|
+
- ❌ \`Combobox value=""\` → Use value={null} for no selection
|
|
3672
|
+
- ❌ \`Combobox options={string[]}\` → Use [{ value: 'ts', label: 'TypeScript' }]
|
|
3673
|
+
- ❌ \`Using Combobox for command palette\` → Use Command for command palettes
|
|
3674
|
+
|
|
3675
|
+
---
|
|
3676
|
+
|
|
3677
|
+
### DataGrid
|
|
3678
|
+
|
|
3679
|
+
Table with built-in column sorting, loading skeletons, and empty state. Filtering and pagination are out of scope — compose with the Pagination component.
|
|
3680
|
+
|
|
3681
|
+
\`\`\`tsx
|
|
3682
|
+
import { DataGrid } from "@usevyre/react"
|
|
3683
|
+
|
|
3684
|
+
// Props:
|
|
3685
|
+
// columns = { key: string; label: string; sortable?: boolean; width?: string }[]
|
|
3686
|
+
// rows = Record<string, unknown>[]
|
|
3687
|
+
// sortKey = string
|
|
3688
|
+
// sortDir = "asc" | "desc"
|
|
3689
|
+
// onSort = (key: string, dir: 'asc' | 'desc') => void
|
|
3690
|
+
// loading = boolean (default: false)
|
|
3691
|
+
// emptyText = string (default: "No data")
|
|
3692
|
+
// stickyHeader = boolean (default: false)
|
|
3693
|
+
|
|
3694
|
+
// Examples:
|
|
3695
|
+
const cols = [{ key: "name", label: "Name", sortable: true }];
|
|
3696
|
+
<DataGrid
|
|
3697
|
+
columns={cols}
|
|
3698
|
+
rows={people}
|
|
3699
|
+
sortKey={sortKey}
|
|
3700
|
+
sortDir={sortDir}
|
|
3701
|
+
onSort={(k, d) => { setSortKey(k); setSortDir(d); }}
|
|
3702
|
+
/>
|
|
3703
|
+
<DataGrid columns={cols} rows={[]} loading />
|
|
3704
|
+
\`\`\`
|
|
3705
|
+
|
|
3706
|
+
**Common mistakes:**
|
|
3707
|
+
- ❌ \`DataGrid expecting built-in pagination\` → Slice rows yourself and use the Pagination component
|
|
3708
|
+
- ❌ \`DataGrid expecting built-in filtering\` → Filter the rows array before passing it in
|
|
3709
|
+
- ❌ \`sortable without onSort\` → Handle onSort and sort the rows array in your state
|
|
3710
|
+
|
|
3711
|
+
---
|
|
3712
|
+
|
|
3713
|
+
### Tag
|
|
3714
|
+
|
|
3715
|
+
Standalone display tag/chip for categories, labels, or filter chips. NOT an input — for tag input use TagsInput. Group multiple with TagGroup.
|
|
3716
|
+
|
|
3717
|
+
\`\`\`tsx
|
|
3718
|
+
import { Tag } from "@usevyre/react"
|
|
3719
|
+
|
|
3720
|
+
// Props:
|
|
3721
|
+
// variant = "default" | "accent" | "danger" (default: default)
|
|
3722
|
+
// size = "sm" | "md" | "lg" (default: md)
|
|
3723
|
+
// onRemove = () => void
|
|
3724
|
+
// onClick = () => void
|
|
3725
|
+
// disabled = boolean (default: false)
|
|
3726
|
+
|
|
3727
|
+
// Examples:
|
|
3728
|
+
<TagGroup>
|
|
3729
|
+
<Tag>Design</Tag>
|
|
3730
|
+
<Tag variant="accent">Featured</Tag>
|
|
3731
|
+
<Tag>Engineering</Tag>
|
|
3732
|
+
</TagGroup>
|
|
3733
|
+
<Tag onRemove={() => removeFilter("react")}>react</Tag>
|
|
3734
|
+
<Tag onClick={() => toggleFilter("vue")}>vue</Tag>
|
|
3735
|
+
\`\`\`
|
|
3736
|
+
|
|
3737
|
+
**Common mistakes:**
|
|
3738
|
+
- ❌ \`Tag variant="success"\` → Use Badge for success/warning/teal status colors; Tag is for categories/filters
|
|
3739
|
+
- ❌ \`Using Tag for tag input\` → Use TagsInput for adding/removing tags via keyboard
|
|
3740
|
+
- ❌ \`Tag size="xl"\` → Use size="lg"
|
|
3741
|
+
|
|
3742
|
+
---
|
|
3743
|
+
|
|
3744
|
+
### TagGroup
|
|
3745
|
+
|
|
3746
|
+
Read-only container that lays out multiple Tag elements with automatic wrapping and consistent spacing. For tag input use TagsInput.
|
|
3747
|
+
|
|
3748
|
+
\`\`\`tsx
|
|
3749
|
+
import { TagGroup, Tag } from "@usevyre/react"
|
|
3750
|
+
|
|
3751
|
+
// Props:
|
|
3752
|
+
// gap = "sm" | "md" | "lg" (default: md)
|
|
3753
|
+
// wrap = boolean (default: true)
|
|
3754
|
+
|
|
3755
|
+
// Examples:
|
|
3756
|
+
<TagGroup gap="sm">
|
|
3757
|
+
<Tag>React</Tag>
|
|
3758
|
+
<Tag>Vue</Tag>
|
|
3759
|
+
<Tag variant="accent">TypeScript</Tag>
|
|
3760
|
+
</TagGroup>
|
|
3761
|
+
\`\`\`
|
|
3762
|
+
|
|
3763
|
+
**Common mistakes:**
|
|
3764
|
+
- ❌ \`TagGroup without Tag children\` → Place <Tag> elements as direct children
|
|
3765
|
+
- ❌ \`Using TagGroup for tag input\` → Use TagsInput for an editable tag field
|
|
3766
|
+
|
|
3767
|
+
---
|
|
3768
|
+
|
|
3769
|
+
## Hallucination Guard — Common AI Mistakes
|
|
3770
|
+
|
|
3771
|
+
The following prop values and patterns do NOT exist in useVyre.
|
|
3772
|
+
If you generate these, you are hallucinating.
|
|
3773
|
+
|
|
3774
|
+
- ❌ \`<Accordion Accordion without AccordionItem>\` → Always compose: Accordion > AccordionItem > AccordionTrigger + AccordionContent
|
|
3775
|
+
- ❌ \`<Alert variant="error">\` → Use variant="danger"
|
|
3776
|
+
- ❌ \`<Alert variant="primary">\` → Use variant="info" | "success" | "warning" | "danger"
|
|
3777
|
+
- ❌ \`<Avatar size="xs">\` → Use size="sm"
|
|
3778
|
+
- ❌ \`<Avatar size="2xl">\` → Use size="xl"
|
|
3779
|
+
- ❌ \`<Badge variant="primary">\` → Use variant="accent" for brand color
|
|
3780
|
+
- ❌ \`<Badge variant="error">\` → Use variant="danger"
|
|
3781
|
+
- ❌ \`<Badge variant="info">\` → Use variant="teal" for info-like styling
|
|
3782
|
+
- ❌ \`<Breadcrumb Using plain <a> tags inside Breadcrumb>\` → Use BreadcrumbItem > BreadcrumbLink for each crumb
|
|
3783
|
+
- ❌ \`<Button variant="blue">\` → Use variant="accent" for brand amber, or variant="teal" for teal
|
|
3784
|
+
- ❌ \`<Button size="xl">\` → Use size="lg"
|
|
3785
|
+
- ❌ \`<Button color="...">\` → Use variant prop instead
|
|
3786
|
+
- ❌ \`<Button icon={...}>\` → Use leftIcon={...} or rightIcon={...}
|
|
3787
|
+
- ❌ \`<Button size="icon" without aria-label>\` → Add aria-label describing the action
|
|
3788
|
+
- ❌ \`<Calendar Using Calendar for time selection>\` → Combine with a separate time Input if time selection is needed
|
|
3789
|
+
- ❌ \`<Card variant="primary">\` → Use variant="elevated" | "outlined" | "ghost" | "accent"
|
|
3790
|
+
- ❌ \`<Checkbox size="lg">\` → Use size="md"
|
|
3791
|
+
- ❌ \`<Command Using Input type="search" for search UI>\` → Use Command + CommandInput + CommandList + CommandItem
|
|
3792
|
+
- ❌ \`<DropdownMenu DropdownItem variant="primary">\` → Use variant="danger" for destructive items only
|
|
3793
|
+
- ❌ \`<Field Applying state prop directly to Input>\` → Wrap Input in <Field state="error"> to apply validation styling
|
|
3794
|
+
- ❌ \`<Input size="icon">\` → Use size="sm" | "md" | "lg"
|
|
3795
|
+
- ❌ \`<Input type="search" for search UI>\` → Import Command from @usevyre/react for search palettes
|
|
3796
|
+
- ❌ \`<Modal size="xl">\` → Use size="lg" or size="full"
|
|
3797
|
+
- ❌ \`<Popover placement="top-center">\` → Use placement="top" for centered placement
|
|
3798
|
+
- ❌ \`<Progress value > 100>\` → Normalize your value to 0–100 range before passing
|
|
3799
|
+
- ❌ \`<Select Passing strings directly as children>\` → Pass options={[{ value: 'a', label: 'Option A' }]}
|
|
3800
|
+
- ❌ \`<Toast Rendering <Toast> directly in JSX>\` → Use: const { toast } = useToast(); then toast({ title, variant })
|
|
3801
|
+
- ❌ \`<Toast variant="error">\` → Use variant="danger"
|
|
3802
|
+
- ❌ \`<Toast variant="info">\` → Use variant="default"
|
|
3803
|
+
- ❌ \`<Tooltip Using Tooltip for rich content (forms, buttons, etc.)>\` → Use Popover for rich interactive content
|
|
3804
|
+
- ❌ \`<Typography Using raw <h1>, <p> tags instead of Typography components>\` → Use <Heading>, <Text>, <Lead> from @usevyre/react
|
|
3805
|
+
- ❌ \`<ButtonGroup ButtonGroup variant="...">\` → Set variant on each <Button> inside the group
|
|
3806
|
+
- ❌ \`<ButtonGroup ButtonGroup without Button children>\` → Place <Button> elements as direct children
|
|
3807
|
+
- ❌ \`<TagsInput TagsInput value={string}>\` → Pass an array: value={['react','vue']}
|
|
3808
|
+
- ❌ \`<TagsInput TagsInput without onChange>\` → Provide value and onChange (React) or v-model (Vue)
|
|
3809
|
+
- ❌ \`<Combobox Combobox value="">\` → Use value={null} for no selection
|
|
3810
|
+
- ❌ \`<Combobox Combobox options={string[]}>\` → Use [{ value: 'ts', label: 'TypeScript' }]
|
|
3811
|
+
- ❌ \`<Combobox Using Combobox for command palette>\` → Use Command for command palettes
|
|
3812
|
+
- ❌ \`<DataGrid DataGrid expecting built-in pagination>\` → Slice rows yourself and use the Pagination component
|
|
3813
|
+
- ❌ \`<DataGrid DataGrid expecting built-in filtering>\` → Filter the rows array before passing it in
|
|
3814
|
+
- ❌ \`<DataGrid sortable without onSort>\` → Handle onSort and sort the rows array in your state
|
|
3815
|
+
- ❌ \`<Tag Tag variant="success">\` → Use Badge for success/warning/teal status colors; Tag is for categories/filters
|
|
3816
|
+
- ❌ \`<Tag Using Tag for tag input>\` → Use TagsInput for adding/removing tags via keyboard
|
|
3817
|
+
- ❌ \`<Tag Tag size="xl">\` → Use size="lg"
|
|
3818
|
+
- ❌ \`<TagGroup TagGroup without Tag children>\` → Place <Tag> elements as direct children
|
|
3819
|
+
- ❌ \`<TagGroup Using TagGroup for tag input>\` → Use TagsInput for an editable tag field
|
|
3820
|
+
|
|
3821
|
+
---
|
|
3822
|
+
|
|
3823
|
+
## Styling Rules for AI Agents
|
|
3162
3824
|
|
|
3163
3825
|
1. ALWAYS use semantic tokens (\`--vyre-color-semantic-*\`), never primitive tokens
|
|
3164
3826
|
2. NEVER hardcode colors — every color decision has a semantic token
|
|
@@ -3204,7 +3866,7 @@ If you generate these, you are hallucinating.
|
|
|
3204
3866
|
\`\`\`
|
|
3205
3867
|
`;
|
|
3206
3868
|
export const copilotInstructions = `# useVyre Copilot Instructions
|
|
3207
|
-
# Version: 1.
|
|
3869
|
+
# Version: 1.1.0
|
|
3208
3870
|
|
|
3209
3871
|
When generating UI code in this project, follow the useVyre design system rules below.
|
|
3210
3872
|
|
|
@@ -4091,6 +4753,188 @@ import { Text, Heading, Lead, Code, Blockquote } from "@usevyre/react"
|
|
|
4091
4753
|
|
|
4092
4754
|
---
|
|
4093
4755
|
|
|
4756
|
+
### ButtonGroup
|
|
4757
|
+
|
|
4758
|
+
Groups multiple Button components into one visual unit (toolbar, segmented control). Pure layout — no internal state.
|
|
4759
|
+
|
|
4760
|
+
\`\`\`tsx
|
|
4761
|
+
import { ButtonGroup, Button } from "@usevyre/react"
|
|
4762
|
+
|
|
4763
|
+
// Props:
|
|
4764
|
+
// orientation = "horizontal" | "vertical" (default: horizontal)
|
|
4765
|
+
// attached = boolean (default: false)
|
|
4766
|
+
// size = "sm" | "md" | "lg" | "icon"
|
|
4767
|
+
|
|
4768
|
+
// Examples:
|
|
4769
|
+
<ButtonGroup attached>
|
|
4770
|
+
<Button variant="secondary">Day</Button>
|
|
4771
|
+
<Button variant="secondary">Week</Button>
|
|
4772
|
+
<Button variant="secondary">Month</Button>
|
|
4773
|
+
</ButtonGroup>
|
|
4774
|
+
<ButtonGroup orientation="vertical" attached>
|
|
4775
|
+
<Button variant="secondary">Top</Button>
|
|
4776
|
+
<Button variant="secondary">Bottom</Button>
|
|
4777
|
+
</ButtonGroup>
|
|
4778
|
+
\`\`\`
|
|
4779
|
+
|
|
4780
|
+
**Common mistakes:**
|
|
4781
|
+
- ❌ \`ButtonGroup variant="..."\` → Set variant on each <Button> inside the group
|
|
4782
|
+
- ❌ \`ButtonGroup without Button children\` → Place <Button> elements as direct children
|
|
4783
|
+
|
|
4784
|
+
---
|
|
4785
|
+
|
|
4786
|
+
### TagsInput
|
|
4787
|
+
|
|
4788
|
+
Multi-tag input. Type and press Enter or comma to add a tag, click x to remove, Backspace on empty input removes the last tag. Controlled.
|
|
4789
|
+
|
|
4790
|
+
\`\`\`tsx
|
|
4791
|
+
import { TagsInput } from "@usevyre/react"
|
|
4792
|
+
|
|
4793
|
+
// Props:
|
|
4794
|
+
// value = string[]
|
|
4795
|
+
// onChange = (tags: string[]) => void
|
|
4796
|
+
// placeholder = string
|
|
4797
|
+
// disabled = boolean (default: false)
|
|
4798
|
+
// max = number
|
|
4799
|
+
// size = "sm" | "md" | "lg" (default: md)
|
|
4800
|
+
|
|
4801
|
+
// Examples:
|
|
4802
|
+
const [tags, setTags] = useState<string[]>([]);
|
|
4803
|
+
<TagsInput value={tags} onChange={setTags} placeholder="Add a tag…" />
|
|
4804
|
+
<TagsInput value={tags} onChange={setTags} max={5} />
|
|
4805
|
+
\`\`\`
|
|
4806
|
+
|
|
4807
|
+
**Common mistakes:**
|
|
4808
|
+
- ❌ \`TagsInput value={string}\` → Pass an array: value={['react','vue']}
|
|
4809
|
+
- ❌ \`TagsInput without onChange\` → Provide value and onChange (React) or v-model (Vue)
|
|
4810
|
+
|
|
4811
|
+
---
|
|
4812
|
+
|
|
4813
|
+
### Combobox
|
|
4814
|
+
|
|
4815
|
+
Searchable single-select dropdown with typeahead filtering and keyboard navigation. Use when the list is long enough to need search. Differs from Select (no search) and Command (palette).
|
|
4816
|
+
|
|
4817
|
+
\`\`\`tsx
|
|
4818
|
+
import { Combobox } from "@usevyre/react"
|
|
4819
|
+
|
|
4820
|
+
// Props:
|
|
4821
|
+
// options = { value: string; label: string; disabled?: boolean }[]
|
|
4822
|
+
// value = string | null
|
|
4823
|
+
// onChange = (value: string | null) => void
|
|
4824
|
+
// placeholder = string (default: "Search…")
|
|
4825
|
+
// disabled = boolean (default: false)
|
|
4826
|
+
// size = "sm" | "md" | "lg" (default: md)
|
|
4827
|
+
// emptyText = string (default: "No results")
|
|
4828
|
+
|
|
4829
|
+
// Examples:
|
|
4830
|
+
const [lang, setLang] = useState<string | null>(null);
|
|
4831
|
+
<Combobox
|
|
4832
|
+
options={[{ value: "ts", label: "TypeScript" }, { value: "go", label: "Go" }]}
|
|
4833
|
+
value={lang}
|
|
4834
|
+
onChange={setLang}
|
|
4835
|
+
placeholder="Search language…"
|
|
4836
|
+
/>
|
|
4837
|
+
\`\`\`
|
|
4838
|
+
|
|
4839
|
+
**Common mistakes:**
|
|
4840
|
+
- ❌ \`Combobox value=""\` → Use value={null} for no selection
|
|
4841
|
+
- ❌ \`Combobox options={string[]}\` → Use [{ value: 'ts', label: 'TypeScript' }]
|
|
4842
|
+
- ❌ \`Using Combobox for command palette\` → Use Command for command palettes
|
|
4843
|
+
|
|
4844
|
+
---
|
|
4845
|
+
|
|
4846
|
+
### DataGrid
|
|
4847
|
+
|
|
4848
|
+
Table with built-in column sorting, loading skeletons, and empty state. Filtering and pagination are out of scope — compose with the Pagination component.
|
|
4849
|
+
|
|
4850
|
+
\`\`\`tsx
|
|
4851
|
+
import { DataGrid } from "@usevyre/react"
|
|
4852
|
+
|
|
4853
|
+
// Props:
|
|
4854
|
+
// columns = { key: string; label: string; sortable?: boolean; width?: string }[]
|
|
4855
|
+
// rows = Record<string, unknown>[]
|
|
4856
|
+
// sortKey = string
|
|
4857
|
+
// sortDir = "asc" | "desc"
|
|
4858
|
+
// onSort = (key: string, dir: 'asc' | 'desc') => void
|
|
4859
|
+
// loading = boolean (default: false)
|
|
4860
|
+
// emptyText = string (default: "No data")
|
|
4861
|
+
// stickyHeader = boolean (default: false)
|
|
4862
|
+
|
|
4863
|
+
// Examples:
|
|
4864
|
+
const cols = [{ key: "name", label: "Name", sortable: true }];
|
|
4865
|
+
<DataGrid
|
|
4866
|
+
columns={cols}
|
|
4867
|
+
rows={people}
|
|
4868
|
+
sortKey={sortKey}
|
|
4869
|
+
sortDir={sortDir}
|
|
4870
|
+
onSort={(k, d) => { setSortKey(k); setSortDir(d); }}
|
|
4871
|
+
/>
|
|
4872
|
+
<DataGrid columns={cols} rows={[]} loading />
|
|
4873
|
+
\`\`\`
|
|
4874
|
+
|
|
4875
|
+
**Common mistakes:**
|
|
4876
|
+
- ❌ \`DataGrid expecting built-in pagination\` → Slice rows yourself and use the Pagination component
|
|
4877
|
+
- ❌ \`DataGrid expecting built-in filtering\` → Filter the rows array before passing it in
|
|
4878
|
+
- ❌ \`sortable without onSort\` → Handle onSort and sort the rows array in your state
|
|
4879
|
+
|
|
4880
|
+
---
|
|
4881
|
+
|
|
4882
|
+
### Tag
|
|
4883
|
+
|
|
4884
|
+
Standalone display tag/chip for categories, labels, or filter chips. NOT an input — for tag input use TagsInput. Group multiple with TagGroup.
|
|
4885
|
+
|
|
4886
|
+
\`\`\`tsx
|
|
4887
|
+
import { Tag } from "@usevyre/react"
|
|
4888
|
+
|
|
4889
|
+
// Props:
|
|
4890
|
+
// variant = "default" | "accent" | "danger" (default: default)
|
|
4891
|
+
// size = "sm" | "md" | "lg" (default: md)
|
|
4892
|
+
// onRemove = () => void
|
|
4893
|
+
// onClick = () => void
|
|
4894
|
+
// disabled = boolean (default: false)
|
|
4895
|
+
|
|
4896
|
+
// Examples:
|
|
4897
|
+
<TagGroup>
|
|
4898
|
+
<Tag>Design</Tag>
|
|
4899
|
+
<Tag variant="accent">Featured</Tag>
|
|
4900
|
+
<Tag>Engineering</Tag>
|
|
4901
|
+
</TagGroup>
|
|
4902
|
+
<Tag onRemove={() => removeFilter("react")}>react</Tag>
|
|
4903
|
+
<Tag onClick={() => toggleFilter("vue")}>vue</Tag>
|
|
4904
|
+
\`\`\`
|
|
4905
|
+
|
|
4906
|
+
**Common mistakes:**
|
|
4907
|
+
- ❌ \`Tag variant="success"\` → Use Badge for success/warning/teal status colors; Tag is for categories/filters
|
|
4908
|
+
- ❌ \`Using Tag for tag input\` → Use TagsInput for adding/removing tags via keyboard
|
|
4909
|
+
- ❌ \`Tag size="xl"\` → Use size="lg"
|
|
4910
|
+
|
|
4911
|
+
---
|
|
4912
|
+
|
|
4913
|
+
### TagGroup
|
|
4914
|
+
|
|
4915
|
+
Read-only container that lays out multiple Tag elements with automatic wrapping and consistent spacing. For tag input use TagsInput.
|
|
4916
|
+
|
|
4917
|
+
\`\`\`tsx
|
|
4918
|
+
import { TagGroup, Tag } from "@usevyre/react"
|
|
4919
|
+
|
|
4920
|
+
// Props:
|
|
4921
|
+
// gap = "sm" | "md" | "lg" (default: md)
|
|
4922
|
+
// wrap = boolean (default: true)
|
|
4923
|
+
|
|
4924
|
+
// Examples:
|
|
4925
|
+
<TagGroup gap="sm">
|
|
4926
|
+
<Tag>React</Tag>
|
|
4927
|
+
<Tag>Vue</Tag>
|
|
4928
|
+
<Tag variant="accent">TypeScript</Tag>
|
|
4929
|
+
</TagGroup>
|
|
4930
|
+
\`\`\`
|
|
4931
|
+
|
|
4932
|
+
**Common mistakes:**
|
|
4933
|
+
- ❌ \`TagGroup without Tag children\` → Place <Tag> elements as direct children
|
|
4934
|
+
- ❌ \`Using TagGroup for tag input\` → Use TagsInput for an editable tag field
|
|
4935
|
+
|
|
4936
|
+
---
|
|
4937
|
+
|
|
4094
4938
|
## Hallucination Guard — Common AI Mistakes
|
|
4095
4939
|
|
|
4096
4940
|
The following prop values and patterns do NOT exist in useVyre.
|
|
@@ -4127,6 +4971,21 @@ If you generate these, you are hallucinating.
|
|
|
4127
4971
|
- ❌ \`<Toast variant="info">\` → Use variant="default"
|
|
4128
4972
|
- ❌ \`<Tooltip Using Tooltip for rich content (forms, buttons, etc.)>\` → Use Popover for rich interactive content
|
|
4129
4973
|
- ❌ \`<Typography Using raw <h1>, <p> tags instead of Typography components>\` → Use <Heading>, <Text>, <Lead> from @usevyre/react
|
|
4974
|
+
- ❌ \`<ButtonGroup ButtonGroup variant="...">\` → Set variant on each <Button> inside the group
|
|
4975
|
+
- ❌ \`<ButtonGroup ButtonGroup without Button children>\` → Place <Button> elements as direct children
|
|
4976
|
+
- ❌ \`<TagsInput TagsInput value={string}>\` → Pass an array: value={['react','vue']}
|
|
4977
|
+
- ❌ \`<TagsInput TagsInput without onChange>\` → Provide value and onChange (React) or v-model (Vue)
|
|
4978
|
+
- ❌ \`<Combobox Combobox value="">\` → Use value={null} for no selection
|
|
4979
|
+
- ❌ \`<Combobox Combobox options={string[]}>\` → Use [{ value: 'ts', label: 'TypeScript' }]
|
|
4980
|
+
- ❌ \`<Combobox Using Combobox for command palette>\` → Use Command for command palettes
|
|
4981
|
+
- ❌ \`<DataGrid DataGrid expecting built-in pagination>\` → Slice rows yourself and use the Pagination component
|
|
4982
|
+
- ❌ \`<DataGrid DataGrid expecting built-in filtering>\` → Filter the rows array before passing it in
|
|
4983
|
+
- ❌ \`<DataGrid sortable without onSort>\` → Handle onSort and sort the rows array in your state
|
|
4984
|
+
- ❌ \`<Tag Tag variant="success">\` → Use Badge for success/warning/teal status colors; Tag is for categories/filters
|
|
4985
|
+
- ❌ \`<Tag Using Tag for tag input>\` → Use TagsInput for adding/removing tags via keyboard
|
|
4986
|
+
- ❌ \`<Tag Tag size="xl">\` → Use size="lg"
|
|
4987
|
+
- ❌ \`<TagGroup TagGroup without Tag children>\` → Place <Tag> elements as direct children
|
|
4988
|
+
- ❌ \`<TagGroup Using TagGroup for tag input>\` → Use TagsInput for an editable tag field
|
|
4130
4989
|
|
|
4131
4990
|
---
|
|
4132
4991
|
|
|
@@ -4178,15 +5037,20 @@ If you generate these, you are hallucinating.
|
|
|
4178
5037
|
|
|
4179
5038
|
export const schema = {
|
|
4180
5039
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
4181
|
-
"version": "1.
|
|
4182
|
-
"generatedAt": "2026-05-
|
|
5040
|
+
"version": "1.1.0",
|
|
5041
|
+
"generatedAt": "2026-05-15",
|
|
4183
5042
|
"package": "@usevyre/react",
|
|
4184
|
-
"packageVersion": "1.
|
|
5043
|
+
"packageVersion": "1.1.0",
|
|
4185
5044
|
"validFor": [
|
|
4186
|
-
"@usevyre/react@1.
|
|
4187
|
-
"@usevyre/vue@1.
|
|
5045
|
+
"@usevyre/react@1.1.0+",
|
|
5046
|
+
"@usevyre/vue@1.1.0+"
|
|
4188
5047
|
],
|
|
4189
5048
|
"changelog": {
|
|
5049
|
+
"1.1.0": {
|
|
5050
|
+
"date": "2026-05-15",
|
|
5051
|
+
"breaking": false,
|
|
5052
|
+
"summary": "Added 6 components: ButtonGroup, TagsInput, Combobox, DataGrid, Tag, TagGroup"
|
|
5053
|
+
},
|
|
4190
5054
|
"1.0.0": {
|
|
4191
5055
|
"date": "2026-05-13",
|
|
4192
5056
|
"breaking": true,
|
|
@@ -5456,12 +6320,370 @@ export const schema = {
|
|
|
5456
6320
|
"code": "<Heading size=\"2xl\" as=\"h1\">Dashboard</Heading>\n<Lead>Welcome back. Here's what's happening today.</Lead>\n<Text size=\"sm\" style={{ color: 'var(--vyre-color-semantic-text-muted)' }}>Last updated 5 minutes ago.</Text>"
|
|
5457
6321
|
}
|
|
5458
6322
|
]
|
|
6323
|
+
},
|
|
6324
|
+
"ButtonGroup": {
|
|
6325
|
+
"description": "Groups multiple Button components into one visual unit (toolbar, segmented control). Pure layout — no internal state.",
|
|
6326
|
+
"import": "import { ButtonGroup, Button } from \"@usevyre/react\"",
|
|
6327
|
+
"props": {
|
|
6328
|
+
"orientation": {
|
|
6329
|
+
"type": "enum",
|
|
6330
|
+
"values": [
|
|
6331
|
+
"horizontal",
|
|
6332
|
+
"vertical"
|
|
6333
|
+
],
|
|
6334
|
+
"default": "horizontal",
|
|
6335
|
+
"description": "Layout direction of grouped buttons"
|
|
6336
|
+
},
|
|
6337
|
+
"attached": {
|
|
6338
|
+
"type": "boolean",
|
|
6339
|
+
"default": false,
|
|
6340
|
+
"description": "Remove gap so buttons share collapsed borders (segmented control look)"
|
|
6341
|
+
},
|
|
6342
|
+
"size": {
|
|
6343
|
+
"type": "enum",
|
|
6344
|
+
"values": [
|
|
6345
|
+
"sm",
|
|
6346
|
+
"md",
|
|
6347
|
+
"lg",
|
|
6348
|
+
"icon"
|
|
6349
|
+
],
|
|
6350
|
+
"description": "Size forwarded to all child buttons"
|
|
6351
|
+
}
|
|
6352
|
+
},
|
|
6353
|
+
"antiPatterns": [
|
|
6354
|
+
{
|
|
6355
|
+
"pattern": "ButtonGroup variant=\"...\"",
|
|
6356
|
+
"reason": "ButtonGroup has no variant prop — variant goes on each child Button",
|
|
6357
|
+
"fix": "Set variant on each <Button> inside the group"
|
|
6358
|
+
},
|
|
6359
|
+
{
|
|
6360
|
+
"pattern": "ButtonGroup without Button children",
|
|
6361
|
+
"reason": "ButtonGroup is a layout wrapper for Button elements",
|
|
6362
|
+
"fix": "Place <Button> elements as direct children"
|
|
6363
|
+
}
|
|
6364
|
+
],
|
|
6365
|
+
"examples": [
|
|
6366
|
+
{
|
|
6367
|
+
"description": "Segmented control",
|
|
6368
|
+
"code": "<ButtonGroup attached>\n <Button variant=\"secondary\">Day</Button>\n <Button variant=\"secondary\">Week</Button>\n <Button variant=\"secondary\">Month</Button>\n</ButtonGroup>"
|
|
6369
|
+
},
|
|
6370
|
+
{
|
|
6371
|
+
"description": "Vertical group",
|
|
6372
|
+
"code": "<ButtonGroup orientation=\"vertical\" attached>\n <Button variant=\"secondary\">Top</Button>\n <Button variant=\"secondary\">Bottom</Button>\n</ButtonGroup>"
|
|
6373
|
+
}
|
|
6374
|
+
]
|
|
6375
|
+
},
|
|
6376
|
+
"TagsInput": {
|
|
6377
|
+
"description": "Multi-tag input. Type and press Enter or comma to add a tag, click x to remove, Backspace on empty input removes the last tag. Controlled.",
|
|
6378
|
+
"import": "import { TagsInput } from \"@usevyre/react\"",
|
|
6379
|
+
"props": {
|
|
6380
|
+
"value": {
|
|
6381
|
+
"type": "string[]",
|
|
6382
|
+
"description": "Controlled list of tags (required)"
|
|
6383
|
+
},
|
|
6384
|
+
"onChange": {
|
|
6385
|
+
"type": "(tags: string[]) => void",
|
|
6386
|
+
"description": "Called with the new tag array on every change. React only — Vue uses v-model"
|
|
6387
|
+
},
|
|
6388
|
+
"placeholder": {
|
|
6389
|
+
"type": "string",
|
|
6390
|
+
"description": "Input placeholder, hidden when max is reached"
|
|
6391
|
+
},
|
|
6392
|
+
"disabled": {
|
|
6393
|
+
"type": "boolean",
|
|
6394
|
+
"default": false,
|
|
6395
|
+
"description": "Disables all interaction"
|
|
6396
|
+
},
|
|
6397
|
+
"max": {
|
|
6398
|
+
"type": "number",
|
|
6399
|
+
"description": "Maximum number of tags; input is disabled when reached"
|
|
6400
|
+
},
|
|
6401
|
+
"size": {
|
|
6402
|
+
"type": "enum",
|
|
6403
|
+
"values": [
|
|
6404
|
+
"sm",
|
|
6405
|
+
"md",
|
|
6406
|
+
"lg"
|
|
6407
|
+
],
|
|
6408
|
+
"default": "md",
|
|
6409
|
+
"description": "Size scale"
|
|
6410
|
+
}
|
|
6411
|
+
},
|
|
6412
|
+
"antiPatterns": [
|
|
6413
|
+
{
|
|
6414
|
+
"pattern": "TagsInput value={string}",
|
|
6415
|
+
"reason": "value must be a string array, not a string",
|
|
6416
|
+
"fix": "Pass an array: value={['react','vue']}"
|
|
6417
|
+
},
|
|
6418
|
+
{
|
|
6419
|
+
"pattern": "TagsInput without onChange",
|
|
6420
|
+
"reason": "TagsInput is controlled — it needs onChange to update",
|
|
6421
|
+
"fix": "Provide value and onChange (React) or v-model (Vue)"
|
|
6422
|
+
}
|
|
6423
|
+
],
|
|
6424
|
+
"examples": [
|
|
6425
|
+
{
|
|
6426
|
+
"description": "Basic tags input",
|
|
6427
|
+
"code": "const [tags, setTags] = useState<string[]>([]);\n<TagsInput value={tags} onChange={setTags} placeholder=\"Add a tag…\" />"
|
|
6428
|
+
},
|
|
6429
|
+
{
|
|
6430
|
+
"description": "Limited to 5 tags",
|
|
6431
|
+
"code": "<TagsInput value={tags} onChange={setTags} max={5} />"
|
|
6432
|
+
}
|
|
6433
|
+
]
|
|
6434
|
+
},
|
|
6435
|
+
"Combobox": {
|
|
6436
|
+
"description": "Searchable single-select dropdown with typeahead filtering and keyboard navigation. Use when the list is long enough to need search. Differs from Select (no search) and Command (palette).",
|
|
6437
|
+
"import": "import { Combobox } from \"@usevyre/react\"",
|
|
6438
|
+
"props": {
|
|
6439
|
+
"options": {
|
|
6440
|
+
"type": "{ value: string; label: string; disabled?: boolean }[]",
|
|
6441
|
+
"description": "Selectable options (required)"
|
|
6442
|
+
},
|
|
6443
|
+
"value": {
|
|
6444
|
+
"type": "string | null",
|
|
6445
|
+
"description": "Controlled selected value; null clears selection (required)"
|
|
6446
|
+
},
|
|
6447
|
+
"onChange": {
|
|
6448
|
+
"type": "(value: string | null) => void",
|
|
6449
|
+
"description": "Called when selection changes. React only — Vue uses v-model"
|
|
6450
|
+
},
|
|
6451
|
+
"placeholder": {
|
|
6452
|
+
"type": "string",
|
|
6453
|
+
"default": "\"Search…\"",
|
|
6454
|
+
"description": "Input placeholder when nothing is selected"
|
|
6455
|
+
},
|
|
6456
|
+
"disabled": {
|
|
6457
|
+
"type": "boolean",
|
|
6458
|
+
"default": false,
|
|
6459
|
+
"description": "Disables the combobox"
|
|
6460
|
+
},
|
|
6461
|
+
"size": {
|
|
6462
|
+
"type": "enum",
|
|
6463
|
+
"values": [
|
|
6464
|
+
"sm",
|
|
6465
|
+
"md",
|
|
6466
|
+
"lg"
|
|
6467
|
+
],
|
|
6468
|
+
"default": "md",
|
|
6469
|
+
"description": "Height scale"
|
|
6470
|
+
},
|
|
6471
|
+
"emptyText": {
|
|
6472
|
+
"type": "string",
|
|
6473
|
+
"default": "\"No results\"",
|
|
6474
|
+
"description": "Text shown when search matches no options"
|
|
6475
|
+
}
|
|
6476
|
+
},
|
|
6477
|
+
"antiPatterns": [
|
|
6478
|
+
{
|
|
6479
|
+
"pattern": "Combobox value=\"\"",
|
|
6480
|
+
"reason": "Empty selection must be null, not empty string",
|
|
6481
|
+
"fix": "Use value={null} for no selection"
|
|
6482
|
+
},
|
|
6483
|
+
{
|
|
6484
|
+
"pattern": "Combobox options={string[]}",
|
|
6485
|
+
"reason": "options must be objects with value and label",
|
|
6486
|
+
"fix": "Use [{ value: 'ts', label: 'TypeScript' }]"
|
|
6487
|
+
},
|
|
6488
|
+
{
|
|
6489
|
+
"pattern": "Using Combobox for command palette",
|
|
6490
|
+
"reason": "Combobox is single-value select, not an action palette",
|
|
6491
|
+
"fix": "Use Command for command palettes"
|
|
6492
|
+
}
|
|
6493
|
+
],
|
|
6494
|
+
"examples": [
|
|
6495
|
+
{
|
|
6496
|
+
"description": "Searchable language picker",
|
|
6497
|
+
"code": "const [lang, setLang] = useState<string | null>(null);\n<Combobox\n options={[{ value: \"ts\", label: \"TypeScript\" }, { value: \"go\", label: \"Go\" }]}\n value={lang}\n onChange={setLang}\n placeholder=\"Search language…\"\n/>"
|
|
6498
|
+
}
|
|
6499
|
+
]
|
|
6500
|
+
},
|
|
6501
|
+
"DataGrid": {
|
|
6502
|
+
"description": "Table with built-in column sorting, loading skeletons, and empty state. Filtering and pagination are out of scope — compose with the Pagination component.",
|
|
6503
|
+
"import": "import { DataGrid } from \"@usevyre/react\"",
|
|
6504
|
+
"props": {
|
|
6505
|
+
"columns": {
|
|
6506
|
+
"type": "{ key: string; label: string; sortable?: boolean; width?: string }[]",
|
|
6507
|
+
"description": "Column definitions (required)"
|
|
6508
|
+
},
|
|
6509
|
+
"rows": {
|
|
6510
|
+
"type": "Record<string, unknown>[]",
|
|
6511
|
+
"description": "Row data; each object keyed by column key (required)"
|
|
6512
|
+
},
|
|
6513
|
+
"sortKey": {
|
|
6514
|
+
"type": "string",
|
|
6515
|
+
"description": "Controlled active sort column key"
|
|
6516
|
+
},
|
|
6517
|
+
"sortDir": {
|
|
6518
|
+
"type": "enum",
|
|
6519
|
+
"values": [
|
|
6520
|
+
"asc",
|
|
6521
|
+
"desc"
|
|
6522
|
+
],
|
|
6523
|
+
"description": "Controlled sort direction"
|
|
6524
|
+
},
|
|
6525
|
+
"onSort": {
|
|
6526
|
+
"type": "(key: string, dir: 'asc' | 'desc') => void",
|
|
6527
|
+
"description": "Called when a sortable header is clicked. React only — Vue emits sort + v-model:sortKey/sortDir"
|
|
6528
|
+
},
|
|
6529
|
+
"loading": {
|
|
6530
|
+
"type": "boolean",
|
|
6531
|
+
"default": false,
|
|
6532
|
+
"description": "Show skeleton placeholder rows"
|
|
6533
|
+
},
|
|
6534
|
+
"emptyText": {
|
|
6535
|
+
"type": "string",
|
|
6536
|
+
"default": "\"No data\"",
|
|
6537
|
+
"description": "Message shown when rows is empty"
|
|
6538
|
+
},
|
|
6539
|
+
"stickyHeader": {
|
|
6540
|
+
"type": "boolean",
|
|
6541
|
+
"default": false,
|
|
6542
|
+
"description": "Keep the header visible while scrolling"
|
|
6543
|
+
}
|
|
6544
|
+
},
|
|
6545
|
+
"antiPatterns": [
|
|
6546
|
+
{
|
|
6547
|
+
"pattern": "DataGrid expecting built-in pagination",
|
|
6548
|
+
"reason": "DataGrid does not paginate — it only sorts",
|
|
6549
|
+
"fix": "Slice rows yourself and use the Pagination component"
|
|
6550
|
+
},
|
|
6551
|
+
{
|
|
6552
|
+
"pattern": "DataGrid expecting built-in filtering",
|
|
6553
|
+
"reason": "DataGrid does not filter rows",
|
|
6554
|
+
"fix": "Filter the rows array before passing it in"
|
|
6555
|
+
},
|
|
6556
|
+
{
|
|
6557
|
+
"pattern": "sortable without onSort",
|
|
6558
|
+
"reason": "Sorting is controlled — the grid does not sort data itself",
|
|
6559
|
+
"fix": "Handle onSort and sort the rows array in your state"
|
|
6560
|
+
}
|
|
6561
|
+
],
|
|
6562
|
+
"examples": [
|
|
6563
|
+
{
|
|
6564
|
+
"description": "Sortable grid",
|
|
6565
|
+
"code": "const cols = [{ key: \"name\", label: \"Name\", sortable: true }];\n<DataGrid\n columns={cols}\n rows={people}\n sortKey={sortKey}\n sortDir={sortDir}\n onSort={(k, d) => { setSortKey(k); setSortDir(d); }}\n/>"
|
|
6566
|
+
},
|
|
6567
|
+
{
|
|
6568
|
+
"description": "Loading state",
|
|
6569
|
+
"code": "<DataGrid columns={cols} rows={[]} loading />"
|
|
6570
|
+
}
|
|
6571
|
+
]
|
|
6572
|
+
},
|
|
6573
|
+
"Tag": {
|
|
6574
|
+
"description": "Standalone display tag/chip for categories, labels, or filter chips. NOT an input — for tag input use TagsInput. Group multiple with TagGroup.",
|
|
6575
|
+
"import": "import { Tag } from \"@usevyre/react\"",
|
|
6576
|
+
"props": {
|
|
6577
|
+
"variant": {
|
|
6578
|
+
"type": "enum",
|
|
6579
|
+
"values": [
|
|
6580
|
+
"default",
|
|
6581
|
+
"accent",
|
|
6582
|
+
"danger"
|
|
6583
|
+
],
|
|
6584
|
+
"default": "default",
|
|
6585
|
+
"description": "Visual style. default=neutral, accent=brand, danger=destructive/error"
|
|
6586
|
+
},
|
|
6587
|
+
"size": {
|
|
6588
|
+
"type": "enum",
|
|
6589
|
+
"values": [
|
|
6590
|
+
"sm",
|
|
6591
|
+
"md",
|
|
6592
|
+
"lg"
|
|
6593
|
+
],
|
|
6594
|
+
"default": "md",
|
|
6595
|
+
"description": "Size scale"
|
|
6596
|
+
},
|
|
6597
|
+
"onRemove": {
|
|
6598
|
+
"type": "() => void",
|
|
6599
|
+
"description": "React only. When provided, renders a × remove button. Vue: use `removable` prop + @remove event"
|
|
6600
|
+
},
|
|
6601
|
+
"onClick": {
|
|
6602
|
+
"type": "() => void",
|
|
6603
|
+
"description": "React only. When provided, makes the whole tag interactive (keyboard accessible). Vue: use `clickable` prop + @click event"
|
|
6604
|
+
},
|
|
6605
|
+
"disabled": {
|
|
6606
|
+
"type": "boolean",
|
|
6607
|
+
"default": false,
|
|
6608
|
+
"description": "Disables interaction (only relevant with onClick/onRemove)"
|
|
6609
|
+
}
|
|
6610
|
+
},
|
|
6611
|
+
"antiPatterns": [
|
|
6612
|
+
{
|
|
6613
|
+
"pattern": "Tag variant=\"success\"",
|
|
6614
|
+
"reason": "Tag only has default, accent, danger variants (unlike Badge which has more)",
|
|
6615
|
+
"fix": "Use Badge for success/warning/teal status colors; Tag is for categories/filters"
|
|
6616
|
+
},
|
|
6617
|
+
{
|
|
6618
|
+
"pattern": "Using Tag for tag input",
|
|
6619
|
+
"reason": "Tag is display-only, it does not accept typed input",
|
|
6620
|
+
"fix": "Use TagsInput for adding/removing tags via keyboard"
|
|
6621
|
+
},
|
|
6622
|
+
{
|
|
6623
|
+
"pattern": "Tag size=\"xl\"",
|
|
6624
|
+
"reason": "Maximum size is 'lg'",
|
|
6625
|
+
"fix": "Use size=\"lg\""
|
|
6626
|
+
}
|
|
6627
|
+
],
|
|
6628
|
+
"examples": [
|
|
6629
|
+
{
|
|
6630
|
+
"description": "Category tags in a group",
|
|
6631
|
+
"code": "<TagGroup>\n <Tag>Design</Tag>\n <Tag variant=\"accent\">Featured</Tag>\n <Tag>Engineering</Tag>\n</TagGroup>"
|
|
6632
|
+
},
|
|
6633
|
+
{
|
|
6634
|
+
"description": "Removable filter chip (React)",
|
|
6635
|
+
"code": "<Tag onRemove={() => removeFilter(\"react\")}>react</Tag>"
|
|
6636
|
+
},
|
|
6637
|
+
{
|
|
6638
|
+
"description": "Clickable toggle tag (React)",
|
|
6639
|
+
"code": "<Tag onClick={() => toggleFilter(\"vue\")}>vue</Tag>"
|
|
6640
|
+
}
|
|
6641
|
+
]
|
|
6642
|
+
},
|
|
6643
|
+
"TagGroup": {
|
|
6644
|
+
"description": "Read-only container that lays out multiple Tag elements with automatic wrapping and consistent spacing. For tag input use TagsInput.",
|
|
6645
|
+
"import": "import { TagGroup, Tag } from \"@usevyre/react\"",
|
|
6646
|
+
"props": {
|
|
6647
|
+
"gap": {
|
|
6648
|
+
"type": "enum",
|
|
6649
|
+
"values": [
|
|
6650
|
+
"sm",
|
|
6651
|
+
"md",
|
|
6652
|
+
"lg"
|
|
6653
|
+
],
|
|
6654
|
+
"default": "md",
|
|
6655
|
+
"description": "Spacing between tags"
|
|
6656
|
+
},
|
|
6657
|
+
"wrap": {
|
|
6658
|
+
"type": "boolean",
|
|
6659
|
+
"default": true,
|
|
6660
|
+
"description": "Wrap tags onto multiple lines when they overflow; set false for single-line scroll"
|
|
6661
|
+
}
|
|
6662
|
+
},
|
|
6663
|
+
"antiPatterns": [
|
|
6664
|
+
{
|
|
6665
|
+
"pattern": "TagGroup without Tag children",
|
|
6666
|
+
"reason": "TagGroup is a layout wrapper for Tag elements",
|
|
6667
|
+
"fix": "Place <Tag> elements as direct children"
|
|
6668
|
+
},
|
|
6669
|
+
{
|
|
6670
|
+
"pattern": "Using TagGroup for tag input",
|
|
6671
|
+
"reason": "TagGroup is display-only",
|
|
6672
|
+
"fix": "Use TagsInput for an editable tag field"
|
|
6673
|
+
}
|
|
6674
|
+
],
|
|
6675
|
+
"examples": [
|
|
6676
|
+
{
|
|
6677
|
+
"description": "Tag group with mixed variants",
|
|
6678
|
+
"code": "<TagGroup gap=\"sm\">\n <Tag>React</Tag>\n <Tag>Vue</Tag>\n <Tag variant=\"accent\">TypeScript</Tag>\n</TagGroup>"
|
|
6679
|
+
}
|
|
6680
|
+
]
|
|
5459
6681
|
}
|
|
5460
6682
|
}
|
|
5461
6683
|
};
|
|
5462
6684
|
|
|
5463
6685
|
export const antiPatterns = {
|
|
5464
|
-
"version": "1.
|
|
6686
|
+
"version": "1.1.0",
|
|
5465
6687
|
"rules": [
|
|
5466
6688
|
{
|
|
5467
6689
|
"component": "Accordion",
|
|
@@ -5679,19 +6901,129 @@ export const antiPatterns = {
|
|
|
5679
6901
|
"reason": "Typography components apply the correct token-based styles",
|
|
5680
6902
|
"fix": "Use <Heading>, <Text>, <Lead> from @usevyre/react",
|
|
5681
6903
|
"severity": "error"
|
|
6904
|
+
},
|
|
6905
|
+
{
|
|
6906
|
+
"component": "ButtonGroup",
|
|
6907
|
+
"pattern": "ButtonGroup variant=\"...\"",
|
|
6908
|
+
"reason": "ButtonGroup has no variant prop — variant goes on each child Button",
|
|
6909
|
+
"fix": "Set variant on each <Button> inside the group",
|
|
6910
|
+
"severity": "error"
|
|
6911
|
+
},
|
|
6912
|
+
{
|
|
6913
|
+
"component": "ButtonGroup",
|
|
6914
|
+
"pattern": "ButtonGroup without Button children",
|
|
6915
|
+
"reason": "ButtonGroup is a layout wrapper for Button elements",
|
|
6916
|
+
"fix": "Place <Button> elements as direct children",
|
|
6917
|
+
"severity": "error"
|
|
6918
|
+
},
|
|
6919
|
+
{
|
|
6920
|
+
"component": "TagsInput",
|
|
6921
|
+
"pattern": "TagsInput value={string}",
|
|
6922
|
+
"reason": "value must be a string array, not a string",
|
|
6923
|
+
"fix": "Pass an array: value={['react','vue']}",
|
|
6924
|
+
"severity": "error"
|
|
6925
|
+
},
|
|
6926
|
+
{
|
|
6927
|
+
"component": "TagsInput",
|
|
6928
|
+
"pattern": "TagsInput without onChange",
|
|
6929
|
+
"reason": "TagsInput is controlled — it needs onChange to update",
|
|
6930
|
+
"fix": "Provide value and onChange (React) or v-model (Vue)",
|
|
6931
|
+
"severity": "error"
|
|
6932
|
+
},
|
|
6933
|
+
{
|
|
6934
|
+
"component": "Combobox",
|
|
6935
|
+
"pattern": "Combobox value=\"\"",
|
|
6936
|
+
"reason": "Empty selection must be null, not empty string",
|
|
6937
|
+
"fix": "Use value={null} for no selection",
|
|
6938
|
+
"severity": "error"
|
|
6939
|
+
},
|
|
6940
|
+
{
|
|
6941
|
+
"component": "Combobox",
|
|
6942
|
+
"pattern": "Combobox options={string[]}",
|
|
6943
|
+
"reason": "options must be objects with value and label",
|
|
6944
|
+
"fix": "Use [{ value: 'ts', label: 'TypeScript' }]",
|
|
6945
|
+
"severity": "error"
|
|
6946
|
+
},
|
|
6947
|
+
{
|
|
6948
|
+
"component": "Combobox",
|
|
6949
|
+
"pattern": "Using Combobox for command palette",
|
|
6950
|
+
"reason": "Combobox is single-value select, not an action palette",
|
|
6951
|
+
"fix": "Use Command for command palettes",
|
|
6952
|
+
"severity": "error"
|
|
6953
|
+
},
|
|
6954
|
+
{
|
|
6955
|
+
"component": "DataGrid",
|
|
6956
|
+
"pattern": "DataGrid expecting built-in pagination",
|
|
6957
|
+
"reason": "DataGrid does not paginate — it only sorts",
|
|
6958
|
+
"fix": "Slice rows yourself and use the Pagination component",
|
|
6959
|
+
"severity": "error"
|
|
6960
|
+
},
|
|
6961
|
+
{
|
|
6962
|
+
"component": "DataGrid",
|
|
6963
|
+
"pattern": "DataGrid expecting built-in filtering",
|
|
6964
|
+
"reason": "DataGrid does not filter rows",
|
|
6965
|
+
"fix": "Filter the rows array before passing it in",
|
|
6966
|
+
"severity": "error"
|
|
6967
|
+
},
|
|
6968
|
+
{
|
|
6969
|
+
"component": "DataGrid",
|
|
6970
|
+
"pattern": "sortable without onSort",
|
|
6971
|
+
"reason": "Sorting is controlled — the grid does not sort data itself",
|
|
6972
|
+
"fix": "Handle onSort and sort the rows array in your state",
|
|
6973
|
+
"severity": "error"
|
|
6974
|
+
},
|
|
6975
|
+
{
|
|
6976
|
+
"component": "Tag",
|
|
6977
|
+
"pattern": "Tag variant=\"success\"",
|
|
6978
|
+
"reason": "Tag only has default, accent, danger variants (unlike Badge which has more)",
|
|
6979
|
+
"fix": "Use Badge for success/warning/teal status colors; Tag is for categories/filters",
|
|
6980
|
+
"severity": "error"
|
|
6981
|
+
},
|
|
6982
|
+
{
|
|
6983
|
+
"component": "Tag",
|
|
6984
|
+
"pattern": "Using Tag for tag input",
|
|
6985
|
+
"reason": "Tag is display-only, it does not accept typed input",
|
|
6986
|
+
"fix": "Use TagsInput for adding/removing tags via keyboard",
|
|
6987
|
+
"severity": "error"
|
|
6988
|
+
},
|
|
6989
|
+
{
|
|
6990
|
+
"component": "Tag",
|
|
6991
|
+
"pattern": "Tag size=\"xl\"",
|
|
6992
|
+
"reason": "Maximum size is 'lg'",
|
|
6993
|
+
"fix": "Use size=\"lg\"",
|
|
6994
|
+
"severity": "error"
|
|
6995
|
+
},
|
|
6996
|
+
{
|
|
6997
|
+
"component": "TagGroup",
|
|
6998
|
+
"pattern": "TagGroup without Tag children",
|
|
6999
|
+
"reason": "TagGroup is a layout wrapper for Tag elements",
|
|
7000
|
+
"fix": "Place <Tag> elements as direct children",
|
|
7001
|
+
"severity": "error"
|
|
7002
|
+
},
|
|
7003
|
+
{
|
|
7004
|
+
"component": "TagGroup",
|
|
7005
|
+
"pattern": "Using TagGroup for tag input",
|
|
7006
|
+
"reason": "TagGroup is display-only",
|
|
7007
|
+
"fix": "Use TagsInput for an editable tag field",
|
|
7008
|
+
"severity": "error"
|
|
5682
7009
|
}
|
|
5683
7010
|
]
|
|
5684
7011
|
};
|
|
5685
7012
|
|
|
5686
7013
|
export const versionInfo = {
|
|
5687
|
-
"version": "1.
|
|
5688
|
-
"packageVersion": "1.
|
|
5689
|
-
"generatedAt": "2026-05-
|
|
7014
|
+
"version": "1.1.0",
|
|
7015
|
+
"packageVersion": "1.1.0",
|
|
7016
|
+
"generatedAt": "2026-05-15T15:01:34.101Z",
|
|
5690
7017
|
"validFor": [
|
|
5691
|
-
"@usevyre/react@1.
|
|
5692
|
-
"@usevyre/vue@1.
|
|
7018
|
+
"@usevyre/react@1.1.0+",
|
|
7019
|
+
"@usevyre/vue@1.1.0+"
|
|
5693
7020
|
],
|
|
5694
7021
|
"changelog": {
|
|
7022
|
+
"1.1.0": {
|
|
7023
|
+
"date": "2026-05-15",
|
|
7024
|
+
"breaking": false,
|
|
7025
|
+
"summary": "Added 6 components: ButtonGroup, TagsInput, Combobox, DataGrid, Tag, TagGroup"
|
|
7026
|
+
},
|
|
5695
7027
|
"1.0.0": {
|
|
5696
7028
|
"date": "2026-05-13",
|
|
5697
7029
|
"breaking": true,
|
|
@@ -5710,211 +7042,253 @@ export const versionInfo = {
|
|
|
5710
7042
|
},
|
|
5711
7043
|
"components": {
|
|
5712
7044
|
"Accordion": {
|
|
5713
|
-
"version": "1.
|
|
5714
|
-
"lastUpdated": "2026-05-
|
|
7045
|
+
"version": "1.1.0",
|
|
7046
|
+
"lastUpdated": "2026-05-15",
|
|
5715
7047
|
"breaking": false,
|
|
5716
7048
|
"stable": true,
|
|
5717
7049
|
"changelog": null
|
|
5718
7050
|
},
|
|
5719
7051
|
"Alert": {
|
|
5720
|
-
"version": "1.
|
|
5721
|
-
"lastUpdated": "2026-05-
|
|
7052
|
+
"version": "1.1.0",
|
|
7053
|
+
"lastUpdated": "2026-05-15",
|
|
5722
7054
|
"breaking": false,
|
|
5723
7055
|
"stable": true,
|
|
5724
7056
|
"changelog": null
|
|
5725
7057
|
},
|
|
5726
7058
|
"Avatar": {
|
|
5727
|
-
"version": "1.
|
|
5728
|
-
"lastUpdated": "2026-05-
|
|
7059
|
+
"version": "1.1.0",
|
|
7060
|
+
"lastUpdated": "2026-05-15",
|
|
5729
7061
|
"breaking": false,
|
|
5730
7062
|
"stable": true,
|
|
5731
7063
|
"changelog": null
|
|
5732
7064
|
},
|
|
5733
7065
|
"Badge": {
|
|
5734
|
-
"version": "1.
|
|
5735
|
-
"lastUpdated": "2026-05-
|
|
7066
|
+
"version": "1.1.0",
|
|
7067
|
+
"lastUpdated": "2026-05-15",
|
|
5736
7068
|
"breaking": false,
|
|
5737
7069
|
"stable": true,
|
|
5738
7070
|
"changelog": null
|
|
5739
7071
|
},
|
|
5740
7072
|
"Breadcrumb": {
|
|
5741
|
-
"version": "1.
|
|
5742
|
-
"lastUpdated": "2026-05-
|
|
7073
|
+
"version": "1.1.0",
|
|
7074
|
+
"lastUpdated": "2026-05-15",
|
|
5743
7075
|
"breaking": false,
|
|
5744
7076
|
"stable": true,
|
|
5745
7077
|
"changelog": null
|
|
5746
7078
|
},
|
|
5747
7079
|
"Button": {
|
|
5748
|
-
"version": "1.
|
|
5749
|
-
"lastUpdated": "2026-05-
|
|
7080
|
+
"version": "1.1.0",
|
|
7081
|
+
"lastUpdated": "2026-05-15",
|
|
5750
7082
|
"breaking": false,
|
|
5751
7083
|
"stable": true,
|
|
5752
7084
|
"changelog": null
|
|
5753
7085
|
},
|
|
5754
7086
|
"Calendar": {
|
|
5755
|
-
"version": "1.
|
|
5756
|
-
"lastUpdated": "2026-05-
|
|
7087
|
+
"version": "1.1.0",
|
|
7088
|
+
"lastUpdated": "2026-05-15",
|
|
5757
7089
|
"breaking": false,
|
|
5758
7090
|
"stable": true,
|
|
5759
7091
|
"changelog": null
|
|
5760
7092
|
},
|
|
5761
7093
|
"Card": {
|
|
5762
|
-
"version": "1.
|
|
5763
|
-
"lastUpdated": "2026-05-
|
|
7094
|
+
"version": "1.1.0",
|
|
7095
|
+
"lastUpdated": "2026-05-15",
|
|
5764
7096
|
"breaking": false,
|
|
5765
7097
|
"stable": true,
|
|
5766
7098
|
"changelog": null
|
|
5767
7099
|
},
|
|
5768
7100
|
"Checkbox": {
|
|
5769
|
-
"version": "1.
|
|
5770
|
-
"lastUpdated": "2026-05-
|
|
7101
|
+
"version": "1.1.0",
|
|
7102
|
+
"lastUpdated": "2026-05-15",
|
|
5771
7103
|
"breaking": false,
|
|
5772
7104
|
"stable": true,
|
|
5773
7105
|
"changelog": null
|
|
5774
7106
|
},
|
|
5775
7107
|
"Command": {
|
|
5776
|
-
"version": "1.
|
|
5777
|
-
"lastUpdated": "2026-05-
|
|
7108
|
+
"version": "1.1.0",
|
|
7109
|
+
"lastUpdated": "2026-05-15",
|
|
5778
7110
|
"breaking": false,
|
|
5779
7111
|
"stable": true,
|
|
5780
7112
|
"changelog": null
|
|
5781
7113
|
},
|
|
5782
7114
|
"DropdownMenu": {
|
|
5783
|
-
"version": "1.
|
|
5784
|
-
"lastUpdated": "2026-05-
|
|
7115
|
+
"version": "1.1.0",
|
|
7116
|
+
"lastUpdated": "2026-05-15",
|
|
5785
7117
|
"breaking": false,
|
|
5786
7118
|
"stable": true,
|
|
5787
7119
|
"changelog": null
|
|
5788
7120
|
},
|
|
5789
7121
|
"Field": {
|
|
5790
|
-
"version": "1.
|
|
5791
|
-
"lastUpdated": "2026-05-
|
|
7122
|
+
"version": "1.1.0",
|
|
7123
|
+
"lastUpdated": "2026-05-15",
|
|
5792
7124
|
"breaking": false,
|
|
5793
7125
|
"stable": true,
|
|
5794
7126
|
"changelog": null
|
|
5795
7127
|
},
|
|
5796
7128
|
"Input": {
|
|
5797
|
-
"version": "1.
|
|
5798
|
-
"lastUpdated": "2026-05-
|
|
7129
|
+
"version": "1.1.0",
|
|
7130
|
+
"lastUpdated": "2026-05-15",
|
|
5799
7131
|
"breaking": false,
|
|
5800
7132
|
"stable": true,
|
|
5801
7133
|
"changelog": null
|
|
5802
7134
|
},
|
|
5803
7135
|
"Label": {
|
|
5804
|
-
"version": "1.
|
|
5805
|
-
"lastUpdated": "2026-05-
|
|
7136
|
+
"version": "1.1.0",
|
|
7137
|
+
"lastUpdated": "2026-05-15",
|
|
5806
7138
|
"breaking": false,
|
|
5807
7139
|
"stable": true,
|
|
5808
7140
|
"changelog": null
|
|
5809
7141
|
},
|
|
5810
7142
|
"Modal": {
|
|
5811
|
-
"version": "1.
|
|
5812
|
-
"lastUpdated": "2026-05-
|
|
7143
|
+
"version": "1.1.0",
|
|
7144
|
+
"lastUpdated": "2026-05-15",
|
|
5813
7145
|
"breaking": false,
|
|
5814
7146
|
"stable": true,
|
|
5815
7147
|
"changelog": null
|
|
5816
7148
|
},
|
|
5817
7149
|
"Pagination": {
|
|
5818
|
-
"version": "1.
|
|
5819
|
-
"lastUpdated": "2026-05-
|
|
7150
|
+
"version": "1.1.0",
|
|
7151
|
+
"lastUpdated": "2026-05-15",
|
|
5820
7152
|
"breaking": false,
|
|
5821
7153
|
"stable": true,
|
|
5822
7154
|
"changelog": null
|
|
5823
7155
|
},
|
|
5824
7156
|
"Popover": {
|
|
5825
|
-
"version": "1.
|
|
5826
|
-
"lastUpdated": "2026-05-
|
|
7157
|
+
"version": "1.1.0",
|
|
7158
|
+
"lastUpdated": "2026-05-15",
|
|
5827
7159
|
"breaking": false,
|
|
5828
7160
|
"stable": true,
|
|
5829
7161
|
"changelog": null
|
|
5830
7162
|
},
|
|
5831
7163
|
"Progress": {
|
|
5832
|
-
"version": "1.
|
|
5833
|
-
"lastUpdated": "2026-05-
|
|
7164
|
+
"version": "1.1.0",
|
|
7165
|
+
"lastUpdated": "2026-05-15",
|
|
5834
7166
|
"breaking": false,
|
|
5835
7167
|
"stable": true,
|
|
5836
7168
|
"changelog": null
|
|
5837
7169
|
},
|
|
5838
7170
|
"Select": {
|
|
5839
|
-
"version": "1.
|
|
5840
|
-
"lastUpdated": "2026-05-
|
|
7171
|
+
"version": "1.1.0",
|
|
7172
|
+
"lastUpdated": "2026-05-15",
|
|
5841
7173
|
"breaking": false,
|
|
5842
7174
|
"stable": true,
|
|
5843
7175
|
"changelog": null
|
|
5844
7176
|
},
|
|
5845
7177
|
"Separator": {
|
|
5846
|
-
"version": "1.
|
|
5847
|
-
"lastUpdated": "2026-05-
|
|
7178
|
+
"version": "1.1.0",
|
|
7179
|
+
"lastUpdated": "2026-05-15",
|
|
5848
7180
|
"breaking": false,
|
|
5849
7181
|
"stable": true,
|
|
5850
7182
|
"changelog": null
|
|
5851
7183
|
},
|
|
5852
7184
|
"Sheet": {
|
|
5853
|
-
"version": "1.
|
|
5854
|
-
"lastUpdated": "2026-05-
|
|
7185
|
+
"version": "1.1.0",
|
|
7186
|
+
"lastUpdated": "2026-05-15",
|
|
5855
7187
|
"breaking": false,
|
|
5856
7188
|
"stable": true,
|
|
5857
7189
|
"changelog": null
|
|
5858
7190
|
},
|
|
5859
7191
|
"Sidebar": {
|
|
5860
|
-
"version": "1.
|
|
5861
|
-
"lastUpdated": "2026-05-
|
|
7192
|
+
"version": "1.1.0",
|
|
7193
|
+
"lastUpdated": "2026-05-15",
|
|
5862
7194
|
"breaking": false,
|
|
5863
7195
|
"stable": true,
|
|
5864
7196
|
"changelog": null
|
|
5865
7197
|
},
|
|
5866
7198
|
"Skeleton": {
|
|
5867
|
-
"version": "1.
|
|
5868
|
-
"lastUpdated": "2026-05-
|
|
7199
|
+
"version": "1.1.0",
|
|
7200
|
+
"lastUpdated": "2026-05-15",
|
|
5869
7201
|
"breaking": false,
|
|
5870
7202
|
"stable": true,
|
|
5871
7203
|
"changelog": null
|
|
5872
7204
|
},
|
|
5873
7205
|
"Slider": {
|
|
5874
|
-
"version": "1.
|
|
5875
|
-
"lastUpdated": "2026-05-
|
|
7206
|
+
"version": "1.1.0",
|
|
7207
|
+
"lastUpdated": "2026-05-15",
|
|
5876
7208
|
"breaking": false,
|
|
5877
7209
|
"stable": true,
|
|
5878
7210
|
"changelog": null
|
|
5879
7211
|
},
|
|
5880
7212
|
"Switch": {
|
|
5881
|
-
"version": "1.
|
|
5882
|
-
"lastUpdated": "2026-05-
|
|
7213
|
+
"version": "1.1.0",
|
|
7214
|
+
"lastUpdated": "2026-05-15",
|
|
5883
7215
|
"breaking": false,
|
|
5884
7216
|
"stable": true,
|
|
5885
7217
|
"changelog": null
|
|
5886
7218
|
},
|
|
5887
7219
|
"Table": {
|
|
5888
|
-
"version": "1.
|
|
5889
|
-
"lastUpdated": "2026-05-
|
|
7220
|
+
"version": "1.1.0",
|
|
7221
|
+
"lastUpdated": "2026-05-15",
|
|
5890
7222
|
"breaking": false,
|
|
5891
7223
|
"stable": true,
|
|
5892
7224
|
"changelog": null
|
|
5893
7225
|
},
|
|
5894
7226
|
"Tabs": {
|
|
5895
|
-
"version": "1.
|
|
5896
|
-
"lastUpdated": "2026-05-
|
|
7227
|
+
"version": "1.1.0",
|
|
7228
|
+
"lastUpdated": "2026-05-15",
|
|
5897
7229
|
"breaking": false,
|
|
5898
7230
|
"stable": true,
|
|
5899
7231
|
"changelog": null
|
|
5900
7232
|
},
|
|
5901
7233
|
"Toast": {
|
|
5902
|
-
"version": "1.
|
|
5903
|
-
"lastUpdated": "2026-05-
|
|
7234
|
+
"version": "1.1.0",
|
|
7235
|
+
"lastUpdated": "2026-05-15",
|
|
5904
7236
|
"breaking": false,
|
|
5905
7237
|
"stable": true,
|
|
5906
7238
|
"changelog": null
|
|
5907
7239
|
},
|
|
5908
7240
|
"Tooltip": {
|
|
5909
|
-
"version": "1.
|
|
5910
|
-
"lastUpdated": "2026-05-
|
|
7241
|
+
"version": "1.1.0",
|
|
7242
|
+
"lastUpdated": "2026-05-15",
|
|
5911
7243
|
"breaking": false,
|
|
5912
7244
|
"stable": true,
|
|
5913
7245
|
"changelog": null
|
|
5914
7246
|
},
|
|
5915
7247
|
"Typography": {
|
|
5916
|
-
"version": "1.
|
|
5917
|
-
"lastUpdated": "2026-05-
|
|
7248
|
+
"version": "1.1.0",
|
|
7249
|
+
"lastUpdated": "2026-05-15",
|
|
7250
|
+
"breaking": false,
|
|
7251
|
+
"stable": true,
|
|
7252
|
+
"changelog": null
|
|
7253
|
+
},
|
|
7254
|
+
"ButtonGroup": {
|
|
7255
|
+
"version": "1.1.0",
|
|
7256
|
+
"lastUpdated": "2026-05-15",
|
|
7257
|
+
"breaking": false,
|
|
7258
|
+
"stable": true,
|
|
7259
|
+
"changelog": null
|
|
7260
|
+
},
|
|
7261
|
+
"TagsInput": {
|
|
7262
|
+
"version": "1.1.0",
|
|
7263
|
+
"lastUpdated": "2026-05-15",
|
|
7264
|
+
"breaking": false,
|
|
7265
|
+
"stable": true,
|
|
7266
|
+
"changelog": null
|
|
7267
|
+
},
|
|
7268
|
+
"Combobox": {
|
|
7269
|
+
"version": "1.1.0",
|
|
7270
|
+
"lastUpdated": "2026-05-15",
|
|
7271
|
+
"breaking": false,
|
|
7272
|
+
"stable": true,
|
|
7273
|
+
"changelog": null
|
|
7274
|
+
},
|
|
7275
|
+
"DataGrid": {
|
|
7276
|
+
"version": "1.1.0",
|
|
7277
|
+
"lastUpdated": "2026-05-15",
|
|
7278
|
+
"breaking": false,
|
|
7279
|
+
"stable": true,
|
|
7280
|
+
"changelog": null
|
|
7281
|
+
},
|
|
7282
|
+
"Tag": {
|
|
7283
|
+
"version": "1.1.0",
|
|
7284
|
+
"lastUpdated": "2026-05-15",
|
|
7285
|
+
"breaking": false,
|
|
7286
|
+
"stable": true,
|
|
7287
|
+
"changelog": null
|
|
7288
|
+
},
|
|
7289
|
+
"TagGroup": {
|
|
7290
|
+
"version": "1.1.0",
|
|
7291
|
+
"lastUpdated": "2026-05-15",
|
|
5918
7292
|
"breaking": false,
|
|
5919
7293
|
"stable": true,
|
|
5920
7294
|
"changelog": null
|
|
@@ -5952,5 +7326,11 @@ export const cheatSheets = {
|
|
|
5952
7326
|
"Tabs": "# Tabs — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Tabbed navigation for switching between content panels.**\n\n```ts\nimport { Tabs, TabList, Tab, TabPanels, TabPanel } from \"@usevyre/react\"\n```\n\n## Examples\n\n**Basic tabs**\n```tsx\n<Tabs defaultIndex={0}>\n <TabList>\n <Tab>Overview</Tab>\n <Tab>Settings</Tab>\n </TabList>\n <TabPanels>\n <TabPanel>Overview content</TabPanel>\n <TabPanel>Settings content</TabPanel>\n </TabPanels>\n</Tabs>\n```\n",
|
|
5953
7327
|
"Toast": "# Toast — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Transient notification. Use the useToast hook to trigger toasts imperatively. React: wrap app in <ToastProvider>. Vue: place <ToastViewport /> once in app root.**\n\n```ts\nimport { useToast, ToastProvider } from \"@usevyre/react\" // Vue: import { useToast, ToastViewport } from \"@usevyre/vue\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `variant` | `\"default\"` \\| `\"success\"` \\| `\"warning\"` \\| `\"danger\"` | `default` |\n\n## Common AI Mistakes\n\n- ❌ `Rendering <Toast> directly in JSX`\n → Use: const { toast } = useToast(); then toast({ title, variant })\n- ❌ `variant=\"error\"`\n → Use variant=\"danger\"\n- ❌ `variant=\"info\"`\n → Use variant=\"default\"\n\n## Examples\n\n**Trigger a success toast**\n```tsx\nconst { toast } = useToast();\n\n<Button onClick={() => toast({ title: 'Saved!', variant: 'success', duration: 3000 })}>\n Save\n</Button>\n```\n\n**Setup: wrap app with ToastProvider**\n```tsx\n<ToastProvider>\n <App />\n</ToastProvider>\n```\n",
|
|
5954
7328
|
"Tooltip": "# Tooltip — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Short label that appears on hover/focus. For rich content use Popover instead.**\n\n```ts\nimport { Tooltip } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `placement` | `\"top\"` \\| `\"bottom\"` \\| `\"left\"` \\| `\"right\"` | `top` |\n\n## Common AI Mistakes\n\n- ❌ `Using Tooltip for rich content (forms, buttons, etc.)`\n → Use Popover for rich interactive content\n\n## Examples\n\n**Tooltip on an icon button**\n```tsx\n<Tooltip content=\"Close dialog\" placement=\"bottom\">\n <Button variant=\"ghost\" size=\"icon\" aria-label=\"Close\">\n <X size={16} />\n </Button>\n</Tooltip>\n```\n",
|
|
5955
|
-
"Typography": "# Typography — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Text rendering components with semantic scale. Includes Text, Heading, Lead, Code, Blockquote.**\n\n```ts\nimport { Text, Heading, Lead, Code, Blockquote } from \"@usevyre/react\"\n```\n\n## Common AI Mistakes\n\n- ❌ `Using raw <h1>, <p> tags instead of Typography components`\n → Use <Heading>, <Text>, <Lead> from @usevyre/react\n\n## Examples\n\n**Page heading and body text**\n```tsx\n<Heading size=\"2xl\" as=\"h1\">Dashboard</Heading>\n<Lead>Welcome back. Here's what's happening today.</Lead>\n<Text size=\"sm\" style={{ color: 'var(--vyre-color-semantic-text-muted)' }}>Last updated 5 minutes ago.</Text>\n```\n"
|
|
7329
|
+
"Typography": "# Typography — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Text rendering components with semantic scale. Includes Text, Heading, Lead, Code, Blockquote.**\n\n```ts\nimport { Text, Heading, Lead, Code, Blockquote } from \"@usevyre/react\"\n```\n\n## Common AI Mistakes\n\n- ❌ `Using raw <h1>, <p> tags instead of Typography components`\n → Use <Heading>, <Text>, <Lead> from @usevyre/react\n\n## Examples\n\n**Page heading and body text**\n```tsx\n<Heading size=\"2xl\" as=\"h1\">Dashboard</Heading>\n<Lead>Welcome back. Here's what's happening today.</Lead>\n<Text size=\"sm\" style={{ color: 'var(--vyre-color-semantic-text-muted)' }}>Last updated 5 minutes ago.</Text>\n```\n",
|
|
7330
|
+
"ButtonGroup": "# ButtonGroup — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Groups multiple Button components into one visual unit (toolbar, segmented control). Pure layout — no internal state.**\n\n```ts\nimport { ButtonGroup, Button } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `orientation` | `\"horizontal\"` \\| `\"vertical\"` | `horizontal` |\n| `size` | `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"icon\"` | — |\n| `attached` | `true` \\| `false` | `false` |\n\n## Common AI Mistakes\n\n- ❌ `ButtonGroup variant=\"...\"`\n → Set variant on each <Button> inside the group\n- ❌ `ButtonGroup without Button children`\n → Place <Button> elements as direct children\n\n## Examples\n\n**Segmented control**\n```tsx\n<ButtonGroup attached>\n <Button variant=\"secondary\">Day</Button>\n <Button variant=\"secondary\">Week</Button>\n <Button variant=\"secondary\">Month</Button>\n</ButtonGroup>\n```\n\n**Vertical group**\n```tsx\n<ButtonGroup orientation=\"vertical\" attached>\n <Button variant=\"secondary\">Top</Button>\n <Button variant=\"secondary\">Bottom</Button>\n</ButtonGroup>\n```\n",
|
|
7331
|
+
"TagsInput": "# TagsInput — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Multi-tag input. Type and press Enter or comma to add a tag, click x to remove, Backspace on empty input removes the last tag. Controlled.**\n\n```ts\nimport { TagsInput } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `size` | `\"sm\"` \\| `\"md\"` \\| `\"lg\"` | `md` |\n| `disabled` | `true` \\| `false` | `false` |\n\n## Common AI Mistakes\n\n- ❌ `TagsInput value={string}`\n → Pass an array: value={['react','vue']}\n- ❌ `TagsInput without onChange`\n → Provide value and onChange (React) or v-model (Vue)\n\n## Examples\n\n**Basic tags input**\n```tsx\nconst [tags, setTags] = useState<string[]>([]);\n<TagsInput value={tags} onChange={setTags} placeholder=\"Add a tag…\" />\n```\n\n**Limited to 5 tags**\n```tsx\n<TagsInput value={tags} onChange={setTags} max={5} />\n```\n",
|
|
7332
|
+
"Combobox": "# Combobox — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Searchable single-select dropdown with typeahead filtering and keyboard navigation. Use when the list is long enough to need search. Differs from Select (no search) and Command (palette).**\n\n```ts\nimport { Combobox } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `size` | `\"sm\"` \\| `\"md\"` \\| `\"lg\"` | `md` |\n| `disabled` | `true` \\| `false` | `false` |\n\n## Common AI Mistakes\n\n- ❌ `Combobox value=\"\"`\n → Use value={null} for no selection\n- ❌ `Combobox options={string[]}`\n → Use [{ value: 'ts', label: 'TypeScript' }]\n- ❌ `Using Combobox for command palette`\n → Use Command for command palettes\n\n## Examples\n\n**Searchable language picker**\n```tsx\nconst [lang, setLang] = useState<string | null>(null);\n<Combobox\n options={[{ value: \"ts\", label: \"TypeScript\" }, { value: \"go\", label: \"Go\" }]}\n value={lang}\n onChange={setLang}\n placeholder=\"Search language…\"\n/>\n```\n",
|
|
7333
|
+
"DataGrid": "# DataGrid — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Table with built-in column sorting, loading skeletons, and empty state. Filtering and pagination are out of scope — compose with the Pagination component.**\n\n```ts\nimport { DataGrid } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `sortDir` | `\"asc\"` \\| `\"desc\"` | — |\n| `loading` | `true` \\| `false` | `false` |\n| `stickyHeader` | `true` \\| `false` | `false` |\n\n## Common AI Mistakes\n\n- ❌ `DataGrid expecting built-in pagination`\n → Slice rows yourself and use the Pagination component\n- ❌ `DataGrid expecting built-in filtering`\n → Filter the rows array before passing it in\n- ❌ `sortable without onSort`\n → Handle onSort and sort the rows array in your state\n\n## Examples\n\n**Sortable grid**\n```tsx\nconst cols = [{ key: \"name\", label: \"Name\", sortable: true }];\n<DataGrid\n columns={cols}\n rows={people}\n sortKey={sortKey}\n sortDir={sortDir}\n onSort={(k, d) => { setSortKey(k); setSortDir(d); }}\n/>\n```\n\n**Loading state**\n```tsx\n<DataGrid columns={cols} rows={[]} loading />\n```\n",
|
|
7334
|
+
"Tag": "# Tag — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Standalone display tag/chip for categories, labels, or filter chips. NOT an input — for tag input use TagsInput. Group multiple with TagGroup.**\n\n```ts\nimport { Tag } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `variant` | `\"default\"` \\| `\"accent\"` \\| `\"danger\"` | `default` |\n| `size` | `\"sm\"` \\| `\"md\"` \\| `\"lg\"` | `md` |\n| `disabled` | `true` \\| `false` | `false` |\n\n## Common AI Mistakes\n\n- ❌ `Tag variant=\"success\"`\n → Use Badge for success/warning/teal status colors; Tag is for categories/filters\n- ❌ `Using Tag for tag input`\n → Use TagsInput for adding/removing tags via keyboard\n- ❌ `Tag size=\"xl\"`\n → Use size=\"lg\"\n\n## Examples\n\n**Category tags in a group**\n```tsx\n<TagGroup>\n <Tag>Design</Tag>\n <Tag variant=\"accent\">Featured</Tag>\n <Tag>Engineering</Tag>\n</TagGroup>\n```\n\n**Removable filter chip (React)**\n```tsx\n<Tag onRemove={() => removeFilter(\"react\")}>react</Tag>\n```\n\n**Clickable toggle tag (React)**\n```tsx\n<Tag onClick={() => toggleFilter(\"vue\")}>vue</Tag>\n```\n",
|
|
7335
|
+
"TagGroup": "# TagGroup — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Read-only container that lays out multiple Tag elements with automatic wrapping and consistent spacing. For tag input use TagsInput.**\n\n```ts\nimport { TagGroup, Tag } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `gap` | `\"sm\"` \\| `\"md\"` \\| `\"lg\"` | `md` |\n| `wrap` | `true` \\| `false` | `true` |\n\n## Common AI Mistakes\n\n- ❌ `TagGroup without Tag children`\n → Place <Tag> elements as direct children\n- ❌ `Using TagGroup for tag input`\n → Use TagsInput for an editable tag field\n\n## Examples\n\n**Tag group with mixed variants**\n```tsx\n<TagGroup gap=\"sm\">\n <Tag>React</Tag>\n <Tag>Vue</Tag>\n <Tag variant=\"accent\">TypeScript</Tag>\n</TagGroup>\n```\n"
|
|
5956
7336
|
};
|