@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.
@@ -1,5 +1,5 @@
1
1
  # useVyre Copilot Instructions
2
- # Version: 1.2.0
2
+ # Version: 1.6.0
3
3
 
4
4
  When generating UI code in this project, follow the useVyre design system rules below.
5
5
 
@@ -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})
@@ -4,7 +4,7 @@ alwaysApply: true
4
4
  ---
5
5
 
6
6
  # useVyre Design System — Cursor Rules
7
- # Version: 1.2.0
7
+ # Version: 1.6.0
8
8
 
9
9
  You are working in a project using the useVyre design system (@usevyre/react).
10
10
  Follow these rules strictly when generating any UI code.
@@ -93,6 +93,7 @@ Never do:
93
93
  - ❌ color="..." → ✅ Use variant prop instead
94
94
  - ❌ icon={...} → ✅ Use leftIcon={...} or rightIcon={...}
95
95
  - ❌ size="icon" without aria-label → ✅ Add aria-label describing the action
96
+ - ❌ 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
96
97
 
97
98
  ## Calendar
98
99
  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.
@@ -125,6 +126,7 @@ Valid props:
125
126
 
126
127
  Never do:
127
128
  - ❌ variant="primary" → ✅ Use variant="elevated" | "outlined" | "ghost" | "accent"
129
+ - ❌ 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
128
130
 
129
131
  ## Checkbox
130
132
  Binary toggle for boolean form values.
@@ -198,6 +200,7 @@ Never do:
198
200
  - ❌ size="icon" → ✅ Use size="sm" | "md" | "lg"
199
201
  - ❌ type="search" for search UI → ✅ Import Command from @usevyre/react for search palettes
200
202
  - ❌ Vue: binding Input/Textarea value without v-model → ✅ Use v-model on <Input>/<Textarea> in Vue; in React use value + onChange
203
+ - ❌ 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
201
204
 
202
205
  ## Label
203
206
  Accessible form label. Associate with input via htmlFor.
@@ -445,6 +448,86 @@ Never do:
445
448
  - ❌ composer without onSend (React) / @send (Vue) → ✅ Provide onSend / @send to append the message to value
446
449
  - ❌ Treating onSend as (text) only when using allowAttachments → ✅ Handle onSend(text, files) — map files to message attachments and append
447
450
 
