@usevyre/ai-context 1.2.2 → 1.3.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/box.md +52 -0
- package/dist/cheat-sheets/button.md +2 -0
- package/dist/cheat-sheets/card.md +2 -0
- package/dist/cheat-sheets/grid.md +50 -0
- package/dist/cheat-sheets/griditem.md +24 -0
- package/dist/cheat-sheets/index.md +4 -0
- package/dist/cheat-sheets/input.md +2 -0
- package/dist/cheat-sheets/stack.md +55 -0
- package/dist/claude-context.md +170 -1
- package/dist/copilot-instructions.md +170 -1
- package/dist/cursor-rules.md +84 -1
- package/dist/full-context.md +169 -0
- package/dist/index.js +1734 -113
- package/dist/schema.json +708 -3
- package/dist/tokens.json +1 -1
- package/dist/tokens.md +1 -1
- package/dist/version-info.json +139 -91
- package/dist/windsurf-rules.md +170 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
// @usevyre/ai-context v1.
|
|
1
|
+
// @usevyre/ai-context v1.6.0
|
|
2
2
|
// Auto-generated — do not edit directly. Edit src/schema/components.json instead.
|
|
3
3
|
|
|
4
|
-
export const version = "1.
|
|
4
|
+
export const version = "1.6.0";
|
|
5
5
|
|
|
6
6
|
export const fullContext = `# useVyre Design System — AI Context
|
|
7
7
|
# Version: 0.2.0
|
|
@@ -344,6 +344,7 @@ import { Button } from "@usevyre/react"
|
|
|
344
344
|
- ❌ \`color="..."\` → Use variant prop instead
|
|
345
345
|
- ❌ \`icon={...}\` → Use leftIcon={...} or rightIcon={...}
|
|
346
346
|
- ❌ \`size="icon" without aria-label\` → Add aria-label describing the action
|
|
347
|
+
- ❌ \`padding / margin / marginTop (any spacing prop) on a useVyre component\` → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
347
348
|
|
|
348
349
|
---
|
|
349
350
|
|
|
@@ -429,6 +430,7 @@ import { Card, CardHeader, CardBody, CardFooter } from "@usevyre/react"
|
|
|
429
430
|
|
|
430
431
|
**Common mistakes:**
|
|
431
432
|
- ❌ \`variant="primary"\` → Use variant="elevated" | "outlined" | "ghost" | "accent"
|
|
433
|
+
- ❌ \`padding / margin / marginTop (any spacing prop) on a useVyre component\` → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
432
434
|
|
|
433
435
|
---
|
|
434
436
|
|
|
@@ -640,6 +642,7 @@ import { Input } from "@usevyre/react"
|
|
|
640
642
|
- ❌ \`size="icon"\` → Use size="sm" | "md" | "lg"
|
|
641
643
|
- ❌ \`type="search" for search UI\` → Import Command from @usevyre/react for search palettes
|
|
642
644
|
- ❌ \`Vue: binding Input/Textarea value without v-model\` → Use v-model on <Input>/<Textarea> in Vue; in React use value + onChange
|
|
645
|
+
- ❌ \`padding / margin / marginTop (any spacing prop) on a useVyre component\` → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
643
646
|
|
|
644
647
|
---
|
|
645
648
|
|
|
@@ -1382,6 +1385,157 @@ const messages = [
|
|
|
1382
1385
|
|
|
1383
1386
|
---
|
|
1384
1387
|
|
|
1388
|
+
### Stack
|
|
1389
|
+
|
|
1390
|
+
Full one-dimensional flex layout primitive. USE INSTEAD OF <div style={{display:'flex'}}>. Covers the whole CSS flexbox surface (direction incl. reverse, wrap, align/justify/alignContent/alignSelf, grow/shrink/basis, per-axis gap) with token-locked spacing. Renders a plain <div> (or \`as\`).
|
|
1391
|
+
|
|
1392
|
+
\`\`\`tsx
|
|
1393
|
+
import { Stack } from "@usevyre/react"
|
|
1394
|
+
|
|
1395
|
+
// Props:
|
|
1396
|
+
// direction = "row" | "column" | "row-reverse" | "column-reverse" (default: row)
|
|
1397
|
+
// inline = boolean (default: false)
|
|
1398
|
+
// gap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" (default: md)
|
|
1399
|
+
// rowGap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
1400
|
+
// columnGap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
1401
|
+
// align = "start" | "center" | "end" | "stretch" | "baseline" (default: stretch)
|
|
1402
|
+
// justify = "start" | "center" | "end" | "between" | "around" | "evenly" (default: start)
|
|
1403
|
+
// alignContent = "start" | "center" | "end" | "stretch" | "between" | "around" | "evenly"
|
|
1404
|
+
// alignSelf = "auto" | "start" | "center" | "end" | "stretch" | "baseline"
|
|
1405
|
+
// wrap = "nowrap" | "wrap" | "wrap-reverse" (default: nowrap)
|
|
1406
|
+
// grow = number
|
|
1407
|
+
// shrink = number
|
|
1408
|
+
// basis = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "auto" | "content" | "0"
|
|
1409
|
+
// width = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
1410
|
+
// height = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
1411
|
+
// as = string (default: div)
|
|
1412
|
+
|
|
1413
|
+
// Examples:
|
|
1414
|
+
<Stack direction="row" gap="md" align="center" justify="between">
|
|
1415
|
+
<Avatar src={user.avatar} />
|
|
1416
|
+
<Text>{user.name}</Text>
|
|
1417
|
+
<Button>Edit</Button>
|
|
1418
|
+
</Stack>
|
|
1419
|
+
<Stack wrap="wrap" rowGap="lg" columnGap="md">
|
|
1420
|
+
{tags.map((t) => <Tag key={t}>{t}</Tag>)}
|
|
1421
|
+
</Stack>
|
|
1422
|
+
\`\`\`
|
|
1423
|
+
|
|
1424
|
+
**Common mistakes:**
|
|
1425
|
+
- ❌ \`<div style={{ display: 'flex', gap: 12 }}>\` → Use <Stack gap="md"> — gap is a token
|
|
1426
|
+
- ❌ \`gap={12} or gap="12px"\` → Use gap="none|xs|sm|md|lg|xl|2xl"
|
|
1427
|
+
- ❌ \`direction="vertical" / "horizontal"\` → Use direction="row" or "column" (also row-reverse / column-reverse)
|
|
1428
|
+
- ❌ \`style={{ width: "100%" }} / style={{ height: 320 }}\` → Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
1429
|
+
|
|
1430
|
+
---
|
|
1431
|
+
|
|
1432
|
+
### Grid
|
|
1433
|
+
|
|
1434
|
+
Two-dimensional CSS grid primitive. Explicit column/row counts (or auto-fit), auto-flow control, token gap. Pair with GridItem for cell spanning/placement. Renders a plain <div> (or \`as\`).
|
|
1435
|
+
|
|
1436
|
+
\`\`\`tsx
|
|
1437
|
+
import { Grid, GridItem } from "@usevyre/react"
|
|
1438
|
+
|
|
1439
|
+
// Props:
|
|
1440
|
+
// columns = number | "auto-fit" (default: 1)
|
|
1441
|
+
// rows = number | "auto"
|
|
1442
|
+
// flow = "row" | "column" | "dense" | "row-dense" | "column-dense"
|
|
1443
|
+
// gap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" (default: md)
|
|
1444
|
+
// rowGap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
1445
|
+
// columnGap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
1446
|
+
// align = "start" | "center" | "end" | "stretch" (default: stretch)
|
|
1447
|
+
// justify = "start" | "center" | "end" | "stretch"
|
|
1448
|
+
// width = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
1449
|
+
// height = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
1450
|
+
// as = string (default: div)
|
|
1451
|
+
|
|
1452
|
+
// Examples:
|
|
1453
|
+
<Grid columns={3} gap="lg">
|
|
1454
|
+
<GridItem colSpan={2}><Card>Wide</Card></GridItem>
|
|
1455
|
+
<Card>Two</Card>
|
|
1456
|
+
<Card>Three</Card>
|
|
1457
|
+
</Grid>
|
|
1458
|
+
<Grid columns="auto-fit" gap="md">
|
|
1459
|
+
{items.map((i) => <Card key={i.id}>{i.title}</Card>)}
|
|
1460
|
+
</Grid>
|
|
1461
|
+
\`\`\`
|
|
1462
|
+
|
|
1463
|
+
**Common mistakes:**
|
|
1464
|
+
- ❌ \`<div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr' }}>\` → Use <Grid columns={3} gap="md">
|
|
1465
|
+
- ❌ \`columns="3" (string)\` → Use columns={3} or columns="auto-fit"
|
|
1466
|
+
- ❌ \`Nested div with inline grid-column for spanning\` → Wrap the cell in <GridItem colSpan={2}>
|
|
1467
|
+
- ❌ \`style={{ width: "100%" }} / style={{ height: 320 }}\` → Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
1468
|
+
|
|
1469
|
+
---
|
|
1470
|
+
|
|
1471
|
+
### GridItem
|
|
1472
|
+
|
|
1473
|
+
Child placement inside <Grid>. Sets column/row span and start lines. Renders a plain <div> (or \`as\`).
|
|
1474
|
+
|
|
1475
|
+
\`\`\`tsx
|
|
1476
|
+
import { GridItem } from "@usevyre/react"
|
|
1477
|
+
|
|
1478
|
+
// Props:
|
|
1479
|
+
// colSpan = number
|
|
1480
|
+
// rowSpan = number
|
|
1481
|
+
// colStart = number
|
|
1482
|
+
// rowStart = number
|
|
1483
|
+
// as = string (default: div)
|
|
1484
|
+
|
|
1485
|
+
// Examples:
|
|
1486
|
+
<Grid columns={4} gap="md">
|
|
1487
|
+
<GridItem colSpan={2}>Featured</GridItem>
|
|
1488
|
+
<div>a</div>
|
|
1489
|
+
<div>b</div>
|
|
1490
|
+
</Grid>
|
|
1491
|
+
\`\`\`
|
|
1492
|
+
|
|
1493
|
+
**Common mistakes:**
|
|
1494
|
+
- ❌ \`GridItem outside a Grid\` → Place <GridItem> directly inside <Grid>
|
|
1495
|
+
|
|
1496
|
+
---
|
|
1497
|
+
|
|
1498
|
+
### Box
|
|
1499
|
+
|
|
1500
|
+
Spacing-only container plus a controlled escape hatch. Token padding/margin with shorthand, per-axis (X/Y) and per-side (Top/Right/Bottom/Left) overrides. The \`style\` prop is an explicit anti-pattern escape hatch. Renders a plain <div> (or \`as\`).
|
|
1501
|
+
|
|
1502
|
+
\`\`\`tsx
|
|
1503
|
+
import { Box } from "@usevyre/react"
|
|
1504
|
+
|
|
1505
|
+
// Props:
|
|
1506
|
+
// padding = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
1507
|
+
// paddingX = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
1508
|
+
// paddingY = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
1509
|
+
// paddingTop = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
1510
|
+
// paddingRight = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
1511
|
+
// paddingBottom = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
1512
|
+
// paddingLeft = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
1513
|
+
// margin = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
1514
|
+
// marginX = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
1515
|
+
// marginY = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
1516
|
+
// marginTop = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
1517
|
+
// marginRight = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
1518
|
+
// marginBottom = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
1519
|
+
// marginLeft = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
1520
|
+
// width = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
1521
|
+
// height = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
1522
|
+
// as = string (default: div)
|
|
1523
|
+
// style = React.CSSProperties
|
|
1524
|
+
|
|
1525
|
+
// Examples:
|
|
1526
|
+
<Box as="section" paddingX="lg" paddingY="md">
|
|
1527
|
+
<Heading>Settings</Heading>
|
|
1528
|
+
</Box>
|
|
1529
|
+
<Box marginTop="xl"><Separator /></Box>
|
|
1530
|
+
\`\`\`
|
|
1531
|
+
|
|
1532
|
+
**Common mistakes:**
|
|
1533
|
+
- ❌ \`<Box style={{ padding: 16 }}>\` → Use <Box padding="md"> (or paddingX/paddingTop/...)
|
|
1534
|
+
- ❌ \`Using Box for flex/grid layout\` → Use <Stack> or <Grid>
|
|
1535
|
+
- ❌ \`style={{ width: "100%" }} / style={{ height: 320 }}\` → Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
1536
|
+
|
|
1537
|
+
---
|
|
1538
|
+
|
|
1385
1539
|
### DateRangePicker
|
|
1386
1540
|
|
|
1387
1541
|
Start/end date range picker. Built on Calendar (mode=range) with a friendlier { from, to } object API, a two-month side-by-side view, and preset shortcuts. Use this for report/filter date ranges; use DatePicker for a single date.
|
|
@@ -1435,11 +1589,13 @@ If you generate these, you are hallucinating.
|
|
|
1435
1589
|
- ❌ \`<Button color="...">\` → Use variant prop instead
|
|
1436
1590
|
- ❌ \`<Button icon={...}>\` → Use leftIcon={...} or rightIcon={...}
|
|
1437
1591
|
- ❌ \`<Button size="icon" without aria-label>\` → Add aria-label describing the action
|
|
1592
|
+
- ❌ \`<Button padding / margin / marginTop (any spacing prop) on a useVyre component>\` → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
1438
1593
|
- ❌ \`<Calendar Calendar for an input field that opens a popover>\` → Use <DatePicker /> (single date) or <DateRangePicker /> (range)
|
|
1439
1594
|
- ❌ \`<Calendar value as tuple for mode="single">\` → Pass value matching mode; use mode="range" for [start,end]
|
|
1440
1595
|
- ❌ \`<DatePicker DatePicker mode="range" for { from, to } object>\` → Use <DateRangePicker /> for the { from, to } object API + presets + dual month
|
|
1441
1596
|
- ❌ \`<DatePicker DatePicker without value/onChange>\` → Provide value and onChange (e.g. from useState)
|
|
1442
1597
|
- ❌ \`<Card variant="primary">\` → Use variant="elevated" | "outlined" | "ghost" | "accent"
|
|
1598
|
+
- ❌ \`<Card padding / margin / marginTop (any spacing prop) on a useVyre component>\` → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
1443
1599
|
- ❌ \`<Checkbox size="lg">\` → Use size="md"
|
|
1444
1600
|
- ❌ \`<RadioGroup <Radio> used outside a <RadioGroup>>\` → Always wrap <Radio> in <RadioGroup>
|
|
1445
1601
|
- ❌ \`<RadioGroup RadioGroup without value/onChange (React) or v-model (Vue)>\` → Bind value + onChange (React) or v-model (Vue); or defaultValue for uncontrolled in React
|
|
@@ -1454,6 +1610,7 @@ If you generate these, you are hallucinating.
|
|
|
1454
1610
|
- ❌ \`<Input size="icon">\` → Use size="sm" | "md" | "lg"
|
|
1455
1611
|
- ❌ \`<Input type="search" for search UI>\` → Import Command from @usevyre/react for search palettes
|
|
1456
1612
|
- ❌ \`<Input Vue: binding Input/Textarea value without v-model>\` → Use v-model on <Input>/<Textarea> in Vue; in React use value + onChange
|
|
1613
|
+
- ❌ \`<Input padding / margin / marginTop (any spacing prop) on a useVyre component>\` → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
1457
1614
|
- ❌ \`<Modal size="xl">\` → Use size="lg" or size="full"
|
|
1458
1615
|
- ❌ \`<Popover placement="top-center">\` → Use placement="top" for centered placement
|
|
1459
1616
|
- ❌ \`<Progress value > 100>\` → Normalize your value to 0–100 range before passing
|
|
@@ -1490,6 +1647,18 @@ If you generate these, you are hallucinating.
|
|
|
1490
1647
|
- ❌ \`<Conversation Expecting Conversation to store/append messages>\` → Append to your own state in onSend (or @send) and pass it back via value
|
|
1491
1648
|
- ❌ \`<Conversation composer without onSend (React) / @send (Vue)>\` → Provide onSend / @send to append the message to value
|
|
1492
1649
|
- ❌ \`<Conversation Treating onSend as (text) only when using allowAttachments>\` → Handle onSend(text, files) — map files to message attachments and append
|
|
1650
|
+
- ❌ \`<Stack <div style={{ display: 'flex', gap: 12 }}>>\` → Use <Stack gap="md"> — gap is a token
|
|
1651
|
+
- ❌ \`<Stack gap={12} or gap="12px">\` → Use gap="none|xs|sm|md|lg|xl|2xl"
|
|
1652
|
+
- ❌ \`<Stack direction="vertical" / "horizontal">\` → Use direction="row" or "column" (also row-reverse / column-reverse)
|
|
1653
|
+
- ❌ \`<Stack style={{ width: "100%" }} / style={{ height: 320 }}>\` → Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
1654
|
+
- ❌ \`<Grid <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr' }}>>\` → Use <Grid columns={3} gap="md">
|
|
1655
|
+
- ❌ \`<Grid columns="3" (string)>\` → Use columns={3} or columns="auto-fit"
|
|
1656
|
+
- ❌ \`<Grid Nested div with inline grid-column for spanning>\` → Wrap the cell in <GridItem colSpan={2}>
|
|
1657
|
+
- ❌ \`<Grid style={{ width: "100%" }} / style={{ height: 320 }}>\` → Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
1658
|
+
- ❌ \`<GridItem GridItem outside a Grid>\` → Place <GridItem> directly inside <Grid>
|
|
1659
|
+
- ❌ \`<Box <Box style={{ padding: 16 }}>>\` → Use <Box padding="md"> (or paddingX/paddingTop/...)
|
|
1660
|
+
- ❌ \`<Box Using Box for flex/grid layout>\` → Use <Stack> or <Grid>
|
|
1661
|
+
- ❌ \`<Box style={{ width: "100%" }} / style={{ height: 320 }}>\` → Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
1493
1662
|
- ❌ \`<DateRangePicker value={[from, to]}>\` → Use value={{ from, to }} and read range.from / range.to
|
|
1494
1663
|
- ❌ \`<DateRangePicker DateRangePicker for a single date>\` → Use <DatePicker /> for a single date
|
|
1495
1664
|
- ❌ \`<DateRangePicker presets="true" (string)>\` → Use the bare prop: presets (or presets={true})
|
|
@@ -1547,7 +1716,7 @@ alwaysApply: true
|
|
|
1547
1716
|
---
|
|
1548
1717
|
|
|
1549
1718
|
# useVyre Design System — Cursor Rules
|
|
1550
|
-
# Version: 1.
|
|
1719
|
+
# Version: 1.6.0
|
|
1551
1720
|
|
|
1552
1721
|
You are working in a project using the useVyre design system (@usevyre/react).
|
|
1553
1722
|
Follow these rules strictly when generating any UI code.
|
|
@@ -1636,6 +1805,7 @@ Never do:
|
|
|
1636
1805
|
- ❌ color="..." → ✅ Use variant prop instead
|
|
1637
1806
|
- ❌ icon={...} → ✅ Use leftIcon={...} or rightIcon={...}
|
|
1638
1807
|
- ❌ size="icon" without aria-label → ✅ Add aria-label describing the action
|
|
1808
|
+
- ❌ padding / margin / marginTop (any spacing prop) on a useVyre component → ✅ Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
1639
1809
|
|
|
1640
1810
|
## Calendar
|
|
1641
1811
|
Inline date-grid widget (always visible, no input). mode: single | range | multiple, optional time picker. For an input + popover use DatePicker; for start/end ranges with presets use DateRangePicker.
|
|
@@ -1668,6 +1838,7 @@ Valid props:
|
|
|
1668
1838
|
|
|
1669
1839
|
Never do:
|
|
1670
1840
|
- ❌ variant="primary" → ✅ Use variant="elevated" | "outlined" | "ghost" | "accent"
|
|
1841
|
+
- ❌ padding / margin / marginTop (any spacing prop) on a useVyre component → ✅ Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
1671
1842
|
|
|
1672
1843
|
## Checkbox
|
|
1673
1844
|
Binary toggle for boolean form values.
|
|
@@ -1741,6 +1912,7 @@ Never do:
|
|
|
1741
1912
|
- ❌ size="icon" → ✅ Use size="sm" | "md" | "lg"
|
|
1742
1913
|
- ❌ type="search" for search UI → ✅ Import Command from @usevyre/react for search palettes
|
|
1743
1914
|
- ❌ Vue: binding Input/Textarea value without v-model → ✅ Use v-model on <Input>/<Textarea> in Vue; in React use value + onChange
|
|
1915
|
+
- ❌ padding / margin / marginTop (any spacing prop) on a useVyre component → ✅ Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
1744
1916
|
|
|
1745
1917
|
## Label
|
|
1746
1918
|
Accessible form label. Associate with input via htmlFor.
|
|
@@ -1988,6 +2160,86 @@ Never do:
|
|
|
1988
2160
|
- ❌ composer without onSend (React) / @send (Vue) → ✅ Provide onSend / @send to append the message to value
|
|
1989
2161
|
- ❌ Treating onSend as (text) only when using allowAttachments → ✅ Handle onSend(text, files) — map files to message attachments and append
|
|
1990
2162
|
|
|
2163
|
+
## Stack
|
|
2164
|
+
Full one-dimensional flex layout primitive. USE INSTEAD OF <div style={{display:'flex'}}>. Covers the whole CSS flexbox surface (direction incl. reverse, wrap, align/justify/alignContent/alignSelf, grow/shrink/basis, per-axis gap) with token-locked spacing. Renders a plain <div> (or \`as\`).
|
|
2165
|
+
Import: \`import { Stack } from "@usevyre/react"\`
|
|
2166
|
+
|
|
2167
|
+
Valid props:
|
|
2168
|
+
- direction: "row" | "column" | "row-reverse" | "column-reverse" [default: row]
|
|
2169
|
+
- gap: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" [default: md]
|
|
2170
|
+
- rowGap: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
2171
|
+
- columnGap: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
2172
|
+
- align: "start" | "center" | "end" | "stretch" | "baseline" [default: stretch]
|
|
2173
|
+
- justify: "start" | "center" | "end" | "between" | "around" | "evenly" [default: start]
|
|
2174
|
+
- alignContent: "start" | "center" | "end" | "stretch" | "between" | "around" | "evenly"
|
|
2175
|
+
- alignSelf: "auto" | "start" | "center" | "end" | "stretch" | "baseline"
|
|
2176
|
+
- wrap: "nowrap" | "wrap" | "wrap-reverse" [default: nowrap]
|
|
2177
|
+
- basis: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "auto" | "content" | "0"
|
|
2178
|
+
- width: "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
2179
|
+
- height: "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
2180
|
+
|
|
2181
|
+
Never do:
|
|
2182
|
+
- ❌ <div style={{ display: 'flex', gap: 12 }}> → ✅ Use <Stack gap="md"> — gap is a token
|
|
2183
|
+
- ❌ gap={12} or gap="12px" → ✅ Use gap="none|xs|sm|md|lg|xl|2xl"
|
|
2184
|
+
- ❌ direction="vertical" / "horizontal" → ✅ Use direction="row" or "column" (also row-reverse / column-reverse)
|
|
2185
|
+
- ❌ style={{ width: "100%" }} / style={{ height: 320 }} → ✅ Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
2186
|
+
|
|
2187
|
+
## Grid
|
|
2188
|
+
Two-dimensional CSS grid primitive. Explicit column/row counts (or auto-fit), auto-flow control, token gap. Pair with GridItem for cell spanning/placement. Renders a plain <div> (or \`as\`).
|
|
2189
|
+
Import: \`import { Grid, GridItem } from "@usevyre/react"\`
|
|
2190
|
+
|
|
2191
|
+
Valid props:
|
|
2192
|
+
- flow: "row" | "column" | "dense" | "row-dense" | "column-dense"
|
|
2193
|
+
- gap: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" [default: md]
|
|
2194
|
+
- rowGap: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
2195
|
+
- columnGap: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
2196
|
+
- align: "start" | "center" | "end" | "stretch" [default: stretch]
|
|
2197
|
+
- justify: "start" | "center" | "end" | "stretch"
|
|
2198
|
+
- width: "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
2199
|
+
- height: "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
2200
|
+
|
|
2201
|
+
Never do:
|
|
2202
|
+
- ❌ <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr' }}> → ✅ Use <Grid columns={3} gap="md">
|
|
2203
|
+
- ❌ columns="3" (string) → ✅ Use columns={3} or columns="auto-fit"
|
|
2204
|
+
- ❌ Nested div with inline grid-column for spanning → ✅ Wrap the cell in <GridItem colSpan={2}>
|
|
2205
|
+
- ❌ style={{ width: "100%" }} / style={{ height: 320 }} → ✅ Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
2206
|
+
|
|
2207
|
+
## GridItem
|
|
2208
|
+
Child placement inside <Grid>. Sets column/row span and start lines. Renders a plain <div> (or \`as\`).
|
|
2209
|
+
Import: \`import { GridItem } from "@usevyre/react"\`
|
|
2210
|
+
|
|
2211
|
+
Valid props:
|
|
2212
|
+
|
|
2213
|
+
Never do:
|
|
2214
|
+
- ❌ GridItem outside a Grid → ✅ Place <GridItem> directly inside <Grid>
|
|
2215
|
+
|
|
2216
|
+
## Box
|
|
2217
|
+
Spacing-only container plus a controlled escape hatch. Token padding/margin with shorthand, per-axis (X/Y) and per-side (Top/Right/Bottom/Left) overrides. The \`style\` prop is an explicit anti-pattern escape hatch. Renders a plain <div> (or \`as\`).
|
|
2218
|
+
Import: \`import { Box } from "@usevyre/react"\`
|
|
2219
|
+
|
|
2220
|
+
Valid props:
|
|
2221
|
+
- padding: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
2222
|
+
- paddingX: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
2223
|
+
- paddingY: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
2224
|
+
- paddingTop: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
2225
|
+
- paddingRight: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
2226
|
+
- paddingBottom: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
2227
|
+
- paddingLeft: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
2228
|
+
- margin: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
2229
|
+
- marginX: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
2230
|
+
- marginY: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
2231
|
+
- marginTop: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
2232
|
+
- marginRight: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
2233
|
+
- marginBottom: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
2234
|
+
- marginLeft: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
2235
|
+
- width: "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
2236
|
+
- height: "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
2237
|
+
|
|
2238
|
+
Never do:
|
|
2239
|
+
- ❌ <Box style={{ padding: 16 }}> → ✅ Use <Box padding="md"> (or paddingX/paddingTop/...)
|
|
2240
|
+
- ❌ Using Box for flex/grid layout → ✅ Use <Stack> or <Grid>
|
|
2241
|
+
- ❌ style={{ width: "100%" }} / style={{ height: 320 }} → ✅ Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
2242
|
+
|
|
1991
2243
|
## DateRangePicker
|
|
1992
2244
|
Start/end date range picker. Built on Calendar (mode=range) with a friendlier { from, to } object API, a two-month side-by-side view, and preset shortcuts. Use this for report/filter date ranges; use DatePicker for a single date.
|
|
1993
2245
|
Import: \`import { DateRangePicker } from "@usevyre/react"\`
|
|
@@ -2007,7 +2259,7 @@ Use --vyre-color-semantic-* for all colors. Never use primitive tokens.
|
|
|
2007
2259
|
Use --vyre-spacing-* for all spacing. Never use raw px in component code.
|
|
2008
2260
|
Use --vyre-border-radius-* for border radius.`;
|
|
2009
2261
|
export const claudeContext = `# useVyre Design System Context
|
|
2010
|
-
# Version: 1.
|
|
2262
|
+
# Version: 1.6.0
|
|
2011
2263
|
|
|
2012
2264
|
You are working in a codebase that uses the useVyre design system.
|
|
2013
2265
|
Follow the rules below strictly when writing any UI code.
|
|
@@ -2353,6 +2605,7 @@ import { Button } from "@usevyre/react"
|
|
|
2353
2605
|
- ❌ \`color="..."\` → Use variant prop instead
|
|
2354
2606
|
- ❌ \`icon={...}\` → Use leftIcon={...} or rightIcon={...}
|
|
2355
2607
|
- ❌ \`size="icon" without aria-label\` → Add aria-label describing the action
|
|
2608
|
+
- ❌ \`padding / margin / marginTop (any spacing prop) on a useVyre component\` → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
2356
2609
|
|
|
2357
2610
|
---
|
|
2358
2611
|
|
|
@@ -2438,6 +2691,7 @@ import { Card, CardHeader, CardBody, CardFooter } from "@usevyre/react"
|
|
|
2438
2691
|
|
|
2439
2692
|
**Common mistakes:**
|
|
2440
2693
|
- ❌ \`variant="primary"\` → Use variant="elevated" | "outlined" | "ghost" | "accent"
|
|
2694
|
+
- ❌ \`padding / margin / marginTop (any spacing prop) on a useVyre component\` → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
2441
2695
|
|
|
2442
2696
|
---
|
|
2443
2697
|
|
|
@@ -2649,6 +2903,7 @@ import { Input } from "@usevyre/react"
|
|
|
2649
2903
|
- ❌ \`size="icon"\` → Use size="sm" | "md" | "lg"
|
|
2650
2904
|
- ❌ \`type="search" for search UI\` → Import Command from @usevyre/react for search palettes
|
|
2651
2905
|
- ❌ \`Vue: binding Input/Textarea value without v-model\` → Use v-model on <Input>/<Textarea> in Vue; in React use value + onChange
|
|
2906
|
+
- ❌ \`padding / margin / marginTop (any spacing prop) on a useVyre component\` → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
2652
2907
|
|
|
2653
2908
|
---
|
|
2654
2909
|
|
|
@@ -3391,6 +3646,157 @@ const messages = [
|
|
|
3391
3646
|
|
|
3392
3647
|
---
|
|
3393
3648
|
|
|
3649
|
+
### Stack
|
|
3650
|
+
|
|
3651
|
+
Full one-dimensional flex layout primitive. USE INSTEAD OF <div style={{display:'flex'}}>. Covers the whole CSS flexbox surface (direction incl. reverse, wrap, align/justify/alignContent/alignSelf, grow/shrink/basis, per-axis gap) with token-locked spacing. Renders a plain <div> (or \`as\`).
|
|
3652
|
+
|
|
3653
|
+
\`\`\`tsx
|
|
3654
|
+
import { Stack } from "@usevyre/react"
|
|
3655
|
+
|
|
3656
|
+
// Props:
|
|
3657
|
+
// direction = "row" | "column" | "row-reverse" | "column-reverse" (default: row)
|
|
3658
|
+
// inline = boolean (default: false)
|
|
3659
|
+
// gap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" (default: md)
|
|
3660
|
+
// rowGap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
3661
|
+
// columnGap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
3662
|
+
// align = "start" | "center" | "end" | "stretch" | "baseline" (default: stretch)
|
|
3663
|
+
// justify = "start" | "center" | "end" | "between" | "around" | "evenly" (default: start)
|
|
3664
|
+
// alignContent = "start" | "center" | "end" | "stretch" | "between" | "around" | "evenly"
|
|
3665
|
+
// alignSelf = "auto" | "start" | "center" | "end" | "stretch" | "baseline"
|
|
3666
|
+
// wrap = "nowrap" | "wrap" | "wrap-reverse" (default: nowrap)
|
|
3667
|
+
// grow = number
|
|
3668
|
+
// shrink = number
|
|
3669
|
+
// basis = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "auto" | "content" | "0"
|
|
3670
|
+
// width = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
3671
|
+
// height = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
3672
|
+
// as = string (default: div)
|
|
3673
|
+
|
|
3674
|
+
// Examples:
|
|
3675
|
+
<Stack direction="row" gap="md" align="center" justify="between">
|
|
3676
|
+
<Avatar src={user.avatar} />
|
|
3677
|
+
<Text>{user.name}</Text>
|
|
3678
|
+
<Button>Edit</Button>
|
|
3679
|
+
</Stack>
|
|
3680
|
+
<Stack wrap="wrap" rowGap="lg" columnGap="md">
|
|
3681
|
+
{tags.map((t) => <Tag key={t}>{t}</Tag>)}
|
|
3682
|
+
</Stack>
|
|
3683
|
+
\`\`\`
|
|
3684
|
+
|
|
3685
|
+
**Common mistakes:**
|
|
3686
|
+
- ❌ \`<div style={{ display: 'flex', gap: 12 }}>\` → Use <Stack gap="md"> — gap is a token
|
|
3687
|
+
- ❌ \`gap={12} or gap="12px"\` → Use gap="none|xs|sm|md|lg|xl|2xl"
|
|
3688
|
+
- ❌ \`direction="vertical" / "horizontal"\` → Use direction="row" or "column" (also row-reverse / column-reverse)
|
|
3689
|
+
- ❌ \`style={{ width: "100%" }} / style={{ height: 320 }}\` → Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
3690
|
+
|
|
3691
|
+
---
|
|
3692
|
+
|
|
3693
|
+
### Grid
|
|
3694
|
+
|
|
3695
|
+
Two-dimensional CSS grid primitive. Explicit column/row counts (or auto-fit), auto-flow control, token gap. Pair with GridItem for cell spanning/placement. Renders a plain <div> (or \`as\`).
|
|
3696
|
+
|
|
3697
|
+
\`\`\`tsx
|
|
3698
|
+
import { Grid, GridItem } from "@usevyre/react"
|
|
3699
|
+
|
|
3700
|
+
// Props:
|
|
3701
|
+
// columns = number | "auto-fit" (default: 1)
|
|
3702
|
+
// rows = number | "auto"
|
|
3703
|
+
// flow = "row" | "column" | "dense" | "row-dense" | "column-dense"
|
|
3704
|
+
// gap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" (default: md)
|
|
3705
|
+
// rowGap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
3706
|
+
// columnGap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
3707
|
+
// align = "start" | "center" | "end" | "stretch" (default: stretch)
|
|
3708
|
+
// justify = "start" | "center" | "end" | "stretch"
|
|
3709
|
+
// width = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
3710
|
+
// height = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
3711
|
+
// as = string (default: div)
|
|
3712
|
+
|
|
3713
|
+
// Examples:
|
|
3714
|
+
<Grid columns={3} gap="lg">
|
|
3715
|
+
<GridItem colSpan={2}><Card>Wide</Card></GridItem>
|
|
3716
|
+
<Card>Two</Card>
|
|
3717
|
+
<Card>Three</Card>
|
|
3718
|
+
</Grid>
|
|
3719
|
+
<Grid columns="auto-fit" gap="md">
|
|
3720
|
+
{items.map((i) => <Card key={i.id}>{i.title}</Card>)}
|
|
3721
|
+
</Grid>
|
|
3722
|
+
\`\`\`
|
|
3723
|
+
|
|
3724
|
+
**Common mistakes:**
|
|
3725
|
+
- ❌ \`<div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr' }}>\` → Use <Grid columns={3} gap="md">
|
|
3726
|
+
- ❌ \`columns="3" (string)\` → Use columns={3} or columns="auto-fit"
|
|
3727
|
+
- ❌ \`Nested div with inline grid-column for spanning\` → Wrap the cell in <GridItem colSpan={2}>
|
|
3728
|
+
- ❌ \`style={{ width: "100%" }} / style={{ height: 320 }}\` → Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
3729
|
+
|
|
3730
|
+
---
|
|
3731
|
+
|
|
3732
|
+
### GridItem
|
|
3733
|
+
|
|
3734
|
+
Child placement inside <Grid>. Sets column/row span and start lines. Renders a plain <div> (or \`as\`).
|
|
3735
|
+
|
|
3736
|
+
\`\`\`tsx
|
|
3737
|
+
import { GridItem } from "@usevyre/react"
|
|
3738
|
+
|
|
3739
|
+
// Props:
|
|
3740
|
+
// colSpan = number
|
|
3741
|
+
// rowSpan = number
|
|
3742
|
+
// colStart = number
|
|
3743
|
+
// rowStart = number
|
|
3744
|
+
// as = string (default: div)
|
|
3745
|
+
|
|
3746
|
+
// Examples:
|
|
3747
|
+
<Grid columns={4} gap="md">
|
|
3748
|
+
<GridItem colSpan={2}>Featured</GridItem>
|
|
3749
|
+
<div>a</div>
|
|
3750
|
+
<div>b</div>
|
|
3751
|
+
</Grid>
|
|
3752
|
+
\`\`\`
|
|
3753
|
+
|
|
3754
|
+
**Common mistakes:**
|
|
3755
|
+
- ❌ \`GridItem outside a Grid\` → Place <GridItem> directly inside <Grid>
|
|
3756
|
+
|
|
3757
|
+
---
|
|
3758
|
+
|
|
3759
|
+
### Box
|
|
3760
|
+
|
|
3761
|
+
Spacing-only container plus a controlled escape hatch. Token padding/margin with shorthand, per-axis (X/Y) and per-side (Top/Right/Bottom/Left) overrides. The \`style\` prop is an explicit anti-pattern escape hatch. Renders a plain <div> (or \`as\`).
|
|
3762
|
+
|
|
3763
|
+
\`\`\`tsx
|
|
3764
|
+
import { Box } from "@usevyre/react"
|
|
3765
|
+
|
|
3766
|
+
// Props:
|
|
3767
|
+
// padding = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
3768
|
+
// paddingX = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
3769
|
+
// paddingY = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
3770
|
+
// paddingTop = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
3771
|
+
// paddingRight = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
3772
|
+
// paddingBottom = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
3773
|
+
// paddingLeft = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
3774
|
+
// margin = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
3775
|
+
// marginX = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
3776
|
+
// marginY = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
3777
|
+
// marginTop = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
3778
|
+
// marginRight = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
3779
|
+
// marginBottom = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
3780
|
+
// marginLeft = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
3781
|
+
// width = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
3782
|
+
// height = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
3783
|
+
// as = string (default: div)
|
|
3784
|
+
// style = React.CSSProperties
|
|
3785
|
+
|
|
3786
|
+
// Examples:
|
|
3787
|
+
<Box as="section" paddingX="lg" paddingY="md">
|
|
3788
|
+
<Heading>Settings</Heading>
|
|
3789
|
+
</Box>
|
|
3790
|
+
<Box marginTop="xl"><Separator /></Box>
|
|
3791
|
+
\`\`\`
|
|
3792
|
+
|
|
3793
|
+
**Common mistakes:**
|
|
3794
|
+
- ❌ \`<Box style={{ padding: 16 }}>\` → Use <Box padding="md"> (or paddingX/paddingTop/...)
|
|
3795
|
+
- ❌ \`Using Box for flex/grid layout\` → Use <Stack> or <Grid>
|
|
3796
|
+
- ❌ \`style={{ width: "100%" }} / style={{ height: 320 }}\` → Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
3797
|
+
|
|
3798
|
+
---
|
|
3799
|
+
|
|
3394
3800
|
### DateRangePicker
|
|
3395
3801
|
|
|
3396
3802
|
Start/end date range picker. Built on Calendar (mode=range) with a friendlier { from, to } object API, a two-month side-by-side view, and preset shortcuts. Use this for report/filter date ranges; use DatePicker for a single date.
|
|
@@ -3444,11 +3850,13 @@ If you generate these, you are hallucinating.
|
|
|
3444
3850
|
- ❌ \`<Button color="...">\` → Use variant prop instead
|
|
3445
3851
|
- ❌ \`<Button icon={...}>\` → Use leftIcon={...} or rightIcon={...}
|
|
3446
3852
|
- ❌ \`<Button size="icon" without aria-label>\` → Add aria-label describing the action
|
|
3853
|
+
- ❌ \`<Button padding / margin / marginTop (any spacing prop) on a useVyre component>\` → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
3447
3854
|
- ❌ \`<Calendar Calendar for an input field that opens a popover>\` → Use <DatePicker /> (single date) or <DateRangePicker /> (range)
|
|
3448
3855
|
- ❌ \`<Calendar value as tuple for mode="single">\` → Pass value matching mode; use mode="range" for [start,end]
|
|
3449
3856
|
- ❌ \`<DatePicker DatePicker mode="range" for { from, to } object>\` → Use <DateRangePicker /> for the { from, to } object API + presets + dual month
|
|
3450
3857
|
- ❌ \`<DatePicker DatePicker without value/onChange>\` → Provide value and onChange (e.g. from useState)
|
|
3451
3858
|
- ❌ \`<Card variant="primary">\` → Use variant="elevated" | "outlined" | "ghost" | "accent"
|
|
3859
|
+
- ❌ \`<Card padding / margin / marginTop (any spacing prop) on a useVyre component>\` → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
3452
3860
|
- ❌ \`<Checkbox size="lg">\` → Use size="md"
|
|
3453
3861
|
- ❌ \`<RadioGroup <Radio> used outside a <RadioGroup>>\` → Always wrap <Radio> in <RadioGroup>
|
|
3454
3862
|
- ❌ \`<RadioGroup RadioGroup without value/onChange (React) or v-model (Vue)>\` → Bind value + onChange (React) or v-model (Vue); or defaultValue for uncontrolled in React
|
|
@@ -3463,6 +3871,7 @@ If you generate these, you are hallucinating.
|
|
|
3463
3871
|
- ❌ \`<Input size="icon">\` → Use size="sm" | "md" | "lg"
|
|
3464
3872
|
- ❌ \`<Input type="search" for search UI>\` → Import Command from @usevyre/react for search palettes
|
|
3465
3873
|
- ❌ \`<Input Vue: binding Input/Textarea value without v-model>\` → Use v-model on <Input>/<Textarea> in Vue; in React use value + onChange
|
|
3874
|
+
- ❌ \`<Input padding / margin / marginTop (any spacing prop) on a useVyre component>\` → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
3466
3875
|
- ❌ \`<Modal size="xl">\` → Use size="lg" or size="full"
|
|
3467
3876
|
- ❌ \`<Popover placement="top-center">\` → Use placement="top" for centered placement
|
|
3468
3877
|
- ❌ \`<Progress value > 100>\` → Normalize your value to 0–100 range before passing
|
|
@@ -3499,6 +3908,18 @@ If you generate these, you are hallucinating.
|
|
|
3499
3908
|
- ❌ \`<Conversation Expecting Conversation to store/append messages>\` → Append to your own state in onSend (or @send) and pass it back via value
|
|
3500
3909
|
- ❌ \`<Conversation composer without onSend (React) / @send (Vue)>\` → Provide onSend / @send to append the message to value
|
|
3501
3910
|
- ❌ \`<Conversation Treating onSend as (text) only when using allowAttachments>\` → Handle onSend(text, files) — map files to message attachments and append
|
|
3911
|
+
- ❌ \`<Stack <div style={{ display: 'flex', gap: 12 }}>>\` → Use <Stack gap="md"> — gap is a token
|
|
3912
|
+
- ❌ \`<Stack gap={12} or gap="12px">\` → Use gap="none|xs|sm|md|lg|xl|2xl"
|
|
3913
|
+
- ❌ \`<Stack direction="vertical" / "horizontal">\` → Use direction="row" or "column" (also row-reverse / column-reverse)
|
|
3914
|
+
- ❌ \`<Stack style={{ width: "100%" }} / style={{ height: 320 }}>\` → Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
3915
|
+
- ❌ \`<Grid <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr' }}>>\` → Use <Grid columns={3} gap="md">
|
|
3916
|
+
- ❌ \`<Grid columns="3" (string)>\` → Use columns={3} or columns="auto-fit"
|
|
3917
|
+
- ❌ \`<Grid Nested div with inline grid-column for spanning>\` → Wrap the cell in <GridItem colSpan={2}>
|
|
3918
|
+
- ❌ \`<Grid style={{ width: "100%" }} / style={{ height: 320 }}>\` → Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
3919
|
+
- ❌ \`<GridItem GridItem outside a Grid>\` → Place <GridItem> directly inside <Grid>
|
|
3920
|
+
- ❌ \`<Box <Box style={{ padding: 16 }}>>\` → Use <Box padding="md"> (or paddingX/paddingTop/...)
|
|
3921
|
+
- ❌ \`<Box Using Box for flex/grid layout>\` → Use <Stack> or <Grid>
|
|
3922
|
+
- ❌ \`<Box style={{ width: "100%" }} / style={{ height: 320 }}>\` → Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
3502
3923
|
- ❌ \`<DateRangePicker value={[from, to]}>\` → Use value={{ from, to }} and read range.from / range.to
|
|
3503
3924
|
- ❌ \`<DateRangePicker DateRangePicker for a single date>\` → Use <DatePicker /> for a single date
|
|
3504
3925
|
- ❌ \`<DateRangePicker presets="true" (string)>\` → Use the bare prop: presets (or presets={true})
|
|
@@ -3551,7 +3972,7 @@ If you generate these, you are hallucinating.
|
|
|
3551
3972
|
\`\`\`
|
|
3552
3973
|
`;
|
|
3553
3974
|
export const windsurfRules = `# useVyre Rules for Windsurf
|
|
3554
|
-
# Version: 1.
|
|
3975
|
+
# Version: 1.6.0
|
|
3555
3976
|
|
|
3556
3977
|
# useVyre Design System — AI Context
|
|
3557
3978
|
# Version: 0.2.0
|
|
@@ -3894,6 +4315,7 @@ import { Button } from "@usevyre/react"
|
|
|
3894
4315
|
- ❌ \`color="..."\` → Use variant prop instead
|
|
3895
4316
|
- ❌ \`icon={...}\` → Use leftIcon={...} or rightIcon={...}
|
|
3896
4317
|
- ❌ \`size="icon" without aria-label\` → Add aria-label describing the action
|
|
4318
|
+
- ❌ \`padding / margin / marginTop (any spacing prop) on a useVyre component\` → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
3897
4319
|
|
|
3898
4320
|
---
|
|
3899
4321
|
|
|
@@ -3979,6 +4401,7 @@ import { Card, CardHeader, CardBody, CardFooter } from "@usevyre/react"
|
|
|
3979
4401
|
|
|
3980
4402
|
**Common mistakes:**
|
|
3981
4403
|
- ❌ \`variant="primary"\` → Use variant="elevated" | "outlined" | "ghost" | "accent"
|
|
4404
|
+
- ❌ \`padding / margin / marginTop (any spacing prop) on a useVyre component\` → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
3982
4405
|
|
|
3983
4406
|
---
|
|
3984
4407
|
|
|
@@ -4190,6 +4613,7 @@ import { Input } from "@usevyre/react"
|
|
|
4190
4613
|
- ❌ \`size="icon"\` → Use size="sm" | "md" | "lg"
|
|
4191
4614
|
- ❌ \`type="search" for search UI\` → Import Command from @usevyre/react for search palettes
|
|
4192
4615
|
- ❌ \`Vue: binding Input/Textarea value without v-model\` → Use v-model on <Input>/<Textarea> in Vue; in React use value + onChange
|
|
4616
|
+
- ❌ \`padding / margin / marginTop (any spacing prop) on a useVyre component\` → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
4193
4617
|
|
|
4194
4618
|
---
|
|
4195
4619
|
|
|
@@ -4932,6 +5356,157 @@ const messages = [
|
|
|
4932
5356
|
|
|
4933
5357
|
---
|
|
4934
5358
|
|
|
5359
|
+
### Stack
|
|
5360
|
+
|
|
5361
|
+
Full one-dimensional flex layout primitive. USE INSTEAD OF <div style={{display:'flex'}}>. Covers the whole CSS flexbox surface (direction incl. reverse, wrap, align/justify/alignContent/alignSelf, grow/shrink/basis, per-axis gap) with token-locked spacing. Renders a plain <div> (or \`as\`).
|
|
5362
|
+
|
|
5363
|
+
\`\`\`tsx
|
|
5364
|
+
import { Stack } from "@usevyre/react"
|
|
5365
|
+
|
|
5366
|
+
// Props:
|
|
5367
|
+
// direction = "row" | "column" | "row-reverse" | "column-reverse" (default: row)
|
|
5368
|
+
// inline = boolean (default: false)
|
|
5369
|
+
// gap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" (default: md)
|
|
5370
|
+
// rowGap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
5371
|
+
// columnGap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
5372
|
+
// align = "start" | "center" | "end" | "stretch" | "baseline" (default: stretch)
|
|
5373
|
+
// justify = "start" | "center" | "end" | "between" | "around" | "evenly" (default: start)
|
|
5374
|
+
// alignContent = "start" | "center" | "end" | "stretch" | "between" | "around" | "evenly"
|
|
5375
|
+
// alignSelf = "auto" | "start" | "center" | "end" | "stretch" | "baseline"
|
|
5376
|
+
// wrap = "nowrap" | "wrap" | "wrap-reverse" (default: nowrap)
|
|
5377
|
+
// grow = number
|
|
5378
|
+
// shrink = number
|
|
5379
|
+
// basis = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "auto" | "content" | "0"
|
|
5380
|
+
// width = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
5381
|
+
// height = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
5382
|
+
// as = string (default: div)
|
|
5383
|
+
|
|
5384
|
+
// Examples:
|
|
5385
|
+
<Stack direction="row" gap="md" align="center" justify="between">
|
|
5386
|
+
<Avatar src={user.avatar} />
|
|
5387
|
+
<Text>{user.name}</Text>
|
|
5388
|
+
<Button>Edit</Button>
|
|
5389
|
+
</Stack>
|
|
5390
|
+
<Stack wrap="wrap" rowGap="lg" columnGap="md">
|
|
5391
|
+
{tags.map((t) => <Tag key={t}>{t}</Tag>)}
|
|
5392
|
+
</Stack>
|
|
5393
|
+
\`\`\`
|
|
5394
|
+
|
|
5395
|
+
**Common mistakes:**
|
|
5396
|
+
- ❌ \`<div style={{ display: 'flex', gap: 12 }}>\` → Use <Stack gap="md"> — gap is a token
|
|
5397
|
+
- ❌ \`gap={12} or gap="12px"\` → Use gap="none|xs|sm|md|lg|xl|2xl"
|
|
5398
|
+
- ❌ \`direction="vertical" / "horizontal"\` → Use direction="row" or "column" (also row-reverse / column-reverse)
|
|
5399
|
+
- ❌ \`style={{ width: "100%" }} / style={{ height: 320 }}\` → Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
5400
|
+
|
|
5401
|
+
---
|
|
5402
|
+
|
|
5403
|
+
### Grid
|
|
5404
|
+
|
|
5405
|
+
Two-dimensional CSS grid primitive. Explicit column/row counts (or auto-fit), auto-flow control, token gap. Pair with GridItem for cell spanning/placement. Renders a plain <div> (or \`as\`).
|
|
5406
|
+
|
|
5407
|
+
\`\`\`tsx
|
|
5408
|
+
import { Grid, GridItem } from "@usevyre/react"
|
|
5409
|
+
|
|
5410
|
+
// Props:
|
|
5411
|
+
// columns = number | "auto-fit" (default: 1)
|
|
5412
|
+
// rows = number | "auto"
|
|
5413
|
+
// flow = "row" | "column" | "dense" | "row-dense" | "column-dense"
|
|
5414
|
+
// gap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" (default: md)
|
|
5415
|
+
// rowGap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
5416
|
+
// columnGap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
5417
|
+
// align = "start" | "center" | "end" | "stretch" (default: stretch)
|
|
5418
|
+
// justify = "start" | "center" | "end" | "stretch"
|
|
5419
|
+
// width = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
5420
|
+
// height = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
5421
|
+
// as = string (default: div)
|
|
5422
|
+
|
|
5423
|
+
// Examples:
|
|
5424
|
+
<Grid columns={3} gap="lg">
|
|
5425
|
+
<GridItem colSpan={2}><Card>Wide</Card></GridItem>
|
|
5426
|
+
<Card>Two</Card>
|
|
5427
|
+
<Card>Three</Card>
|
|
5428
|
+
</Grid>
|
|
5429
|
+
<Grid columns="auto-fit" gap="md">
|
|
5430
|
+
{items.map((i) => <Card key={i.id}>{i.title}</Card>)}
|
|
5431
|
+
</Grid>
|
|
5432
|
+
\`\`\`
|
|
5433
|
+
|
|
5434
|
+
**Common mistakes:**
|
|
5435
|
+
- ❌ \`<div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr' }}>\` → Use <Grid columns={3} gap="md">
|
|
5436
|
+
- ❌ \`columns="3" (string)\` → Use columns={3} or columns="auto-fit"
|
|
5437
|
+
- ❌ \`Nested div with inline grid-column for spanning\` → Wrap the cell in <GridItem colSpan={2}>
|
|
5438
|
+
- ❌ \`style={{ width: "100%" }} / style={{ height: 320 }}\` → Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
5439
|
+
|
|
5440
|
+
---
|
|
5441
|
+
|
|
5442
|
+
### GridItem
|
|
5443
|
+
|
|
5444
|
+
Child placement inside <Grid>. Sets column/row span and start lines. Renders a plain <div> (or \`as\`).
|
|
5445
|
+
|
|
5446
|
+
\`\`\`tsx
|
|
5447
|
+
import { GridItem } from "@usevyre/react"
|
|
5448
|
+
|
|
5449
|
+
// Props:
|
|
5450
|
+
// colSpan = number
|
|
5451
|
+
// rowSpan = number
|
|
5452
|
+
// colStart = number
|
|
5453
|
+
// rowStart = number
|
|
5454
|
+
// as = string (default: div)
|
|
5455
|
+
|
|
5456
|
+
// Examples:
|
|
5457
|
+
<Grid columns={4} gap="md">
|
|
5458
|
+
<GridItem colSpan={2}>Featured</GridItem>
|
|
5459
|
+
<div>a</div>
|
|
5460
|
+
<div>b</div>
|
|
5461
|
+
</Grid>
|
|
5462
|
+
\`\`\`
|
|
5463
|
+
|
|
5464
|
+
**Common mistakes:**
|
|
5465
|
+
- ❌ \`GridItem outside a Grid\` → Place <GridItem> directly inside <Grid>
|
|
5466
|
+
|
|
5467
|
+
---
|
|
5468
|
+
|
|
5469
|
+
### Box
|
|
5470
|
+
|
|
5471
|
+
Spacing-only container plus a controlled escape hatch. Token padding/margin with shorthand, per-axis (X/Y) and per-side (Top/Right/Bottom/Left) overrides. The \`style\` prop is an explicit anti-pattern escape hatch. Renders a plain <div> (or \`as\`).
|
|
5472
|
+
|
|
5473
|
+
\`\`\`tsx
|
|
5474
|
+
import { Box } from "@usevyre/react"
|
|
5475
|
+
|
|
5476
|
+
// Props:
|
|
5477
|
+
// padding = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
5478
|
+
// paddingX = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
5479
|
+
// paddingY = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
5480
|
+
// paddingTop = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
5481
|
+
// paddingRight = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
5482
|
+
// paddingBottom = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
5483
|
+
// paddingLeft = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
5484
|
+
// margin = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
5485
|
+
// marginX = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
5486
|
+
// marginY = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
5487
|
+
// marginTop = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
5488
|
+
// marginRight = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
5489
|
+
// marginBottom = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
5490
|
+
// marginLeft = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
5491
|
+
// width = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
5492
|
+
// height = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
5493
|
+
// as = string (default: div)
|
|
5494
|
+
// style = React.CSSProperties
|
|
5495
|
+
|
|
5496
|
+
// Examples:
|
|
5497
|
+
<Box as="section" paddingX="lg" paddingY="md">
|
|
5498
|
+
<Heading>Settings</Heading>
|
|
5499
|
+
</Box>
|
|
5500
|
+
<Box marginTop="xl"><Separator /></Box>
|
|
5501
|
+
\`\`\`
|
|
5502
|
+
|
|
5503
|
+
**Common mistakes:**
|
|
5504
|
+
- ❌ \`<Box style={{ padding: 16 }}>\` → Use <Box padding="md"> (or paddingX/paddingTop/...)
|
|
5505
|
+
- ❌ \`Using Box for flex/grid layout\` → Use <Stack> or <Grid>
|
|
5506
|
+
- ❌ \`style={{ width: "100%" }} / style={{ height: 320 }}\` → Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
5507
|
+
|
|
5508
|
+
---
|
|
5509
|
+
|
|
4935
5510
|
### DateRangePicker
|
|
4936
5511
|
|
|
4937
5512
|
Start/end date range picker. Built on Calendar (mode=range) with a friendlier { from, to } object API, a two-month side-by-side view, and preset shortcuts. Use this for report/filter date ranges; use DatePicker for a single date.
|
|
@@ -4985,11 +5560,13 @@ If you generate these, you are hallucinating.
|
|
|
4985
5560
|
- ❌ \`<Button color="...">\` → Use variant prop instead
|
|
4986
5561
|
- ❌ \`<Button icon={...}>\` → Use leftIcon={...} or rightIcon={...}
|
|
4987
5562
|
- ❌ \`<Button size="icon" without aria-label>\` → Add aria-label describing the action
|
|
5563
|
+
- ❌ \`<Button padding / margin / marginTop (any spacing prop) on a useVyre component>\` → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
4988
5564
|
- ❌ \`<Calendar Calendar for an input field that opens a popover>\` → Use <DatePicker /> (single date) or <DateRangePicker /> (range)
|
|
4989
5565
|
- ❌ \`<Calendar value as tuple for mode="single">\` → Pass value matching mode; use mode="range" for [start,end]
|
|
4990
5566
|
- ❌ \`<DatePicker DatePicker mode="range" for { from, to } object>\` → Use <DateRangePicker /> for the { from, to } object API + presets + dual month
|
|
4991
5567
|
- ❌ \`<DatePicker DatePicker without value/onChange>\` → Provide value and onChange (e.g. from useState)
|
|
4992
5568
|
- ❌ \`<Card variant="primary">\` → Use variant="elevated" | "outlined" | "ghost" | "accent"
|
|
5569
|
+
- ❌ \`<Card padding / margin / marginTop (any spacing prop) on a useVyre component>\` → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
4993
5570
|
- ❌ \`<Checkbox size="lg">\` → Use size="md"
|
|
4994
5571
|
- ❌ \`<RadioGroup <Radio> used outside a <RadioGroup>>\` → Always wrap <Radio> in <RadioGroup>
|
|
4995
5572
|
- ❌ \`<RadioGroup RadioGroup without value/onChange (React) or v-model (Vue)>\` → Bind value + onChange (React) or v-model (Vue); or defaultValue for uncontrolled in React
|
|
@@ -5004,6 +5581,7 @@ If you generate these, you are hallucinating.
|
|
|
5004
5581
|
- ❌ \`<Input size="icon">\` → Use size="sm" | "md" | "lg"
|
|
5005
5582
|
- ❌ \`<Input type="search" for search UI>\` → Import Command from @usevyre/react for search palettes
|
|
5006
5583
|
- ❌ \`<Input Vue: binding Input/Textarea value without v-model>\` → Use v-model on <Input>/<Textarea> in Vue; in React use value + onChange
|
|
5584
|
+
- ❌ \`<Input padding / margin / marginTop (any spacing prop) on a useVyre component>\` → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
5007
5585
|
- ❌ \`<Modal size="xl">\` → Use size="lg" or size="full"
|
|
5008
5586
|
- ❌ \`<Popover placement="top-center">\` → Use placement="top" for centered placement
|
|
5009
5587
|
- ❌ \`<Progress value > 100>\` → Normalize your value to 0–100 range before passing
|
|
@@ -5040,6 +5618,18 @@ If you generate these, you are hallucinating.
|
|
|
5040
5618
|
- ❌ \`<Conversation Expecting Conversation to store/append messages>\` → Append to your own state in onSend (or @send) and pass it back via value
|
|
5041
5619
|
- ❌ \`<Conversation composer without onSend (React) / @send (Vue)>\` → Provide onSend / @send to append the message to value
|
|
5042
5620
|
- ❌ \`<Conversation Treating onSend as (text) only when using allowAttachments>\` → Handle onSend(text, files) — map files to message attachments and append
|
|
5621
|
+
- ❌ \`<Stack <div style={{ display: 'flex', gap: 12 }}>>\` → Use <Stack gap="md"> — gap is a token
|
|
5622
|
+
- ❌ \`<Stack gap={12} or gap="12px">\` → Use gap="none|xs|sm|md|lg|xl|2xl"
|
|
5623
|
+
- ❌ \`<Stack direction="vertical" / "horizontal">\` → Use direction="row" or "column" (also row-reverse / column-reverse)
|
|
5624
|
+
- ❌ \`<Stack style={{ width: "100%" }} / style={{ height: 320 }}>\` → Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
5625
|
+
- ❌ \`<Grid <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr' }}>>\` → Use <Grid columns={3} gap="md">
|
|
5626
|
+
- ❌ \`<Grid columns="3" (string)>\` → Use columns={3} or columns="auto-fit"
|
|
5627
|
+
- ❌ \`<Grid Nested div with inline grid-column for spanning>\` → Wrap the cell in <GridItem colSpan={2}>
|
|
5628
|
+
- ❌ \`<Grid style={{ width: "100%" }} / style={{ height: 320 }}>\` → Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
5629
|
+
- ❌ \`<GridItem GridItem outside a Grid>\` → Place <GridItem> directly inside <Grid>
|
|
5630
|
+
- ❌ \`<Box <Box style={{ padding: 16 }}>>\` → Use <Box padding="md"> (or paddingX/paddingTop/...)
|
|
5631
|
+
- ❌ \`<Box Using Box for flex/grid layout>\` → Use <Stack> or <Grid>
|
|
5632
|
+
- ❌ \`<Box style={{ width: "100%" }} / style={{ height: 320 }}>\` → Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
5043
5633
|
- ❌ \`<DateRangePicker value={[from, to]}>\` → Use value={{ from, to }} and read range.from / range.to
|
|
5044
5634
|
- ❌ \`<DateRangePicker DateRangePicker for a single date>\` → Use <DatePicker /> for a single date
|
|
5045
5635
|
- ❌ \`<DateRangePicker presets="true" (string)>\` → Use the bare prop: presets (or presets={true})
|
|
@@ -5092,7 +5682,7 @@ If you generate these, you are hallucinating.
|
|
|
5092
5682
|
\`\`\`
|
|
5093
5683
|
`;
|
|
5094
5684
|
export const copilotInstructions = `# useVyre Copilot Instructions
|
|
5095
|
-
# Version: 1.
|
|
5685
|
+
# Version: 1.6.0
|
|
5096
5686
|
|
|
5097
5687
|
When generating UI code in this project, follow the useVyre design system rules below.
|
|
5098
5688
|
|
|
@@ -5437,6 +6027,7 @@ import { Button } from "@usevyre/react"
|
|
|
5437
6027
|
- ❌ \`color="..."\` → Use variant prop instead
|
|
5438
6028
|
- ❌ \`icon={...}\` → Use leftIcon={...} or rightIcon={...}
|
|
5439
6029
|
- ❌ \`size="icon" without aria-label\` → Add aria-label describing the action
|
|
6030
|
+
- ❌ \`padding / margin / marginTop (any spacing prop) on a useVyre component\` → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
5440
6031
|
|
|
5441
6032
|
---
|
|
5442
6033
|
|
|
@@ -5522,6 +6113,7 @@ import { Card, CardHeader, CardBody, CardFooter } from "@usevyre/react"
|
|
|
5522
6113
|
|
|
5523
6114
|
**Common mistakes:**
|
|
5524
6115
|
- ❌ \`variant="primary"\` → Use variant="elevated" | "outlined" | "ghost" | "accent"
|
|
6116
|
+
- ❌ \`padding / margin / marginTop (any spacing prop) on a useVyre component\` → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
5525
6117
|
|
|
5526
6118
|
---
|
|
5527
6119
|
|
|
@@ -5733,6 +6325,7 @@ import { Input } from "@usevyre/react"
|
|
|
5733
6325
|
- ❌ \`size="icon"\` → Use size="sm" | "md" | "lg"
|
|
5734
6326
|
- ❌ \`type="search" for search UI\` → Import Command from @usevyre/react for search palettes
|
|
5735
6327
|
- ❌ \`Vue: binding Input/Textarea value without v-model\` → Use v-model on <Input>/<Textarea> in Vue; in React use value + onChange
|
|
6328
|
+
- ❌ \`padding / margin / marginTop (any spacing prop) on a useVyre component\` → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
5736
6329
|
|
|
5737
6330
|
---
|
|
5738
6331
|
|
|
@@ -6475,6 +7068,157 @@ const messages = [
|
|
|
6475
7068
|
|
|
6476
7069
|
---
|
|
6477
7070
|
|
|
7071
|
+
### Stack
|
|
7072
|
+
|
|
7073
|
+
Full one-dimensional flex layout primitive. USE INSTEAD OF <div style={{display:'flex'}}>. Covers the whole CSS flexbox surface (direction incl. reverse, wrap, align/justify/alignContent/alignSelf, grow/shrink/basis, per-axis gap) with token-locked spacing. Renders a plain <div> (or \`as\`).
|
|
7074
|
+
|
|
7075
|
+
\`\`\`tsx
|
|
7076
|
+
import { Stack } from "@usevyre/react"
|
|
7077
|
+
|
|
7078
|
+
// Props:
|
|
7079
|
+
// direction = "row" | "column" | "row-reverse" | "column-reverse" (default: row)
|
|
7080
|
+
// inline = boolean (default: false)
|
|
7081
|
+
// gap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" (default: md)
|
|
7082
|
+
// rowGap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
7083
|
+
// columnGap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
7084
|
+
// align = "start" | "center" | "end" | "stretch" | "baseline" (default: stretch)
|
|
7085
|
+
// justify = "start" | "center" | "end" | "between" | "around" | "evenly" (default: start)
|
|
7086
|
+
// alignContent = "start" | "center" | "end" | "stretch" | "between" | "around" | "evenly"
|
|
7087
|
+
// alignSelf = "auto" | "start" | "center" | "end" | "stretch" | "baseline"
|
|
7088
|
+
// wrap = "nowrap" | "wrap" | "wrap-reverse" (default: nowrap)
|
|
7089
|
+
// grow = number
|
|
7090
|
+
// shrink = number
|
|
7091
|
+
// basis = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "auto" | "content" | "0"
|
|
7092
|
+
// width = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
7093
|
+
// height = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
7094
|
+
// as = string (default: div)
|
|
7095
|
+
|
|
7096
|
+
// Examples:
|
|
7097
|
+
<Stack direction="row" gap="md" align="center" justify="between">
|
|
7098
|
+
<Avatar src={user.avatar} />
|
|
7099
|
+
<Text>{user.name}</Text>
|
|
7100
|
+
<Button>Edit</Button>
|
|
7101
|
+
</Stack>
|
|
7102
|
+
<Stack wrap="wrap" rowGap="lg" columnGap="md">
|
|
7103
|
+
{tags.map((t) => <Tag key={t}>{t}</Tag>)}
|
|
7104
|
+
</Stack>
|
|
7105
|
+
\`\`\`
|
|
7106
|
+
|
|
7107
|
+
**Common mistakes:**
|
|
7108
|
+
- ❌ \`<div style={{ display: 'flex', gap: 12 }}>\` → Use <Stack gap="md"> — gap is a token
|
|
7109
|
+
- ❌ \`gap={12} or gap="12px"\` → Use gap="none|xs|sm|md|lg|xl|2xl"
|
|
7110
|
+
- ❌ \`direction="vertical" / "horizontal"\` → Use direction="row" or "column" (also row-reverse / column-reverse)
|
|
7111
|
+
- ❌ \`style={{ width: "100%" }} / style={{ height: 320 }}\` → Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
7112
|
+
|
|
7113
|
+
---
|
|
7114
|
+
|
|
7115
|
+
### Grid
|
|
7116
|
+
|
|
7117
|
+
Two-dimensional CSS grid primitive. Explicit column/row counts (or auto-fit), auto-flow control, token gap. Pair with GridItem for cell spanning/placement. Renders a plain <div> (or \`as\`).
|
|
7118
|
+
|
|
7119
|
+
\`\`\`tsx
|
|
7120
|
+
import { Grid, GridItem } from "@usevyre/react"
|
|
7121
|
+
|
|
7122
|
+
// Props:
|
|
7123
|
+
// columns = number | "auto-fit" (default: 1)
|
|
7124
|
+
// rows = number | "auto"
|
|
7125
|
+
// flow = "row" | "column" | "dense" | "row-dense" | "column-dense"
|
|
7126
|
+
// gap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" (default: md)
|
|
7127
|
+
// rowGap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
7128
|
+
// columnGap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
7129
|
+
// align = "start" | "center" | "end" | "stretch" (default: stretch)
|
|
7130
|
+
// justify = "start" | "center" | "end" | "stretch"
|
|
7131
|
+
// width = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
7132
|
+
// height = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
7133
|
+
// as = string (default: div)
|
|
7134
|
+
|
|
7135
|
+
// Examples:
|
|
7136
|
+
<Grid columns={3} gap="lg">
|
|
7137
|
+
<GridItem colSpan={2}><Card>Wide</Card></GridItem>
|
|
7138
|
+
<Card>Two</Card>
|
|
7139
|
+
<Card>Three</Card>
|
|
7140
|
+
</Grid>
|
|
7141
|
+
<Grid columns="auto-fit" gap="md">
|
|
7142
|
+
{items.map((i) => <Card key={i.id}>{i.title}</Card>)}
|
|
7143
|
+
</Grid>
|
|
7144
|
+
\`\`\`
|
|
7145
|
+
|
|
7146
|
+
**Common mistakes:**
|
|
7147
|
+
- ❌ \`<div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr' }}>\` → Use <Grid columns={3} gap="md">
|
|
7148
|
+
- ❌ \`columns="3" (string)\` → Use columns={3} or columns="auto-fit"
|
|
7149
|
+
- ❌ \`Nested div with inline grid-column for spanning\` → Wrap the cell in <GridItem colSpan={2}>
|
|
7150
|
+
- ❌ \`style={{ width: "100%" }} / style={{ height: 320 }}\` → Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
7151
|
+
|
|
7152
|
+
---
|
|
7153
|
+
|
|
7154
|
+
### GridItem
|
|
7155
|
+
|
|
7156
|
+
Child placement inside <Grid>. Sets column/row span and start lines. Renders a plain <div> (or \`as\`).
|
|
7157
|
+
|
|
7158
|
+
\`\`\`tsx
|
|
7159
|
+
import { GridItem } from "@usevyre/react"
|
|
7160
|
+
|
|
7161
|
+
// Props:
|
|
7162
|
+
// colSpan = number
|
|
7163
|
+
// rowSpan = number
|
|
7164
|
+
// colStart = number
|
|
7165
|
+
// rowStart = number
|
|
7166
|
+
// as = string (default: div)
|
|
7167
|
+
|
|
7168
|
+
// Examples:
|
|
7169
|
+
<Grid columns={4} gap="md">
|
|
7170
|
+
<GridItem colSpan={2}>Featured</GridItem>
|
|
7171
|
+
<div>a</div>
|
|
7172
|
+
<div>b</div>
|
|
7173
|
+
</Grid>
|
|
7174
|
+
\`\`\`
|
|
7175
|
+
|
|
7176
|
+
**Common mistakes:**
|
|
7177
|
+
- ❌ \`GridItem outside a Grid\` → Place <GridItem> directly inside <Grid>
|
|
7178
|
+
|
|
7179
|
+
---
|
|
7180
|
+
|
|
7181
|
+
### Box
|
|
7182
|
+
|
|
7183
|
+
Spacing-only container plus a controlled escape hatch. Token padding/margin with shorthand, per-axis (X/Y) and per-side (Top/Right/Bottom/Left) overrides. The \`style\` prop is an explicit anti-pattern escape hatch. Renders a plain <div> (or \`as\`).
|
|
7184
|
+
|
|
7185
|
+
\`\`\`tsx
|
|
7186
|
+
import { Box } from "@usevyre/react"
|
|
7187
|
+
|
|
7188
|
+
// Props:
|
|
7189
|
+
// padding = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
7190
|
+
// paddingX = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
7191
|
+
// paddingY = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
7192
|
+
// paddingTop = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
7193
|
+
// paddingRight = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
7194
|
+
// paddingBottom = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
7195
|
+
// paddingLeft = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
7196
|
+
// margin = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
7197
|
+
// marginX = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
7198
|
+
// marginY = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
7199
|
+
// marginTop = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
7200
|
+
// marginRight = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
7201
|
+
// marginBottom = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
7202
|
+
// marginLeft = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
7203
|
+
// width = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
7204
|
+
// height = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
|
|
7205
|
+
// as = string (default: div)
|
|
7206
|
+
// style = React.CSSProperties
|
|
7207
|
+
|
|
7208
|
+
// Examples:
|
|
7209
|
+
<Box as="section" paddingX="lg" paddingY="md">
|
|
7210
|
+
<Heading>Settings</Heading>
|
|
7211
|
+
</Box>
|
|
7212
|
+
<Box marginTop="xl"><Separator /></Box>
|
|
7213
|
+
\`\`\`
|
|
7214
|
+
|
|
7215
|
+
**Common mistakes:**
|
|
7216
|
+
- ❌ \`<Box style={{ padding: 16 }}>\` → Use <Box padding="md"> (or paddingX/paddingTop/...)
|
|
7217
|
+
- ❌ \`Using Box for flex/grid layout\` → Use <Stack> or <Grid>
|
|
7218
|
+
- ❌ \`style={{ width: "100%" }} / style={{ height: 320 }}\` → Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
7219
|
+
|
|
7220
|
+
---
|
|
7221
|
+
|
|
6478
7222
|
### DateRangePicker
|
|
6479
7223
|
|
|
6480
7224
|
Start/end date range picker. Built on Calendar (mode=range) with a friendlier { from, to } object API, a two-month side-by-side view, and preset shortcuts. Use this for report/filter date ranges; use DatePicker for a single date.
|
|
@@ -6528,11 +7272,13 @@ If you generate these, you are hallucinating.
|
|
|
6528
7272
|
- ❌ \`<Button color="...">\` → Use variant prop instead
|
|
6529
7273
|
- ❌ \`<Button icon={...}>\` → Use leftIcon={...} or rightIcon={...}
|
|
6530
7274
|
- ❌ \`<Button size="icon" without aria-label>\` → Add aria-label describing the action
|
|
7275
|
+
- ❌ \`<Button padding / margin / marginTop (any spacing prop) on a useVyre component>\` → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
6531
7276
|
- ❌ \`<Calendar Calendar for an input field that opens a popover>\` → Use <DatePicker /> (single date) or <DateRangePicker /> (range)
|
|
6532
7277
|
- ❌ \`<Calendar value as tuple for mode="single">\` → Pass value matching mode; use mode="range" for [start,end]
|
|
6533
7278
|
- ❌ \`<DatePicker DatePicker mode="range" for { from, to } object>\` → Use <DateRangePicker /> for the { from, to } object API + presets + dual month
|
|
6534
7279
|
- ❌ \`<DatePicker DatePicker without value/onChange>\` → Provide value and onChange (e.g. from useState)
|
|
6535
7280
|
- ❌ \`<Card variant="primary">\` → Use variant="elevated" | "outlined" | "ghost" | "accent"
|
|
7281
|
+
- ❌ \`<Card padding / margin / marginTop (any spacing prop) on a useVyre component>\` → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
6536
7282
|
- ❌ \`<Checkbox size="lg">\` → Use size="md"
|
|
6537
7283
|
- ❌ \`<RadioGroup <Radio> used outside a <RadioGroup>>\` → Always wrap <Radio> in <RadioGroup>
|
|
6538
7284
|
- ❌ \`<RadioGroup RadioGroup without value/onChange (React) or v-model (Vue)>\` → Bind value + onChange (React) or v-model (Vue); or defaultValue for uncontrolled in React
|
|
@@ -6547,6 +7293,7 @@ If you generate these, you are hallucinating.
|
|
|
6547
7293
|
- ❌ \`<Input size="icon">\` → Use size="sm" | "md" | "lg"
|
|
6548
7294
|
- ❌ \`<Input type="search" for search UI>\` → Import Command from @usevyre/react for search palettes
|
|
6549
7295
|
- ❌ \`<Input Vue: binding Input/Textarea value without v-model>\` → Use v-model on <Input>/<Textarea> in Vue; in React use value + onChange
|
|
7296
|
+
- ❌ \`<Input padding / margin / marginTop (any spacing prop) on a useVyre component>\` → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it
|
|
6550
7297
|
- ❌ \`<Modal size="xl">\` → Use size="lg" or size="full"
|
|
6551
7298
|
- ❌ \`<Popover placement="top-center">\` → Use placement="top" for centered placement
|
|
6552
7299
|
- ❌ \`<Progress value > 100>\` → Normalize your value to 0–100 range before passing
|
|
@@ -6583,6 +7330,18 @@ If you generate these, you are hallucinating.
|
|
|
6583
7330
|
- ❌ \`<Conversation Expecting Conversation to store/append messages>\` → Append to your own state in onSend (or @send) and pass it back via value
|
|
6584
7331
|
- ❌ \`<Conversation composer without onSend (React) / @send (Vue)>\` → Provide onSend / @send to append the message to value
|
|
6585
7332
|
- ❌ \`<Conversation Treating onSend as (text) only when using allowAttachments>\` → Handle onSend(text, files) — map files to message attachments and append
|
|
7333
|
+
- ❌ \`<Stack <div style={{ display: 'flex', gap: 12 }}>>\` → Use <Stack gap="md"> — gap is a token
|
|
7334
|
+
- ❌ \`<Stack gap={12} or gap="12px">\` → Use gap="none|xs|sm|md|lg|xl|2xl"
|
|
7335
|
+
- ❌ \`<Stack direction="vertical" / "horizontal">\` → Use direction="row" or "column" (also row-reverse / column-reverse)
|
|
7336
|
+
- ❌ \`<Stack style={{ width: "100%" }} / style={{ height: 320 }}>\` → Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
7337
|
+
- ❌ \`<Grid <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr' }}>>\` → Use <Grid columns={3} gap="md">
|
|
7338
|
+
- ❌ \`<Grid columns="3" (string)>\` → Use columns={3} or columns="auto-fit"
|
|
7339
|
+
- ❌ \`<Grid Nested div with inline grid-column for spanning>\` → Wrap the cell in <GridItem colSpan={2}>
|
|
7340
|
+
- ❌ \`<Grid style={{ width: "100%" }} / style={{ height: 320 }}>\` → Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
7341
|
+
- ❌ \`<GridItem GridItem outside a Grid>\` → Place <GridItem> directly inside <Grid>
|
|
7342
|
+
- ❌ \`<Box <Box style={{ padding: 16 }}>>\` → Use <Box padding="md"> (or paddingX/paddingTop/...)
|
|
7343
|
+
- ❌ \`<Box Using Box for flex/grid layout>\` → Use <Stack> or <Grid>
|
|
7344
|
+
- ❌ \`<Box style={{ width: "100%" }} / style={{ height: 320 }}>\` → Use the width / height prop: width="full", width="md", height="screen", etc.
|
|
6586
7345
|
- ❌ \`<DateRangePicker value={[from, to]}>\` → Use value={{ from, to }} and read range.from / range.to
|
|
6587
7346
|
- ❌ \`<DateRangePicker DateRangePicker for a single date>\` → Use <DatePicker /> for a single date
|
|
6588
7347
|
- ❌ \`<DateRangePicker presets="true" (string)>\` → Use the bare prop: presets (or presets={true})
|
|
@@ -6637,15 +7396,35 @@ If you generate these, you are hallucinating.
|
|
|
6637
7396
|
|
|
6638
7397
|
export const schema = {
|
|
6639
7398
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
6640
|
-
"version": "1.
|
|
6641
|
-
"generatedAt": "2026-05-
|
|
7399
|
+
"version": "1.6.0",
|
|
7400
|
+
"generatedAt": "2026-05-18",
|
|
6642
7401
|
"package": "@usevyre/react",
|
|
6643
|
-
"packageVersion": "1.
|
|
7402
|
+
"packageVersion": "1.6.0",
|
|
6644
7403
|
"validFor": [
|
|
6645
7404
|
"@usevyre/react@1.1.0+",
|
|
6646
7405
|
"@usevyre/vue@1.1.0+"
|
|
6647
7406
|
],
|
|
6648
7407
|
"changelog": {
|
|
7408
|
+
"1.6.0": {
|
|
7409
|
+
"date": "2026-05-18",
|
|
7410
|
+
"breaking": false,
|
|
7411
|
+
"summary": "Documented the spacing model as an explicit anti-pattern on representative components (Button, Card, Input): useVyre components take no padding/margin props — use Stack/Grid gap or a Box wrapper. No API change."
|
|
7412
|
+
},
|
|
7413
|
+
"1.5.0": {
|
|
7414
|
+
"date": "2026-05-18",
|
|
7415
|
+
"breaking": false,
|
|
7416
|
+
"summary": "Stack, Grid and Box gain token-locked width / height props (keywords auto/full/fit/screen + fixed-rem token sizes xs–2xl), removing the need for an inline width/height style for common layout sizing."
|
|
7417
|
+
},
|
|
7418
|
+
"1.4.0": {
|
|
7419
|
+
"date": "2026-05-18",
|
|
7420
|
+
"breaking": false,
|
|
7421
|
+
"summary": "Layout primitives expanded: Stack now covers the full CSS flexbox surface (reverse directions, wrap modes, alignContent/alignSelf, grow/shrink/basis, per-axis gap); Grid gains rows/flow/justify + a new GridItem subcomponent for span/placement; Box gains per-axis (X/Y) and per-side (Top/Right/Bottom/Left) token padding/margin. Fixes Grid columns being overwritten when a user style prop was passed."
|
|
7422
|
+
},
|
|
7423
|
+
"1.3.0": {
|
|
7424
|
+
"date": "2026-05-18",
|
|
7425
|
+
"breaking": false,
|
|
7426
|
+
"summary": "Added Stack, Grid and Box layout primitives. Token-locked spacing (no raw px/rem) to eliminate hallucinated inline flex/grid styles; Box exposes a documented style escape hatch flagged as an anti-pattern."
|
|
7427
|
+
},
|
|
6649
7428
|
"1.2.0": {
|
|
6650
7429
|
"date": "2026-05-16",
|
|
6651
7430
|
"breaking": false,
|
|
@@ -7038,6 +7817,11 @@ export const schema = {
|
|
|
7038
7817
|
"pattern": "size=\"icon\" without aria-label",
|
|
7039
7818
|
"reason": "Icon-only buttons have no visible text — screen readers need aria-label",
|
|
7040
7819
|
"fix": "Add aria-label describing the action"
|
|
7820
|
+
},
|
|
7821
|
+
{
|
|
7822
|
+
"pattern": "padding / margin / marginTop (any spacing prop) on a useVyre component",
|
|
7823
|
+
"reason": "Components have NO spacing props by design — internal spacing is fixed by tokens for visual consistency",
|
|
7824
|
+
"fix": "Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it"
|
|
7041
7825
|
}
|
|
7042
7826
|
],
|
|
7043
7827
|
"examples": [
|
|
@@ -7221,6 +8005,11 @@ export const schema = {
|
|
|
7221
8005
|
"pattern": "variant=\"primary\"",
|
|
7222
8006
|
"reason": "Card has no 'primary' variant",
|
|
7223
8007
|
"fix": "Use variant=\"elevated\" | \"outlined\" | \"ghost\" | \"accent\""
|
|
8008
|
+
},
|
|
8009
|
+
{
|
|
8010
|
+
"pattern": "padding / margin / marginTop (any spacing prop) on a useVyre component",
|
|
8011
|
+
"reason": "Components have NO spacing props by design — internal spacing is fixed by tokens for visual consistency",
|
|
8012
|
+
"fix": "Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it"
|
|
7224
8013
|
}
|
|
7225
8014
|
],
|
|
7226
8015
|
"examples": [
|
|
@@ -7591,6 +8380,11 @@ export const schema = {
|
|
|
7591
8380
|
"pattern": "Vue: binding Input/Textarea value without v-model",
|
|
7592
8381
|
"reason": "Vue Input & Textarea support v-model (modelValue); manual :value alone won't update",
|
|
7593
8382
|
"fix": "Use v-model on <Input>/<Textarea> in Vue; in React use value + onChange"
|
|
8383
|
+
},
|
|
8384
|
+
{
|
|
8385
|
+
"pattern": "padding / margin / marginTop (any spacing prop) on a useVyre component",
|
|
8386
|
+
"reason": "Components have NO spacing props by design — internal spacing is fixed by tokens for visual consistency",
|
|
8387
|
+
"fix": "Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it"
|
|
7594
8388
|
}
|
|
7595
8389
|
],
|
|
7596
8390
|
"examples": [
|
|
@@ -8847,17 +9641,687 @@ export const schema = {
|
|
|
8847
9641
|
}
|
|
8848
9642
|
]
|
|
8849
9643
|
},
|
|
8850
|
-
"
|
|
8851
|
-
"description": "
|
|
8852
|
-
"import": "import {
|
|
9644
|
+
"Stack": {
|
|
9645
|
+
"description": "Full one-dimensional flex layout primitive. USE INSTEAD OF <div style={{display:'flex'}}>. Covers the whole CSS flexbox surface (direction incl. reverse, wrap, align/justify/alignContent/alignSelf, grow/shrink/basis, per-axis gap) with token-locked spacing. Renders a plain <div> (or `as`).",
|
|
9646
|
+
"import": "import { Stack } from \"@usevyre/react\"",
|
|
8853
9647
|
"props": {
|
|
8854
|
-
"
|
|
8855
|
-
"type": "
|
|
8856
|
-
"
|
|
9648
|
+
"direction": {
|
|
9649
|
+
"type": "enum",
|
|
9650
|
+
"values": [
|
|
9651
|
+
"row",
|
|
9652
|
+
"column",
|
|
9653
|
+
"row-reverse",
|
|
9654
|
+
"column-reverse"
|
|
9655
|
+
],
|
|
9656
|
+
"default": "row",
|
|
9657
|
+
"description": "flex-direction"
|
|
8857
9658
|
},
|
|
8858
|
-
"
|
|
8859
|
-
"type": "
|
|
8860
|
-
"
|
|
9659
|
+
"inline": {
|
|
9660
|
+
"type": "boolean",
|
|
9661
|
+
"default": false,
|
|
9662
|
+
"description": "Render as inline-flex instead of flex"
|
|
9663
|
+
},
|
|
9664
|
+
"gap": {
|
|
9665
|
+
"type": "enum",
|
|
9666
|
+
"values": [
|
|
9667
|
+
"none",
|
|
9668
|
+
"xs",
|
|
9669
|
+
"sm",
|
|
9670
|
+
"md",
|
|
9671
|
+
"lg",
|
|
9672
|
+
"xl",
|
|
9673
|
+
"2xl"
|
|
9674
|
+
],
|
|
9675
|
+
"default": "md",
|
|
9676
|
+
"description": "Space between children. Maps to --vyre-spacing tokens. NEVER a raw px/rem value."
|
|
9677
|
+
},
|
|
9678
|
+
"rowGap": {
|
|
9679
|
+
"type": "enum",
|
|
9680
|
+
"values": [
|
|
9681
|
+
"none",
|
|
9682
|
+
"xs",
|
|
9683
|
+
"sm",
|
|
9684
|
+
"md",
|
|
9685
|
+
"lg",
|
|
9686
|
+
"xl",
|
|
9687
|
+
"2xl"
|
|
9688
|
+
],
|
|
9689
|
+
"description": "Row-gap override. Maps to --vyre-spacing tokens. NEVER a raw px/rem value."
|
|
9690
|
+
},
|
|
9691
|
+
"columnGap": {
|
|
9692
|
+
"type": "enum",
|
|
9693
|
+
"values": [
|
|
9694
|
+
"none",
|
|
9695
|
+
"xs",
|
|
9696
|
+
"sm",
|
|
9697
|
+
"md",
|
|
9698
|
+
"lg",
|
|
9699
|
+
"xl",
|
|
9700
|
+
"2xl"
|
|
9701
|
+
],
|
|
9702
|
+
"description": "Column-gap override. Maps to --vyre-spacing tokens. NEVER a raw px/rem value."
|
|
9703
|
+
},
|
|
9704
|
+
"align": {
|
|
9705
|
+
"type": "enum",
|
|
9706
|
+
"values": [
|
|
9707
|
+
"start",
|
|
9708
|
+
"center",
|
|
9709
|
+
"end",
|
|
9710
|
+
"stretch",
|
|
9711
|
+
"baseline"
|
|
9712
|
+
],
|
|
9713
|
+
"default": "stretch",
|
|
9714
|
+
"description": "align-items (cross axis)"
|
|
9715
|
+
},
|
|
9716
|
+
"justify": {
|
|
9717
|
+
"type": "enum",
|
|
9718
|
+
"values": [
|
|
9719
|
+
"start",
|
|
9720
|
+
"center",
|
|
9721
|
+
"end",
|
|
9722
|
+
"between",
|
|
9723
|
+
"around",
|
|
9724
|
+
"evenly"
|
|
9725
|
+
],
|
|
9726
|
+
"default": "start",
|
|
9727
|
+
"description": "justify-content (main axis)"
|
|
9728
|
+
},
|
|
9729
|
+
"alignContent": {
|
|
9730
|
+
"type": "enum",
|
|
9731
|
+
"values": [
|
|
9732
|
+
"start",
|
|
9733
|
+
"center",
|
|
9734
|
+
"end",
|
|
9735
|
+
"stretch",
|
|
9736
|
+
"between",
|
|
9737
|
+
"around",
|
|
9738
|
+
"evenly"
|
|
9739
|
+
],
|
|
9740
|
+
"description": "align-content (multi-line cross axis)"
|
|
9741
|
+
},
|
|
9742
|
+
"alignSelf": {
|
|
9743
|
+
"type": "enum",
|
|
9744
|
+
"values": [
|
|
9745
|
+
"auto",
|
|
9746
|
+
"start",
|
|
9747
|
+
"center",
|
|
9748
|
+
"end",
|
|
9749
|
+
"stretch",
|
|
9750
|
+
"baseline"
|
|
9751
|
+
],
|
|
9752
|
+
"description": "align-self for this element"
|
|
9753
|
+
},
|
|
9754
|
+
"wrap": {
|
|
9755
|
+
"type": "enum",
|
|
9756
|
+
"values": [
|
|
9757
|
+
"nowrap",
|
|
9758
|
+
"wrap",
|
|
9759
|
+
"wrap-reverse"
|
|
9760
|
+
],
|
|
9761
|
+
"default": "nowrap",
|
|
9762
|
+
"description": "flex-wrap"
|
|
9763
|
+
},
|
|
9764
|
+
"grow": {
|
|
9765
|
+
"type": "number",
|
|
9766
|
+
"description": "flex-grow"
|
|
9767
|
+
},
|
|
9768
|
+
"shrink": {
|
|
9769
|
+
"type": "number",
|
|
9770
|
+
"description": "flex-shrink"
|
|
9771
|
+
},
|
|
9772
|
+
"basis": {
|
|
9773
|
+
"type": "enum",
|
|
9774
|
+
"values": [
|
|
9775
|
+
"none",
|
|
9776
|
+
"xs",
|
|
9777
|
+
"sm",
|
|
9778
|
+
"md",
|
|
9779
|
+
"lg",
|
|
9780
|
+
"xl",
|
|
9781
|
+
"2xl",
|
|
9782
|
+
"auto",
|
|
9783
|
+
"content",
|
|
9784
|
+
"0"
|
|
9785
|
+
],
|
|
9786
|
+
"description": "flex-basis — token, 'auto', 'content', or '0'"
|
|
9787
|
+
},
|
|
9788
|
+
"width": {
|
|
9789
|
+
"type": "enum",
|
|
9790
|
+
"values": [
|
|
9791
|
+
"auto",
|
|
9792
|
+
"full",
|
|
9793
|
+
"fit",
|
|
9794
|
+
"screen",
|
|
9795
|
+
"xs",
|
|
9796
|
+
"sm",
|
|
9797
|
+
"md",
|
|
9798
|
+
"lg",
|
|
9799
|
+
"xl",
|
|
9800
|
+
"2xl"
|
|
9801
|
+
],
|
|
9802
|
+
"description": "Width — keyword (auto/full=100%/fit=fit-content/screen) or a fixed-rem token size (xs 8 · sm 12 · md 16 · lg 24 · xl 32 · 2xl 42). Avoids an inline width style."
|
|
9803
|
+
},
|
|
9804
|
+
"height": {
|
|
9805
|
+
"type": "enum",
|
|
9806
|
+
"values": [
|
|
9807
|
+
"auto",
|
|
9808
|
+
"full",
|
|
9809
|
+
"fit",
|
|
9810
|
+
"screen",
|
|
9811
|
+
"xs",
|
|
9812
|
+
"sm",
|
|
9813
|
+
"md",
|
|
9814
|
+
"lg",
|
|
9815
|
+
"xl",
|
|
9816
|
+
"2xl"
|
|
9817
|
+
],
|
|
9818
|
+
"description": "Height — keyword (auto/full=100%/fit=fit-content/screen) or a fixed-rem token size (xs 8 · sm 12 · md 16 · lg 24 · xl 32 · 2xl 42). Avoids an inline height style."
|
|
9819
|
+
},
|
|
9820
|
+
"as": {
|
|
9821
|
+
"type": "string",
|
|
9822
|
+
"default": "div",
|
|
9823
|
+
"description": "HTML tag to render"
|
|
9824
|
+
}
|
|
9825
|
+
},
|
|
9826
|
+
"antiPatterns": [
|
|
9827
|
+
{
|
|
9828
|
+
"pattern": "<div style={{ display: 'flex', gap: 12 }}>",
|
|
9829
|
+
"reason": "Inline flex styles bypass the design system and use magic-number spacing",
|
|
9830
|
+
"fix": "Use <Stack gap=\"md\"> — gap is a token"
|
|
9831
|
+
},
|
|
9832
|
+
{
|
|
9833
|
+
"pattern": "gap={12} or gap=\"12px\"",
|
|
9834
|
+
"reason": "Stack gap is a closed token enum",
|
|
9835
|
+
"fix": "Use gap=\"none|xs|sm|md|lg|xl|2xl\""
|
|
9836
|
+
},
|
|
9837
|
+
{
|
|
9838
|
+
"pattern": "direction=\"vertical\" / \"horizontal\"",
|
|
9839
|
+
"reason": "Stack mirrors CSS flex-direction names",
|
|
9840
|
+
"fix": "Use direction=\"row\" or \"column\" (also row-reverse / column-reverse)"
|
|
9841
|
+
},
|
|
9842
|
+
{
|
|
9843
|
+
"pattern": "style={{ width: \"100%\" }} / style={{ height: 320 }}",
|
|
9844
|
+
"reason": "Inline width/height bypass the design system and use magic numbers",
|
|
9845
|
+
"fix": "Use the width / height prop: width=\"full\", width=\"md\", height=\"screen\", etc."
|
|
9846
|
+
}
|
|
9847
|
+
],
|
|
9848
|
+
"examples": [
|
|
9849
|
+
{
|
|
9850
|
+
"description": "Row, vertically centered, spaced apart",
|
|
9851
|
+
"code": "<Stack direction=\"row\" gap=\"md\" align=\"center\" justify=\"between\">\n <Avatar src={user.avatar} />\n <Text>{user.name}</Text>\n <Button>Edit</Button>\n</Stack>"
|
|
9852
|
+
},
|
|
9853
|
+
{
|
|
9854
|
+
"description": "Wrapping grid-ish gallery with per-axis gap",
|
|
9855
|
+
"code": "<Stack wrap=\"wrap\" rowGap=\"lg\" columnGap=\"md\">\n {tags.map((t) => <Tag key={t}>{t}</Tag>)}\n</Stack>"
|
|
9856
|
+
}
|
|
9857
|
+
]
|
|
9858
|
+
},
|
|
9859
|
+
"Grid": {
|
|
9860
|
+
"description": "Two-dimensional CSS grid primitive. Explicit column/row counts (or auto-fit), auto-flow control, token gap. Pair with GridItem for cell spanning/placement. Renders a plain <div> (or `as`).",
|
|
9861
|
+
"import": "import { Grid, GridItem } from \"@usevyre/react\"",
|
|
9862
|
+
"subcomponents": [
|
|
9863
|
+
"GridItem"
|
|
9864
|
+
],
|
|
9865
|
+
"props": {
|
|
9866
|
+
"columns": {
|
|
9867
|
+
"type": "number | \"auto-fit\"",
|
|
9868
|
+
"default": 1,
|
|
9869
|
+
"description": "Equal-width column count (1-12), or 'auto-fit' for responsive wrapping"
|
|
9870
|
+
},
|
|
9871
|
+
"rows": {
|
|
9872
|
+
"type": "number | \"auto\"",
|
|
9873
|
+
"description": "Explicit row count, or 'auto'"
|
|
9874
|
+
},
|
|
9875
|
+
"flow": {
|
|
9876
|
+
"type": "enum",
|
|
9877
|
+
"values": [
|
|
9878
|
+
"row",
|
|
9879
|
+
"column",
|
|
9880
|
+
"dense",
|
|
9881
|
+
"row-dense",
|
|
9882
|
+
"column-dense"
|
|
9883
|
+
],
|
|
9884
|
+
"description": "grid-auto-flow"
|
|
9885
|
+
},
|
|
9886
|
+
"gap": {
|
|
9887
|
+
"type": "enum",
|
|
9888
|
+
"values": [
|
|
9889
|
+
"none",
|
|
9890
|
+
"xs",
|
|
9891
|
+
"sm",
|
|
9892
|
+
"md",
|
|
9893
|
+
"lg",
|
|
9894
|
+
"xl",
|
|
9895
|
+
"2xl"
|
|
9896
|
+
],
|
|
9897
|
+
"default": "md",
|
|
9898
|
+
"description": "Space between cells. Maps to --vyre-spacing tokens. NEVER a raw px/rem value."
|
|
9899
|
+
},
|
|
9900
|
+
"rowGap": {
|
|
9901
|
+
"type": "enum",
|
|
9902
|
+
"values": [
|
|
9903
|
+
"none",
|
|
9904
|
+
"xs",
|
|
9905
|
+
"sm",
|
|
9906
|
+
"md",
|
|
9907
|
+
"lg",
|
|
9908
|
+
"xl",
|
|
9909
|
+
"2xl"
|
|
9910
|
+
],
|
|
9911
|
+
"description": "Row-gap override. Maps to --vyre-spacing tokens. NEVER a raw px/rem value."
|
|
9912
|
+
},
|
|
9913
|
+
"columnGap": {
|
|
9914
|
+
"type": "enum",
|
|
9915
|
+
"values": [
|
|
9916
|
+
"none",
|
|
9917
|
+
"xs",
|
|
9918
|
+
"sm",
|
|
9919
|
+
"md",
|
|
9920
|
+
"lg",
|
|
9921
|
+
"xl",
|
|
9922
|
+
"2xl"
|
|
9923
|
+
],
|
|
9924
|
+
"description": "Column-gap override. Maps to --vyre-spacing tokens. NEVER a raw px/rem value."
|
|
9925
|
+
},
|
|
9926
|
+
"align": {
|
|
9927
|
+
"type": "enum",
|
|
9928
|
+
"values": [
|
|
9929
|
+
"start",
|
|
9930
|
+
"center",
|
|
9931
|
+
"end",
|
|
9932
|
+
"stretch"
|
|
9933
|
+
],
|
|
9934
|
+
"default": "stretch",
|
|
9935
|
+
"description": "align-items"
|
|
9936
|
+
},
|
|
9937
|
+
"justify": {
|
|
9938
|
+
"type": "enum",
|
|
9939
|
+
"values": [
|
|
9940
|
+
"start",
|
|
9941
|
+
"center",
|
|
9942
|
+
"end",
|
|
9943
|
+
"stretch"
|
|
9944
|
+
],
|
|
9945
|
+
"description": "justify-items"
|
|
9946
|
+
},
|
|
9947
|
+
"width": {
|
|
9948
|
+
"type": "enum",
|
|
9949
|
+
"values": [
|
|
9950
|
+
"auto",
|
|
9951
|
+
"full",
|
|
9952
|
+
"fit",
|
|
9953
|
+
"screen",
|
|
9954
|
+
"xs",
|
|
9955
|
+
"sm",
|
|
9956
|
+
"md",
|
|
9957
|
+
"lg",
|
|
9958
|
+
"xl",
|
|
9959
|
+
"2xl"
|
|
9960
|
+
],
|
|
9961
|
+
"description": "Width — keyword (auto/full=100%/fit=fit-content/screen) or a fixed-rem token size (xs 8 · sm 12 · md 16 · lg 24 · xl 32 · 2xl 42). Avoids an inline width style."
|
|
9962
|
+
},
|
|
9963
|
+
"height": {
|
|
9964
|
+
"type": "enum",
|
|
9965
|
+
"values": [
|
|
9966
|
+
"auto",
|
|
9967
|
+
"full",
|
|
9968
|
+
"fit",
|
|
9969
|
+
"screen",
|
|
9970
|
+
"xs",
|
|
9971
|
+
"sm",
|
|
9972
|
+
"md",
|
|
9973
|
+
"lg",
|
|
9974
|
+
"xl",
|
|
9975
|
+
"2xl"
|
|
9976
|
+
],
|
|
9977
|
+
"description": "Height — keyword (auto/full=100%/fit=fit-content/screen) or a fixed-rem token size (xs 8 · sm 12 · md 16 · lg 24 · xl 32 · 2xl 42). Avoids an inline height style."
|
|
9978
|
+
},
|
|
9979
|
+
"as": {
|
|
9980
|
+
"type": "string",
|
|
9981
|
+
"default": "div",
|
|
9982
|
+
"description": "HTML tag to render"
|
|
9983
|
+
}
|
|
9984
|
+
},
|
|
9985
|
+
"antiPatterns": [
|
|
9986
|
+
{
|
|
9987
|
+
"pattern": "<div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr' }}>",
|
|
9988
|
+
"reason": "Inline grid styles bypass the design system",
|
|
9989
|
+
"fix": "Use <Grid columns={3} gap=\"md\">"
|
|
9990
|
+
},
|
|
9991
|
+
{
|
|
9992
|
+
"pattern": "columns=\"3\" (string)",
|
|
9993
|
+
"reason": "columns is a number or the literal 'auto-fit'",
|
|
9994
|
+
"fix": "Use columns={3} or columns=\"auto-fit\""
|
|
9995
|
+
},
|
|
9996
|
+
{
|
|
9997
|
+
"pattern": "Nested div with inline grid-column for spanning",
|
|
9998
|
+
"reason": "Spanning has a dedicated primitive",
|
|
9999
|
+
"fix": "Wrap the cell in <GridItem colSpan={2}>"
|
|
10000
|
+
},
|
|
10001
|
+
{
|
|
10002
|
+
"pattern": "style={{ width: \"100%\" }} / style={{ height: 320 }}",
|
|
10003
|
+
"reason": "Inline width/height bypass the design system and use magic numbers",
|
|
10004
|
+
"fix": "Use the width / height prop: width=\"full\", width=\"md\", height=\"screen\", etc."
|
|
10005
|
+
}
|
|
10006
|
+
],
|
|
10007
|
+
"examples": [
|
|
10008
|
+
{
|
|
10009
|
+
"description": "Three-column grid with a wide first cell",
|
|
10010
|
+
"code": "<Grid columns={3} gap=\"lg\">\n <GridItem colSpan={2}><Card>Wide</Card></GridItem>\n <Card>Two</Card>\n <Card>Three</Card>\n</Grid>"
|
|
10011
|
+
},
|
|
10012
|
+
{
|
|
10013
|
+
"description": "Responsive auto-fit grid",
|
|
10014
|
+
"code": "<Grid columns=\"auto-fit\" gap=\"md\">\n {items.map((i) => <Card key={i.id}>{i.title}</Card>)}\n</Grid>"
|
|
10015
|
+
}
|
|
10016
|
+
]
|
|
10017
|
+
},
|
|
10018
|
+
"GridItem": {
|
|
10019
|
+
"description": "Child placement inside <Grid>. Sets column/row span and start lines. Renders a plain <div> (or `as`).",
|
|
10020
|
+
"import": "import { GridItem } from \"@usevyre/react\"",
|
|
10021
|
+
"props": {
|
|
10022
|
+
"colSpan": {
|
|
10023
|
+
"type": "number",
|
|
10024
|
+
"description": "Number of columns this item spans"
|
|
10025
|
+
},
|
|
10026
|
+
"rowSpan": {
|
|
10027
|
+
"type": "number",
|
|
10028
|
+
"description": "Number of rows this item spans"
|
|
10029
|
+
},
|
|
10030
|
+
"colStart": {
|
|
10031
|
+
"type": "number",
|
|
10032
|
+
"description": "1-based column line to start at"
|
|
10033
|
+
},
|
|
10034
|
+
"rowStart": {
|
|
10035
|
+
"type": "number",
|
|
10036
|
+
"description": "1-based row line to start at"
|
|
10037
|
+
},
|
|
10038
|
+
"as": {
|
|
10039
|
+
"type": "string",
|
|
10040
|
+
"default": "div",
|
|
10041
|
+
"description": "HTML tag to render"
|
|
10042
|
+
}
|
|
10043
|
+
},
|
|
10044
|
+
"antiPatterns": [
|
|
10045
|
+
{
|
|
10046
|
+
"pattern": "GridItem outside a Grid",
|
|
10047
|
+
"reason": "GridItem only has effect as a direct child of Grid",
|
|
10048
|
+
"fix": "Place <GridItem> directly inside <Grid>"
|
|
10049
|
+
}
|
|
10050
|
+
],
|
|
10051
|
+
"examples": [
|
|
10052
|
+
{
|
|
10053
|
+
"description": "Span two columns",
|
|
10054
|
+
"code": "<Grid columns={4} gap=\"md\">\n <GridItem colSpan={2}>Featured</GridItem>\n <div>a</div>\n <div>b</div>\n</Grid>"
|
|
10055
|
+
}
|
|
10056
|
+
]
|
|
10057
|
+
},
|
|
10058
|
+
"Box": {
|
|
10059
|
+
"description": "Spacing-only container plus a controlled escape hatch. Token padding/margin with shorthand, per-axis (X/Y) and per-side (Top/Right/Bottom/Left) overrides. The `style` prop is an explicit anti-pattern escape hatch. Renders a plain <div> (or `as`).",
|
|
10060
|
+
"import": "import { Box } from \"@usevyre/react\"",
|
|
10061
|
+
"props": {
|
|
10062
|
+
"padding": {
|
|
10063
|
+
"type": "enum",
|
|
10064
|
+
"values": [
|
|
10065
|
+
"none",
|
|
10066
|
+
"xs",
|
|
10067
|
+
"sm",
|
|
10068
|
+
"md",
|
|
10069
|
+
"lg",
|
|
10070
|
+
"xl",
|
|
10071
|
+
"2xl"
|
|
10072
|
+
],
|
|
10073
|
+
"description": "Inner spacing, all sides. Maps to --vyre-spacing tokens. NEVER a raw px/rem value."
|
|
10074
|
+
},
|
|
10075
|
+
"paddingX": {
|
|
10076
|
+
"type": "enum",
|
|
10077
|
+
"values": [
|
|
10078
|
+
"none",
|
|
10079
|
+
"xs",
|
|
10080
|
+
"sm",
|
|
10081
|
+
"md",
|
|
10082
|
+
"lg",
|
|
10083
|
+
"xl",
|
|
10084
|
+
"2xl"
|
|
10085
|
+
],
|
|
10086
|
+
"description": "Inner spacing, left + right. Maps to --vyre-spacing tokens. NEVER a raw px/rem value."
|
|
10087
|
+
},
|
|
10088
|
+
"paddingY": {
|
|
10089
|
+
"type": "enum",
|
|
10090
|
+
"values": [
|
|
10091
|
+
"none",
|
|
10092
|
+
"xs",
|
|
10093
|
+
"sm",
|
|
10094
|
+
"md",
|
|
10095
|
+
"lg",
|
|
10096
|
+
"xl",
|
|
10097
|
+
"2xl"
|
|
10098
|
+
],
|
|
10099
|
+
"description": "Inner spacing, top + bottom. Maps to --vyre-spacing tokens. NEVER a raw px/rem value."
|
|
10100
|
+
},
|
|
10101
|
+
"paddingTop": {
|
|
10102
|
+
"type": "enum",
|
|
10103
|
+
"values": [
|
|
10104
|
+
"none",
|
|
10105
|
+
"xs",
|
|
10106
|
+
"sm",
|
|
10107
|
+
"md",
|
|
10108
|
+
"lg",
|
|
10109
|
+
"xl",
|
|
10110
|
+
"2xl"
|
|
10111
|
+
],
|
|
10112
|
+
"description": "Inner spacing, top. Maps to --vyre-spacing tokens. NEVER a raw px/rem value."
|
|
10113
|
+
},
|
|
10114
|
+
"paddingRight": {
|
|
10115
|
+
"type": "enum",
|
|
10116
|
+
"values": [
|
|
10117
|
+
"none",
|
|
10118
|
+
"xs",
|
|
10119
|
+
"sm",
|
|
10120
|
+
"md",
|
|
10121
|
+
"lg",
|
|
10122
|
+
"xl",
|
|
10123
|
+
"2xl"
|
|
10124
|
+
],
|
|
10125
|
+
"description": "Inner spacing, right. Maps to --vyre-spacing tokens. NEVER a raw px/rem value."
|
|
10126
|
+
},
|
|
10127
|
+
"paddingBottom": {
|
|
10128
|
+
"type": "enum",
|
|
10129
|
+
"values": [
|
|
10130
|
+
"none",
|
|
10131
|
+
"xs",
|
|
10132
|
+
"sm",
|
|
10133
|
+
"md",
|
|
10134
|
+
"lg",
|
|
10135
|
+
"xl",
|
|
10136
|
+
"2xl"
|
|
10137
|
+
],
|
|
10138
|
+
"description": "Inner spacing, bottom. Maps to --vyre-spacing tokens. NEVER a raw px/rem value."
|
|
10139
|
+
},
|
|
10140
|
+
"paddingLeft": {
|
|
10141
|
+
"type": "enum",
|
|
10142
|
+
"values": [
|
|
10143
|
+
"none",
|
|
10144
|
+
"xs",
|
|
10145
|
+
"sm",
|
|
10146
|
+
"md",
|
|
10147
|
+
"lg",
|
|
10148
|
+
"xl",
|
|
10149
|
+
"2xl"
|
|
10150
|
+
],
|
|
10151
|
+
"description": "Inner spacing, left. Maps to --vyre-spacing tokens. NEVER a raw px/rem value."
|
|
10152
|
+
},
|
|
10153
|
+
"margin": {
|
|
10154
|
+
"type": "enum",
|
|
10155
|
+
"values": [
|
|
10156
|
+
"none",
|
|
10157
|
+
"xs",
|
|
10158
|
+
"sm",
|
|
10159
|
+
"md",
|
|
10160
|
+
"lg",
|
|
10161
|
+
"xl",
|
|
10162
|
+
"2xl"
|
|
10163
|
+
],
|
|
10164
|
+
"description": "Outer spacing, all sides. Maps to --vyre-spacing tokens. NEVER a raw px/rem value."
|
|
10165
|
+
},
|
|
10166
|
+
"marginX": {
|
|
10167
|
+
"type": "enum",
|
|
10168
|
+
"values": [
|
|
10169
|
+
"none",
|
|
10170
|
+
"xs",
|
|
10171
|
+
"sm",
|
|
10172
|
+
"md",
|
|
10173
|
+
"lg",
|
|
10174
|
+
"xl",
|
|
10175
|
+
"2xl"
|
|
10176
|
+
],
|
|
10177
|
+
"description": "Outer spacing, left + right. Maps to --vyre-spacing tokens. NEVER a raw px/rem value."
|
|
10178
|
+
},
|
|
10179
|
+
"marginY": {
|
|
10180
|
+
"type": "enum",
|
|
10181
|
+
"values": [
|
|
10182
|
+
"none",
|
|
10183
|
+
"xs",
|
|
10184
|
+
"sm",
|
|
10185
|
+
"md",
|
|
10186
|
+
"lg",
|
|
10187
|
+
"xl",
|
|
10188
|
+
"2xl"
|
|
10189
|
+
],
|
|
10190
|
+
"description": "Outer spacing, top + bottom. Maps to --vyre-spacing tokens. NEVER a raw px/rem value."
|
|
10191
|
+
},
|
|
10192
|
+
"marginTop": {
|
|
10193
|
+
"type": "enum",
|
|
10194
|
+
"values": [
|
|
10195
|
+
"none",
|
|
10196
|
+
"xs",
|
|
10197
|
+
"sm",
|
|
10198
|
+
"md",
|
|
10199
|
+
"lg",
|
|
10200
|
+
"xl",
|
|
10201
|
+
"2xl"
|
|
10202
|
+
],
|
|
10203
|
+
"description": "Outer spacing, top. Maps to --vyre-spacing tokens. NEVER a raw px/rem value."
|
|
10204
|
+
},
|
|
10205
|
+
"marginRight": {
|
|
10206
|
+
"type": "enum",
|
|
10207
|
+
"values": [
|
|
10208
|
+
"none",
|
|
10209
|
+
"xs",
|
|
10210
|
+
"sm",
|
|
10211
|
+
"md",
|
|
10212
|
+
"lg",
|
|
10213
|
+
"xl",
|
|
10214
|
+
"2xl"
|
|
10215
|
+
],
|
|
10216
|
+
"description": "Outer spacing, right. Maps to --vyre-spacing tokens. NEVER a raw px/rem value."
|
|
10217
|
+
},
|
|
10218
|
+
"marginBottom": {
|
|
10219
|
+
"type": "enum",
|
|
10220
|
+
"values": [
|
|
10221
|
+
"none",
|
|
10222
|
+
"xs",
|
|
10223
|
+
"sm",
|
|
10224
|
+
"md",
|
|
10225
|
+
"lg",
|
|
10226
|
+
"xl",
|
|
10227
|
+
"2xl"
|
|
10228
|
+
],
|
|
10229
|
+
"description": "Outer spacing, bottom. Maps to --vyre-spacing tokens. NEVER a raw px/rem value."
|
|
10230
|
+
},
|
|
10231
|
+
"marginLeft": {
|
|
10232
|
+
"type": "enum",
|
|
10233
|
+
"values": [
|
|
10234
|
+
"none",
|
|
10235
|
+
"xs",
|
|
10236
|
+
"sm",
|
|
10237
|
+
"md",
|
|
10238
|
+
"lg",
|
|
10239
|
+
"xl",
|
|
10240
|
+
"2xl"
|
|
10241
|
+
],
|
|
10242
|
+
"description": "Outer spacing, left. Maps to --vyre-spacing tokens. NEVER a raw px/rem value."
|
|
10243
|
+
},
|
|
10244
|
+
"width": {
|
|
10245
|
+
"type": "enum",
|
|
10246
|
+
"values": [
|
|
10247
|
+
"auto",
|
|
10248
|
+
"full",
|
|
10249
|
+
"fit",
|
|
10250
|
+
"screen",
|
|
10251
|
+
"xs",
|
|
10252
|
+
"sm",
|
|
10253
|
+
"md",
|
|
10254
|
+
"lg",
|
|
10255
|
+
"xl",
|
|
10256
|
+
"2xl"
|
|
10257
|
+
],
|
|
10258
|
+
"description": "Width — keyword (auto/full=100%/fit=fit-content/screen) or a fixed-rem token size (xs 8 · sm 12 · md 16 · lg 24 · xl 32 · 2xl 42). Avoids an inline width style."
|
|
10259
|
+
},
|
|
10260
|
+
"height": {
|
|
10261
|
+
"type": "enum",
|
|
10262
|
+
"values": [
|
|
10263
|
+
"auto",
|
|
10264
|
+
"full",
|
|
10265
|
+
"fit",
|
|
10266
|
+
"screen",
|
|
10267
|
+
"xs",
|
|
10268
|
+
"sm",
|
|
10269
|
+
"md",
|
|
10270
|
+
"lg",
|
|
10271
|
+
"xl",
|
|
10272
|
+
"2xl"
|
|
10273
|
+
],
|
|
10274
|
+
"description": "Height — keyword (auto/full=100%/fit=fit-content/screen) or a fixed-rem token size (xs 8 · sm 12 · md 16 · lg 24 · xl 32 · 2xl 42). Avoids an inline height style."
|
|
10275
|
+
},
|
|
10276
|
+
"as": {
|
|
10277
|
+
"type": "string",
|
|
10278
|
+
"default": "div",
|
|
10279
|
+
"description": "HTML tag to render"
|
|
10280
|
+
},
|
|
10281
|
+
"style": {
|
|
10282
|
+
"type": "React.CSSProperties",
|
|
10283
|
+
"description": "ANTI-PATTERN escape hatch. Only for values the design system cannot express. Flagged by @usevyre/eslint-plugin."
|
|
10284
|
+
}
|
|
10285
|
+
},
|
|
10286
|
+
"antiPatterns": [
|
|
10287
|
+
{
|
|
10288
|
+
"pattern": "<Box style={{ padding: 16 }}>",
|
|
10289
|
+
"reason": "padding is a token prop; style is a last resort",
|
|
10290
|
+
"fix": "Use <Box padding=\"md\"> (or paddingX/paddingTop/...)"
|
|
10291
|
+
},
|
|
10292
|
+
{
|
|
10293
|
+
"pattern": "Using Box for flex/grid layout",
|
|
10294
|
+
"reason": "Box is spacing-only and has no layout props",
|
|
10295
|
+
"fix": "Use <Stack> or <Grid>"
|
|
10296
|
+
},
|
|
10297
|
+
{
|
|
10298
|
+
"pattern": "style={{ width: \"100%\" }} / style={{ height: 320 }}",
|
|
10299
|
+
"reason": "Inline width/height bypass the design system and use magic numbers",
|
|
10300
|
+
"fix": "Use the width / height prop: width=\"full\", width=\"md\", height=\"screen\", etc."
|
|
10301
|
+
}
|
|
10302
|
+
],
|
|
10303
|
+
"examples": [
|
|
10304
|
+
{
|
|
10305
|
+
"description": "Asymmetric padding",
|
|
10306
|
+
"code": "<Box as=\"section\" paddingX=\"lg\" paddingY=\"md\">\n <Heading>Settings</Heading>\n</Box>"
|
|
10307
|
+
},
|
|
10308
|
+
{
|
|
10309
|
+
"description": "Vertical rhythm via margin-top",
|
|
10310
|
+
"code": "<Box marginTop=\"xl\"><Separator /></Box>"
|
|
10311
|
+
}
|
|
10312
|
+
]
|
|
10313
|
+
},
|
|
10314
|
+
"DateRangePicker": {
|
|
10315
|
+
"description": "Start/end date range picker. Built on Calendar (mode=range) with a friendlier { from, to } object API, a two-month side-by-side view, and preset shortcuts. Use this for report/filter date ranges; use DatePicker for a single date.",
|
|
10316
|
+
"import": "import { DateRangePicker } from \"@usevyre/react\"",
|
|
10317
|
+
"props": {
|
|
10318
|
+
"value": {
|
|
10319
|
+
"type": "{ from: Date | null; to: Date | null } | null",
|
|
10320
|
+
"description": "Selected range (controlled). Pass an OBJECT, not a tuple."
|
|
10321
|
+
},
|
|
10322
|
+
"onChange": {
|
|
10323
|
+
"type": "function",
|
|
10324
|
+
"description": "Callback (range: { from, to }) => void when the range changes"
|
|
8861
10325
|
},
|
|
8862
10326
|
"placeholder": {
|
|
8863
10327
|
"type": "string",
|
|
@@ -8932,7 +10396,7 @@ export const schema = {
|
|
|
8932
10396
|
};
|
|
8933
10397
|
|
|
8934
10398
|
export const antiPatterns = {
|
|
8935
|
-
"version": "1.
|
|
10399
|
+
"version": "1.6.0",
|
|
8936
10400
|
"rules": [
|
|
8937
10401
|
{
|
|
8938
10402
|
"component": "Accordion",
|
|
@@ -9053,6 +10517,13 @@ export const antiPatterns = {
|
|
|
9053
10517
|
"fix": "Add aria-label describing the action",
|
|
9054
10518
|
"severity": "error"
|
|
9055
10519
|
},
|
|
10520
|
+
{
|
|
10521
|
+
"component": "Button",
|
|
10522
|
+
"pattern": "padding / margin / marginTop (any spacing prop) on a useVyre component",
|
|
10523
|
+
"reason": "Components have NO spacing props by design — internal spacing is fixed by tokens for visual consistency",
|
|
10524
|
+
"fix": "Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it",
|
|
10525
|
+
"severity": "error"
|
|
10526
|
+
},
|
|
9056
10527
|
{
|
|
9057
10528
|
"component": "Calendar",
|
|
9058
10529
|
"pattern": "Calendar for an input field that opens a popover",
|
|
@@ -9088,6 +10559,13 @@ export const antiPatterns = {
|
|
|
9088
10559
|
"fix": "Use variant=\"elevated\" | \"outlined\" | \"ghost\" | \"accent\"",
|
|
9089
10560
|
"severity": "error"
|
|
9090
10561
|
},
|
|
10562
|
+
{
|
|
10563
|
+
"component": "Card",
|
|
10564
|
+
"pattern": "padding / margin / marginTop (any spacing prop) on a useVyre component",
|
|
10565
|
+
"reason": "Components have NO spacing props by design — internal spacing is fixed by tokens for visual consistency",
|
|
10566
|
+
"fix": "Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it",
|
|
10567
|
+
"severity": "error"
|
|
10568
|
+
},
|
|
9091
10569
|
{
|
|
9092
10570
|
"component": "Checkbox",
|
|
9093
10571
|
"pattern": "size=\"lg\"",
|
|
@@ -9186,6 +10664,13 @@ export const antiPatterns = {
|
|
|
9186
10664
|
"fix": "Use v-model on <Input>/<Textarea> in Vue; in React use value + onChange",
|
|
9187
10665
|
"severity": "error"
|
|
9188
10666
|
},
|
|
10667
|
+
{
|
|
10668
|
+
"component": "Input",
|
|
10669
|
+
"pattern": "padding / margin / marginTop (any spacing prop) on a useVyre component",
|
|
10670
|
+
"reason": "Components have NO spacing props by design — internal spacing is fixed by tokens for visual consistency",
|
|
10671
|
+
"fix": "Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it",
|
|
10672
|
+
"severity": "error"
|
|
10673
|
+
},
|
|
9189
10674
|
{
|
|
9190
10675
|
"component": "Modal",
|
|
9191
10676
|
"pattern": "size=\"xl\"",
|
|
@@ -9438,6 +10923,90 @@ export const antiPatterns = {
|
|
|
9438
10923
|
"fix": "Handle onSend(text, files) — map files to message attachments and append",
|
|
9439
10924
|
"severity": "error"
|
|
9440
10925
|
},
|
|
10926
|
+
{
|
|
10927
|
+
"component": "Stack",
|
|
10928
|
+
"pattern": "<div style={{ display: 'flex', gap: 12 }}>",
|
|
10929
|
+
"reason": "Inline flex styles bypass the design system and use magic-number spacing",
|
|
10930
|
+
"fix": "Use <Stack gap=\"md\"> — gap is a token",
|
|
10931
|
+
"severity": "error"
|
|
10932
|
+
},
|
|
10933
|
+
{
|
|
10934
|
+
"component": "Stack",
|
|
10935
|
+
"pattern": "gap={12} or gap=\"12px\"",
|
|
10936
|
+
"reason": "Stack gap is a closed token enum",
|
|
10937
|
+
"fix": "Use gap=\"none|xs|sm|md|lg|xl|2xl\"",
|
|
10938
|
+
"severity": "error"
|
|
10939
|
+
},
|
|
10940
|
+
{
|
|
10941
|
+
"component": "Stack",
|
|
10942
|
+
"pattern": "direction=\"vertical\" / \"horizontal\"",
|
|
10943
|
+
"reason": "Stack mirrors CSS flex-direction names",
|
|
10944
|
+
"fix": "Use direction=\"row\" or \"column\" (also row-reverse / column-reverse)",
|
|
10945
|
+
"severity": "error"
|
|
10946
|
+
},
|
|
10947
|
+
{
|
|
10948
|
+
"component": "Stack",
|
|
10949
|
+
"pattern": "style={{ width: \"100%\" }} / style={{ height: 320 }}",
|
|
10950
|
+
"reason": "Inline width/height bypass the design system and use magic numbers",
|
|
10951
|
+
"fix": "Use the width / height prop: width=\"full\", width=\"md\", height=\"screen\", etc.",
|
|
10952
|
+
"severity": "error"
|
|
10953
|
+
},
|
|
10954
|
+
{
|
|
10955
|
+
"component": "Grid",
|
|
10956
|
+
"pattern": "<div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr' }}>",
|
|
10957
|
+
"reason": "Inline grid styles bypass the design system",
|
|
10958
|
+
"fix": "Use <Grid columns={3} gap=\"md\">",
|
|
10959
|
+
"severity": "error"
|
|
10960
|
+
},
|
|
10961
|
+
{
|
|
10962
|
+
"component": "Grid",
|
|
10963
|
+
"pattern": "columns=\"3\" (string)",
|
|
10964
|
+
"reason": "columns is a number or the literal 'auto-fit'",
|
|
10965
|
+
"fix": "Use columns={3} or columns=\"auto-fit\"",
|
|
10966
|
+
"severity": "error"
|
|
10967
|
+
},
|
|
10968
|
+
{
|
|
10969
|
+
"component": "Grid",
|
|
10970
|
+
"pattern": "Nested div with inline grid-column for spanning",
|
|
10971
|
+
"reason": "Spanning has a dedicated primitive",
|
|
10972
|
+
"fix": "Wrap the cell in <GridItem colSpan={2}>",
|
|
10973
|
+
"severity": "error"
|
|
10974
|
+
},
|
|
10975
|
+
{
|
|
10976
|
+
"component": "Grid",
|
|
10977
|
+
"pattern": "style={{ width: \"100%\" }} / style={{ height: 320 }}",
|
|
10978
|
+
"reason": "Inline width/height bypass the design system and use magic numbers",
|
|
10979
|
+
"fix": "Use the width / height prop: width=\"full\", width=\"md\", height=\"screen\", etc.",
|
|
10980
|
+
"severity": "error"
|
|
10981
|
+
},
|
|
10982
|
+
{
|
|
10983
|
+
"component": "GridItem",
|
|
10984
|
+
"pattern": "GridItem outside a Grid",
|
|
10985
|
+
"reason": "GridItem only has effect as a direct child of Grid",
|
|
10986
|
+
"fix": "Place <GridItem> directly inside <Grid>",
|
|
10987
|
+
"severity": "error"
|
|
10988
|
+
},
|
|
10989
|
+
{
|
|
10990
|
+
"component": "Box",
|
|
10991
|
+
"pattern": "<Box style={{ padding: 16 }}>",
|
|
10992
|
+
"reason": "padding is a token prop; style is a last resort",
|
|
10993
|
+
"fix": "Use <Box padding=\"md\"> (or paddingX/paddingTop/...)",
|
|
10994
|
+
"severity": "error"
|
|
10995
|
+
},
|
|
10996
|
+
{
|
|
10997
|
+
"component": "Box",
|
|
10998
|
+
"pattern": "Using Box for flex/grid layout",
|
|
10999
|
+
"reason": "Box is spacing-only and has no layout props",
|
|
11000
|
+
"fix": "Use <Stack> or <Grid>",
|
|
11001
|
+
"severity": "error"
|
|
11002
|
+
},
|
|
11003
|
+
{
|
|
11004
|
+
"component": "Box",
|
|
11005
|
+
"pattern": "style={{ width: \"100%\" }} / style={{ height: 320 }}",
|
|
11006
|
+
"reason": "Inline width/height bypass the design system and use magic numbers",
|
|
11007
|
+
"fix": "Use the width / height prop: width=\"full\", width=\"md\", height=\"screen\", etc.",
|
|
11008
|
+
"severity": "error"
|
|
11009
|
+
},
|
|
9441
11010
|
{
|
|
9442
11011
|
"component": "DateRangePicker",
|
|
9443
11012
|
"pattern": "value={[from, to]}",
|
|
@@ -9463,14 +11032,34 @@ export const antiPatterns = {
|
|
|
9463
11032
|
};
|
|
9464
11033
|
|
|
9465
11034
|
export const versionInfo = {
|
|
9466
|
-
"version": "1.
|
|
9467
|
-
"packageVersion": "1.
|
|
9468
|
-
"generatedAt": "2026-05-
|
|
11035
|
+
"version": "1.6.0",
|
|
11036
|
+
"packageVersion": "1.6.0",
|
|
11037
|
+
"generatedAt": "2026-05-18T02:16:10.599Z",
|
|
9469
11038
|
"validFor": [
|
|
9470
11039
|
"@usevyre/react@1.1.0+",
|
|
9471
11040
|
"@usevyre/vue@1.1.0+"
|
|
9472
11041
|
],
|
|
9473
11042
|
"changelog": {
|
|
11043
|
+
"1.6.0": {
|
|
11044
|
+
"date": "2026-05-18",
|
|
11045
|
+
"breaking": false,
|
|
11046
|
+
"summary": "Documented the spacing model as an explicit anti-pattern on representative components (Button, Card, Input): useVyre components take no padding/margin props — use Stack/Grid gap or a Box wrapper. No API change."
|
|
11047
|
+
},
|
|
11048
|
+
"1.5.0": {
|
|
11049
|
+
"date": "2026-05-18",
|
|
11050
|
+
"breaking": false,
|
|
11051
|
+
"summary": "Stack, Grid and Box gain token-locked width / height props (keywords auto/full/fit/screen + fixed-rem token sizes xs–2xl), removing the need for an inline width/height style for common layout sizing."
|
|
11052
|
+
},
|
|
11053
|
+
"1.4.0": {
|
|
11054
|
+
"date": "2026-05-18",
|
|
11055
|
+
"breaking": false,
|
|
11056
|
+
"summary": "Layout primitives expanded: Stack now covers the full CSS flexbox surface (reverse directions, wrap modes, alignContent/alignSelf, grow/shrink/basis, per-axis gap); Grid gains rows/flow/justify + a new GridItem subcomponent for span/placement; Box gains per-axis (X/Y) and per-side (Top/Right/Bottom/Left) token padding/margin. Fixes Grid columns being overwritten when a user style prop was passed."
|
|
11057
|
+
},
|
|
11058
|
+
"1.3.0": {
|
|
11059
|
+
"date": "2026-05-18",
|
|
11060
|
+
"breaking": false,
|
|
11061
|
+
"summary": "Added Stack, Grid and Box layout primitives. Token-locked spacing (no raw px/rem) to eliminate hallucinated inline flex/grid styles; Box exposes a documented style escape hatch flagged as an anti-pattern."
|
|
11062
|
+
},
|
|
9474
11063
|
"1.2.0": {
|
|
9475
11064
|
"date": "2026-05-16",
|
|
9476
11065
|
"breaking": false,
|
|
@@ -9499,309 +11088,337 @@ export const versionInfo = {
|
|
|
9499
11088
|
},
|
|
9500
11089
|
"components": {
|
|
9501
11090
|
"Accordion": {
|
|
9502
|
-
"version": "1.
|
|
9503
|
-
"lastUpdated": "2026-05-
|
|
11091
|
+
"version": "1.6.0",
|
|
11092
|
+
"lastUpdated": "2026-05-18",
|
|
9504
11093
|
"breaking": false,
|
|
9505
11094
|
"stable": true,
|
|
9506
11095
|
"changelog": null
|
|
9507
11096
|
},
|
|
9508
11097
|
"Alert": {
|
|
9509
|
-
"version": "1.
|
|
9510
|
-
"lastUpdated": "2026-05-
|
|
11098
|
+
"version": "1.6.0",
|
|
11099
|
+
"lastUpdated": "2026-05-18",
|
|
9511
11100
|
"breaking": false,
|
|
9512
11101
|
"stable": true,
|
|
9513
11102
|
"changelog": null
|
|
9514
11103
|
},
|
|
9515
11104
|
"AlertDialog": {
|
|
9516
|
-
"version": "1.
|
|
9517
|
-
"lastUpdated": "2026-05-
|
|
11105
|
+
"version": "1.6.0",
|
|
11106
|
+
"lastUpdated": "2026-05-18",
|
|
9518
11107
|
"breaking": false,
|
|
9519
11108
|
"stable": true,
|
|
9520
11109
|
"changelog": null
|
|
9521
11110
|
},
|
|
9522
11111
|
"Avatar": {
|
|
9523
|
-
"version": "1.
|
|
9524
|
-
"lastUpdated": "2026-05-
|
|
11112
|
+
"version": "1.6.0",
|
|
11113
|
+
"lastUpdated": "2026-05-18",
|
|
9525
11114
|
"breaking": false,
|
|
9526
11115
|
"stable": true,
|
|
9527
11116
|
"changelog": null
|
|
9528
11117
|
},
|
|
9529
11118
|
"Badge": {
|
|
9530
|
-
"version": "1.
|
|
9531
|
-
"lastUpdated": "2026-05-
|
|
11119
|
+
"version": "1.6.0",
|
|
11120
|
+
"lastUpdated": "2026-05-18",
|
|
9532
11121
|
"breaking": false,
|
|
9533
11122
|
"stable": true,
|
|
9534
11123
|
"changelog": null
|
|
9535
11124
|
},
|
|
9536
11125
|
"Breadcrumb": {
|
|
9537
|
-
"version": "1.
|
|
9538
|
-
"lastUpdated": "2026-05-
|
|
11126
|
+
"version": "1.6.0",
|
|
11127
|
+
"lastUpdated": "2026-05-18",
|
|
9539
11128
|
"breaking": false,
|
|
9540
11129
|
"stable": true,
|
|
9541
11130
|
"changelog": null
|
|
9542
11131
|
},
|
|
9543
11132
|
"Button": {
|
|
9544
|
-
"version": "1.
|
|
9545
|
-
"lastUpdated": "2026-05-
|
|
11133
|
+
"version": "1.6.0",
|
|
11134
|
+
"lastUpdated": "2026-05-18",
|
|
9546
11135
|
"breaking": false,
|
|
9547
11136
|
"stable": true,
|
|
9548
11137
|
"changelog": null
|
|
9549
11138
|
},
|
|
9550
11139
|
"Calendar": {
|
|
9551
|
-
"version": "1.
|
|
9552
|
-
"lastUpdated": "2026-05-
|
|
11140
|
+
"version": "1.6.0",
|
|
11141
|
+
"lastUpdated": "2026-05-18",
|
|
9553
11142
|
"breaking": false,
|
|
9554
11143
|
"stable": true,
|
|
9555
11144
|
"changelog": null
|
|
9556
11145
|
},
|
|
9557
11146
|
"DatePicker": {
|
|
9558
|
-
"version": "1.
|
|
9559
|
-
"lastUpdated": "2026-05-
|
|
11147
|
+
"version": "1.6.0",
|
|
11148
|
+
"lastUpdated": "2026-05-18",
|
|
9560
11149
|
"breaking": false,
|
|
9561
11150
|
"stable": true,
|
|
9562
11151
|
"changelog": null
|
|
9563
11152
|
},
|
|
9564
11153
|
"Card": {
|
|
9565
|
-
"version": "1.
|
|
9566
|
-
"lastUpdated": "2026-05-
|
|
11154
|
+
"version": "1.6.0",
|
|
11155
|
+
"lastUpdated": "2026-05-18",
|
|
9567
11156
|
"breaking": false,
|
|
9568
11157
|
"stable": true,
|
|
9569
11158
|
"changelog": null
|
|
9570
11159
|
},
|
|
9571
11160
|
"Checkbox": {
|
|
9572
|
-
"version": "1.
|
|
9573
|
-
"lastUpdated": "2026-05-
|
|
11161
|
+
"version": "1.6.0",
|
|
11162
|
+
"lastUpdated": "2026-05-18",
|
|
9574
11163
|
"breaking": false,
|
|
9575
11164
|
"stable": true,
|
|
9576
11165
|
"changelog": null
|
|
9577
11166
|
},
|
|
9578
11167
|
"RadioGroup": {
|
|
9579
|
-
"version": "1.
|
|
9580
|
-
"lastUpdated": "2026-05-
|
|
11168
|
+
"version": "1.6.0",
|
|
11169
|
+
"lastUpdated": "2026-05-18",
|
|
9581
11170
|
"breaking": false,
|
|
9582
11171
|
"stable": true,
|
|
9583
11172
|
"changelog": null
|
|
9584
11173
|
},
|
|
9585
11174
|
"RichTextEditor": {
|
|
9586
|
-
"version": "1.
|
|
9587
|
-
"lastUpdated": "2026-05-
|
|
11175
|
+
"version": "1.6.0",
|
|
11176
|
+
"lastUpdated": "2026-05-18",
|
|
9588
11177
|
"breaking": false,
|
|
9589
11178
|
"stable": true,
|
|
9590
11179
|
"changelog": null
|
|
9591
11180
|
},
|
|
9592
11181
|
"Command": {
|
|
9593
|
-
"version": "1.
|
|
9594
|
-
"lastUpdated": "2026-05-
|
|
11182
|
+
"version": "1.6.0",
|
|
11183
|
+
"lastUpdated": "2026-05-18",
|
|
9595
11184
|
"breaking": false,
|
|
9596
11185
|
"stable": true,
|
|
9597
11186
|
"changelog": null
|
|
9598
11187
|
},
|
|
9599
11188
|
"DropdownMenu": {
|
|
9600
|
-
"version": "1.
|
|
9601
|
-
"lastUpdated": "2026-05-
|
|
11189
|
+
"version": "1.6.0",
|
|
11190
|
+
"lastUpdated": "2026-05-18",
|
|
9602
11191
|
"breaking": false,
|
|
9603
11192
|
"stable": true,
|
|
9604
11193
|
"changelog": null
|
|
9605
11194
|
},
|
|
9606
11195
|
"Field": {
|
|
9607
|
-
"version": "1.
|
|
9608
|
-
"lastUpdated": "2026-05-
|
|
11196
|
+
"version": "1.6.0",
|
|
11197
|
+
"lastUpdated": "2026-05-18",
|
|
9609
11198
|
"breaking": false,
|
|
9610
11199
|
"stable": true,
|
|
9611
11200
|
"changelog": null
|
|
9612
11201
|
},
|
|
9613
11202
|
"Input": {
|
|
9614
|
-
"version": "1.
|
|
9615
|
-
"lastUpdated": "2026-05-
|
|
11203
|
+
"version": "1.6.0",
|
|
11204
|
+
"lastUpdated": "2026-05-18",
|
|
9616
11205
|
"breaking": false,
|
|
9617
11206
|
"stable": true,
|
|
9618
11207
|
"changelog": null
|
|
9619
11208
|
},
|
|
9620
11209
|
"Label": {
|
|
9621
|
-
"version": "1.
|
|
9622
|
-
"lastUpdated": "2026-05-
|
|
11210
|
+
"version": "1.6.0",
|
|
11211
|
+
"lastUpdated": "2026-05-18",
|
|
9623
11212
|
"breaking": false,
|
|
9624
11213
|
"stable": true,
|
|
9625
11214
|
"changelog": null
|
|
9626
11215
|
},
|
|
9627
11216
|
"Modal": {
|
|
9628
|
-
"version": "1.
|
|
9629
|
-
"lastUpdated": "2026-05-
|
|
11217
|
+
"version": "1.6.0",
|
|
11218
|
+
"lastUpdated": "2026-05-18",
|
|
9630
11219
|
"breaking": false,
|
|
9631
11220
|
"stable": true,
|
|
9632
11221
|
"changelog": null
|
|
9633
11222
|
},
|
|
9634
11223
|
"Pagination": {
|
|
9635
|
-
"version": "1.
|
|
9636
|
-
"lastUpdated": "2026-05-
|
|
11224
|
+
"version": "1.6.0",
|
|
11225
|
+
"lastUpdated": "2026-05-18",
|
|
9637
11226
|
"breaking": false,
|
|
9638
11227
|
"stable": true,
|
|
9639
11228
|
"changelog": null
|
|
9640
11229
|
},
|
|
9641
11230
|
"Popover": {
|
|
9642
|
-
"version": "1.
|
|
9643
|
-
"lastUpdated": "2026-05-
|
|
11231
|
+
"version": "1.6.0",
|
|
11232
|
+
"lastUpdated": "2026-05-18",
|
|
9644
11233
|
"breaking": false,
|
|
9645
11234
|
"stable": true,
|
|
9646
11235
|
"changelog": null
|
|
9647
11236
|
},
|
|
9648
11237
|
"Progress": {
|
|
9649
|
-
"version": "1.
|
|
9650
|
-
"lastUpdated": "2026-05-
|
|
11238
|
+
"version": "1.6.0",
|
|
11239
|
+
"lastUpdated": "2026-05-18",
|
|
9651
11240
|
"breaking": false,
|
|
9652
11241
|
"stable": true,
|
|
9653
11242
|
"changelog": null
|
|
9654
11243
|
},
|
|
9655
11244
|
"Select": {
|
|
9656
|
-
"version": "1.
|
|
9657
|
-
"lastUpdated": "2026-05-
|
|
11245
|
+
"version": "1.6.0",
|
|
11246
|
+
"lastUpdated": "2026-05-18",
|
|
9658
11247
|
"breaking": false,
|
|
9659
11248
|
"stable": true,
|
|
9660
11249
|
"changelog": null
|
|
9661
11250
|
},
|
|
9662
11251
|
"Separator": {
|
|
9663
|
-
"version": "1.
|
|
9664
|
-
"lastUpdated": "2026-05-
|
|
11252
|
+
"version": "1.6.0",
|
|
11253
|
+
"lastUpdated": "2026-05-18",
|
|
9665
11254
|
"breaking": false,
|
|
9666
11255
|
"stable": true,
|
|
9667
11256
|
"changelog": null
|
|
9668
11257
|
},
|
|
9669
11258
|
"Sheet": {
|
|
9670
|
-
"version": "1.
|
|
9671
|
-
"lastUpdated": "2026-05-
|
|
11259
|
+
"version": "1.6.0",
|
|
11260
|
+
"lastUpdated": "2026-05-18",
|
|
9672
11261
|
"breaking": false,
|
|
9673
11262
|
"stable": true,
|
|
9674
11263
|
"changelog": null
|
|
9675
11264
|
},
|
|
9676
11265
|
"Sidebar": {
|
|
9677
|
-
"version": "1.
|
|
9678
|
-
"lastUpdated": "2026-05-
|
|
11266
|
+
"version": "1.6.0",
|
|
11267
|
+
"lastUpdated": "2026-05-18",
|
|
9679
11268
|
"breaking": false,
|
|
9680
11269
|
"stable": true,
|
|
9681
11270
|
"changelog": null
|
|
9682
11271
|
},
|
|
9683
11272
|
"Skeleton": {
|
|
9684
|
-
"version": "1.
|
|
9685
|
-
"lastUpdated": "2026-05-
|
|
11273
|
+
"version": "1.6.0",
|
|
11274
|
+
"lastUpdated": "2026-05-18",
|
|
9686
11275
|
"breaking": false,
|
|
9687
11276
|
"stable": true,
|
|
9688
11277
|
"changelog": null
|
|
9689
11278
|
},
|
|
9690
11279
|
"Slider": {
|
|
9691
|
-
"version": "1.
|
|
9692
|
-
"lastUpdated": "2026-05-
|
|
11280
|
+
"version": "1.6.0",
|
|
11281
|
+
"lastUpdated": "2026-05-18",
|
|
9693
11282
|
"breaking": false,
|
|
9694
11283
|
"stable": true,
|
|
9695
11284
|
"changelog": null
|
|
9696
11285
|
},
|
|
9697
11286
|
"Switch": {
|
|
9698
|
-
"version": "1.
|
|
9699
|
-
"lastUpdated": "2026-05-
|
|
11287
|
+
"version": "1.6.0",
|
|
11288
|
+
"lastUpdated": "2026-05-18",
|
|
9700
11289
|
"breaking": false,
|
|
9701
11290
|
"stable": true,
|
|
9702
11291
|
"changelog": null
|
|
9703
11292
|
},
|
|
9704
11293
|
"Table": {
|
|
9705
|
-
"version": "1.
|
|
9706
|
-
"lastUpdated": "2026-05-
|
|
11294
|
+
"version": "1.6.0",
|
|
11295
|
+
"lastUpdated": "2026-05-18",
|
|
9707
11296
|
"breaking": false,
|
|
9708
11297
|
"stable": true,
|
|
9709
11298
|
"changelog": null
|
|
9710
11299
|
},
|
|
9711
11300
|
"Tabs": {
|
|
9712
|
-
"version": "1.
|
|
9713
|
-
"lastUpdated": "2026-05-
|
|
11301
|
+
"version": "1.6.0",
|
|
11302
|
+
"lastUpdated": "2026-05-18",
|
|
9714
11303
|
"breaking": false,
|
|
9715
11304
|
"stable": true,
|
|
9716
11305
|
"changelog": null
|
|
9717
11306
|
},
|
|
9718
11307
|
"Toast": {
|
|
9719
|
-
"version": "1.
|
|
9720
|
-
"lastUpdated": "2026-05-
|
|
11308
|
+
"version": "1.6.0",
|
|
11309
|
+
"lastUpdated": "2026-05-18",
|
|
9721
11310
|
"breaking": false,
|
|
9722
11311
|
"stable": true,
|
|
9723
11312
|
"changelog": null
|
|
9724
11313
|
},
|
|
9725
11314
|
"Tooltip": {
|
|
9726
|
-
"version": "1.
|
|
9727
|
-
"lastUpdated": "2026-05-
|
|
11315
|
+
"version": "1.6.0",
|
|
11316
|
+
"lastUpdated": "2026-05-18",
|
|
9728
11317
|
"breaking": false,
|
|
9729
11318
|
"stable": true,
|
|
9730
11319
|
"changelog": null
|
|
9731
11320
|
},
|
|
9732
11321
|
"Typography": {
|
|
9733
|
-
"version": "1.
|
|
9734
|
-
"lastUpdated": "2026-05-
|
|
11322
|
+
"version": "1.6.0",
|
|
11323
|
+
"lastUpdated": "2026-05-18",
|
|
9735
11324
|
"breaking": false,
|
|
9736
11325
|
"stable": true,
|
|
9737
11326
|
"changelog": null
|
|
9738
11327
|
},
|
|
9739
11328
|
"ButtonGroup": {
|
|
9740
|
-
"version": "1.
|
|
9741
|
-
"lastUpdated": "2026-05-
|
|
11329
|
+
"version": "1.6.0",
|
|
11330
|
+
"lastUpdated": "2026-05-18",
|
|
9742
11331
|
"breaking": false,
|
|
9743
11332
|
"stable": true,
|
|
9744
11333
|
"changelog": null
|
|
9745
11334
|
},
|
|
9746
11335
|
"TagsInput": {
|
|
9747
|
-
"version": "1.
|
|
9748
|
-
"lastUpdated": "2026-05-
|
|
11336
|
+
"version": "1.6.0",
|
|
11337
|
+
"lastUpdated": "2026-05-18",
|
|
9749
11338
|
"breaking": false,
|
|
9750
11339
|
"stable": true,
|
|
9751
11340
|
"changelog": null
|
|
9752
11341
|
},
|
|
9753
11342
|
"Combobox": {
|
|
9754
|
-
"version": "1.
|
|
9755
|
-
"lastUpdated": "2026-05-
|
|
11343
|
+
"version": "1.6.0",
|
|
11344
|
+
"lastUpdated": "2026-05-18",
|
|
9756
11345
|
"breaking": false,
|
|
9757
11346
|
"stable": true,
|
|
9758
11347
|
"changelog": null
|
|
9759
11348
|
},
|
|
9760
11349
|
"DataGrid": {
|
|
9761
|
-
"version": "1.
|
|
9762
|
-
"lastUpdated": "2026-05-
|
|
11350
|
+
"version": "1.6.0",
|
|
11351
|
+
"lastUpdated": "2026-05-18",
|
|
9763
11352
|
"breaking": false,
|
|
9764
11353
|
"stable": true,
|
|
9765
11354
|
"changelog": null
|
|
9766
11355
|
},
|
|
9767
11356
|
"Tag": {
|
|
9768
|
-
"version": "1.
|
|
9769
|
-
"lastUpdated": "2026-05-
|
|
11357
|
+
"version": "1.6.0",
|
|
11358
|
+
"lastUpdated": "2026-05-18",
|
|
9770
11359
|
"breaking": false,
|
|
9771
11360
|
"stable": true,
|
|
9772
11361
|
"changelog": null
|
|
9773
11362
|
},
|
|
9774
11363
|
"TagGroup": {
|
|
9775
|
-
"version": "1.
|
|
9776
|
-
"lastUpdated": "2026-05-
|
|
11364
|
+
"version": "1.6.0",
|
|
11365
|
+
"lastUpdated": "2026-05-18",
|
|
9777
11366
|
"breaking": false,
|
|
9778
11367
|
"stable": true,
|
|
9779
11368
|
"changelog": null
|
|
9780
11369
|
},
|
|
9781
11370
|
"Item": {
|
|
9782
|
-
"version": "1.
|
|
9783
|
-
"lastUpdated": "2026-05-
|
|
11371
|
+
"version": "1.6.0",
|
|
11372
|
+
"lastUpdated": "2026-05-18",
|
|
9784
11373
|
"breaking": false,
|
|
9785
11374
|
"stable": true,
|
|
9786
11375
|
"changelog": null
|
|
9787
11376
|
},
|
|
9788
11377
|
"Kanban": {
|
|
9789
|
-
"version": "1.
|
|
9790
|
-
"lastUpdated": "2026-05-
|
|
11378
|
+
"version": "1.6.0",
|
|
11379
|
+
"lastUpdated": "2026-05-18",
|
|
9791
11380
|
"breaking": false,
|
|
9792
11381
|
"stable": true,
|
|
9793
11382
|
"changelog": null
|
|
9794
11383
|
},
|
|
9795
11384
|
"Conversation": {
|
|
9796
|
-
"version": "1.
|
|
9797
|
-
"lastUpdated": "2026-05-
|
|
11385
|
+
"version": "1.6.0",
|
|
11386
|
+
"lastUpdated": "2026-05-18",
|
|
11387
|
+
"breaking": false,
|
|
11388
|
+
"stable": true,
|
|
11389
|
+
"changelog": null
|
|
11390
|
+
},
|
|
11391
|
+
"Stack": {
|
|
11392
|
+
"version": "1.6.0",
|
|
11393
|
+
"lastUpdated": "2026-05-18",
|
|
11394
|
+
"breaking": false,
|
|
11395
|
+
"stable": true,
|
|
11396
|
+
"changelog": null
|
|
11397
|
+
},
|
|
11398
|
+
"Grid": {
|
|
11399
|
+
"version": "1.6.0",
|
|
11400
|
+
"lastUpdated": "2026-05-18",
|
|
11401
|
+
"breaking": false,
|
|
11402
|
+
"stable": true,
|
|
11403
|
+
"changelog": null
|
|
11404
|
+
},
|
|
11405
|
+
"GridItem": {
|
|
11406
|
+
"version": "1.6.0",
|
|
11407
|
+
"lastUpdated": "2026-05-18",
|
|
11408
|
+
"breaking": false,
|
|
11409
|
+
"stable": true,
|
|
11410
|
+
"changelog": null
|
|
11411
|
+
},
|
|
11412
|
+
"Box": {
|
|
11413
|
+
"version": "1.6.0",
|
|
11414
|
+
"lastUpdated": "2026-05-18",
|
|
9798
11415
|
"breaking": false,
|
|
9799
11416
|
"stable": true,
|
|
9800
11417
|
"changelog": null
|
|
9801
11418
|
},
|
|
9802
11419
|
"DateRangePicker": {
|
|
9803
|
-
"version": "1.
|
|
9804
|
-
"lastUpdated": "2026-05-
|
|
11420
|
+
"version": "1.6.0",
|
|
11421
|
+
"lastUpdated": "2026-05-18",
|
|
9805
11422
|
"breaking": false,
|
|
9806
11423
|
"stable": true,
|
|
9807
11424
|
"changelog": null
|
|
@@ -9816,17 +11433,17 @@ export const cheatSheets = {
|
|
|
9816
11433
|
"Avatar": "# Avatar — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**User profile image with fallback initials or icon.**\n\n```ts\nimport { Avatar } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `size` | `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` | `md` |\n| `status` | `\"online\"` \\| `\"offline\"` \\| `\"busy\"` \\| `\"away\"` | — |\n\n## Common AI Mistakes\n\n- ❌ `size=\"xs\"`\n → Use size=\"sm\"\n- ❌ `size=\"2xl\"`\n → Use size=\"xl\"\n\n## Examples\n\n**Avatar with image and online status**\n```tsx\n<Avatar src=\"/user.png\" alt=\"Jane Doe\" size=\"lg\" status=\"online\" />\n```\n\n**Fallback initials**\n```tsx\n<Avatar fallback=\"JD\" size=\"md\" />\n```\n",
|
|
9817
11434
|
"Badge": "# Badge — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Small label for status, category, or count. Use dot prop for live status indicator.**\n\n```ts\nimport { Badge } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `variant` | `\"default\"` \\| `\"accent\"` \\| `\"teal\"` \\| `\"success\"` \\| `\"warning\"` \\| `\"danger\"` | `default` |\n| `dot` | `true` \\| `false` | `false` |\n\n## Common AI Mistakes\n\n- ❌ `variant=\"primary\"`\n → Use variant=\"accent\" for brand color\n- ❌ `variant=\"error\"`\n → Use variant=\"danger\"\n- ❌ `variant=\"info\"`\n → Use variant=\"teal\" for info-like styling\n\n## Examples\n\n**Live status with dot**\n```tsx\n<Badge variant=\"success\" dot>Online</Badge>\n```\n\n**Warning badge**\n```tsx\n<Badge variant=\"warning\">Beta</Badge>\n```\n\n**Danger badge**\n```tsx\n<Badge variant=\"danger\">Error</Badge>\n```\n",
|
|
9818
11435
|
"Breadcrumb": "# Breadcrumb — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Navigation trail showing current page location in hierarchy.**\n\n```ts\nimport { Breadcrumb, BreadcrumbItem, BreadcrumbLink, BreadcrumbSeparator } from \"@usevyre/react\"\n```\n\n## Common AI Mistakes\n\n- ❌ `Using plain <a> tags inside Breadcrumb`\n → Use BreadcrumbItem > BreadcrumbLink for each crumb\n\n## Examples\n\n**Basic breadcrumb**\n```tsx\n<Breadcrumb>\n <BreadcrumbItem><BreadcrumbLink href=\"/\">Home</BreadcrumbLink></BreadcrumbItem>\n <BreadcrumbSeparator />\n <BreadcrumbItem><BreadcrumbLink href=\"/docs\">Docs</BreadcrumbLink></BreadcrumbItem>\n <BreadcrumbSeparator />\n <BreadcrumbItem aria-current=\"page\">Button</BreadcrumbItem>\n</Breadcrumb>\n```\n",
|
|
9819
|
-
"Button": "# Button — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Triggers actions and navigation. The most commonly used interactive element.**\n\n```ts\nimport { Button } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `variant` | `\"primary\"` \\| `\"secondary\"` \\| `\"ghost\"` \\| `\"accent\"` \\| `\"teal\"` \\| `\"danger\"` | `secondary` |\n| `size` | `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"icon\"` | `md` |\n| `loading` | `true` \\| `false` | `false` |\n| `disabled` | `true` \\| `false` | `false` |\n\n## Common AI Mistakes\n\n- ❌ `variant=\"blue\"`\n → Use variant=\"accent\" for brand amber, or variant=\"teal\" for teal\n- ❌ `size=\"xl\"`\n → Use size=\"lg\"\n- ❌ `color=\"...\"`\n → Use variant prop instead\n- ❌ `icon={...}`\n → Use leftIcon={...} or rightIcon={...}\n- ❌ `size=\"icon\" without aria-label`\n → Add aria-label describing the action\n\n## Examples\n\n**Primary CTA**\n```tsx\n<Button variant=\"primary\">Get Started</Button>\n```\n\n**Large accent button**\n```tsx\n<Button variant=\"accent\" size=\"lg\">Launch App</Button>\n```\n\n**Loading state**\n```tsx\n<Button variant=\"danger\" loading>Deleting...</Button>\n```\n\n**Link button**\n```tsx\n<Button as=\"a\" href=\"/docs\" variant=\"secondary\">Read Docs</Button>\n```\n\n**Icon-only button**\n```tsx\n<Button variant=\"ghost\" size=\"icon\" aria-label=\"Close\">\n <X size={16} />\n</Button>\n```\n\n## Accessibility\n\n- Always add aria-label when using size='icon' (no visible text)\n",
|
|
11436
|
+
"Button": "# Button — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Triggers actions and navigation. The most commonly used interactive element.**\n\n```ts\nimport { Button } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `variant` | `\"primary\"` \\| `\"secondary\"` \\| `\"ghost\"` \\| `\"accent\"` \\| `\"teal\"` \\| `\"danger\"` | `secondary` |\n| `size` | `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"icon\"` | `md` |\n| `loading` | `true` \\| `false` | `false` |\n| `disabled` | `true` \\| `false` | `false` |\n\n## Common AI Mistakes\n\n- ❌ `variant=\"blue\"`\n → Use variant=\"accent\" for brand amber, or variant=\"teal\" for teal\n- ❌ `size=\"xl\"`\n → Use size=\"lg\"\n- ❌ `color=\"...\"`\n → Use variant prop instead\n- ❌ `icon={...}`\n → Use leftIcon={...} or rightIcon={...}\n- ❌ `size=\"icon\" without aria-label`\n → Add aria-label describing the action\n- ❌ `padding / margin / marginTop (any spacing prop) on a useVyre component`\n → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it\n\n## Examples\n\n**Primary CTA**\n```tsx\n<Button variant=\"primary\">Get Started</Button>\n```\n\n**Large accent button**\n```tsx\n<Button variant=\"accent\" size=\"lg\">Launch App</Button>\n```\n\n**Loading state**\n```tsx\n<Button variant=\"danger\" loading>Deleting...</Button>\n```\n\n**Link button**\n```tsx\n<Button as=\"a\" href=\"/docs\" variant=\"secondary\">Read Docs</Button>\n```\n\n**Icon-only button**\n```tsx\n<Button variant=\"ghost\" size=\"icon\" aria-label=\"Close\">\n <X size={16} />\n</Button>\n```\n\n## Accessibility\n\n- Always add aria-label when using size='icon' (no visible text)\n",
|
|
9820
11437
|
"Calendar": "# Calendar — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Inline date-grid widget (always visible, no input). mode: single | range | multiple, optional time picker. For an input + popover use DatePicker; for start/end ranges with presets use DateRangePicker.**\n\n```ts\nimport { Calendar } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `disabled` | `true` \\| `false` | `false` |\n\n## Common AI Mistakes\n\n- ❌ `Calendar for an input field that opens a popover`\n → Use <DatePicker /> (single date) or <DateRangePicker /> (range)\n- ❌ `value as tuple for mode=\"single\"`\n → Pass value matching mode; use mode=\"range\" for [start,end]\n\n## Examples\n\n**Controlled date picker**\n```tsx\nconst [date, setDate] = useState(null);\n<Calendar value={date} onChange={setDate} />\n```\n",
|
|
9821
11438
|
"DatePicker": "# DatePicker — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Input trigger that opens a Calendar in a popover. Same modes as Calendar (single | range | multiple) plus a placeholder. Use this for a compact date field; use Calendar for an always-visible grid, or DateRangePicker for start/end ranges with presets.**\n\n```ts\nimport { DatePicker } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `mode` | `\"single\"` \\| `\"range\"` \\| `\"multiple\"` | `single` |\n| `weekStartsOn` | `\"0\"` \\| `\"1\"` | `1` |\n| `showTime` | `true` \\| `false` | `false` |\n\n## Common AI Mistakes\n\n- ❌ `DatePicker mode=\"range\" for { from, to } object`\n → Use <DateRangePicker /> for the { from, to } object API + presets + dual month\n- ❌ `DatePicker without value/onChange`\n → Provide value and onChange (e.g. from useState)\n\n## Examples\n\n**Single date field**\n```tsx\nconst [date, setDate] = useState(null);\n<DatePicker value={date} onChange={setDate} placeholder=\"Pick a date\" />\n```\n\n**Date + time**\n```tsx\n<DatePicker value={date} onChange={setDate} showTime />\n```\n",
|
|
9822
|
-
"Card": "# Card — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Content container with optional header, body, and footer sections.**\n\n```ts\nimport { Card, CardHeader, CardBody, CardFooter } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `variant` | `\"default\"` \\| `\"elevated\"` \\| `\"outlined\"` \\| `\"ghost\"` \\| `\"accent\"` | `default` |\n| `hoverable` | `true` \\| `false` | `false` |\n| `clickable` | `true` \\| `false` | `false` |\n\n## Common AI Mistakes\n\n- ❌ `variant=\"primary\"`\n → Use variant=\"elevated\" | \"outlined\" | \"ghost\" | \"accent\"\n\n## Examples\n\n**Elevated card with sections**\n```tsx\n<Card variant=\"elevated\">\n <CardHeader><Badge variant=\"teal\">New</Badge></CardHeader>\n <CardBody>\n <h3>Card Title</h3>\n <p>Description text.</p>\n </CardBody>\n <CardFooter>\n <Button variant=\"ghost\" size=\"sm\">Learn more</Button>\n </CardFooter>\n</Card>\n```\n",
|
|
11439
|
+
"Card": "# Card — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Content container with optional header, body, and footer sections.**\n\n```ts\nimport { Card, CardHeader, CardBody, CardFooter } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `variant` | `\"default\"` \\| `\"elevated\"` \\| `\"outlined\"` \\| `\"ghost\"` \\| `\"accent\"` | `default` |\n| `hoverable` | `true` \\| `false` | `false` |\n| `clickable` | `true` \\| `false` | `false` |\n\n## Common AI Mistakes\n\n- ❌ `variant=\"primary\"`\n → Use variant=\"elevated\" | \"outlined\" | \"ghost\" | \"accent\"\n- ❌ `padding / margin / marginTop (any spacing prop) on a useVyre component`\n → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it\n\n## Examples\n\n**Elevated card with sections**\n```tsx\n<Card variant=\"elevated\">\n <CardHeader><Badge variant=\"teal\">New</Badge></CardHeader>\n <CardBody>\n <h3>Card Title</h3>\n <p>Description text.</p>\n </CardBody>\n <CardFooter>\n <Button variant=\"ghost\" size=\"sm\">Learn more</Button>\n </CardFooter>\n</Card>\n```\n",
|
|
9823
11440
|
"Checkbox": "# Checkbox — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Binary toggle for boolean form values.**\n\n```ts\nimport { Checkbox } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `size` | `\"sm\"` \\| `\"md\"` | `md` |\n| `checked` | `true` \\| `false` | — |\n| `disabled` | `true` \\| `false` | `false` |\n| `indeterminate` | `true` \\| `false` | `false` |\n\n## Common AI Mistakes\n\n- ❌ `size=\"lg\"`\n → Use size=\"md\"\n\n## Examples\n\n**Labeled checkbox**\n```tsx\n<label style={{ display: 'flex', alignItems: 'center', gap: 'var(--vyre-spacing-2)' }}>\n <Checkbox checked={agreed} onChange={e => setAgreed(e.target.checked)} />\n I agree to the terms\n</label>\n```\n",
|
|
9824
11441
|
"RadioGroup": "# RadioGroup — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Controlled single-choice group. RadioGroup owns the selected value; render it data-driven via the options array OR with composable <Radio> children for custom content. role=radiogroup with proper labelling. For multi-select use Checkbox; for a compact dropdown use Select.**\n\n```ts\nimport { RadioGroup, Radio } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `size` | `\"sm\"` \\| `\"md\"` | `md` |\n| `orientation` | `\"vertical\"` \\| `\"horizontal\"` | `vertical` |\n| `disabled` | `true` \\| `false` | `false` |\n\n## Common AI Mistakes\n\n- ❌ `<Radio> used outside a <RadioGroup>`\n → Always wrap <Radio> in <RadioGroup>\n- ❌ `RadioGroup without value/onChange (React) or v-model (Vue)`\n → Bind value + onChange (React) or v-model (Vue); or defaultValue for uncontrolled in React\n- ❌ `Using Checkbox for mutually-exclusive choices`\n → Use RadioGroup + Radio (or options) for one-of-many\n\n## Examples\n\n**Data-driven**\n```tsx\n<RadioGroup\n value={plan}\n onChange={setPlan}\n options={[\n { value: \"free\", label: \"Free\", description: \"For hobby projects\" },\n { value: \"pro\", label: \"Pro\", description: \"For teams\" },\n ]}\n/>\n```\n\n**Composable children**\n```tsx\n<RadioGroup value={plan} onChange={setPlan} orientation=\"horizontal\">\n <Radio value=\"free\" label=\"Free\" />\n <Radio value=\"pro\" label=\"Pro\" />\n</RadioGroup>\n```\n",
|
|
9825
11442
|
"RichTextEditor": "# RichTextEditor — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Controlled WYSIWYG editor. value is an HTML string; you own it in state and set it in onChange (React) / v-model (Vue). Native contentEditable + execCommand — zero dependencies. Toolbar: bold, italic, underline, strike, h1-h3, ordered/unordered lists, quote, code block, link, clear formatting.**\n\n```ts\nimport { RichTextEditor } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `disabled` | `true` \\| `false` | `false` |\n| `readOnly` | `true` \\| `false` | `false` |\n\n## Common AI Mistakes\n\n- ❌ `RichTextEditor without value/onChange (React) or v-model (Vue)`\n → Keep the HTML string in state and update it in onChange / v-model\n- ❌ `Rendering value as text or with dangerouslySetInnerHTML elsewhere without sanitising`\n → Sanitise (e.g. DOMPurify) before re-rendering untrusted RTE output\n- ❌ `toolbar=\"bold\" (string)`\n → Pass an array, e.g. toolbar={[\"bold\",\"italic\",\"link\"]}\n\n## Examples\n\n**Controlled editor**\n```tsx\nconst [html, setHtml] = useState(\"<p>Hello <strong>world</strong></p>\");\n<RichTextEditor value={html} onChange={setHtml} placeholder=\"Write…\" />\n```\n\n**Minimal toolbar**\n```tsx\n<RichTextEditor\n value={html}\n onChange={setHtml}\n toolbar={[\"bold\", \"italic\", \"link\"]}\n/>\n```\n",
|
|
9826
11443
|
"Command": "# Command — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Command palette / search dialog. Use for search-first navigation or quick actions.**\n\n```ts\nimport { Command, CommandInput, CommandList, CommandEmpty, CommandGroup, CommandItem, CommandDialog } from \"@usevyre/react\"\n```\n\n## Common AI Mistakes\n\n- ❌ `Using Input type=\"search\" for search UI`\n → Use Command + CommandInput + CommandList + CommandItem\n\n## Examples\n\n**Basic command palette**\n```tsx\n<Command>\n <CommandInput placeholder=\"Search...\" />\n <CommandList>\n <CommandEmpty>No results found.</CommandEmpty>\n <CommandGroup heading=\"Suggestions\">\n <CommandItem onSelect={() => handleSelect('dashboard')}>Dashboard</CommandItem>\n <CommandItem onSelect={() => handleSelect('settings')}>Settings</CommandItem>\n </CommandGroup>\n </CommandList>\n</Command>\n```\n",
|
|
9827
11444
|
"DropdownMenu": "# DropdownMenu — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Contextual menu triggered by a button. Supports items, separators, checkbox items, radio groups, and sub-menus.**\n\n```ts\nimport { DropdownMenu, DropdownItem, DropdownSeparator, DropdownCheckboxItem, DropdownRadioGroup, DropdownRadioItem, DropdownSub } from \"@usevyre/react\"\n```\n\n## Common AI Mistakes\n\n- ❌ `DropdownItem variant=\"primary\"`\n → Use variant=\"danger\" for destructive items only\n\n## Examples\n\n**Dropdown with danger item**\n```tsx\n<DropdownMenu trigger={<Button variant=\"secondary\">Options</Button>}>\n <DropdownItem onSelect={() => handleEdit()}>Edit</DropdownItem>\n <DropdownItem onSelect={() => handleDuplicate()}>Duplicate</DropdownItem>\n <DropdownSeparator />\n <DropdownItem variant=\"danger\" onSelect={() => handleDelete()}>Delete</DropdownItem>\n</DropdownMenu>\n```\n",
|
|
9828
11445
|
"Field": "# Field — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Form field wrapper. Two ways to use it (both supported): (1) props-based — pass label/hint/state/required for the common case; (2) composable — use the parts FieldLabel, FieldDescription, FieldError, FieldGroup, FieldSet for richer layouts (multiple controls, custom error placement). The props-based API is unchanged and still works.**\n\n```ts\nimport { Field, Input, Textarea } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `state` | `\"idle\"` \\| `\"error\"` \\| `\"success\"` \\| `\"warning\"` | `idle` |\n| `required` | `true` \\| `false` | `false` |\n\n## Common AI Mistakes\n\n- ❌ `Applying state prop directly to Input`\n → Wrap Input in <Field state=\"error\"> to apply validation styling\n- ❌ `Mixing props label/hint AND FieldLabel/FieldError for the same field`\n → Pick one: either props-based (label/hint/state) OR composable parts\n\n## Examples\n\n**Error state field**\n```tsx\n<Field label=\"Email\" state=\"error\" hint=\"Invalid email format\">\n <Input type=\"email\" placeholder=\"you@example.com\" />\n</Field>\n```\n\n**Search field with left icon**\n```tsx\n<Field label=\"Search\">\n <Input leftElement={<SearchIcon />} placeholder=\"Search...\" />\n</Field>\n```\n\n**Composable field with explicit parts**\n```tsx\n<Field>\n <FieldLabel required htmlFor=\"email\">Email</FieldLabel>\n <Input id=\"email\" type=\"email\" />\n <FieldDescription>We\\u2019ll never share it.</FieldDescription>\n <FieldError>{errors.email}</FieldError>\n</Field>\n\n// Two controls side by side\n<FieldGroup orientation=\"horizontal\">\n <Field label=\"First name\"><Input /></Field>\n <Field label=\"Last name\"><Input /></Field>\n</FieldGroup>\n```\n",
|
|
9829
|
-
"Input": "# Input — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Text input field. Wrap in Field for labels and validation. Use leftElement/rightElement for icons.**\n\n```ts\nimport { Input } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `size` | `\"sm\"` \\| `\"md\"` \\| `\"lg\"` | `md` |\n\n## Common AI Mistakes\n\n- ❌ `size=\"icon\"`\n → Use size=\"sm\" | \"md\" | \"lg\"\n- ❌ `type=\"search\" for search UI`\n → Import Command from @usevyre/react for search palettes\n- ❌ `Vue: binding Input/Textarea value without v-model`\n → Use v-model on <Input>/<Textarea> in Vue; in React use value + onChange\n\n## Examples\n\n**Password input with icon**\n```tsx\n<Input type=\"password\" rightElement={<EyeIcon />} placeholder=\"Password\" />\n```\n",
|
|
11446
|
+
"Input": "# Input — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Text input field. Wrap in Field for labels and validation. Use leftElement/rightElement for icons.**\n\n```ts\nimport { Input } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `size` | `\"sm\"` \\| `\"md\"` \\| `\"lg\"` | `md` |\n\n## Common AI Mistakes\n\n- ❌ `size=\"icon\"`\n → Use size=\"sm\" | \"md\" | \"lg\"\n- ❌ `type=\"search\" for search UI`\n → Import Command from @usevyre/react for search palettes\n- ❌ `Vue: binding Input/Textarea value without v-model`\n → Use v-model on <Input>/<Textarea> in Vue; in React use value + onChange\n- ❌ `padding / margin / marginTop (any spacing prop) on a useVyre component`\n → Space BETWEEN components with <Stack gap> / <Grid gap>; space AROUND a block with <Box padding/margin> wrapping it\n\n## Examples\n\n**Password input with icon**\n```tsx\n<Input type=\"password\" rightElement={<EyeIcon />} placeholder=\"Password\" />\n```\n",
|
|
9830
11447
|
"Label": "# Label — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Accessible form label. Associate with input via htmlFor.**\n\n```ts\nimport { Label } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `required` | `true` \\| `false` | `false` |\n\n## Examples\n\n**Label with input**\n```tsx\n<Label htmlFor=\"email\">Email address</Label>\n<Input id=\"email\" type=\"email\" />\n```\n",
|
|
9831
11448
|
"Modal": "# Modal — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Dialog overlay for confirmations, forms, or focused content.**\n\n```ts\nimport { Modal, ModalHeader, ModalBody, ModalFooter } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `size` | `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"full\"` | `md` |\n| `open` | `true` \\| `false` | — |\n\n## Common AI Mistakes\n\n- ❌ `size=\"xl\"`\n → Use size=\"lg\" or size=\"full\"\n\n## Examples\n\n**Confirmation modal**\n```tsx\n<Modal open={isOpen} onClose={() => setIsOpen(false)} title=\"Confirm Delete\" size=\"sm\">\n <ModalBody>Are you sure you want to delete this item?</ModalBody>\n <ModalFooter>\n <Button variant=\"ghost\" onClick={() => setIsOpen(false)}>Cancel</Button>\n <Button variant=\"danger\" onClick={handleDelete}>Delete</Button>\n </ModalFooter>\n</Modal>\n```\n",
|
|
9832
11449
|
"Pagination": "# Pagination — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Page navigation for paginated lists or tables.**\n\n```ts\nimport { Pagination } from \"@usevyre/react\"\n```\n\n## Examples\n\n**Basic pagination**\n```tsx\n<Pagination page={currentPage} total={totalPages} onChange={setCurrentPage} />\n```\n",
|
|
@@ -9853,5 +11470,9 @@ export const cheatSheets = {
|
|
|
9853
11470
|
"Item": "# Item — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Layout primitive for list rows, settings rows, and notification rows. Denser than Card — use Item (not Card) for repeated list rows.**\n\n```ts\nimport { Item, ItemMedia, ItemContent, ItemTitle, ItemDescription, ItemActions, ItemGroup } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `variant` | `\"default\"` \\| `\"outlined\"` \\| `\"muted\"` \\| `\"plain\"` | `default` |\n| `size` | `\"sm\"` \\| `\"md\"` \\| `\"lg\"` | `md` |\n| `clickable` | `true` \\| `false` | `false` |\n\n## Common AI Mistakes\n\n- ❌ `Card used for repeated list rows`\n → Use <Item> (optionally inside <ItemGroup separated>) for list/settings rows\n- ❌ `Item variant=\"primary\"`\n → Use variant=\"default\" | \"outlined\" | \"muted\"\n- ❌ `raw text directly inside Item`\n → Wrap text in <ItemContent><ItemTitle>…</ItemTitle></ItemContent>\n\n## Examples\n\n**Settings row with media, content and a trailing switch**\n```tsx\n<Item>\n <ItemMedia><BellIcon /></ItemMedia>\n <ItemContent>\n <ItemTitle>Notifications</ItemTitle>\n <ItemDescription>Receive an email when someone mentions you.</ItemDescription>\n </ItemContent>\n <ItemActions>\n <Switch defaultChecked />\n </ItemActions>\n</Item>\n```\n\n**Grouped clickable list with dividers**\n```tsx\n<ItemGroup separated>\n <Item clickable>\n <ItemContent><ItemTitle>Profile</ItemTitle></ItemContent>\n </Item>\n <Item clickable>\n <ItemContent><ItemTitle>Billing</ItemTitle></ItemContent>\n </Item>\n</ItemGroup>\n```\n",
|
|
9854
11471
|
"Kanban": "# Kanban — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Drag-and-drop board: cards move between columns (or reorder within a column). CONTROLLED & data-driven like DataGrid. While dragging, a placeholder shows the exact drop position. Each card is wrapped in a Card (variant=\"outlined\"); renderCard (React) / #card slot (Vue) can render ANY content incl. complex components (Avatar/Badge/Progress). Columns and cards accept an optional semantic color tint. Native HTML5 DnD, zero deps.**\n\n```ts\nimport { Kanban } from \"@usevyre/react\"\n```\n\n## Common AI Mistakes\n\n- ❌ `Kanban without onChange (or ignoring it)`\n → Store columns in state and setColumns in onChange (v-model in Vue)\n- ❌ `Duplicate card ids across columns`\n → Use globally-unique card ids across the entire board\n- ❌ `Mutating value in place then calling onChange`\n → Pass the new array Kanban gives you straight to setState / v-model\n- ❌ `color=\"blue\" (or any non-semantic value)`\n → Use one of: \"default\" | \"accent\" | \"teal\" | \"success\" | \"warning\" | \"danger\"\n\n## Examples\n\n**Controlled board**\n```tsx\nconst [columns, setColumns] = useState([\n { id: \"todo\", title: \"To Do\", cards: [{ id: \"1\", title: \"Spec API\" }] },\n { id: \"doing\", title: \"In Progress\", cards: [] },\n { id: \"done\", title: \"Done\", cards: [{ id: \"2\", title: \"Kickoff\" }] },\n]);\n<Kanban value={columns} onChange={setColumns} />\n```\n\n**Custom card body + click handler**\n```tsx\n<Kanban\n value={columns}\n onChange={setColumns}\n onCardClick={(card) => openDetail(card.id)}\n renderCard={(card) => (\n <><strong>{card.title}</strong><Badge>{card.id}</Badge></>\n )}\n/>\n```\n\n**Tinted columns/cards + complex card content**\n```tsx\nconst [cols, setCols] = useState([\n { id: \"doing\", title: \"In Progress\", color: \"teal\", cards: [\n { id: \"t1\", title: \"OAuth\", assignee: \"AK\", progress: 60, color: \"warning\" },\n ]},\n]);\n<Kanban\n value={cols}\n onChange={setCols}\n renderCard={(card) => (\n <><strong>{card.title}</strong><Progress value={card.progress} /></>\n )}\n/>\n```\n",
|
|
9855
11472
|
"Conversation": "# Conversation — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Chat / inbox message thread. CONTROLLED & data-driven like Kanban — you own `value` (messages array) and append in your own send handler; Conversation holds no message state. Consecutive messages from the same author are grouped (avatar + name shown once), day separators are inserted on date change, and outgoing messages (authorId === currentUserId) align right.**\n\n```ts\nimport { Conversation } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `composer` | `true` \\| `false` | `false` |\n| `allowAttachments` | `true` \\| `false` | `false` |\n\n## Common AI Mistakes\n\n- ❌ `Conversation without currentUserId`\n → Always pass currentUserId matching one of the message authorId values\n- ❌ `Expecting Conversation to store/append messages`\n → Append to your own state in onSend (or @send) and pass it back via value\n- ❌ `composer without onSend (React) / @send (Vue)`\n → Provide onSend / @send to append the message to value\n- ❌ `Treating onSend as (text) only when using allowAttachments`\n → Handle onSend(text, files) — map files to message attachments and append\n\n## Examples\n\n**Controlled thread with built-in composer**\n```tsx\nconst [messages, setMessages] = useState([\n { id: \"1\", authorId: \"sam\", authorName: \"Sam\", text: \"Hey!\" },\n { id: \"2\", authorId: \"me\", text: \"Hi \\ud83d\\udc4b\", status: \"read\" },\n]);\n<Conversation\n value={messages}\n currentUserId=\"me\"\n composer\n onSend={(t) => setMessages((m) => [...m, { id: crypto.randomUUID(), authorId: \"me\", text: t }])}\n/>\n```\n\n**Typing indicator + custom bubble**\n```tsx\n<Conversation\n value={messages}\n currentUserId=\"me\"\n typing=\"Sam is typing\"\n renderMessage={(m) => <strong>{m.text}</strong>}\n/>\n```\n\n**Message with image + file attachments**\n```tsx\nconst messages = [\n { id: \"1\", authorId: \"sam\", authorName: \"Sam\", text: \"Moodboard \\ud83d\\udc47\",\n attachments: [{ kind: \"image\", url: \"/board.png\", name: \"board.png\" }] },\n { id: \"2\", authorId: \"me\", text: \"Specs:\", status: \"read\",\n attachments: [{ kind: \"file\", url: \"/spec.pdf\", name: \"spec.pdf\", size: \"2.4 MB\" }] },\n];\n<Conversation value={messages} currentUserId=\"me\" />\n```\n",
|
|
11473
|
+
"Stack": "# Stack — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Full one-dimensional flex layout primitive. USE INSTEAD OF <div style={{display:'flex'}}>. Covers the whole CSS flexbox surface (direction incl. reverse, wrap, align/justify/alignContent/alignSelf, grow/shrink/basis, per-axis gap) with token-locked spacing. Renders a plain <div> (or `as`).**\n\n```ts\nimport { Stack } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `direction` | `\"row\"` \\| `\"column\"` \\| `\"row-reverse\"` \\| `\"column-reverse\"` | `row` |\n| `gap` | `\"none\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` | `md` |\n| `rowGap` | `\"none\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` | — |\n| `columnGap` | `\"none\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` | — |\n| `align` | `\"start\"` \\| `\"center\"` \\| `\"end\"` \\| `\"stretch\"` \\| `\"baseline\"` | `stretch` |\n| `justify` | `\"start\"` \\| `\"center\"` \\| `\"end\"` \\| `\"between\"` \\| `\"around\"` \\| `\"evenly\"` | `start` |\n| `alignContent` | `\"start\"` \\| `\"center\"` \\| `\"end\"` \\| `\"stretch\"` \\| `\"between\"` \\| `\"around\"` \\| `\"evenly\"` | — |\n| `alignSelf` | `\"auto\"` \\| `\"start\"` \\| `\"center\"` \\| `\"end\"` \\| `\"stretch\"` \\| `\"baseline\"` | — |\n| `wrap` | `\"nowrap\"` \\| `\"wrap\"` \\| `\"wrap-reverse\"` | `nowrap` |\n| `basis` | `\"none\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` \\| `\"auto\"` \\| `\"content\"` \\| `\"0\"` | — |\n| `width` | `\"auto\"` \\| `\"full\"` \\| `\"fit\"` \\| `\"screen\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` | — |\n| `height` | `\"auto\"` \\| `\"full\"` \\| `\"fit\"` \\| `\"screen\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` | — |\n| `inline` | `true` \\| `false` | `false` |\n\n## Common AI Mistakes\n\n- ❌ `<div style={{ display: 'flex', gap: 12 }}>`\n → Use <Stack gap=\"md\"> — gap is a token\n- ❌ `gap={12} or gap=\"12px\"`\n → Use gap=\"none|xs|sm|md|lg|xl|2xl\"\n- ❌ `direction=\"vertical\" / \"horizontal\"`\n → Use direction=\"row\" or \"column\" (also row-reverse / column-reverse)\n- ❌ `style={{ width: \"100%\" }} / style={{ height: 320 }}`\n → Use the width / height prop: width=\"full\", width=\"md\", height=\"screen\", etc.\n\n## Examples\n\n**Row, vertically centered, spaced apart**\n```tsx\n<Stack direction=\"row\" gap=\"md\" align=\"center\" justify=\"between\">\n <Avatar src={user.avatar} />\n <Text>{user.name}</Text>\n <Button>Edit</Button>\n</Stack>\n```\n\n**Wrapping grid-ish gallery with per-axis gap**\n```tsx\n<Stack wrap=\"wrap\" rowGap=\"lg\" columnGap=\"md\">\n {tags.map((t) => <Tag key={t}>{t}</Tag>)}\n</Stack>\n```\n",
|
|
11474
|
+
"Grid": "# Grid — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Two-dimensional CSS grid primitive. Explicit column/row counts (or auto-fit), auto-flow control, token gap. Pair with GridItem for cell spanning/placement. Renders a plain <div> (or `as`).**\n\n```ts\nimport { Grid, GridItem } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `flow` | `\"row\"` \\| `\"column\"` \\| `\"dense\"` \\| `\"row-dense\"` \\| `\"column-dense\"` | — |\n| `gap` | `\"none\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` | `md` |\n| `rowGap` | `\"none\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` | — |\n| `columnGap` | `\"none\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` | — |\n| `align` | `\"start\"` \\| `\"center\"` \\| `\"end\"` \\| `\"stretch\"` | `stretch` |\n| `justify` | `\"start\"` \\| `\"center\"` \\| `\"end\"` \\| `\"stretch\"` | — |\n| `width` | `\"auto\"` \\| `\"full\"` \\| `\"fit\"` \\| `\"screen\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` | — |\n| `height` | `\"auto\"` \\| `\"full\"` \\| `\"fit\"` \\| `\"screen\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` | — |\n\n## Common AI Mistakes\n\n- ❌ `<div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr' }}>`\n → Use <Grid columns={3} gap=\"md\">\n- ❌ `columns=\"3\" (string)`\n → Use columns={3} or columns=\"auto-fit\"\n- ❌ `Nested div with inline grid-column for spanning`\n → Wrap the cell in <GridItem colSpan={2}>\n- ❌ `style={{ width: \"100%\" }} / style={{ height: 320 }}`\n → Use the width / height prop: width=\"full\", width=\"md\", height=\"screen\", etc.\n\n## Examples\n\n**Three-column grid with a wide first cell**\n```tsx\n<Grid columns={3} gap=\"lg\">\n <GridItem colSpan={2}><Card>Wide</Card></GridItem>\n <Card>Two</Card>\n <Card>Three</Card>\n</Grid>\n```\n\n**Responsive auto-fit grid**\n```tsx\n<Grid columns=\"auto-fit\" gap=\"md\">\n {items.map((i) => <Card key={i.id}>{i.title}</Card>)}\n</Grid>\n```\n",
|
|
11475
|
+
"GridItem": "# GridItem — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Child placement inside <Grid>. Sets column/row span and start lines. Renders a plain <div> (or `as`).**\n\n```ts\nimport { GridItem } from \"@usevyre/react\"\n```\n\n## Common AI Mistakes\n\n- ❌ `GridItem outside a Grid`\n → Place <GridItem> directly inside <Grid>\n\n## Examples\n\n**Span two columns**\n```tsx\n<Grid columns={4} gap=\"md\">\n <GridItem colSpan={2}>Featured</GridItem>\n <div>a</div>\n <div>b</div>\n</Grid>\n```\n",
|
|
11476
|
+
"Box": "# Box — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Spacing-only container plus a controlled escape hatch. Token padding/margin with shorthand, per-axis (X/Y) and per-side (Top/Right/Bottom/Left) overrides. The `style` prop is an explicit anti-pattern escape hatch. Renders a plain <div> (or `as`).**\n\n```ts\nimport { Box } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `padding` | `\"none\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` | — |\n| `paddingX` | `\"none\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` | — |\n| `paddingY` | `\"none\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` | — |\n| `paddingTop` | `\"none\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` | — |\n| `paddingRight` | `\"none\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` | — |\n| `paddingBottom` | `\"none\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` | — |\n| `paddingLeft` | `\"none\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` | — |\n| `margin` | `\"none\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` | — |\n| `marginX` | `\"none\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` | — |\n| `marginY` | `\"none\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` | — |\n| `marginTop` | `\"none\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` | — |\n| `marginRight` | `\"none\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` | — |\n| `marginBottom` | `\"none\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` | — |\n| `marginLeft` | `\"none\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` | — |\n| `width` | `\"auto\"` \\| `\"full\"` \\| `\"fit\"` \\| `\"screen\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` | — |\n| `height` | `\"auto\"` \\| `\"full\"` \\| `\"fit\"` \\| `\"screen\"` \\| `\"xs\"` \\| `\"sm\"` \\| `\"md\"` \\| `\"lg\"` \\| `\"xl\"` \\| `\"2xl\"` | — |\n\n## Common AI Mistakes\n\n- ❌ `<Box style={{ padding: 16 }}>`\n → Use <Box padding=\"md\"> (or paddingX/paddingTop/...)\n- ❌ `Using Box for flex/grid layout`\n → Use <Stack> or <Grid>\n- ❌ `style={{ width: \"100%\" }} / style={{ height: 320 }}`\n → Use the width / height prop: width=\"full\", width=\"md\", height=\"screen\", etc.\n\n## Examples\n\n**Asymmetric padding**\n```tsx\n<Box as=\"section\" paddingX=\"lg\" paddingY=\"md\">\n <Heading>Settings</Heading>\n</Box>\n```\n\n**Vertical rhythm via margin-top**\n```tsx\n<Box marginTop=\"xl\"><Separator /></Box>\n```\n",
|
|
9856
11477
|
"DateRangePicker": "# DateRangePicker — AI Cheat Sheet\n> Quick reference for Claude / Cursor / Copilot\n\n**Start/end date range picker. Built on Calendar (mode=range) with a friendlier { from, to } object API, a two-month side-by-side view, and preset shortcuts. Use this for report/filter date ranges; use DatePicker for a single date.**\n\n```ts\nimport { DateRangePicker } from \"@usevyre/react\"\n```\n\n## Valid Props\n\n| Prop | Values | Default |\n|------|--------|---------|\n| `numberOfMonths` | `\"1\"` \\| `\"2\"` | `2` |\n| `weekStartsOn` | `\"0\"` \\| `\"1\"` | `1` |\n\n## Common AI Mistakes\n\n- ❌ `value={[from, to]}`\n → Use value={{ from, to }} and read range.from / range.to\n- ❌ `DateRangePicker for a single date`\n → Use <DatePicker /> for a single date\n- ❌ `presets=\"true\" (string)`\n → Use the bare prop: presets (or presets={true})\n\n## Examples\n\n**Range picker with built-in presets**\n```tsx\nconst [range, setRange] = useState({ from: null, to: null });\n<DateRangePicker value={range} onChange={setRange} presets />\n```\n\n**Single month, no presets**\n```tsx\n<DateRangePicker value={range} onChange={setRange} numberOfMonths={1} />\n```\n"
|
|
9857
11478
|
};
|