@blakesteve/roster 3.0.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -31,13 +31,19 @@ Roster ships pre-compiled CSS, so you do not need Tailwind installed in your hos
31
31
  ```
32
32
 
33
33
  `DataTable` additionally needs TanStack Table v9, declared as an **optional**
34
- peer. Install it only if you use `DataTable`; every other component works
35
- without it.
34
+ peer. It ships from its own entry point so that peer stays genuinely optional:
35
+ importing anything from `@blakesteve/roster` never pulls TanStack in, because a
36
+ bundler resolves imports before it tree-shakes. Install it only if you use
37
+ `DataTable`; every other component works without it.
36
38
 
37
39
  ```bash
38
40
  npm install @tanstack/react-table
39
41
  ```
40
42
 
43
+ ```tsx
44
+ import { DataTable, type RosterTableFeatures } from "@blakesteve/roster/data-table";
45
+ ```
46
+
41
47
  It is a peer rather than a bundled dependency because v9 types column
42
48
  definitions against the feature set that built the table. Two copies of the
43
49
  package would mean two incompatible sets of those types, so roster and your
@@ -56,9 +62,10 @@ import "@blakesteve/roster/style.css";
56
62
  import "@blakesteve/roster/tokens.css";
57
63
  ```
58
64
 
59
- ### Import Roster before Tailwind
65
+ ### Cascade layers
60
66
 
61
- If your app uses Tailwind, import Roster's CSS **before** it:
67
+ Roster ships its styles inside a `roster` cascade layer and declares the full
68
+ layer order in its own stylesheet, so importing it is normally enough:
62
69
 
63
70
  ```css
64
71
  /* globals.css */
@@ -67,11 +74,23 @@ If your app uses Tailwind, import Roster's CSS **before** it:
67
74
  @import "tailwindcss";
68
75
  ```
69
76
 
70
- Roster ships its styles inside a `roster` cascade layer, and CSS orders layers
71
- by *first registration*. Importing Roster first places its layer beneath your
72
- app's own utilities, so your styles always win. Import it second and the
73
- opposite happens: Roster's `.block` starts beating your `dark:hidden`, and
74
- variants fail silently with the rule present in the stylesheet.
77
+ The order Roster declares is:
78
+
79
+ ```css
80
+ @layer roster-preflight, theme, base, components, roster, utilities;
81
+ ```
82
+
83
+ `roster` has to sit in that exact slot. **Above `base`**, because Tailwind's
84
+ preflight resets `*{margin:0;padding:0;border:0 solid}` — put Roster below it
85
+ and that reset outranks Roster's own spacing and border utilities, silently
86
+ stripping padding off buttons and turning `border-transparent` into a visible
87
+ 1px line. **Below `utilities`**, so your app's classes and variants such as
88
+ `dark:hidden` still win.
89
+
90
+ Layers are ordered by *first registration*, so importing Roster before Tailwind
91
+ is the reliable arrangement. If you would rather not depend on import order at
92
+ all, declare the same line yourself at the top of your global stylesheet and it
93
+ holds regardless.
75
94
 
76
95
  ### The global reset is opt-in
77
96
 
@@ -91,6 +110,39 @@ import "@blakesteve/roster/style.css";
91
110
  Skip it and components render against browser defaults: serif type, bulleted
92
111
  lists, and `content-box` sizing.
93
112
 
113
+ ### Dark mode
114
+
115
+ Every component reads a `.dark` class on an ancestor, so dark mode is whatever
116
+ puts that class on your document root. `ThemeToggle` is the component that does
117
+ it, and it persists the choice to `localStorage`:
118
+
119
+ ```tsx
120
+ import { ThemeToggle } from "@blakesteve/roster";
121
+
122
+ <ThemeToggle />;
123
+ ```
124
+
125
+ A toggle alone cannot prevent a flash of the wrong theme on first paint, because
126
+ the class has to be on `<html>` before React runs. Add a blocking script to your
127
+ document head:
128
+
129
+ ```html
130
+ <script>
131
+ try {
132
+ var s = localStorage.getItem("roster-theme");
133
+ var dark = s ? s === "dark" : matchMedia("(prefers-color-scheme: dark)").matches;
134
+ if (dark) document.documentElement.classList.add("dark");
135
+ } catch (e) {}
136
+ </script>
137
+ ```
138
+
139
+ If you pass a custom `storageKey`, change the script to match — a mismatch means
140
+ the script and the toggle disagree, which shows up as a flash on every reload.
141
+
142
+ `Navbar`'s `themeMode` prop is a different thing: it describes what palette the
143
+ bar paints *itself* with. Pair them with `themeMode="auto"` and the nav follows
144
+ whatever `ThemeToggle` sets.
145
+
94
146
  ## Quick start