451
+ ## Stack
452
+ 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`).
453
+ Import: `import { Stack } from "@usevyre/react"`
454
+
455
+ Valid props:
456
+ - direction: "row" | "column" | "row-reverse" | "column-reverse" [default: row]
457
+ - gap: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" [default: md]
458
+ - rowGap: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
459
+ - columnGap: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
460
+ - align: "start" | "center" | "end" | "stretch" | "baseline" [default: stretch]
461
+ - justify: "start" | "center" | "end" | "between" | "around" | "evenly" [default: start]
462
+ - alignContent: "start" | "center" | "end" | "stretch" | "between" | "around" | "evenly"
463
+ - alignSelf: "auto" | "start" | "center" | "end" | "stretch" | "baseline"
464
+ - wrap: "nowrap" | "wrap" | "wrap-reverse" [default: nowrap]
465
+ - basis: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "auto" | "content" | "0"
466
+ - width: "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
467
+ - height: "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
468
+
469
+ Never do:
470
+ - ❌ <div style={{ display: 'flex', gap: 12 }}> → ✅ Use <Stack gap="md"> — gap is a token
471
+ - ❌ gap={12} or gap="12px" → ✅ Use gap="none|xs|sm|md|lg|xl|2xl"
472
+ - ❌ direction="vertical" / "horizontal" → ✅ Use direction="row" or "column" (also row-reverse / column-reverse)
473
+ - ❌ style={{ width: "100%" }} / style={{ height: 320 }} → ✅ Use the width / height prop: width="full", width="md", height="screen", etc.
474
+
475
+ ## Grid
476
+ 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`).
477
+ Import: `import { Grid, GridItem } from "@usevyre/react"`
478
+
479
+ Valid props:
480
+ - flow: "row" | "column" | "dense" | "row-dense" | "column-dense"
481
+ - gap: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" [default: md]
482
+ - rowGap: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
483
+ - columnGap: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
484
+ - align: "start" | "center" | "end" | "stretch" [default: stretch]
485
+ - justify: "start" | "center" | "end" | "stretch"
486
+ - width: "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
487
+ - height: "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
488
+
489
+ Never do:
490
+ - ❌ <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr' }}> → ✅ Use <Grid columns={3} gap="md">
491
+ - ❌ columns="3" (string) → ✅ Use columns={3} or columns="auto-fit"
492
+ - ❌ Nested div with inline grid-column for spanning → ✅ Wrap the cell in <GridItem colSpan={2}>
493
+ - ❌ style={{ width: "100%" }} / style={{ height: 320 }} → ✅ Use the width / height prop: width="full", width="md", height="screen", etc.
494
+
495
+ ## GridItem
496
+ Child placement inside <Grid>. Sets column/row span and start lines. Renders a plain <div> (or `as`).
497
+ Import: `import { GridItem } from "@usevyre/react"`
498
+
499
+ Valid props:
500
+
501
+ Never do:
502
+ - ❌ GridItem outside a Grid → ✅ Place <GridItem> directly inside <Grid>
503
+
504
+ ## Box
505
+ 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`).
506
+ Import: `import { Box } from "@usevyre/react"`
507
+
508
+ Valid props:
509
+ - padding: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
510
+ - paddingX: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
511
+ - paddingY: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
512
+ - paddingTop: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
513
+ - paddingRight: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
514
+ - paddingBottom: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
515
+ - paddingLeft: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
516
+ - margin: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
517
+ - marginX: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
518
+ - marginY: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
519
+ - marginTop: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
520
+ - marginRight: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
521
+ - marginBottom: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
522
+ - marginLeft: "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
523
+ - width: "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
524
+ - height: "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
525
+
526
+ Never do:
527
+ - ❌ <Box style={{ padding: 16 }}> → ✅ Use <Box padding="md"> (or paddingX/paddingTop/...)
528
+ - ❌ Using Box for flex/grid layout → ✅ Use <Stack> or <Grid>
529
+ - ❌ style={{ width: "100%" }} / style={{ height: 320 }} → ✅ Use the width / height prop: width="full", width="md", height="screen", etc.
530
+
448
531
  ## DateRangePicker
449
532
  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.
450
533
  Import: `import { DateRangePicker } from "@usevyre/react"`
@@ -339,6 +339,7 @@ import { Button } from "@usevyre/react"
339
339
  - ❌ `color="..."` → Use variant prop instead
340
340
  - ❌ `icon={...}` → Use leftIcon={...} or rightIcon={...}
341
341
  - ❌ `size="icon" without aria-label` → Add aria-label describing the action
342
+ - ❌ `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
342
343
 
343
344
  ---
344
345
 
@@ -424,6 +425,7 @@ import { Card, CardHeader, CardBody, CardFooter } from "@usevyre/react"
424
425
 
425
426
  **Common mistakes:**
426
427
  - ❌ `variant="primary"` → Use variant="elevated" | "outlined" | "ghost" | "accent"
428
+ - ❌ `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
427
429
 
428
430
  ---
429
431
 
@@ -635,6 +637,7 @@ import { Input } from "@usevyre/react"
635
637
  - ❌ `size="icon"` → Use size="sm" | "md" | "lg"
636
638
  - ❌ `type="search" for search UI` → Import Command from @usevyre/react for search palettes
637
639
  - ❌ `Vue: binding Input/Textarea value without v-model` → Use v-model on <Input>/<Textarea> in Vue; in React use value + onChange
640
+ - ❌ `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
638
641
 
639
642
  ---
640
643
 
