@engineio/ui 0.4.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.
Files changed (156) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +274 -0
  3. package/dist/components/brand/engine-icon.svelte +75 -0
  4. package/dist/components/brand/engine-icon.svelte.d.ts +25 -0
  5. package/dist/components/brand/engine-wordmark.svelte +104 -0
  6. package/dist/components/brand/engine-wordmark.svelte.d.ts +16 -0
  7. package/dist/components/brand/index.d.ts +3 -0
  8. package/dist/components/brand/index.js +3 -0
  9. package/dist/components/ui/alert/alert-description.svelte +22 -0
  10. package/dist/components/ui/alert/alert-description.svelte.d.ts +5 -0
  11. package/dist/components/ui/alert/alert-title.svelte +31 -0
  12. package/dist/components/ui/alert/alert-title.svelte.d.ts +8 -0
  13. package/dist/components/ui/alert/alert.svelte +114 -0
  14. package/dist/components/ui/alert/alert.svelte.d.ts +70 -0
  15. package/dist/components/ui/alert/index.d.ts +5 -0
  16. package/dist/components/ui/alert/index.js +7 -0
  17. package/dist/components/ui/badge/badge.svelte +96 -0
  18. package/dist/components/ui/badge/badge.svelte.d.ts +88 -0
  19. package/dist/components/ui/badge/index.d.ts +2 -0
  20. package/dist/components/ui/badge/index.js +2 -0
  21. package/dist/components/ui/button/button.svelte +137 -0
  22. package/dist/components/ui/button/button.svelte.d.ts +154 -0
  23. package/dist/components/ui/button/index.d.ts +2 -0
  24. package/dist/components/ui/button/index.js +4 -0
  25. package/dist/components/ui/card/card-content.svelte +16 -0
  26. package/dist/components/ui/card/card-content.svelte.d.ts +5 -0
  27. package/dist/components/ui/card/card-description.svelte +20 -0
  28. package/dist/components/ui/card/card-description.svelte.d.ts +5 -0
  29. package/dist/components/ui/card/card-footer.svelte +20 -0
  30. package/dist/components/ui/card/card-footer.svelte.d.ts +5 -0
  31. package/dist/components/ui/card/card-header.svelte +20 -0
  32. package/dist/components/ui/card/card-header.svelte.d.ts +5 -0
  33. package/dist/components/ui/card/card-title.svelte +25 -0
  34. package/dist/components/ui/card/card-title.svelte.d.ts +8 -0
  35. package/dist/components/ui/card/card.svelte +23 -0
  36. package/dist/components/ui/card/card.svelte.d.ts +5 -0
  37. package/dist/components/ui/card/index.d.ts +7 -0
  38. package/dist/components/ui/card/index.js +9 -0
  39. package/dist/components/ui/checkbox/checkbox.svelte +38 -0
  40. package/dist/components/ui/checkbox/checkbox.svelte.d.ts +4 -0
  41. package/dist/components/ui/checkbox/index.d.ts +2 -0
  42. package/dist/components/ui/checkbox/index.js +4 -0
  43. package/dist/components/ui/dialog/dialog-content.svelte +41 -0
  44. package/dist/components/ui/dialog/dialog-content.svelte.d.ts +9 -0
  45. package/dist/components/ui/dialog/dialog-description.svelte +16 -0
  46. package/dist/components/ui/dialog/dialog-description.svelte.d.ts +4 -0
  47. package/dist/components/ui/dialog/dialog-footer.svelte +23 -0
  48. package/dist/components/ui/dialog/dialog-footer.svelte.d.ts +5 -0
  49. package/dist/components/ui/dialog/dialog-header.svelte +20 -0
  50. package/dist/components/ui/dialog/dialog-header.svelte.d.ts +5 -0
  51. package/dist/components/ui/dialog/dialog-overlay.svelte +19 -0
  52. package/dist/components/ui/dialog/dialog-overlay.svelte.d.ts +4 -0
  53. package/dist/components/ui/dialog/dialog-title.svelte +16 -0
  54. package/dist/components/ui/dialog/dialog-title.svelte.d.ts +4 -0
  55. package/dist/components/ui/dialog/index.d.ts +12 -0
  56. package/dist/components/ui/dialog/index.js +14 -0
  57. package/dist/components/ui/input/index.d.ts +2 -0
  58. package/dist/components/ui/input/index.js +4 -0
  59. package/dist/components/ui/input/input.svelte +52 -0
  60. package/dist/components/ui/input/input.svelte.d.ts +13 -0
  61. package/dist/components/ui/label/index.d.ts +2 -0
  62. package/dist/components/ui/label/index.js +4 -0
  63. package/dist/components/ui/label/label.svelte +19 -0
  64. package/dist/components/ui/label/label.svelte.d.ts +4 -0
  65. package/dist/components/ui/popover/index.d.ts +6 -0
  66. package/dist/components/ui/popover/index.js +8 -0
  67. package/dist/components/ui/popover/popover-content.svelte +28 -0
  68. package/dist/components/ui/popover/popover-content.svelte.d.ts +7 -0
  69. package/dist/components/ui/progress/index.d.ts +2 -0
  70. package/dist/components/ui/progress/index.js +4 -0
  71. package/dist/components/ui/progress/progress.svelte +25 -0
  72. package/dist/components/ui/progress/progress.svelte.d.ts +4 -0
  73. package/dist/components/ui/radio-group/index.d.ts +3 -0
  74. package/dist/components/ui/radio-group/index.js +5 -0
  75. package/dist/components/ui/radio-group/radio-group-item.svelte +28 -0
  76. package/dist/components/ui/radio-group/radio-group-item.svelte.d.ts +4 -0
  77. package/dist/components/ui/radio-group/radio-group.svelte +13 -0
  78. package/dist/components/ui/radio-group/radio-group.svelte.d.ts +4 -0
  79. package/dist/components/ui/select/index.d.ts +11 -0
  80. package/dist/components/ui/select/index.js +13 -0
  81. package/dist/components/ui/select/select-content.svelte +39 -0
  82. package/dist/components/ui/select/select-content.svelte.d.ts +7 -0
  83. package/dist/components/ui/select/select-group-heading.svelte +16 -0
  84. package/dist/components/ui/select/select-group-heading.svelte.d.ts +4 -0
  85. package/dist/components/ui/select/select-item.svelte +37 -0
  86. package/dist/components/ui/select/select-item.svelte.d.ts +4 -0
  87. package/dist/components/ui/select/select-scroll-down-button.svelte +19 -0
  88. package/dist/components/ui/select/select-scroll-down-button.svelte.d.ts +4 -0
  89. package/dist/components/ui/select/select-scroll-up-button.svelte +19 -0
  90. package/dist/components/ui/select/select-scroll-up-button.svelte.d.ts +4 -0
  91. package/dist/components/ui/select/select-separator.svelte +13 -0
  92. package/dist/components/ui/select/select-separator.svelte.d.ts +4 -0
  93. package/dist/components/ui/select/select-trigger.svelte +24 -0
  94. package/dist/components/ui/select/select-trigger.svelte.d.ts +4 -0
  95. package/dist/components/ui/separator/index.d.ts +2 -0
  96. package/dist/components/ui/separator/index.js +4 -0
  97. package/dist/components/ui/separator/separator.svelte +22 -0
  98. package/dist/components/ui/separator/separator.svelte.d.ts +4 -0
  99. package/dist/components/ui/skeleton/index.d.ts +2 -0
  100. package/dist/components/ui/skeleton/index.js +4 -0
  101. package/dist/components/ui/skeleton/skeleton.svelte +17 -0
  102. package/dist/components/ui/skeleton/skeleton.svelte.d.ts +5 -0
  103. package/dist/components/ui/switch/index.d.ts +2 -0
  104. package/dist/components/ui/switch/index.js +4 -0
  105. package/dist/components/ui/switch/switch.svelte +27 -0
  106. package/dist/components/ui/switch/switch.svelte.d.ts +4 -0
  107. package/dist/components/ui/table/index.d.ts +9 -0
  108. package/dist/components/ui/table/index.js +11 -0
  109. package/dist/components/ui/table/table-body.svelte +22 -0
  110. package/dist/components/ui/table/table-body.svelte.d.ts +5 -0
  111. package/dist/components/ui/table/table-caption.svelte +21 -0
  112. package/dist/components/ui/table/table-caption.svelte.d.ts +5 -0
  113. package/dist/components/ui/table/table-cell.svelte +33 -0
  114. package/dist/components/ui/table/table-cell.svelte.d.ts +5 -0
  115. package/dist/components/ui/table/table-footer.svelte +29 -0
  116. package/dist/components/ui/table/table-footer.svelte.d.ts +5 -0
  117. package/dist/components/ui/table/table-head.svelte +36 -0
  118. package/dist/components/ui/table/table-head.svelte.d.ts +5 -0
  119. package/dist/components/ui/table/table-header.svelte +23 -0
  120. package/dist/components/ui/table/table-header.svelte.d.ts +5 -0
  121. package/dist/components/ui/table/table-row.svelte +32 -0
  122. package/dist/components/ui/table/table-row.svelte.d.ts +5 -0
  123. package/dist/components/ui/table/table.svelte +36 -0
  124. package/dist/components/ui/table/table.svelte.d.ts +5 -0
  125. package/dist/components/ui/tabs/index.d.ts +6 -0
  126. package/dist/components/ui/tabs/index.js +8 -0
  127. package/dist/components/ui/tabs/tabs-content.svelte +19 -0
  128. package/dist/components/ui/tabs/tabs-content.svelte.d.ts +4 -0
  129. package/dist/components/ui/tabs/tabs-list.svelte +27 -0
  130. package/dist/components/ui/tabs/tabs-list.svelte.d.ts +7 -0
  131. package/dist/components/ui/tabs/tabs-trigger.svelte +29 -0
  132. package/dist/components/ui/tabs/tabs-trigger.svelte.d.ts +7 -0
  133. package/dist/components/ui/textarea/index.d.ts +2 -0
  134. package/dist/components/ui/textarea/index.js +4 -0
  135. package/dist/components/ui/textarea/textarea.svelte +22 -0
  136. package/dist/components/ui/textarea/textarea.svelte.d.ts +5 -0
  137. package/dist/components/ui/tooltip/index.d.ts +6 -0
  138. package/dist/components/ui/tooltip/index.js +8 -0
  139. package/dist/components/ui/tooltip/tooltip-content.svelte +21 -0
  140. package/dist/components/ui/tooltip/tooltip-content.svelte.d.ts +4 -0
  141. package/dist/fonts/ProximaNova-ExtraCondensedThin.otf +0 -0
  142. package/dist/fonts/ProximaNovaBlack.otf +0 -0
  143. package/dist/fonts/ProximaNovaBold.otf +0 -0
  144. package/dist/fonts/ProximaNovaCondensedBlack.otf +0 -0
  145. package/dist/fonts/ProximaNovaExtraCondensedBlack.otf +0 -0
  146. package/dist/fonts/ProximaNovaRegular.otf +0 -0
  147. package/dist/fonts/ProximaNovaSemibold.otf +0 -0
  148. package/dist/index.d.ts +45 -0
  149. package/dist/index.js +44 -0
  150. package/dist/styles/fonts.css +116 -0
  151. package/dist/styles/index.css +28 -0
  152. package/dist/styles/tokens.css +221 -0
  153. package/dist/styles/utilities.css +129 -0
  154. package/dist/utils.d.ts +18 -0
  155. package/dist/utils.js +22 -0
  156. package/package.json +92 -0