95
147
 
96
148
  ```tsx
@@ -127,7 +179,10 @@ function App() {
127
179
  | `Card` | Bordered surface container |
128
180
  | `Checkbox` | Accessible checkbox with label support |
129
181
  | `Disclosure` | Show/hide toggle using HeadlessUI |
182
+ | `Eyebrow` | Small tracked-out uppercase label above a heading or beside a rule |
183
+ | `InlineCode` | Inline `<code>` for identifiers in running prose |
130
184
  | `Input` | Text input with label, error state, and icon slots |
185
+ | `LabeledDivider` | Horizontal rule carrying a label, with an optional trailing count |
131
186
  | `Link` | Styled anchor with variant support |
132
187
  | `PasswordInput` | Password field with a show/hide reveal toggle |
133
188
  | `Pill` | Inline phrase chrome: social proof, live state, applied filters |
@@ -136,9 +191,11 @@ function App() {
136
191
  | `LiquidTabs` | Controlled tab strip with a liquid sliding pill indicator: pill and filled variants |
137
192
  | `Select` | Dropdown selector |
138
193
  | `SegmentBar` | Proportional horizontal bar divided into colored segments with optional legend |
194
+ | `Stat` | A single figure with its label and, optionally, where the figure came from |
139
195
  | `Spinner` | Loading indicator |
140
196
  | `Switch` | Toggle switch |
141
197
  | `Textarea` | Multi-line text input |
198
+ | `ThemeToggle` | Flips class-based dark mode on the document root and remembers the choice |
142
199
  | `Tooltip` | Radix-powered tooltip: hover/focus on desktop, tap-to-toggle on mobile |
143
200
 
144
201
  ### Molecules
@@ -149,9 +206,11 @@ function App() {
149
206
  | `Alert` | Inline notice strip with optional title and dismiss |
150
207
  | `Breadcrumbs` | Navigation trail |
151
208
  | `CallToAction` | Prominent hero-style CTA block |
209
+ | `DescriptionList` | Label and value pairs as a real `<dl>`: inline, stacked, or split |
152
210
  | `EmptyState` | Zero-data placeholder with icon and action slot |
153
211
  | `ErrorState` | Error display with retry action |
154
212
  | `MatchupCard` | Head-to-head comparison card |
213
+ | `Pullquote` | A line lifted out of prose, as `<figure>` + `<blockquote>` + `<figcaption>` |
155
214
 
156
215
  ### Organisms
157
216
 
@@ -159,7 +218,7 @@ function App() {
159
218
  |---|---|
160
219
  | `ActionBar` | Sticky bottom action strip |
161
220
  | `Countdown` | Live countdown timer |
162
- | `DataTable` | Full-featured table with sorting and pagination via TanStack Table v9 (see [DataTable columns](#datatable-columns)) |
221
+ | `DataTable` | Full-featured table with sorting and pagination via TanStack Table v9. Imported from `@blakesteve/roster/data-table` (see [DataTable columns](#datatable-columns)) |
163
222
  | `Dialog` | Modal dialog |
164
223
  | `Footer` | Site footer |
165
224
  | `Navbar` | Responsive navigation bar with mobile slide-out |
@@ -172,7 +231,7 @@ the table. `DataTable` registers sorting and pagination and exports that set as
172
231
  `RosterTableFeatures`, so your columns name it:
173
232
 
174
233
  ```tsx
175
- import { DataTable, type RosterTableFeatures } from "@blakesteve/roster";
234
+ import { DataTable, type RosterTableFeatures } from "@blakesteve/roster/data-table";
176
235
  import { createColumnHelper, type ColumnDef } from "@tanstack/react-table";
177
236
 
178
237
  type Player = { name: string; points: number };
@@ -197,6 +256,7 @@ entry's value as `unknown` and recovers the real type per column through
197
256
  | Hook | Description |
198
257
  |---|---|
199
258
  | `useCountdown` | Countdown timer logic without the UI |
259
+ | `useKeySequence` | Fires a callback when a sequence of keys is typed in order. Ships `KONAMI_CODE` |
200
260
 
201
261
  ## Development
202
262
 
@@ -233,6 +293,7 @@ Output in `dist/`:
233
293
  |---|---|
234
294
  | `roster.es.js` | ES module bundle |
235
295
  | `roster.umd.js` | UMD bundle |
296
+ | `data-table.es.js` | DataTable entry, keeping the TanStack import out of the main bundle |
236
297
  | `roster.css` | Compiled component styles, in the `roster` cascade layer |
237
298
  | `tokens.css` | Design token CSS variables |
238
299
  | `preflight.css` | Optional global reset (see Setup) |