@@ -1377,6 +1380,157 @@ const messages = [
1377
1380
 
1378
1381
  ---
1379
1382
 
1383
+ ### Stack
1384
+
1385
+ 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`).
1386
+
1387
+ ```tsx
1388
+ import { Stack } from "@usevyre/react"
1389
+
1390
+ // Props:
1391
+ // direction = "row" | "column" | "row-reverse" | "column-reverse" (default: row)
1392
+ // inline = boolean (default: false)
1393
+ // gap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" (default: md)
1394
+ // rowGap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
1395
+ // columnGap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
1396
+ // align = "start" | "center" | "end" | "stretch" | "baseline" (default: stretch)
1397
+ // justify = "start" | "center" | "end" | "between" | "around" | "evenly" (default: start)
1398
+ // alignContent = "start" | "center" | "end" | "stretch" | "between" | "around" | "evenly"
1399
+ // alignSelf = "auto" | "start" | "center" | "end" | "stretch" | "baseline"
1400
+ // wrap = "nowrap" | "wrap" | "wrap-reverse" (default: nowrap)
1401
+ // grow = number
1402
+ // shrink = number
1403
+ // basis = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" | "auto" | "content" | "0"
1404
+ // width = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
1405
+ // height = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
1406
+ // as = string (default: div)
1407
+
1408
+ // Examples:
1409
+ <Stack direction="row" gap="md" align="center" justify="between">
1410
+ <Avatar src={user.avatar} />
1411
+ <Text>{user.name}</Text>
1412
+ <Button>Edit</Button>
1413
+ </Stack>
1414
+ <Stack wrap="wrap" rowGap="lg" columnGap="md">
1415
+ {tags.map((t) => <Tag key={t}>{t}</Tag>)}
1416
+ </Stack>
1417
+ ```
1418
+
1419
+ **Common mistakes:**
1420
+ - ❌ `<div style={{ display: 'flex', gap: 12 }}>` → Use <Stack gap="md"> — gap is a token
1421
+ - ❌ `gap={12} or gap="12px"` → Use gap="none|xs|sm|md|lg|xl|2xl"
1422
+ - ❌ `direction="vertical" / "horizontal"` → Use direction="row" or "column" (also row-reverse / column-reverse)
1423
+ - ❌ `style={{ width: "100%" }} / style={{ height: 320 }}` → Use the width / height prop: width="full", width="md", height="screen", etc.
1424
+
1425
+ ---
1426
+
1427
+ ### Grid
1428
+
1429
+ 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`).
1430
+
1431
+ ```tsx
1432
+ import { Grid, GridItem } from "@usevyre/react"
1433
+
1434
+ // Props:
1435
+ // columns = number | "auto-fit" (default: 1)
1436
+ // rows = number | "auto"
1437
+ // flow = "row" | "column" | "dense" | "row-dense" | "column-dense"
1438
+ // gap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl" (default: md)
1439
+ // rowGap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
1440
+ // columnGap = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
1441
+ // align = "start" | "center" | "end" | "stretch" (default: stretch)
1442
+ // justify = "start" | "center" | "end" | "stretch"
1443
+ // width = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
1444
+ // height = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
1445
+ // as = string (default: div)
1446
+
1447
+ // Examples:
1448
+ <Grid columns={3} gap="lg">
1449
+ <GridItem colSpan={2}><Card>Wide</Card></GridItem>
1450
+ <Card>Two</Card>
1451
+ <Card>Three</Card>
1452
+ </Grid>
1453
+ <Grid columns="auto-fit" gap="md">
1454
+ {items.map((i) => <Card key={i.id}>{i.title}</Card>)}
1455
+ </Grid>
1456
+ ```
1457
+
1458
+ **Common mistakes:**
1459
+ - ❌ `<div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr' }}>` → Use <Grid columns={3} gap="md">
1460
+ - ❌ `columns="3" (string)` → Use columns={3} or columns="auto-fit"
1461
+ - ❌ `Nested div with inline grid-column for spanning` → Wrap the cell in <GridItem colSpan={2}>
1462
+ - ❌ `style={{ width: "100%" }} / style={{ height: 320 }}` → Use the width / height prop: width="full", width="md", height="screen", etc.
1463
+
1464
+ ---
1465
+
1466
+ ### GridItem
1467
+
1468
+ Child placement inside <Grid>. Sets column/row span and start lines. Renders a plain <div> (or `as`).
1469
+
1470
+ ```tsx
1471
+ import { GridItem } from "@usevyre/react"
1472
+
1473
+ // Props:
1474
+ // colSpan = number
1475
+ // rowSpan = number
1476
+ // colStart = number
1477
+ // rowStart = number
1478
+ // as = string (default: div)
1479
+
1480
+ // Examples:
1481
+ <Grid columns={4} gap="md">
1482
+ <GridItem colSpan={2}>Featured</GridItem>
1483
+ <div>a</div>
1484
+ <div>b</div>
1485
+ </Grid>
1486
+ ```
1487
+
1488
+ **Common mistakes:**
1489
+ - ❌ `GridItem outside a Grid` → Place <GridItem> directly inside <Grid>
1490
+
1491
+ ---
1492
+
1493
+ ### Box
1494
+
1495
+ 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`).
1496
+
1497
+ ```tsx
1498
+ import { Box } from "@usevyre/react"
1499
+
1500
+ // Props:
1501
+ // padding = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
1502
+ // paddingX = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
1503
+ // paddingY = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
1504
+ // paddingTop = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
1505
+ // paddingRight = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
1506
+ // paddingBottom = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
1507
+ // paddingLeft = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
1508
+ // margin = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
1509
+ // marginX = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
1510
+ // marginY = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
1511
+ // marginTop = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
1512
+ // marginRight = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
1513
+ // marginBottom = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
1514
+ // marginLeft = "none" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
1515
+ // width = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
1516
+ // height = "auto" | "full" | "fit" | "screen" | "xs" | "sm" | "md" | "lg" | "xl" | "2xl"
1517
+ // as = string (default: div)
1518
+ // style = React.CSSProperties
1519
+
1520
+ // Examples:
1521
+ <Box as="section" paddingX="lg" paddingY="md">
1522
+ <Heading>Settings</Heading>
1523
+ </Box>
1524
+ <Box marginTop="xl"><Separator /></Box>
1525
+ ```
1526
+
1527
+ **Common mistakes:**
1528
+ - ❌ `<Box style={{ padding: 16 }}>` → Use <Box padding="md"> (or paddingX/paddingTop/...)
1529
+ - ❌ `Using Box for flex/grid layout` → Use <Stack> or <Grid>
1530
+ - ❌ `style={{ width: "100%" }} / style={{ height: 320 }}` → Use the width / height prop: width="full", width="md", height="screen", etc.
1531
+
1532
+ ---
1533
+
1380
1534
  ### DateRangePicker
1381
1535
 
1382
1536
  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.
@@ -1430,11 +1584,13 @@ If you generate these, you are hallucinating.
1430
1584
  - ❌ `<Button color="...">` → Use variant prop instead
1431
1585
  - ❌ `<Button icon={...}>` → Use leftIcon={...} or rightIcon={...}
1432
1586
  - ❌ `<Button size="icon" without aria-label>` → Add aria-label describing the action
1587
+ - ❌ `<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
1433
1588
  - ❌ `<Calendar Calendar for an input field that opens a popover>` → Use <DatePicker /> (single date) or <DateRangePicker /> (range)
