@usevyre/ai-context 1.0.0 → 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 +1504 -114
- package/dist/schema.json +373 -5
- package/dist/tokens.json +1 -1
- package/dist/tokens.md +1 -1
- package/dist/version-info.json +117 -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
|
|
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 = "
|
|
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:
|
|
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:
|
|
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:
|
|
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
|
-
- ❌ \`<Alert variant="primary">\` → Use variant="info" | "success" | "warning" | "danger"
|
|
3130
|
-
- ❌ \`<Avatar size="xs">\` → Use size="sm"
|
|
3131
|
-
- ❌ \`<Avatar size="2xl">\` → Use size="xl"
|
|
3132
|
-
- ❌ \`<Badge variant="primary">\` → Use variant="accent" for brand color
|
|
3133
|
-
- ❌ \`<Badge variant="error">\` → Use variant="danger"
|
|
3134
|
-
- ❌ \`<Badge variant="info">\` → Use variant="teal" for info-like styling
|
|
3135
|
-
- ❌ \`<Breadcrumb Using plain <a> tags inside Breadcrumb>\` → Use BreadcrumbItem > BreadcrumbLink for each crumb
|
|
3136
|
-
- ❌ \`<Button variant="blue">\` → Use variant="accent" for brand amber, or variant="teal" for teal
|
|
3137
|
-
- ❌ \`<Button size="xl">\` → Use size="lg"
|
|
3138
|
-
- ❌ \`<Button color="...">\` → Use variant prop instead
|
|
3139
|
-
- ❌ \`<Button icon={...}>\` → Use leftIcon={...} or rightIcon={...}
|
|
3140
|
-
- ❌ \`<Button size="icon" without aria-label>\` → Add aria-label describing the action
|
|
3141
|
-
- ❌ \`<Calendar Using Calendar for time selection>\` → Combine with a separate time Input if time selection is needed
|
|
3142
|
-
- ❌ \`<Card variant="primary">\` → Use variant="elevated" | "outlined" | "ghost" | "accent"
|
|
3143
|
-
- ❌ \`<Checkbox size="lg">\` → Use size="md"
|
|
3144
|
-
- ❌ \`<Command Using Input type="search" for search UI>\` → Use Command + CommandInput + CommandList + CommandItem
|
|
3145
|
-
- ❌ \`<DropdownMenu DropdownItem variant="primary">\` → Use variant="danger" for destructive items only
|
|
3146
|
-
- ❌ \`<Field Applying state prop directly to Input>\` → Wrap Input in <Field state="error"> to apply validation styling
|
|
3147
|
-
- ❌ \`<Input size="icon">\` → Use size="sm" | "md" | "lg"
|
|
3148
|
-
- ❌ \`<Input type="search" for search UI>\` → Import Command from @usevyre/react for search palettes
|
|
3149
|
-
- ❌ \`<Modal size="xl">\` → Use size="lg" or size="full"
|
|
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"
|
|
3158
3593
|
|
|
3159
|
-
|
|
3594
|
+
// Props:
|
|
3595
|
+
// orientation = "horizontal" | "vertical" (default: horizontal)
|
|
3596
|
+
// attached = boolean (default: false)
|
|
3597
|
+
// size = "sm" | "md" | "lg" | "icon"
|
|
3160
3598
|
|
|
3161
|
-
|
|
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
|
|
3614
|
+
|
|
3615
|
+
---
|
|
3616
|
+
|
|
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:
|
|
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,25 @@ 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": "
|
|
4182
|
-
"generatedAt": "2026-05-
|
|
5040
|
+
"version": "1.1.0",
|
|
5041
|
+
"generatedAt": "2026-05-15",
|
|
4183
5042
|
"package": "@usevyre/react",
|
|
4184
|
-
"packageVersion": "
|
|
5043
|
+
"packageVersion": "1.1.0",
|
|
4185
5044
|
"validFor": [
|
|
4186
|
-
"@usevyre/react@
|
|
4187
|
-
"@usevyre/vue@
|
|
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
|
+
},
|
|
5054
|
+
"1.0.0": {
|
|
5055
|
+
"date": "2026-05-13",
|
|
5056
|
+
"breaking": true,
|
|
5057
|
+
"summary": "Stable v1.0 release — VyreCode renamed to Code in Vue, BreadcrumbLink + BreadcrumbSeparator added to React, Toast setup updated"
|
|
5058
|
+
},
|
|
4190
5059
|
"0.2.0": {
|
|
4191
5060
|
"date": "2026-05-08",
|
|
4192
5061
|
"breaking": false,
|
|
@@ -5451,12 +6320,370 @@ export const schema = {
|
|
|
5451
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>"
|
|
5452
6321
|
}
|
|
5453
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
|
+
]
|
|
5454
6681
|
}
|
|
5455
6682
|
}
|
|
5456
6683
|
};
|
|
5457
6684
|
|
|
5458
6685
|
export const antiPatterns = {
|
|
5459
|
-
"version": "
|
|
6686
|
+
"version": "1.1.0",
|
|
5460
6687
|
"rules": [
|
|
5461
6688
|
{
|
|
5462
6689
|
"component": "Accordion",
|
|
@@ -5674,19 +6901,134 @@ export const antiPatterns = {
|
|
|
5674
6901
|
"reason": "Typography components apply the correct token-based styles",
|
|
5675
6902
|
"fix": "Use <Heading>, <Text>, <Lead> from @usevyre/react",
|
|
5676
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"
|
|
5677
7009
|
}
|
|
5678
7010
|
]
|
|
5679
7011
|
};
|
|
5680
7012
|
|
|
5681
7013
|
export const versionInfo = {
|
|
5682
|
-
"version": "
|
|
5683
|
-
"packageVersion": "
|
|
5684
|
-
"generatedAt": "2026-05-
|
|
7014
|
+
"version": "1.1.0",
|
|
7015
|
+
"packageVersion": "1.1.0",
|
|
7016
|
+
"generatedAt": "2026-05-15T15:01:34.101Z",
|
|
5685
7017
|
"validFor": [
|
|
5686
|
-
"@usevyre/react@
|
|
5687
|
-
"@usevyre/vue@
|
|
7018
|
+
"@usevyre/react@1.1.0+",
|
|
7019
|
+
"@usevyre/vue@1.1.0+"
|
|
5688
7020
|
],
|
|
5689
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
|
+
},
|
|
7027
|
+
"1.0.0": {
|
|
7028
|
+
"date": "2026-05-13",
|
|
7029
|
+
"breaking": true,
|
|
7030
|
+
"summary": "Stable v1.0 release — VyreCode renamed to Code in Vue, BreadcrumbLink + BreadcrumbSeparator added to React, Toast setup updated"
|
|
7031
|
+
},
|
|
5690
7032
|
"0.2.0": {
|
|
5691
7033
|
"date": "2026-05-08",
|
|
5692
7034
|
"breaking": false,
|
|
@@ -5700,211 +7042,253 @@ export const versionInfo = {
|
|
|
5700
7042
|
},
|
|
5701
7043
|
"components": {
|
|
5702
7044
|
"Accordion": {
|
|
5703
|
-
"version": "
|
|
5704
|
-
"lastUpdated": "2026-05-
|
|
7045
|
+
"version": "1.1.0",
|
|
7046
|
+
"lastUpdated": "2026-05-15",
|
|
5705
7047
|
"breaking": false,
|
|
5706
7048
|
"stable": true,
|
|
5707
7049
|
"changelog": null
|
|
5708
7050
|
},
|
|
5709
7051
|
"Alert": {
|
|
5710
|
-
"version": "
|
|
5711
|
-
"lastUpdated": "2026-05-
|
|
7052
|
+
"version": "1.1.0",
|
|
7053
|
+
"lastUpdated": "2026-05-15",
|
|
5712
7054
|
"breaking": false,
|
|
5713
7055
|
"stable": true,
|
|
5714
7056
|
"changelog": null
|
|
5715
7057
|
},
|
|
5716
7058
|
"Avatar": {
|
|
5717
|
-
"version": "
|
|
5718
|
-
"lastUpdated": "2026-05-
|
|
7059
|
+
"version": "1.1.0",
|
|
7060
|
+
"lastUpdated": "2026-05-15",
|
|
5719
7061
|
"breaking": false,
|
|
5720
7062
|
"stable": true,
|
|
5721
7063
|
"changelog": null
|
|
5722
7064
|
},
|
|
5723
7065
|
"Badge": {
|
|
5724
|
-
"version": "
|
|
5725
|
-
"lastUpdated": "2026-05-
|
|
7066
|
+
"version": "1.1.0",
|
|
7067
|
+
"lastUpdated": "2026-05-15",
|
|
5726
7068
|
"breaking": false,
|
|
5727
7069
|
"stable": true,
|
|
5728
7070
|
"changelog": null
|
|
5729
7071
|
},
|
|
5730
7072
|
"Breadcrumb": {
|
|
5731
|
-
"version": "
|
|
5732
|
-
"lastUpdated": "2026-05-
|
|
7073
|
+
"version": "1.1.0",
|
|
7074
|
+
"lastUpdated": "2026-05-15",
|
|
5733
7075
|
"breaking": false,
|
|
5734
7076
|
"stable": true,
|
|
5735
7077
|
"changelog": null
|
|
5736
7078
|
},
|
|
5737
7079
|
"Button": {
|
|
5738
|
-
"version": "
|
|
5739
|
-
"lastUpdated": "2026-05-
|
|
7080
|
+
"version": "1.1.0",
|
|
7081
|
+
"lastUpdated": "2026-05-15",
|
|
5740
7082
|
"breaking": false,
|
|
5741
7083
|
"stable": true,
|
|
5742
7084
|
"changelog": null
|
|
5743
7085
|
},
|
|
5744
7086
|
"Calendar": {
|
|
5745
|
-
"version": "
|
|
5746
|
-
"lastUpdated": "2026-05-
|
|
7087
|
+
"version": "1.1.0",
|
|
7088
|
+
"lastUpdated": "2026-05-15",
|
|
5747
7089
|
"breaking": false,
|
|
5748
7090
|
"stable": true,
|
|
5749
7091
|
"changelog": null
|
|
5750
7092
|
},
|
|
5751
7093
|
"Card": {
|
|
5752
|
-
"version": "
|
|
5753
|
-
"lastUpdated": "2026-05-
|
|
7094
|
+
"version": "1.1.0",
|
|
7095
|
+
"lastUpdated": "2026-05-15",
|
|
5754
7096
|
"breaking": false,
|
|
5755
7097
|
"stable": true,
|
|
5756
7098
|
"changelog": null
|
|
5757
7099
|
},
|
|
5758
7100
|
"Checkbox": {
|
|
5759
|
-
"version": "
|
|
5760
|
-
"lastUpdated": "2026-05-
|
|
7101
|
+
"version": "1.1.0",
|
|
7102
|
+
"lastUpdated": "2026-05-15",
|
|
5761
7103
|
"breaking": false,
|
|
5762
7104
|
"stable": true,
|
|
5763
7105
|
"changelog": null
|
|
5764
7106
|
},
|
|
5765
7107
|
"Command": {
|
|
5766
|
-
"version": "
|
|
5767
|
-
"lastUpdated": "2026-05-
|
|
7108
|
+
"version": "1.1.0",
|
|
7109
|
+
"lastUpdated": "2026-05-15",
|
|
5768
7110
|
"breaking": false,
|
|
5769
7111
|
"stable": true,
|
|
5770
7112
|
"changelog": null
|
|
5771
7113
|
},
|
|
5772
7114
|
"DropdownMenu": {
|
|
5773
|
-
"version": "
|
|
5774
|
-
"lastUpdated": "2026-05-
|
|
7115
|
+
"version": "1.1.0",
|
|
7116
|
+
"lastUpdated": "2026-05-15",
|
|
5775
7117
|
"breaking": false,
|
|
5776
7118
|
"stable": true,
|
|
5777
7119
|
"changelog": null
|
|
5778
7120
|
},
|
|
5779
7121
|
"Field": {
|
|
5780
|
-
"version": "
|
|
5781
|
-
"lastUpdated": "2026-05-
|
|
7122
|
+
"version": "1.1.0",
|
|
7123
|
+
"lastUpdated": "2026-05-15",
|
|
5782
7124
|
"breaking": false,
|
|
5783
7125
|
"stable": true,
|
|
5784
7126
|
"changelog": null
|
|
5785
7127
|
},
|
|
5786
7128
|
"Input": {
|
|
5787
|
-
"version": "
|
|
5788
|
-
"lastUpdated": "2026-05-
|
|
7129
|
+
"version": "1.1.0",
|
|
7130
|
+
"lastUpdated": "2026-05-15",
|
|
5789
7131
|
"breaking": false,
|
|
5790
7132
|
"stable": true,
|
|
5791
7133
|
"changelog": null
|
|
5792
7134
|
},
|
|
5793
7135
|
"Label": {
|
|
5794
|
-
"version": "
|
|
5795
|
-
"lastUpdated": "2026-05-
|
|
7136
|
+
"version": "1.1.0",
|
|
7137
|
+
"lastUpdated": "2026-05-15",
|
|
5796
7138
|
"breaking": false,
|
|
5797
7139
|
"stable": true,
|
|
5798
7140
|
"changelog": null
|
|
5799
7141
|
},
|
|
5800
7142
|
"Modal": {
|
|
5801
|
-
"version": "
|
|
5802
|
-
"lastUpdated": "2026-05-
|
|
7143
|
+
"version": "1.1.0",
|
|
7144
|
+
"lastUpdated": "2026-05-15",
|
|
5803
7145
|
"breaking": false,
|
|
5804
7146
|
"stable": true,
|
|
5805
7147
|
"changelog": null
|
|
5806
7148
|
},
|
|
5807
7149
|
"Pagination": {
|
|
5808
|
-
"version": "
|
|
5809
|
-
"lastUpdated": "2026-05-
|
|
7150
|
+
"version": "1.1.0",
|
|
7151
|
+
"lastUpdated": "2026-05-15",
|
|
5810
7152
|
"breaking": false,
|
|
5811
7153
|
"stable": true,
|
|
5812
7154
|
"changelog": null
|
|
5813
7155
|
},
|
|
5814
7156
|
"Popover": {
|
|
5815
|
-
"version": "
|
|
5816
|
-
"lastUpdated": "2026-05-
|
|
7157
|
+
"version": "1.1.0",
|
|
7158
|
+
"lastUpdated": "2026-05-15",
|
|
5817
7159
|
"breaking": false,
|
|
5818
7160
|
"stable": true,
|
|
5819
7161
|
"changelog": null
|
|
5820
7162
|
},
|
|
5821
7163
|
"Progress": {
|
|
5822
|
-
"version": "
|
|
5823
|
-
"lastUpdated": "2026-05-
|
|
7164
|
+
"version": "1.1.0",
|
|
7165
|
+
"lastUpdated": "2026-05-15",
|
|
5824
7166
|
"breaking": false,
|
|
5825
7167
|
"stable": true,
|
|
5826
7168
|
"changelog": null
|
|
5827
7169
|
},
|
|
5828
7170
|
"Select": {
|
|
5829
|
-
"version": "
|
|
5830
|
-
"lastUpdated": "2026-05-
|
|
7171
|
+
"version": "1.1.0",
|
|
7172
|
+
"lastUpdated": "2026-05-15",
|
|
5831
7173
|
"breaking": false,
|
|
5832
7174
|
"stable": true,
|
|
5833
7175
|
"changelog": null
|
|
5834
7176
|
},
|
|
5835
7177
|
"Separator": {
|
|
5836
|
-
"version": "
|
|
5837
|
-
"lastUpdated": "2026-05-
|
|
7178
|
+
"version": "1.1.0",
|
|
7179
|
+
"lastUpdated": "2026-05-15",
|
|
5838
7180
|
"breaking": false,
|
|
5839
7181
|
"stable": true,
|
|
5840
7182
|
"changelog": null
|
|
5841
7183
|
},
|
|
5842
7184
|
"Sheet": {
|
|
5843
|
-
"version": "
|
|
5844
|
-
"lastUpdated": "2026-05-
|
|
7185
|
+
"version": "1.1.0",
|
|
7186
|
+
"lastUpdated": "2026-05-15",
|
|
5845
7187
|
"breaking": false,
|
|
5846
7188
|
"stable": true,
|
|
5847
7189
|
"changelog": null
|
|
5848
7190
|
},
|
|
5849
7191
|
"Sidebar": {
|
|
5850
|
-
"version": "
|
|
5851
|
-
"lastUpdated": "2026-05-
|
|
7192
|
+
"version": "1.1.0",
|
|
7193
|
+
"lastUpdated": "2026-05-15",
|
|
5852
7194
|
"breaking": false,
|
|
5853
7195
|
"stable": true,
|
|
5854
7196
|
"changelog": null
|
|
5855
7197
|
},
|
|
5856
7198
|
"Skeleton": {
|
|
5857
|
-
"version": "
|
|
5858
|
-
"lastUpdated": "2026-05-
|
|
7199
|
+
"version": "1.1.0",
|
|
7200
|
+
"lastUpdated": "2026-05-15",
|
|
5859
7201
|
"breaking": false,
|
|
5860
7202
|
"stable": true,
|
|
5861
7203
|
"changelog": null
|
|
5862
7204
|
},
|
|
5863
7205
|
"Slider": {
|
|
5864
|
-
"version": "
|
|
5865
|
-
"lastUpdated": "2026-05-
|
|
7206
|
+
"version": "1.1.0",
|
|
7207
|
+
"lastUpdated": "2026-05-15",
|
|
5866
7208
|
"breaking": false,
|
|
5867
7209
|
"stable": true,
|
|
5868
7210
|
"changelog": null
|
|
5869
7211
|
},
|
|
5870
7212
|
"Switch": {
|
|
5871
|
-
"version": "
|
|
5872
|
-
"lastUpdated": "2026-05-
|
|
7213
|
+
"version": "1.1.0",
|
|
7214
|
+
"lastUpdated": "2026-05-15",
|
|
5873
7215
|
"breaking": false,
|
|
5874
7216
|
"stable": true,
|
|
5875
7217
|
"changelog": null
|
|
5876
7218
|
},
|
|
5877
7219
|
"Table": {
|
|
5878
|
-
"version": "
|
|
5879
|
-
"lastUpdated": "2026-05-
|
|
7220
|
+
"version": "1.1.0",
|
|
7221
|
+
"lastUpdated": "2026-05-15",
|
|
5880
7222
|
"breaking": false,
|
|
5881
7223
|
"stable": true,
|
|
5882
7224
|
"changelog": null
|
|
5883
7225
|
},
|
|
5884
7226
|
"Tabs": {
|
|
5885
|
-
"version": "
|
|
5886
|
-
"lastUpdated": "2026-05-
|
|
7227
|
+
"version": "1.1.0",
|
|
7228
|
+
"lastUpdated": "2026-05-15",
|
|
5887
7229
|
"breaking": false,
|
|
5888
7230
|
"stable": true,
|
|
5889
7231
|
"changelog": null
|
|
5890
7232
|
},
|
|
5891
7233
|
"Toast": {
|
|
5892
|
-
"version": "
|
|
5893
|
-
"lastUpdated": "2026-05-
|
|
7234
|
+
"version": "1.1.0",
|
|
7235
|
+
"lastUpdated": "2026-05-15",
|
|
5894
7236
|
"breaking": false,
|
|
5895
7237
|
"stable": true,
|
|
5896
7238
|
"changelog": null
|
|
5897
7239
|
},
|
|
5898
7240
|
"Tooltip": {
|
|
5899
|
-
"version": "
|
|
5900
|
-
"lastUpdated": "2026-05-
|
|
7241
|
+
"version": "1.1.0",
|
|
7242
|
+
"lastUpdated": "2026-05-15",
|
|
5901
7243
|
"breaking": false,
|
|
5902
7244
|
"stable": true,
|
|
5903
7245
|
"changelog": null
|
|
5904
7246
|
},
|
|
5905
7247
|
"Typography": {
|
|
5906
|
-
"version": "
|
|
5907
|
-
"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",
|
|
5908
7292
|
"breaking": false,
|
|
5909
7293
|
"stable": true,
|
|
5910
7294
|
"changelog": null
|
|
@@ -5942,5 +7326,11 @@ export const cheatSheets = {
|
|
|
5942
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",
|
|
5943
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",
|
|
5944
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",
|
|
5945
|
-
"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"
|
|
5946
7336
|
};
|