@charcuterie/ui 2.6.0 → 2.7.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
@@ -37,7 +37,7 @@ import { Button, Card } from "@charcuterie/ui"
37
37
  @import "tailwindcss";
38
38
  @import "@charcuterie/tokens/theme.css"; /* colours, type ramp, radii, motion */
39
39
  @import "@charcuterie/tokens/fonts.css"; /* Baloo 2, Outfit, Victor Mono */
40
- @import "@charcuterie/ui/styles.css"; /* the four looping affordances */
40
+ @import "@charcuterie/ui/styles.css"; /* the four looping affordances + `.charcuterie-scrollbar` */
41
41
 
42
42
  @source "../node_modules/@charcuterie/ui/dist";
43
43
  ```
@@ -105,6 +105,7 @@ an hour of confusion.
105
105
  | Size | `controlStyles.ts` — `h-(--control-height-md)`, so `[data-density]` decides |
106
106
  | Type | `text-sm`/`text-md`/`text-lg`, which are **ours**: `theme.css` bridges `--text-*` onto the density-scaled `--font-size-*` |
107
107
  | Motion | `styles.css`, at `--duration-loop-*`, switched off under `prefers-reduced-motion` |
108
+ | Scrollbar | `styles.css` — add `charcuterie-scrollbar` to any scrolling element for a token-tinted bar (rounded thumb on Chromium/Safari; thin standard match on Firefox) that flips with `[data-scheme]` |
108
109
  | State | `@charcuterie/logic` — `useUniqueId` for label wiring, `useStatus` for `MediaTile`'s three image states |
109
110
 
110
111
  **Class names are never interpolated.** `` `bg-intent-${intent}-solid` `` generates nothing
package/dist/styles.css CHANGED
@@ -1,14 +1,19 @@
1
- /* `@charcuterie/ui/styles.css` — the four looping affordances, and
2
- * nothing else.
1
+ /* `@charcuterie/ui/styles.css` — the four looping affordances and
2
+ * the token-tinted scrollbar: the visuals a Tailwind utility cannot
3
+ * express against our tokens, and nothing else.
3
4
  *
4
5
  * Every other visual in this package is a Tailwind utility reading
5
6
  * a token, which is what makes a scheme/density/variant flip a
6
- * repaint with no re-render. Animation is the one thing utilities
7
- * cannot express against our tokens: Tailwind's own `animate-spin`
8
- * and `animate-pulse` hardcode 1s and 2s, ignore
9
- * `prefers-reduced-motion`, and are therefore beyond the theme's
10
- * reach — which is exactly why `MotionTokens` carries a separate
11
- * `loopFast`/`loopSlow` ramp.
7
+ * repaint with no re-render. Two things sit outside that reach.
8
+ * Animation is one: Tailwind's own `animate-spin` and `animate-pulse`
9
+ * hardcode 1s and 2s, ignore `prefers-reduced-motion`, and are
10
+ * therefore beyond the theme's reach — which is exactly why
11
+ * `MotionTokens` carries a separate `loopFast`/`loopSlow` ramp. The
12
+ * scrollbar is the other: the `::-webkit-scrollbar` pseudo-elements
13
+ * (and Firefox's `scrollbar-width`/`scrollbar-color`) have no
14
+ * `@theme`-generated utility, so `.charcuterie-scrollbar` at the foot
15
+ * of this file reads the same `--color-*` roles by hand and flips with
16
+ * `data-scheme` on the same repaint as everything else.
12
17
  *
13
18
  * Consumers import this once, after `@charcuterie/tokens/theme.css`.
14
19
  *
@@ -128,3 +133,78 @@
128
133
  );
129
134
  }
130
135
  }
136
+
137
+ /* `.charcuterie-scrollbar` — a token-tinted scrollbar for any element
138
+ * that scrolls. The fleet grew this twice by hand (gallery-downloader's
139
+ * `scrollbar-thin-token`, image-viewer's global `::-webkit-scrollbar`
140
+ * block); this is the one copy, promoted here so a scheme flip
141
+ * repaints it for free.
142
+ *
143
+ * The *designed* look is the `::-webkit-scrollbar` path: a 12px bar, a
144
+ * rounded thumb, a track-coloured inset, no step arrows. That is what
145
+ * Chromium, Edge, and Safari paint. Chromium 121+ will *prefer*
146
+ * `scrollbar-width` / `scrollbar-color` over these pseudo-elements
147
+ * whenever both are set, which collapses the bar to the thin OS chrome
148
+ * (arrows and all on Windows) — so the standard properties are scoped
149
+ * to Firefox only, where `::-webkit-scrollbar` never runs.
150
+ *
151
+ * Firefox gets the closest standard-property match (thin, token-tinted
152
+ * thumb, transparent track). It cannot round a corner or draw a track
153
+ * inset — a platform limit, not an omission here.
154
+ *
155
+ * `::-webkit-scrollbar-button` is suppressed deliberately: the
156
+ * affordance is the thumb on a track, not step arrows.
157
+ *
158
+ * Both engines read the same three roles — `border-strong` for the
159
+ * thumb, `surface-sunken` for the track, `content-muted` for the thumb
160
+ * on hover — so the bar is themed by `[data-scheme]` on `<html>` with
161
+ * nothing in React observing it. `width`/`height` rather than a
162
+ * logical property is not a lapse: the `::-webkit-scrollbar`
163
+ * pseudo-elements size only by the physical pair, and a vertical bar's
164
+ * thickness is its `width` regardless of writing direction. */
165
+
166
+ /* The designed bar — Chromium, Edge, Safari. */
167
+ .charcuterie-scrollbar::-webkit-scrollbar {
168
+ width: 12px;
169
+ height: 12px;
170
+ }
171
+
172
+ .charcuterie-scrollbar::-webkit-scrollbar-button {
173
+ display: none;
174
+ width: 0;
175
+ height: 0;
176
+ }
177
+
178
+ .charcuterie-scrollbar::-webkit-scrollbar-track {
179
+ background-color: var(--color-surface-sunken);
180
+ }
181
+
182
+ .charcuterie-scrollbar::-webkit-scrollbar-thumb {
183
+ background-color: var(--color-border-strong);
184
+ border: 2px solid var(--color-surface-sunken);
185
+ border-radius: 6px;
186
+ }
187
+
188
+ .charcuterie-scrollbar::-webkit-scrollbar-thumb:hover {
189
+ background-color: var(--color-content-muted);
190
+ }
191
+
192
+ .charcuterie-scrollbar::-webkit-scrollbar-corner {
193
+ background-color: var(--color-surface-sunken);
194
+ }
195
+
196
+ /* Firefox only: it never paints `::-webkit-scrollbar`. `-moz-appearance`
197
+ * is the supports probe that Chromium and Safari reject, so this block
198
+ * does not reintroduce the standard properties on engines that would
199
+ * then drop the designed bar. */
200
+ @supports (-moz-appearance: none) {
201
+ .charcuterie-scrollbar {
202
+ scrollbar-width: thin;
203
+ scrollbar-color: color-mix(
204
+ in oklab,
205
+ var(--color-border-strong) 70%,
206
+ transparent
207
+ )
208
+ transparent;
209
+ }
210
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@charcuterie/ui",
3
- "version": "2.6.0",
3
+ "version": "2.7.0",
4
4
  "description": "The Charcuterie components. Tokens for look, @charcuterie/logic for state, ARIA that agents can actually drive.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/src/styles.css CHANGED
@@ -1,14 +1,19 @@
1
- /* `@charcuterie/ui/styles.css` — the four looping affordances, and
2
- * nothing else.
1
+ /* `@charcuterie/ui/styles.css` — the four looping affordances and
2
+ * the token-tinted scrollbar: the visuals a Tailwind utility cannot
3
+ * express against our tokens, and nothing else.
3
4
  *
4
5
  * Every other visual in this package is a Tailwind utility reading
5
6
  * a token, which is what makes a scheme/density/variant flip a
6
- * repaint with no re-render. Animation is the one thing utilities
7
- * cannot express against our tokens: Tailwind's own `animate-spin`
8
- * and `animate-pulse` hardcode 1s and 2s, ignore
9
- * `prefers-reduced-motion`, and are therefore beyond the theme's
10
- * reach — which is exactly why `MotionTokens` carries a separate
11
- * `loopFast`/`loopSlow` ramp.
7
+ * repaint with no re-render. Two things sit outside that reach.
8
+ * Animation is one: Tailwind's own `animate-spin` and `animate-pulse`
9
+ * hardcode 1s and 2s, ignore `prefers-reduced-motion`, and are
10
+ * therefore beyond the theme's reach — which is exactly why
11
+ * `MotionTokens` carries a separate `loopFast`/`loopSlow` ramp. The
12
+ * scrollbar is the other: the `::-webkit-scrollbar` pseudo-elements
13
+ * (and Firefox's `scrollbar-width`/`scrollbar-color`) have no
14
+ * `@theme`-generated utility, so `.charcuterie-scrollbar` at the foot
15
+ * of this file reads the same `--color-*` roles by hand and flips with
16
+ * `data-scheme` on the same repaint as everything else.
12
17
  *
13
18
  * Consumers import this once, after `@charcuterie/tokens/theme.css`.
14
19
  *
@@ -128,3 +133,78 @@
128
133
  );
129
134
  }
130
135
  }
136
+
137
+ /* `.charcuterie-scrollbar` — a token-tinted scrollbar for any element
138
+ * that scrolls. The fleet grew this twice by hand (gallery-downloader's
139
+ * `scrollbar-thin-token`, image-viewer's global `::-webkit-scrollbar`
140
+ * block); this is the one copy, promoted here so a scheme flip
141
+ * repaints it for free.
142
+ *
143
+ * The *designed* look is the `::-webkit-scrollbar` path: a 12px bar, a
144
+ * rounded thumb, a track-coloured inset, no step arrows. That is what
145
+ * Chromium, Edge, and Safari paint. Chromium 121+ will *prefer*
146
+ * `scrollbar-width` / `scrollbar-color` over these pseudo-elements
147
+ * whenever both are set, which collapses the bar to the thin OS chrome
148
+ * (arrows and all on Windows) — so the standard properties are scoped
149
+ * to Firefox only, where `::-webkit-scrollbar` never runs.
150
+ *
151
+ * Firefox gets the closest standard-property match (thin, token-tinted
152
+ * thumb, transparent track). It cannot round a corner or draw a track
153
+ * inset — a platform limit, not an omission here.
154
+ *
155
+ * `::-webkit-scrollbar-button` is suppressed deliberately: the
156
+ * affordance is the thumb on a track, not step arrows.
157
+ *
158
+ * Both engines read the same three roles — `border-strong` for the
159
+ * thumb, `surface-sunken` for the track, `content-muted` for the thumb
160
+ * on hover — so the bar is themed by `[data-scheme]` on `<html>` with
161
+ * nothing in React observing it. `width`/`height` rather than a
162
+ * logical property is not a lapse: the `::-webkit-scrollbar`
163
+ * pseudo-elements size only by the physical pair, and a vertical bar's
164
+ * thickness is its `width` regardless of writing direction. */
165
+
166
+ /* The designed bar — Chromium, Edge, Safari. */
167
+ .charcuterie-scrollbar::-webkit-scrollbar {
168
+ width: 12px;
169
+ height: 12px;
170
+ }
171
+
172
+ .charcuterie-scrollbar::-webkit-scrollbar-button {
173
+ display: none;
174
+ width: 0;
175
+ height: 0;
176
+ }
177
+
178
+ .charcuterie-scrollbar::-webkit-scrollbar-track {
179
+ background-color: var(--color-surface-sunken);
180
+ }
181
+
182
+ .charcuterie-scrollbar::-webkit-scrollbar-thumb {
183
+ background-color: var(--color-border-strong);
184
+ border: 2px solid var(--color-surface-sunken);
185
+ border-radius: 6px;
186
+ }
187
+
188
+ .charcuterie-scrollbar::-webkit-scrollbar-thumb:hover {
189
+ background-color: var(--color-content-muted);
190
+ }
191
+
192
+ .charcuterie-scrollbar::-webkit-scrollbar-corner {
193
+ background-color: var(--color-surface-sunken);
194
+ }
195
+
196
+ /* Firefox only: it never paints `::-webkit-scrollbar`. `-moz-appearance`
197
+ * is the supports probe that Chromium and Safari reject, so this block
198
+ * does not reintroduce the standard properties on engines that would
199
+ * then drop the designed bar. */
200
+ @supports (-moz-appearance: none) {
201
+ .charcuterie-scrollbar {
202
+ scrollbar-width: thin;
203
+ scrollbar-color: color-mix(
204
+ in oklab,
205
+ var(--color-border-strong) 70%,
206
+ transparent
207
+ )
208
+ transparent;
209
+ }
210
+ }