1434
1589
  - ❌ `<Calendar value as tuple for mode="single">` → Pass value matching mode; use mode="range" for [start,end]
1435
1590
  - ❌ `<DatePicker DatePicker mode="range" for { from, to } object>` → Use <DateRangePicker /> for the { from, to } object API + presets + dual month
1436
1591
  - ❌ `<DatePicker DatePicker without value/onChange>` → Provide value and onChange (e.g. from useState)
1437
1592
  - ❌ `<Card variant="primary">` → Use variant="elevated" | "outlined" | "ghost" | "accent"
1593
+ - ❌ `<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
1438
1594
  - ❌ `<Checkbox size="lg">` → Use size="md"
1439
1595
  - ❌ `<RadioGroup <Radio> used outside a <RadioGroup>>` → Always wrap <Radio> in <RadioGroup>
1440
1596
  - ❌ `<RadioGroup RadioGroup without value/onChange (React) or v-model (Vue)>` → Bind value + onChange (React) or v-model (Vue); or defaultValue for uncontrolled in React
@@ -1449,6 +1605,7 @@ If you generate these, you are hallucinating.
1449
1605
  - ❌ `<Input size="icon">` → Use size="sm" | "md" | "lg"
1450
1606
  - ❌ `<Input type="search" for search UI>` → Import Command from @usevyre/react for search palettes
1451
1607
  - ❌ `<Input Vue: binding Input/Textarea value without v-model>` → Use v-model on <Input>/<Textarea> in Vue; in React use value + onChange
1608
+ - ❌ `<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
1452
1609
  - ❌ `<Modal size="xl">` → Use size="lg" or size="full"
