@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/index.js CHANGED
@@ -1,7 +1,7 @@
1
- // @usevyre/ai-context v0.2.0
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 = "0.2.0";
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: 0.2.0
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: 0.2.0
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: 0.2.0
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
- ## Hallucination Guard — Common AI Mistakes
3587
+ ### ButtonGroup
3123
3588
 
3124
- The following prop values and patterns do NOT exist in useVyre.
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
- - ❌ \`<Accordion Accordion without AccordionItem>\` → Always compose: Accordion > AccordionItem > AccordionTrigger + AccordionContent
3128
- - \`<Alert variant="error">\` Use variant="danger"
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
- ## Styling Rules for AI Agents
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: 0.2.0
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": "0.2.0",
4182
- "generatedAt": "2026-05-08",
5040
+ "version": "1.1.0",
5041
+ "generatedAt": "2026-05-15",
4183
5042
  "package": "@usevyre/react",
4184
- "packageVersion": "0.1.1",
5043
+ "packageVersion": "1.1.0",
4185
5044
  "validFor": [
4186
- "@usevyre/react@0.1.1+",
4187
- "@usevyre/vue@0.1.1+"
5045
+ "@usevyre/react@1.1.0+",
5046
+ "@usevyre/vue@1.1.0+"
4188
5047
  ],
4189
5048
  "changelog": {
5049
+ "1.1.0": {
5050
+ "date": "2026-05-15",
5051
+ "breaking": false,
5052
+ "summary": "Added 6 components: ButtonGroup, TagsInput, Combobox, DataGrid, Tag, TagGroup"
5053
+ },
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": "0.2.0",
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": "0.2.0",
5683
- "packageVersion": "0.1.1",
5684
- "generatedAt": "2026-05-10T13:15:02.040Z",
7014
+ "version": "1.1.0",
7015
+ "packageVersion": "1.1.0",
7016
+ "generatedAt": "2026-05-15T15:01:34.101Z",
5685
7017
  "validFor": [
5686
- "@usevyre/react@0.1.1+",
5687
- "@usevyre/vue@0.1.1+"
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": "0.1.1",
5704
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5711
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5718
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5725
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5732
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5739
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5746
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5753
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5760
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5767
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5774
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5781
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5788
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5795
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5802
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5809
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5816
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5823
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5830
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5837
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5844
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5851
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5858
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5865
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5872
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5879
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5886
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5893
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5900
- "lastUpdated": "2026-05-08",
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": "0.1.1",
5907
- "lastUpdated": "2026-05-08",
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
  };