@engineio/ui 0.4.1 → 0.4.2

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.
Files changed (3) hide show
  1. package/AGENTS.md +138 -0
  2. package/README.md +29 -0
  3. package/package.json +12 -6
package/AGENTS.md ADDED
@@ -0,0 +1,138 @@
1
+ # @engineio/ui — agent reference
2
+
3
+ The Engine design system. This file ships inside the package, so it arrives in
4
+ `node_modules/@engineio/ui/AGENTS.md` and versions with the code — point at it
5
+ rather than copying its contents into a repo, or the copy goes stale.
6
+
7
+ Authoritative source: `docs/brand/ENGINE-DESIGN-SYSTEM.md` and
8
+ `ENGINE-BRAND.md` in the `engineio/engine` repo. Where this file and those
9
+ disagree, **they win and this is a bug**.
10
+
11
+ ## Setup
12
+
13
+ ```css
14
+ @import "tailwindcss";
15
+ @import "@engineio/ui/styles";
16
+ @source "../../../node_modules/@engineio/ui/dist";
17
+ ```
18
+
19
+ **The `@source` line is not optional and its absence is silent.** Tailwind 4
20
+ does not scan `node_modules`, so without it the utility classes the components
21
+ are written against are never generated. The tokens still land and any class
22
+ that also appears in local source still works, so you get a half-styled app
23
+ that reads like a component bug. Path is relative to the CSS file declaring it.
24
+
25
+ ## Importing
26
+
27
+ ```svelte
28
+ import { Button, Card, CardHeader } from "@engineio/ui"
29
+ import { Button } from "@engineio/ui/components/ui/button/index.js"
30
+ import * as Card from "@engineio/ui/components/ui/card/index.js"
31
+ import { EngineWordmark } from "@engineio/ui/components/brand/index.js"
32
+ ```
33
+
34
+ Root barrel exports flat prefixed names (`CardHeader`). Subpath modules export
35
+ `Root`/`Header`/`Content`, so `import * as Card` works. Both `/index.js` and the
36
+ bare subpath resolve.
37
+
38
+ ## Components
39
+
40
+ Alert, Badge, Button, Card, Checkbox, Dialog, Input, Label, Popover, Progress,
41
+ RadioGroup, Select, Separator, Skeleton, Switch, Table, Tabs, Textarea, Tooltip.
42
+ Marks: `EngineWordmark`, `EngineIcon`.
43
+
44
+ Not shipped, on purpose: `sonner`, `form`, `data-table`, `drawer`, `resizable`,
45
+ `carousel`, `chart`. Copy from the engine repo if needed.
46
+
47
+ | Component | Variants |
48
+ | --- | --- |
49
+ | Button | `default` `inverse` `outline` `ghost` `secondary` `link` `icon` `destructive` `success`; sizes `sm` `default` `lg` `icon` `icon-sm` `icon-lg` |
50
+ | Badge | `default` `secondary` `outline` `partner` `success` `warning` `danger` `destructive` |
51
+ | Alert | `default` `success` `warning` `danger` `destructive`; optional `onDismiss` |
52
+ | Marks | `variant="primary"` (white) or `"secondary"` (Off Black) |
53
+
54
+ There is **one** chip. Badge absorbed Tag — a soft tinted chip, not a solid
55
+ pill. There is no `Tag` export and no `solid` badge variant: an opaque fill can
56
+ only be correct on one surface, and badge fills are translucent so they read on
57
+ the page, on a card and on a table tile alike.
58
+
59
+ ## Tokens
60
+
61
+ Use these names; never a literal.
62
+
63
+ ```
64
+ colour --color-background #0E0E0E --color-foreground #FFFFFF
65
+ --color-primary #FF006A --color-primary-press #D60059
66
+ --color-primary-300 #FF5C9B (ink on a magenta tint)
67
+ --color-primary-tint-12 / -24
68
+ --color-card #161616 --color-popover #1C1C1C
69
+ --color-grey-950 … --color-grey-050 (the only greys)
70
+ --color-partner-yellow #FFDD00 (reserved, not in use)
71
+ status --color-success #00C46A --color-warning #FFB020 --color-danger #FF3B30
72
+ each with -foreground (always Off Black) and -tint-12
73
+ --color-destructive aliases danger
74
+ radii --radius-tag 6 --radius-field 10 --radius-card-inner 10
75
+ --radius-media 14 --radius-card 18 --radius-frame 26
76
+ --radius-control 999
77
+ motion --ease-brand --ease-brand-out --ease-brand-accelerate
78
+ 140ms controls · 220ms surfaces · 360–640ms reveals
79
+ type --font-brand (Proxima Nova) --font-mono (JetBrains Mono, see gaps)
80
+ depth --shadow-panel --shadow-modal (product chrome and modals only)
81
+ utility `field` — the shared input skin, incl. the focus ring
82
+ ```
83
+
84
+ ## Rules
85
+
86
+ - **Three brand colours**: Off Black, Pure White, Magenta. One accent per
87
+ surface, never two.
88
+ - **Status colour is functional.** `success`/`warning`/`danger` report state.
89
+ Never use them as a categorical palette — `success` for "slots" because green
90
+ looked right spends the only signal they carry.
91
+ - **No off-palette colour.** Not Tailwind's stock ramps, not a hex literal. CI
92
+ fails on both.
93
+ - **Retired and unavailable**: Originals Orange `#FF6200`, Sportsbook Blue
94
+ `#00CCFF`. No accents, no charts, no status.
95
+ - **Ink on any status or accent fill is Off Black.** White fails AA on all three.
96
+ - **Magenta text**: never below 15px bold. Use `--color-primary-300` on a tint.
97
+ - No gradients. No light theme. No `dark:` variants — the dark palette is the
98
+ only palette. No drop shadows on brand surfaces. No coloured borders, and no
99
+ coloured left-edge accent to signal category or ownership.
100
+ - Radii by role, and the outer frame is always larger than the inner panel.
101
+ - Borders are 1px hairline or 1.5px container rule. Nothing else.
102
+ - **No emoji, anywhere.** Only `×` for close and `✱` for footnotes.
103
+ - Voice: declarative, British/AU spelling, headlines end in a full stop.
104
+ - Icons: Lucide, 2px stroke, `currentColor`.
105
+
106
+ ## Extending
107
+
108
+ Do not fork a component to add a variant, and do not upstream a product-only
109
+ variant. Every variant map is exported:
110
+
111
+ ```ts
112
+ import { buttonVariants } from "@engineio/ui"
113
+ import { tv } from "tailwind-variants"
114
+
115
+ export const appButtonVariants = tv({
116
+ extend: buttonVariants,
117
+ variants: { variant: { drawer: "w-full justify-start rounded-none …" } },
118
+ })
119
+ ```
120
+
121
+ Brand rules stay in the package; product variants stay in the product. Every
122
+ primitive also passes `class` through `cn`, so `<Button class="w-full" />` works
123
+ without `!important`.
124
+
125
+ ## Known gaps
126
+
127
+ State these rather than working around them silently.
128
+
129
+ 1. **No categorical palette.** A per-topic hue set is an unmade brand decision.
130
+ 2. **Two deviations from the brand document**, both deliberate: Badge is one
131
+ component where §6 specifies two, and Alert signals state with a coloured
132
+ left-edge bar which §11 prohibits for *category or ownership* — state is a
133
+ narrower reading, not an exemption.
134
+ 3. **JetBrains Mono is not loaded.** `--font-mono` falls back to the platform
135
+ monospace, so every mono surface is off-brand until the binary ships.
136
+ 4. **Proxima Nova is commercially licensed** and ships inside this package.
137
+ 5. **Engine Integration's accent is unsettled** — build Integration in magenta;
138
+ `--color-partner-yellow` exists but is not in use.
package/README.md CHANGED
@@ -121,6 +121,35 @@ engine repo into your product if you need them. `sonner` was excluded because
121
121
  toasts need success and error colours that did not exist; now that they do, it