1453
1610
  - ❌ `<Popover placement="top-center">` → Use placement="top" for centered placement
1454
1611
  - ❌ `<Progress value > 100>` → Normalize your value to 0–100 range before passing
@@ -1485,6 +1642,18 @@ If you generate these, you are hallucinating.
1485
1642
  - ❌ `<Conversation Expecting Conversation to store/append messages>` → Append to your own state in onSend (or @send) and pass it back via value
1486
1643
  - ❌ `<Conversation composer without onSend (React) / @send (Vue)>` → Provide onSend / @send to append the message to value
1487
1644
  - ❌ `<Conversation Treating onSend as (text) only when using allowAttachments>` → Handle onSend(text, files) — map files to message attachments and append
1645
+ - ❌ `<Stack <div style={{ display: 'flex', gap: 12 }}>>` → Use <Stack gap="md"> — gap is a token
1646
+ - ❌ `<Stack gap={12} or gap="12px">` → Use gap="none|xs|sm|md|lg|xl|2xl"
1647
+ - ❌ `<Stack direction="vertical" / "horizontal">` → Use direction="row" or "column" (also row-reverse / column-reverse)
1648
+ - ❌ `<Stack style={{ width: "100%" }} / style={{ height: 320 }}>` → Use the width / height prop: width="full", width="md", height="screen", etc.
1649
+ - ❌ `<Grid <div style={{ display:'grid', gridTemplateColumns:'1fr 1fr 1fr' }}>>` → Use <Grid columns={3} gap="md">
1650
+ - ❌ `<Grid columns="3" (string)>` → Use columns={3} or columns="auto-fit"
1651
+ - ❌ `<Grid Nested div with inline grid-column for spanning>` → Wrap the cell in <GridItem colSpan={2}>
1652
+ - ❌ `<Grid style={{ width: "100%" }} / style={{ height: 320 }}>` → Use the width / height prop: width="full", width="md", height="screen", etc.
1653
+ - ❌ `<GridItem GridItem outside a Grid>` → Place <GridItem> directly inside <Grid>
1654
+ - ❌ `<Box <Box style={{ padding: 16 }}>>` → Use <Box padding="md"> (or paddingX/paddingTop/...)
1655
+ - ❌ `<Box Using Box for flex/grid layout>` → Use <Stack> or <Grid>
1656
+ - ❌ `<Box style={{ width: "100%" }} / style={{ height: 320 }}>` → Use the width / height prop: width="full", width="md", height="screen", etc.
1488
1657
  - ❌ `<DateRangePicker value={[from, to]}>` → Use value={{ from, to }} and read range.from / range.to
1489
1658
  - ❌ `<DateRangePicker DateRangePicker for a single date>` → Use <DatePicker /> for a single date
1490
1659
  - ❌ `<DateRangePicker presets="true" (string)>` → Use the bare prop: presets (or presets={true})