@@ -0,0 +1,221 @@
1
+ /*
2
+ Engine design system — tokens.
3
+
4
+ Source of truth: docs/brand/ENGINE-DESIGN-SYSTEM.md in the engine repo.
5
+ Everything here traces back to that document; nothing here was invented.
6
+
7
+ The brand is three colours:
8
+
9
+ #0E0E0E Off Black — the page, and ink on any accent
10
+ #FFFFFF Pure White — text
11
+ #FF006A Magenta — the primary, and the only accent
12
+
13
+ Everything else is a neutral step between the outer two. There is no light
14
+ theme and no `dark` variant — this is the whole palette, so it lives at the
15
+ root.
16
+
17
+ Token names follow Tailwind 4's `@theme` namespaces rather than the design
18
+ document's bare names (`--color-primary`, not `--magenta`). That is
19
+ deliberate: it is what generates the `bg-primary` / `rounded-card` /
20
+ `ease-brand` utilities the primitives are written against. The document's
21
+ names are the spec; these are its implementation.
22
+ */
23
+
24
+ @theme {
25
+ --tw-border-style: solid;
26
+
27
+ /* ── Page and text ─────────────────────────────────────────────────── */
28
+ --color-background: #0e0e0e;
29
+ --color-foreground: #ffffff;
30
+
31
+ /* Surfaces lift away from the page rather than relying on borders alone. */
32
+ --color-card: #161616;
33
+ --color-card-foreground: #ffffff;
34
+ --color-popover: #1c1c1c;
35
+ --color-popover-foreground: #ffffff;
36
+
37
+ /* ── The accent ────────────────────────────────────────────────────── */
38
+ /* White on magenta lands at 3.9:1 — under the 4.5:1 AA threshold for
39
+ normal text. Keep magenta fills to labels at 15px bold or larger, where
40
+ the 3:1 large-text threshold applies. Off Black on magenta is always
41
+ safe. The primitives honour this: every magenta fill in this package
42
+ sets 15px/700 or above. */
43
+ --color-primary: #ff006a;
44
+ --color-primary-foreground: #ffffff;
45
+ --color-primary-press: #d60059;
46
+
47
+ /* Tints, for washes on transparent controls and for soft label fills. */
48
+ --color-primary-tint-12: rgb(255 0 106 / 0.12);
49
+ --color-primary-tint-24: rgb(255 0 106 / 0.24);
50
+
51
+ /* A lighter magenta, for ink on a magenta tint. Pure #FF006A on its own 12%
52
+ tint measures 4.37:1 — under AA — and the brand bans magenta text below
53
+ 15px bold outright, which rules it out for a 13px label. This step gets
54
+ 5.81:1 on the same fill.
55
+
56
+ Not invented here: it ships today as `--brand-300` in integration.css in
57
+ both the engine and rgs repos. Declared as a named step rather than left
58
+ as a one-off so a soft label has a legal ink. See the note in Tag. */
59
+ --color-primary-300: #ff5c9b;
60
+
61
+ /* Engine Integration's reserved accent. NOT IN USE — the brand direction
62
+ assigns it to Integration, but every shipped surface is magenta and was
63
+ deliberately migrated there. Build Integration in magenta; a
64
+ half-migrated accent is worse than a consistent one. Declared because it
65
+ is a real brand colour with a real owner, unlike the retired ramps.
66
+ Partner Yellow carries Off Black ink only, never white. */
67
+ --color-partner-yellow: #ffdd00;
68
+ --color-partner-yellow-press: #e0c200;
69
+ --color-partner-yellow-tint-12: rgb(255 221 0 / 0.12);
70
+
71
+ /* ── Neutral ramp — the only greys ─────────────────────────────────── */
72
+ --color-grey-950: #0a0a0a;
73
+ --color-grey-900: #0e0e0e;
74
+ --color-grey-850: #141414;
75
+ --color-grey-800: #1a1a1a;
76
+ --color-grey-700: #242424;
77
+ --color-grey-600: #2e2e2e;
78
+ --color-grey-500: #3d3d3d;
79
+ --color-grey-400: #6b6b6b;
80
+ --color-grey-300: #8c8c8c;
81
+ --color-grey-200: #b4b4b4;
82
+ --color-grey-100: #d9d9d9;
83
+ --color-grey-050: #f2f2f2;
84
+
85
+ /* ── Semantic neutrals ─────────────────────────────────────────────── */
86
+ --color-secondary: #232323;
87
+ --color-secondary-foreground: #ffffff;
88
+ --color-muted: #232323;
89
+ --color-muted-foreground: #a1a1a1;
90
+ --color-accent: #2a2a2a;
91
+ --color-accent-foreground: #ffffff;
92
+
93
+ --color-border: #2a2a2a;
94
+ --color-input: #2a2a2a;
95
+ --color-ring: #ff006a;
96
+
97
+ /* ── Status ───────────────────────────────────────────────────────────
98
+ The design system document (§3, §12) states that no status palette
99
+ exists and that one must not be invented locally. IT NOW EXISTS: these
100
+ three were commissioned deliberately, at the repo owner's direction, to
101
+ close that gap. They are a decision, not a workaround — but the brand
102
+ documents in the engine repo still say otherwise, so ENGINE-BRAND.md §10
103
+ and ENGINE-DESIGN-SYSTEM.md §12 need updating to match, and the brand
104
+ team should ratify the values.
105
+
106
+ Chosen against the theme rather than picked off a stock ramp: one high
107
+ chroma step each, cool-leaning, clinical rather than sweet, and sitting
108
+ well clear of magenta so the accent stays the accent. Status is
109
+ FUNCTIONAL colour — it reports state. It is never decoration, never an
110
+ accent, and never a substitute for magenta.
111
+
112
+ Every value below clears 4.5:1 three ways: Off Black as ink on the solid
113
+ fill, and the colour itself as text on both the page and its own 12%
114
+ tint. Ink on a status fill is ALWAYS Off Black — white fails on all
115
+ three (danger is the tightest at 3.4:1).
116
+
117
+ role value blk-on-fill on-page on-tint dE vs magenta
118
+ success #00C46A 8.37 8.37 6.53 146
119
+ warning #FFB020 10.56 10.56 7.91 --
120
+ danger #FF3B30 5.44 5.44 4.56 38
121
+
122
+ Warning sits ΔE 28.7 from Partner Yellow #FFDD00 — visibly amber next to
123
+ that pure yellow, but not dramatically so. It does not matter today
124
+ because Partner Yellow is unused; if Engine Integration ever adopts it,
125
+ a warning chip beside a Partner badge on one surface wants a second look.
126
+
127
+ No `info` colour. The obvious choice is a blue, and any blue here would
128
+ read as the retired Sportsbook Blue coming back. Use the neutral ramp
129
+ for informational states instead. */
130
+ --color-success: #00c46a;
131
+ --color-success-foreground: #0e0e0e;
132
+ --color-success-tint-12: rgb(0 196 106 / 0.12);
133
+
134
+ --color-warning: #ffb020;
135
+ --color-warning-foreground: #0e0e0e;
136
+ --color-warning-tint-12: rgb(255 176 32 / 0.12);
137
+
138
+ --color-danger: #ff3b30;
139
+ --color-danger-foreground: #0e0e0e;
140
+ --color-danger-tint-12: rgb(255 59 48 / 0.12);
141
+
142
+ /* shadcn's name for the same thing. Kept as an alias so Alert, Input's
143
+ aria-invalid state and the Button's destructive variant keep resolving,
144
+ and so there is exactly one red in the system rather than two. */
145
+ --color-destructive: var(--color-danger);
146
+ --color-destructive-foreground: var(--color-danger-foreground);
147
+
148
+ /* ── Radii, by role ───────────────────────────────────────────────── */
149
+ /* Never mixed arbitrarily on one surface — the outer frame is always
150
+ larger than the inner panel (18px card → 10px inner). */
151
+ --radius-tag: 6px;
152
+ --radius-field: 10px;
153
+ --radius-card-inner: 10px;
154
+ --radius-media: 14px;
155
+ --radius-card: 18px;
156
+ --radius-frame: 26px;
157
+ --radius-control: 999px;
158
+
159
+ /* The generic scale, for shadcn primitives that predate the role-based
160
+ radii above. Prefer the named roles in new work. */
161
+ --radius: 0.5rem;
162
+ --radius-sm: calc(var(--radius) - 4px);
163
+ --radius-md: calc(var(--radius) - 2px);
164
+ --radius-lg: var(--radius);
165
+ --radius-xl: calc(var(--radius) + 4px);
166
+
167
+ /* ── Depth ────────────────────────────────────────────────────────── */
168
+ /* Depth comes from rules and nested panels, not shadow. These two exist
169
+ for product chrome and modals only — never on a brand surface. */
170
+ --shadow-panel: 0 12px 32px rgb(0 0 0 / 0.55);
171
+ --shadow-modal: 0 24px 64px rgb(0 0 0 / 0.7);
172
+
173
+ /* ── Motion ───────────────────────────────────────────────────────── */
174
+ /* Fast and mechanical: 140ms control states, 220ms surfaces, 360–640ms
175
+ reveals. Never bounce, spring, or parallax. */
176
+ --ease-brand: cubic-bezier(0.2, 0, 0.2, 1);
177
+ --ease-brand-out: cubic-bezier(0.16, 1, 0.3, 1);
178
+ --ease-brand-accelerate: cubic-bezier(0.6, 0, 0.3, 1);
179
+
180
+ /* ── Type ─────────────────────────────────────────────────────────── */
181
+ /* Proxima Nova is the brand face and ships with this package. Inter is the
182
+ documented substitute where the licence does not reach. */
183
+ --font-brand:
184
+ "ProximaNova", "Inter", "Helvetica Neue", Arial, sans-serif;
185
+ --font-sans: var(--font-brand);
186
+ --font-condensed:
187
+ "ProximaNovaCondensed", "ProximaNova", Arial, sans-serif;
188
+ --font-extra-condensed:
189
+ "ProximaNovaExtraCondensed", "ProximaNovaCondensed", Arial, sans-serif;
190
+ /* JetBrains Mono is specified for numerics, keys, IDs, code and eyebrow
191
+ labels. No binary ships with this package yet — see README, Known gaps —
192
+ so this currently resolves to the platform monospace. */
193
+ --font-mono:
194
+ "JetBrains Mono", ui-monospace, SFMono-Regular, Menlo, monospace;
195
+
196
+ --breakpoint-2xl: 1400px;
197
+
198
+ /* ── Sidebar ──────────────────────────────────────────────────────── */
199
+ /* Left-nav hover and active states: magenta at very low lightness, so the
200
+ wash reads as brand-tinted rather than plain grey. */
201
+ --color-sidebar-background: #131313;
202
+ --color-sidebar-foreground: #ffffff;
203
+ --color-sidebar-primary: #ff006a;
204
+ --color-sidebar-primary-foreground: #ffffff;
205
+ --color-sidebar-accent: #291319;
206
+ --color-sidebar-accent-foreground: #ffffff;
207
+ --color-sidebar-border: #2a2a2a;
208
+ --color-sidebar-ring: #ff006a;
209
+ }
210
+
211
+ /*
212
+ RETIRED COLOURS ARE NOT DECLARED HERE, AND THAT IS DELIBERATE.
213
+
214
+ Originals Orange #FF6200 and Sportsbook Blue #00CCFF belonged to sub-brands
215
+ that no longer exist. They have no owner, so per the brand's
216
+ conditional-colour rule they are not available — no accents, no charts, no
217
+ status. The engine repo still declares them in app.css for historical
218
+ reasons; this package does not, because you cannot misuse a token that does
219
+ not exist. The `originals` / `sportsbook` variants that shipped on Badge and
220
+ Tag upstream are gone for the same reason.
221
+ */
@@ -0,0 +1,129 @@
1
+ /*
2
+ Engine design system — base layer and shared utilities.
3
+
4
+ Everything the primitives need beyond raw tokens. Import order matters:
5
+ this must come after `tailwindcss` so `@utility` and `@layer base` resolve.
6
+ */
7
+
8
+ @layer base {
9
+ body {
10
+ background-color: var(--color-background);
11
+ color: var(--color-foreground);
12
+ font-family: var(--font-brand);
13
+ font-weight: 400;
14
+ -webkit-font-smoothing: antialiased;
15
+ -moz-osx-font-smoothing: grayscale;
16
+ }
17
+
18
+ /* Native chrome follows the page, not the OS. Without `color-scheme` the
19
+ browser paints light scrollbars, form controls, spinners and autofill
20
+ over a dark UI — this is what makes a default scrollbar read as a light
21
+ strip down the right-hand edge. */
22
+ :root {
23
+ color-scheme: dark;
24
+ }
25
+
26
+ /* The scrollbar on the grey ramp: a thumb that reads as part of the page
27
+ and a track that stays out of the way. Firefox takes the two-value
28
+ `scrollbar-color`; WebKit needs the pseudo-elements. The thumb's
29
+ transparent border plus `background-clip` is what insets it from the
30
+ edge — WebKit has no padding on the thumb. */
31
+ * {
32
+ scrollbar-width: thin;
33
+ scrollbar-color: var(--color-grey-600) transparent;
34
+ }
35
+
36
+ ::-webkit-scrollbar {
37
+ width: 10px;
38
+ height: 10px;
39
+ }
40
+
41
+ ::-webkit-scrollbar-track,
42
+ ::-webkit-scrollbar-corner {
43
+ background: transparent;
44
+ }
45
+
46
+ ::-webkit-scrollbar-thumb {
47
+ background: var(--color-grey-600);
48
+ background-clip: padding-box;
49
+ border: 2px solid transparent;
50
+ border-radius: 999px;
51
+ }
52
+
53
+ ::-webkit-scrollbar-thumb:hover {
54
+ background: var(--color-grey-500);
55
+ background-clip: padding-box;
56
+ }
57
+
58
+ /* Motion is fast and mechanical, but it is never mandatory.
59
+ `prefers-reduced-motion` drops everything to fades. */
60
+ @media (prefers-reduced-motion: reduce) {
61
+ *,
62
+ *::before,
63
+ *::after {
64
+ animation-duration: 0.01ms !important;
65
+ animation-iteration-count: 1 !important;
66
+ transition-duration: 0.01ms !important;
67
+ scroll-behavior: auto !important;
68
+ }
69
+ }
70
+ }
71
+
72
+ /*
73
+ The system's field surface, defined once. Height, width and text size stay
74
+ at the call site — this is only the skin, so an `h-9` search box and a
75
+ `min-h-20` textarea can share it without fighting over utilities.
76
+
77
+ Input, Textarea and SelectTrigger all consume this. If you are building a
78
+ new field-shaped control, use it rather than restating the border and focus
79
+ ring: it is the one place the 2px magenta focus ring is defined.
80
+ */
81
+ @utility field {
82
+ border-radius: var(--radius-field);
83
+ border: 1px solid var(--color-grey-700);
84
+ background-color: var(--color-grey-850);
85
+ color: var(--color-foreground);
86
+ transition:
87
+ border-color 140ms var(--ease-brand),
88
+ box-shadow 140ms var(--ease-brand);
89
+
90
+ &::placeholder {
91
+ color: var(--color-grey-400);
92
+ }
93
+
94
+ /* 2px magenta ring, offset by the page colour, per the system's focus
95
+ rule. Always visible on keyboard focus — never removed.
96
+
97
+ The border deliberately stays on its resting grey. Recolouring it to
98
+ magenta as well drew a second magenta line inside the offset gap, so a
99
+ focused field read as a double border — magenta, page colour, magenta.
100
+ The ring is the affordance; the border's job is to delineate the field,
101
+ and it does that whether or not the field has focus. */
102
+ &:focus,
103
+ &:focus-visible {
104
+ outline: none;
105
+ box-shadow:
106
+ 0 0 0 2px var(--color-background),
107
+ 0 0 0 4px var(--color-ring);
108
+ }
109
+
110
+ &[aria-invalid="true"] {
111
+ border-color: var(--color-destructive);
112
+ }
113
+
114
+ &:disabled {
115
+ cursor: not-allowed;
116
+ opacity: 0.38;
117
+ }
118
+ }
119
+
120
+ @layer utilities {
121
+ .scrollbar-hide {
122
+ -ms-overflow-style: none;
123
+ scrollbar-width: none;
124
+ }
125
+
126
+ .scrollbar-hide::-webkit-scrollbar {
127
+ display: none;
128
+ }
129
+ }
@@ -0,0 +1,18 @@
1
+ import { type ClassValue } from "clsx";
2
+ /**
3
+ * Merge Tailwind classes, letting later ones win over conflicting earlier
4
+ * ones. Every primitive in this package passes its own classes through `cn`
5
+ * with the caller's `class` prop last, which is what makes
6
+ * `<Button class="w-full" />` work without `!important`.
7
+ */
8
+ export declare function cn(...inputs: ClassValue[]): string;
9
+ export type WithoutChild<T> = T extends {
10
+ child?: any;
11
+ } ? Omit<T, "child"> : T;
12
+ export type WithoutChildren<T> = T extends {
13
+ children?: any;
14
+ } ? Omit<T, "children"> : T;
15
+ export type WithoutChildrenOrChild<T> = WithoutChildren<WithoutChild<T>>;
16
+ export type WithElementRef<T, U extends HTMLElement = HTMLElement> = T & {
17
+ ref?: U | null;
18
+ };
package/dist/utils.js ADDED
@@ -0,0 +1,22 @@
1
+ import { clsx } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+ /**
4
+ * Merge Tailwind classes, letting later ones win over conflicting earlier
5
+ * ones. Every primitive in this package passes its own classes through `cn`
6
+ * with the caller's `class` prop last, which is what makes
7
+ * `<Button class="w-full" />` work without `!important`.
8
+ */
9
+ export function cn(...inputs) {
10
+ return twMerge(clsx(inputs));
11
+ }
12
+ /*
13
+ Upstream `$lib/utils.ts` in the engine repo is a grab-bag: alongside `cn` it
14
+ carries `copyToClipboard` (which pulls in svelte-sonner), `humanFileSize`,
15
+ `getDateFromUUIDv7`, `slugify`, `formatDate` and `jurisdictionLabel` — the
16
+ last of which encodes iGaming domain knowledge.
17
+
18
+ None of that belongs in a design system, and importing it here would have
19
+ made svelte-sonner a hard dependency of every consumer. Only `cn` and the
20
+ type helpers the primitives genuinely need are re-exported. The rest stays
21
+ in the products, where it already lives.
22
+ */
package/package.json ADDED
@@ -0,0 +1,92 @@
1
+ {
2
+ "name": "@engineio/ui",
3
+ "version": "0.4.0",
4
+ "description": "The Engine design system — tokens, fonts and Svelte primitives.",
5
+ "license": "MIT",
6
+ "private": false,
7
+ "type": "module",
8
+ "packageManager": "bun@1.3.14",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/engineio/ui.git"
12
+ },
13
+ "publishConfig": {
14
+ "access": "public",
15
+ "registry": "https://registry.npmjs.org"
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "!dist/**/*.test.*",
20
+ "!dist/**/*.spec.*"
21
+ ],
22
+ "sideEffects": [
23
+ "**/*.css"
24
+ ],
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.ts",
28
+ "svelte": "./dist/index.js"
29
+ },
30
+ "./styles": "./dist/styles/index.css",
31
+ "./styles/tokens": "./dist/styles/tokens.css",
32
+ "./styles/fonts": "./dist/styles/fonts.css",
33
+ "./styles/utilities": "./dist/styles/utilities.css",
34
+ "./fonts/*": "./dist/fonts/*",
35
+ "./utils": {
36
+ "types": "./dist/utils.d.ts",
37
+ "default": "./dist/utils.js"
38
+ },
39
+ "./components/ui/*": {
40
+ "types": "./dist/components/ui/*/index.d.ts",
41
+ "svelte": "./dist/components/ui/*/index.js"
42
+ },
43
+ "./components/ui/*/index.js": {
44
+ "types": "./dist/components/ui/*/index.d.ts",
45
+ "svelte": "./dist/components/ui/*/index.js"
46
+ },
47
+ "./components/brand": {
48
+ "types": "./dist/components/brand/index.d.ts",
49
+ "svelte": "./dist/components/brand/index.js"
50
+ },
51
+ "./components/brand/index.js": {
52
+ "types": "./dist/components/brand/index.d.ts",
53
+ "svelte": "./dist/components/brand/index.js"
54
+ }
55
+ },
56
+ "scripts": {
57
+ "dev": "vite dev",
58
+ "build": "svelte-kit sync && svelte-package && publint",
59
+ "preview": "vite preview",
60
+ "build:gallery": "svelte-kit sync && vite build",
61
+ "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
62
+ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
63
+ "prepublishOnly": "bun run build"
64
+ },
65
+ "dependencies": {
66
+ "@lucide/svelte": "^0.544.0",
67
+ "bits-ui": "^1.4.7",
68
+ "clsx": "^2.1.1",
69
+ "tailwind-merge": "^3.3.1",
70
+ "tailwind-variants": "^0.2.1"
71
+ },
72
+ "peerDependencies": {
73
+ "svelte": "^5.0.0",
74
+ "tailwindcss": "^4.0.0"
75
+ },
76
+ "devDependencies": {
77
+ "@sveltejs/adapter-static": "^3.0.10",
78
+ "@sveltejs/kit": "2.63.0",
79
+ "@sveltejs/package": "^2.5.4",
80
+ "@sveltejs/vite-plugin-svelte": "7.1.2",
81
+ "@tailwindcss/vite": "^4.3.0",
82
+ "@types/node": "^26.2.0",
83
+ "conventional-changelog-conventionalcommits": "9",
84
+ "publint": "^0.3.15",
85
+ "semantic-release": "^25.0.9",
86
+ "svelte": "5.56.1",
87
+ "svelte-check": "4.5.0",
88
+ "tailwindcss": "^4.3.0",
89
+ "typescript": "6.0.3",
90
+ "vite": "8.1.0"
91
+ }
92
+ }