122
122
  is a candidate for the next release.
123
123
 
124
+ ## Using it with AI agents
125
+
126
+ The package ships `AGENTS.md`, so it lands at
127
+ `node_modules/@engineio/ui/AGENTS.md` and **versions with the code**. Point at
128
+ that path from a consuming repo rather than copying the rules in — a copy in
129
+ someone's `CLAUDE.md` silently goes stale on the next version bump, and stale
130
+ brand rules are worse than none.
131
+
132
+ In a consumer's `AGENTS.md` or `CLAUDE.md`:
133
+
134
+ ```md
135
+ UI is built on `@engineio/ui`. Read `node_modules/@engineio/ui/AGENTS.md`
136
+ before writing or reviewing any UI.
137
+ ```
138
+
139
+ For Claude Code specifically, copy the skill instead — it loads only when
140
+ relevant, so the reference costs nothing until a UI task actually needs it:
141
+
142
+ ```bash
143
+ mkdir -p .claude/skills
144
+ cp -R node_modules/@engineio/ui/../../../ui/.claude/skills/engine-design-system \
145
+ .claude/skills/ # or from a checkout of engineio/ui
146
+ ```
147
+
148
+ Skills have to live in `.claude/skills/`, `~/.claude/skills/` or a plugin —
149
+ Claude Code does not load them from `node_modules` — which is why the substance
150
+ lives in `AGENTS.md` and the skill is a thin pointer to it. That way the copied
151
+ file has nothing in it that can rot.
152
+
124
153
  ## Development
125
154
 
126
155
  ```bash
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@engineio/ui",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "description": "The Engine design system — tokens, fonts and Svelte primitives.",
5
5
  "license": "MIT",
6
6
  "private": false,
@@ -16,6 +16,7 @@
16
16
  },
17
17
  "files": [
18
18
  "dist",
19
+ "AGENTS.md",
19
20
  "!dist/**/*.test.*",
20
21
  "!dist/**/*.spec.*"
21
22
  ],
@@ -25,7 +26,8 @@
25
26
  "exports": {
26
27
  ".": {
27
28
  "types": "./dist/index.d.ts",
28
- "svelte": "./dist/index.js"
29
+ "svelte": "./dist/index.js",
30
+ "default": "./dist/index.js"
29
31
  },
30
32
  "./styles": "./dist/styles/index.css",
31
33
  "./styles/tokens": "./dist/styles/tokens.css",
@@ -38,19 +40,23 @@
38
40
  },
39
41
  "./components/ui/*": {
40
42
  "types": "./dist/components/ui/*/index.d.ts",
41
- "svelte": "./dist/components/ui/*/index.js"
43
+ "svelte": "./dist/components/ui/*/index.js",
44
+ "default": "./dist/components/ui/*/index.js"
42
45
  },
43
46
  "./components/ui/*/index.js": {
44
47
  "types": "./dist/components/ui/*/index.d.ts",
45
- "svelte": "./dist/components/ui/*/index.js"
48
+ "svelte": "./dist/components/ui/*/index.js",
49
+ "default": "./dist/components/ui/*/index.js"
46
50
  },
47
51
  "./components/brand": {
48
52
  "types": "./dist/components/brand/index.d.ts",
49
- "svelte": "./dist/components/brand/index.js"
53
+ "svelte": "./dist/components/brand/index.js",
54
+ "default": "./dist/components/brand/index.js"
50
55
  },
51
56
  "./components/brand/index.js": {
52
57
  "types": "./dist/components/brand/index.d.ts",
53
- "svelte": "./dist/components/brand/index.js"
58
+ "svelte": "./dist/components/brand/index.js",
59
+ "default": "./dist/components/brand/index.js"
54
60
  }
55
61
  },
56
62
  "scripts": {