@hanzo/ui 8.1.17 → 8.1.19

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.
@@ -26,12 +26,17 @@ const jsx_runtime_1 = require("react/jsx-runtime");
26
26
  * clip built in, and a caller cannot forget a thing it does not have to write.
27
27
  *
28
28
  * WHY NOT CSS GRID, which expresses this as one line — `grid-template-rows: auto
29
- * 1fr auto` — with no escape hatch at all: because this package's premise is that
30
- * one import runs on web AND native, and React Native lays out through Yoga,
31
- * which implements flexbox and has no grid. That is not a gap a fork can close;
32
- * Yoga is the native runtime's engine. Grid is right where the target is a
33
- * browser, and `Grid` exists for that. A shell has to work on both, so it is
34
- * flexbox on the inside and neither caller has to know.
29
+ * 1fr auto` — with no escape hatch at all: because React Native lays out through
30
+ * Yoga, and Yoga ships flexbox only. That is a gap a fork CAN close — Yoga is
31
+ * open-source C++, and an experimental patch adds a real `YGDisplayGrid`
32
+ * (GridLayout.cpp, AutoPlacement.h, TrackSizing.h) with working iOS and Android
33
+ * builds, native layout rather than a webview. It is not closed here yet: the
34
+ * patch wants React Native 0.83-rc and an Expo canary, and taking it means this
35
+ * fork carries a C++ layout-engine patch rebased on every upgrade.
36
+ *
37
+ * So the reason is a pin, not a law, and `Screen` is what the shell looks like
38
+ * either way — a caller writes the same two components whether the inside is
39
+ * flexbox today or grid later. `Grid` already exists for web-only surfaces.
35
40
  */
36
41
  const gui_1 = require("@hanzo/gui");
37
42
  const slot_1 = require("./slot.cjs");
@@ -21,12 +21,17 @@
21
21
  * clip built in, and a caller cannot forget a thing it does not have to write.
22
22
  *
23
23
  * WHY NOT CSS GRID, which expresses this as one line — `grid-template-rows: auto
24
- * 1fr auto` — with no escape hatch at all: because this package's premise is that
25
- * one import runs on web AND native, and React Native lays out through Yoga,
26
- * which implements flexbox and has no grid. That is not a gap a fork can close;
27
- * Yoga is the native runtime's engine. Grid is right where the target is a
28
- * browser, and `Grid` exists for that. A shell has to work on both, so it is
29
- * flexbox on the inside and neither caller has to know.
24
+ * 1fr auto` — with no escape hatch at all: because React Native lays out through
25
+ * Yoga, and Yoga ships flexbox only. That is a gap a fork CAN close — Yoga is
26
+ * open-source C++, and an experimental patch adds a real `YGDisplayGrid`
27
+ * (GridLayout.cpp, AutoPlacement.h, TrackSizing.h) with working iOS and Android
28
+ * builds, native layout rather than a webview. It is not closed here yet: the
29
+ * patch wants React Native 0.83-rc and an Expo canary, and taking it means this
30
+ * fork carries a C++ layout-engine patch rebased on every upgrade.
31
+ *
32
+ * So the reason is a pin, not a law, and `Screen` is what the shell looks like
33
+ * either way — a caller writes the same two components whether the inside is
34
+ * flexbox today or grid later. `Grid` already exists for web-only surfaces.
30
35
  */
31
36
  import { type YStackProps } from '@hanzo/gui';
32
37
  export interface ScreenProps extends YStackProps {
@@ -1 +1 @@
1
- {"version":3,"file":"screen.d.ts","sourceRoot":"","sources":["../../../src/backends/gui/screen.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,YAAY,CAAA;AAGrD,MAAM,WAAW,WAAY,SAAQ,WAAW;CAAG;AAEnD;;;;GAIG;AACH,QAAA,MAAM,MAAM,GAAI,wBAAwB,WAAW,4CAkBlD,CAAA;AAED,MAAM,WAAW,SAAU,SAAQ,WAAW;IAC5C,6EAA6E;IAC7E,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED;;;;;;;GAOG;AACH,QAAA,MAAM,IAAI,GAAI,gCAAuC,SAAS,4CAY7D,CAAA;AAED,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAA"}
1
+ {"version":3,"file":"screen.d.ts","sourceRoot":"","sources":["../../../src/backends/gui/screen.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,EAAU,KAAK,WAAW,EAAE,MAAM,YAAY,CAAA;AAGrD,MAAM,WAAW,WAAY,SAAQ,WAAW;CAAG;AAEnD;;;;GAIG;AACH,QAAA,MAAM,MAAM,GAAI,wBAAwB,WAAW,4CAkBlD,CAAA;AAED,MAAM,WAAW,SAAU,SAAQ,WAAW;IAC5C,6EAA6E;IAC7E,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED;;;;;;;GAOG;AACH,QAAA,MAAM,IAAI,GAAI,gCAAuC,SAAS,4CAY7D,CAAA;AAED,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAA"}
@@ -23,12 +23,17 @@ import { jsx as _jsx } from "react/jsx-runtime";
23
23
  * clip built in, and a caller cannot forget a thing it does not have to write.
24
24
  *
25
25
  * WHY NOT CSS GRID, which expresses this as one line — `grid-template-rows: auto
26
- * 1fr auto` — with no escape hatch at all: because this package's premise is that
27
- * one import runs on web AND native, and React Native lays out through Yoga,
28
- * which implements flexbox and has no grid. That is not a gap a fork can close;
29
- * Yoga is the native runtime's engine. Grid is right where the target is a
30
- * browser, and `Grid` exists for that. A shell has to work on both, so it is
31
- * flexbox on the inside and neither caller has to know.
26
+ * 1fr auto` — with no escape hatch at all: because React Native lays out through
27
+ * Yoga, and Yoga ships flexbox only. That is a gap a fork CAN close — Yoga is
28
+ * open-source C++, and an experimental patch adds a real `YGDisplayGrid`
29
+ * (GridLayout.cpp, AutoPlacement.h, TrackSizing.h) with working iOS and Android
30
+ * builds, native layout rather than a webview. It is not closed here yet: the
31
+ * patch wants React Native 0.83-rc and an Expo canary, and taking it means this
32
+ * fork carries a C++ layout-engine patch rebased on every upgrade.
33
+ *
34
+ * So the reason is a pin, not a law, and `Screen` is what the shell looks like
35
+ * either way — a caller writes the same two components whether the inside is
36
+ * flexbox today or grid later. `Grid` already exists for web-only surfaces.
32
37
  */
33
38
  import { YStack } from '@hanzo/gui';
34
39
  import { slot } from './slot.js';
@@ -1 +1 @@
1
- {"version":3,"file":"screen.js","sourceRoot":"","sources":["../../../src/backends/gui/screen.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,OAAO,EAAE,MAAM,EAAoB,MAAM,YAAY,CAAA;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAI7B;;;;GAIG;AACH,MAAM,MAAM,GAAG,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAe,EAAE,EAAE,CAAC,CACtD,KAAC,MAAM,OACD,IAAI,CAAC,QAAQ,CAAC;IAClB,yEAAyE;IACzE,6EAA6E;IAC7E,4EAA4E;IAC5E,wEAAwE;IACxE,0EAA0E;IAC1E,8EAA8E;IAC9E,IAAI,EAAE,CAAC,EACP,SAAS,EAAC,MAAM,EAChB,IAAI,EAAE,CAAC,EACP,KAAK,EAAC,MAAM,EACZ,QAAQ,EAAC,QAAQ,KACb,KAAK,YAER,QAAQ,GACF,CACV,CAAA;AAOD;;;;;;;GAOG;AACH,MAAM,IAAI,GAAG,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,KAAK,EAAa,EAAE,EAAE,CAAC,CACjE,KAAC,MAAM,OACD,IAAI,CAAC,MAAM,CAAC,EAChB,IAAI,EAAE,CAAC,EACP,SAAS,EAAE,CAAC,EACZ,IAAI,EAAE,CAAC,EACP,KAAK,EAAC,MAAM,EACZ,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,KACjC,KAAK,YAER,QAAQ,GACF,CACV,CAAA;AAED,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAA"}
1
+ {"version":3,"file":"screen.js","sourceRoot":"","sources":["../../../src/backends/gui/screen.tsx"],"names":[],"mappings":"AAAA,YAAY,CAAA;;AAEZ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,EAAE,MAAM,EAAoB,MAAM,YAAY,CAAA;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAA;AAI7B;;;;GAIG;AACH,MAAM,MAAM,GAAG,CAAC,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAe,EAAE,EAAE,CAAC,CACtD,KAAC,MAAM,OACD,IAAI,CAAC,QAAQ,CAAC;IAClB,yEAAyE;IACzE,6EAA6E;IAC7E,4EAA4E;IAC5E,wEAAwE;IACxE,0EAA0E;IAC1E,8EAA8E;IAC9E,IAAI,EAAE,CAAC,EACP,SAAS,EAAC,MAAM,EAChB,IAAI,EAAE,CAAC,EACP,KAAK,EAAC,MAAM,EACZ,QAAQ,EAAC,QAAQ,KACb,KAAK,YAER,QAAQ,GACF,CACV,CAAA;AAOD;;;;;;;GAOG;AACH,MAAM,IAAI,GAAG,CAAC,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,EAAE,GAAG,KAAK,EAAa,EAAE,EAAE,CAAC,CACjE,KAAC,MAAM,OACD,IAAI,CAAC,MAAM,CAAC,EAChB,IAAI,EAAE,CAAC,EACP,SAAS,EAAE,CAAC,EACZ,IAAI,EAAE,CAAC,EACP,KAAK,EAAC,MAAM,EACZ,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,KACjC,KAAK,YAER,QAAQ,GACF,CACV,CAAA;AAED,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,CAAA"}
package/dist/gallery.html CHANGED
@@ -1,4 +1,4 @@
1
- <!doctype html><html lang="en" class="t_dark"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>@hanzo/ui 8.1.17</title><style>/* @hanzo/ui — generated by scripts/gen-css.mjs. Do not edit. */
1
+ <!doctype html><html lang="en" class="t_dark"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>@hanzo/ui 8.1.19</title><style>/* @hanzo/ui — generated by scripts/gen-css.mjs. Do not edit. */
2
2
  :root { --hanzo-ui-styles: 1; }
3
3
  /* Hanzo Design System — the entry point. Import THIS one file.
4
4
  *
@@ -1953,6 +1953,146 @@
1953
1953
  display: block;
1954
1954
  }
1955
1955
 
1956
+
1957
+ /* ─────────────────────────────────────────────────────────────────────────────
1958
+ Scrollbars, on the surfaces this package scrolls.
1959
+
1960
+ A scroll region is a component decision, so its scrollbar is one too. Left to
1961
+ the platform it is not neutral: on Linux/GTK Chrome draws a wide track with
1962
+ STEPPER ARROWS at both ends, and a dark product grows two grey buttons per
1963
+ scroll region — visible in chat's thread, its source strip and the composer at
1964
+ the same time. Windows draws a wide light track. macOS overlays a thin one and
1965
+ hides it, which is the behaviour the other two should have had.
1966
+
1967
+ So the package states it, and states it ONCE, for the five slots that actually
1968
+ scroll (measured, not guessed: textarea, fill, thread, sources-strip,
1969
+ composer-field). Scoping to our own slots is the point — a component library
1970
+ restyling the HOST's page scrollbars is taking a decision that is not its own.
1971
+
1972
+ `::-webkit-scrollbar-button { display: none }` is the line that removes the
1973
+ steppers; without it the arrows survive every other rule here. The thumb sits
1974
+ on the same alpha ladder as every other edge, so it lifts with its surface
1975
+ instead of being a fixed grey that only suits one theme.
1976
+ ───────────────────────────────────────────────────────────────────────────── */
1977
+ :where(
1978
+ [data-slot='fill'],
1979
+ [data-slot='thread'],
1980
+ [data-slot='sources-strip'],
1981
+ [data-slot='sidebar-scroll'],
1982
+ [data-slot='scroll-area-viewport'],
1983
+ [data-slot='textarea'],
1984
+ [data-slot='composer-field']
1985
+ ) {
1986
+ /* Firefox — no pseudo-elements, two properties, same intent. */
1987
+ scrollbar-width: thin;
1988
+ scrollbar-color: rgb(255 255 255 / 0.18) transparent;
1989
+ }
1990
+
1991
+ :where(
1992
+ [data-slot='fill'],
1993
+ [data-slot='thread'],
1994
+ [data-slot='sources-strip'],
1995
+ [data-slot='sidebar-scroll'],
1996
+ [data-slot='scroll-area-viewport'],
1997
+ [data-slot='textarea'],
1998
+ [data-slot='composer-field']
1999
+ )::-webkit-scrollbar {
2000
+ width: 8px;
2001
+ height: 8px;
2002
+ }
2003
+
2004
+ /* The steppers. This is the rule that removes the arrows. */
2005
+ :where(
2006
+ [data-slot='fill'],
2007
+ [data-slot='thread'],
2008
+ [data-slot='sources-strip'],
2009
+ [data-slot='sidebar-scroll'],
2010
+ [data-slot='scroll-area-viewport'],
2011
+ [data-slot='textarea'],
2012
+ [data-slot='composer-field']
2013
+ )::-webkit-scrollbar-button {
2014
+ display: none;
2015
+ width: 0;
2016
+ height: 0;
2017
+ }
2018
+
2019
+ :where(
2020
+ [data-slot='fill'],
2021
+ [data-slot='thread'],
2022
+ [data-slot='sources-strip'],
2023
+ [data-slot='sidebar-scroll'],
2024
+ [data-slot='scroll-area-viewport'],
2025
+ [data-slot='textarea'],
2026
+ [data-slot='composer-field']
2027
+ )::-webkit-scrollbar-track {
2028
+ background: transparent;
2029
+ }
2030
+
2031
+ :where(
2032
+ [data-slot='fill'],
2033
+ [data-slot='thread'],
2034
+ [data-slot='sources-strip'],
2035
+ [data-slot='sidebar-scroll'],
2036
+ [data-slot='scroll-area-viewport'],
2037
+ [data-slot='textarea'],
2038
+ [data-slot='composer-field']
2039
+ )::-webkit-scrollbar-thumb {
2040
+ background: rgb(255 255 255 / 0.18);
2041
+ border-radius: 999px;
2042
+ /* A transparent border with background-clip keeps the thumb off the very edge
2043
+ without a track colour doing it, which is what makes it read as an overlay
2044
+ rather than a channel. */
2045
+ border: 2px solid transparent;
2046
+ background-clip: content-box;
2047
+ }
2048
+
2049
+ :where(
2050
+ [data-slot='fill'],
2051
+ [data-slot='thread'],
2052
+ [data-slot='sources-strip'],
2053
+ [data-slot='sidebar-scroll'],
2054
+ [data-slot='scroll-area-viewport'],
2055
+ [data-slot='textarea'],
2056
+ [data-slot='composer-field']
2057
+ )::-webkit-scrollbar-thumb:hover {
2058
+ background: rgb(255 255 255 / 0.30);
2059
+ background-clip: content-box;
2060
+ }
2061
+
2062
+ /* The light theme reads the same ladder from the other side. */
2063
+ .t_light :where(
2064
+ [data-slot='fill'],
2065
+ [data-slot='thread'],
2066
+ [data-slot='sources-strip'],
2067
+ [data-slot='sidebar-scroll'],
2068
+ [data-slot='scroll-area-viewport'],
2069
+ [data-slot='textarea'],
2070
+ [data-slot='composer-field']
2071
+ ) {
2072
+ scrollbar-color: rgb(0 0 0 / 0.20) transparent;
2073
+ }
2074
+
2075
+ .t_light :where(
2076
+ [data-slot='fill'],
2077
+ [data-slot='thread'],
2078
+ [data-slot='sources-strip'],
2079
+ [data-slot='sidebar-scroll'],
2080
+ [data-slot='scroll-area-viewport'],
2081
+ [data-slot='textarea'],
2082
+ [data-slot='composer-field']
2083
+ )::-webkit-scrollbar-thumb {
2084
+ background: rgb(0 0 0 / 0.20);
2085
+ background-clip: content-box;
2086
+ }
2087
+
2088
+ /* The textarea's resize grip is the other platform artefact in the same family:
2089
+ a diagonal hatch in the corner of every Textarea and composer, drawn by the UA
2090
+ and matching nothing. A composer that grows with its content does not need a
2091
+ drag handle, and one that does not grow should not offer a broken one. */
2092
+ :where([data-slot='textarea'], [data-slot='composer-field']) {
2093
+ resize: none;
2094
+ }
2095
+
1956
2096
  ._ovs-contain {overscroll-behavior:contain;}
1957
2097
  .t_unmounted .is_View, .t_unmounted .is_Text { transition: none !important; }
1958
2098
  .is_View { display: flex; align-items: stretch; flex-direction: column; flex-basis: auto; box-sizing: border-box; min-height: 0; min-width: 0; flex-shrink: 0; }
@@ -264,3 +264,143 @@
264
264
  object-fit: cover;
265
265
  display: block;
266
266
  }
267
+
268
+
269
+ /* ─────────────────────────────────────────────────────────────────────────────
270
+ Scrollbars, on the surfaces this package scrolls.
271
+
272
+ A scroll region is a component decision, so its scrollbar is one too. Left to
273
+ the platform it is not neutral: on Linux/GTK Chrome draws a wide track with
274
+ STEPPER ARROWS at both ends, and a dark product grows two grey buttons per
275
+ scroll region — visible in chat's thread, its source strip and the composer at
276
+ the same time. Windows draws a wide light track. macOS overlays a thin one and
277
+ hides it, which is the behaviour the other two should have had.
278
+
279
+ So the package states it, and states it ONCE, for the five slots that actually
280
+ scroll (measured, not guessed: textarea, fill, thread, sources-strip,
281
+ composer-field). Scoping to our own slots is the point — a component library
282
+ restyling the HOST's page scrollbars is taking a decision that is not its own.
283
+
284
+ `::-webkit-scrollbar-button { display: none }` is the line that removes the
285
+ steppers; without it the arrows survive every other rule here. The thumb sits
286
+ on the same alpha ladder as every other edge, so it lifts with its surface
287
+ instead of being a fixed grey that only suits one theme.
288
+ ───────────────────────────────────────────────────────────────────────────── */
289
+ :where(
290
+ [data-slot='fill'],
291
+ [data-slot='thread'],
292
+ [data-slot='sources-strip'],
293
+ [data-slot='sidebar-scroll'],
294
+ [data-slot='scroll-area-viewport'],
295
+ [data-slot='textarea'],
296
+ [data-slot='composer-field']
297
+ ) {
298
+ /* Firefox — no pseudo-elements, two properties, same intent. */
299
+ scrollbar-width: thin;
300
+ scrollbar-color: rgb(255 255 255 / 0.18) transparent;
301
+ }
302
+
303
+ :where(
304
+ [data-slot='fill'],
305
+ [data-slot='thread'],
306
+ [data-slot='sources-strip'],
307
+ [data-slot='sidebar-scroll'],
308
+ [data-slot='scroll-area-viewport'],
309
+ [data-slot='textarea'],
310
+ [data-slot='composer-field']
311
+ )::-webkit-scrollbar {
312
+ width: 8px;
313
+ height: 8px;
314
+ }
315
+
316
+ /* The steppers. This is the rule that removes the arrows. */
317
+ :where(
318
+ [data-slot='fill'],
319
+ [data-slot='thread'],
320
+ [data-slot='sources-strip'],
321
+ [data-slot='sidebar-scroll'],
322
+ [data-slot='scroll-area-viewport'],
323
+ [data-slot='textarea'],
324
+ [data-slot='composer-field']
325
+ )::-webkit-scrollbar-button {
326
+ display: none;
327
+ width: 0;
328
+ height: 0;
329
+ }
330
+
331
+ :where(
332
+ [data-slot='fill'],
333
+ [data-slot='thread'],
334
+ [data-slot='sources-strip'],
335
+ [data-slot='sidebar-scroll'],
336
+ [data-slot='scroll-area-viewport'],
337
+ [data-slot='textarea'],
338
+ [data-slot='composer-field']
339
+ )::-webkit-scrollbar-track {
340
+ background: transparent;
341
+ }
342
+
343
+ :where(
344
+ [data-slot='fill'],
345
+ [data-slot='thread'],
346
+ [data-slot='sources-strip'],
347
+ [data-slot='sidebar-scroll'],
348
+ [data-slot='scroll-area-viewport'],
349
+ [data-slot='textarea'],
350
+ [data-slot='composer-field']
351
+ )::-webkit-scrollbar-thumb {
352
+ background: rgb(255 255 255 / 0.18);
353
+ border-radius: 999px;
354
+ /* A transparent border with background-clip keeps the thumb off the very edge
355
+ without a track colour doing it, which is what makes it read as an overlay
356
+ rather than a channel. */
357
+ border: 2px solid transparent;
358
+ background-clip: content-box;
359
+ }
360
+
361
+ :where(
362
+ [data-slot='fill'],
363
+ [data-slot='thread'],
364
+ [data-slot='sources-strip'],
365
+ [data-slot='sidebar-scroll'],
366
+ [data-slot='scroll-area-viewport'],
367
+ [data-slot='textarea'],
368
+ [data-slot='composer-field']
369
+ )::-webkit-scrollbar-thumb:hover {
370
+ background: rgb(255 255 255 / 0.30);
371
+ background-clip: content-box;
372
+ }
373
+
374
+ /* The light theme reads the same ladder from the other side. */
375
+ .t_light :where(
376
+ [data-slot='fill'],
377
+ [data-slot='thread'],
378
+ [data-slot='sources-strip'],
379
+ [data-slot='sidebar-scroll'],
380
+ [data-slot='scroll-area-viewport'],
381
+ [data-slot='textarea'],
382
+ [data-slot='composer-field']
383
+ ) {
384
+ scrollbar-color: rgb(0 0 0 / 0.20) transparent;
385
+ }
386
+
387
+ .t_light :where(
388
+ [data-slot='fill'],
389
+ [data-slot='thread'],
390
+ [data-slot='sources-strip'],
391
+ [data-slot='sidebar-scroll'],
392
+ [data-slot='scroll-area-viewport'],
393
+ [data-slot='textarea'],
394
+ [data-slot='composer-field']
395
+ )::-webkit-scrollbar-thumb {
396
+ background: rgb(0 0 0 / 0.20);
397
+ background-clip: content-box;
398
+ }
399
+
400
+ /* The textarea's resize grip is the other platform artefact in the same family:
401
+ a diagonal hatch in the corner of every Textarea and composer, drawn by the UA
402
+ and matching nothing. A composer that grows with its content does not need a
403
+ drag handle, and one that does not grow should not offer a broken one. */
404
+ :where([data-slot='textarea'], [data-slot='composer-field']) {
405
+ resize: none;
406
+ }
package/dist/styles.css CHANGED
@@ -1953,6 +1953,146 @@
1953
1953
  display: block;
1954
1954
  }
1955
1955
 
1956
+
1957
+ /* ─────────────────────────────────────────────────────────────────────────────
1958
+ Scrollbars, on the surfaces this package scrolls.
1959
+
1960
+ A scroll region is a component decision, so its scrollbar is one too. Left to
1961
+ the platform it is not neutral: on Linux/GTK Chrome draws a wide track with
1962
+ STEPPER ARROWS at both ends, and a dark product grows two grey buttons per
1963
+ scroll region — visible in chat's thread, its source strip and the composer at
1964
+ the same time. Windows draws a wide light track. macOS overlays a thin one and
1965
+ hides it, which is the behaviour the other two should have had.
1966
+
1967
+ So the package states it, and states it ONCE, for the five slots that actually
1968
+ scroll (measured, not guessed: textarea, fill, thread, sources-strip,
1969
+ composer-field). Scoping to our own slots is the point — a component library
1970
+ restyling the HOST's page scrollbars is taking a decision that is not its own.
1971
+
1972
+ `::-webkit-scrollbar-button { display: none }` is the line that removes the
1973
+ steppers; without it the arrows survive every other rule here. The thumb sits
1974
+ on the same alpha ladder as every other edge, so it lifts with its surface
1975
+ instead of being a fixed grey that only suits one theme.
1976
+ ───────────────────────────────────────────────────────────────────────────── */
1977
+ :where(
1978
+ [data-slot='fill'],
1979
+ [data-slot='thread'],
1980
+ [data-slot='sources-strip'],
1981
+ [data-slot='sidebar-scroll'],
1982
+ [data-slot='scroll-area-viewport'],
1983
+ [data-slot='textarea'],
1984
+ [data-slot='composer-field']
1985
+ ) {
1986
+ /* Firefox — no pseudo-elements, two properties, same intent. */
1987
+ scrollbar-width: thin;
1988
+ scrollbar-color: rgb(255 255 255 / 0.18) transparent;
1989
+ }
1990
+
1991
+ :where(
1992
+ [data-slot='fill'],
1993
+ [data-slot='thread'],
1994
+ [data-slot='sources-strip'],
1995
+ [data-slot='sidebar-scroll'],
1996
+ [data-slot='scroll-area-viewport'],
1997
+ [data-slot='textarea'],
1998
+ [data-slot='composer-field']
1999
+ )::-webkit-scrollbar {
2000
+ width: 8px;
2001
+ height: 8px;
2002
+ }
2003
+
2004
+ /* The steppers. This is the rule that removes the arrows. */
2005
+ :where(
2006
+ [data-slot='fill'],
2007
+ [data-slot='thread'],
2008
+ [data-slot='sources-strip'],
2009
+ [data-slot='sidebar-scroll'],
2010
+ [data-slot='scroll-area-viewport'],
2011
+ [data-slot='textarea'],
2012
+ [data-slot='composer-field']
2013
+ )::-webkit-scrollbar-button {
2014
+ display: none;
2015
+ width: 0;
2016
+ height: 0;
2017
+ }
2018
+
2019
+ :where(
2020
+ [data-slot='fill'],
2021
+ [data-slot='thread'],
2022
+ [data-slot='sources-strip'],
2023
+ [data-slot='sidebar-scroll'],
2024
+ [data-slot='scroll-area-viewport'],
2025
+ [data-slot='textarea'],
2026
+ [data-slot='composer-field']
2027
+ )::-webkit-scrollbar-track {
2028
+ background: transparent;
2029
+ }
2030
+
2031
+ :where(
2032
+ [data-slot='fill'],
2033
+ [data-slot='thread'],
2034
+ [data-slot='sources-strip'],
2035
+ [data-slot='sidebar-scroll'],
2036
+ [data-slot='scroll-area-viewport'],
2037
+ [data-slot='textarea'],
2038
+ [data-slot='composer-field']
2039
+ )::-webkit-scrollbar-thumb {
2040
+ background: rgb(255 255 255 / 0.18);
2041
+ border-radius: 999px;
2042
+ /* A transparent border with background-clip keeps the thumb off the very edge
2043
+ without a track colour doing it, which is what makes it read as an overlay
2044
+ rather than a channel. */
2045
+ border: 2px solid transparent;
2046
+ background-clip: content-box;
2047
+ }
2048
+
2049
+ :where(
2050
+ [data-slot='fill'],
2051
+ [data-slot='thread'],
2052
+ [data-slot='sources-strip'],
2053
+ [data-slot='sidebar-scroll'],
2054
+ [data-slot='scroll-area-viewport'],
2055
+ [data-slot='textarea'],
2056
+ [data-slot='composer-field']
2057
+ )::-webkit-scrollbar-thumb:hover {
2058
+ background: rgb(255 255 255 / 0.30);
2059
+ background-clip: content-box;
2060
+ }
2061
+
2062
+ /* The light theme reads the same ladder from the other side. */
2063
+ .t_light :where(
2064
+ [data-slot='fill'],
2065
+ [data-slot='thread'],
2066
+ [data-slot='sources-strip'],
2067
+ [data-slot='sidebar-scroll'],
2068
+ [data-slot='scroll-area-viewport'],
2069
+ [data-slot='textarea'],
2070
+ [data-slot='composer-field']
2071
+ ) {
2072
+ scrollbar-color: rgb(0 0 0 / 0.20) transparent;
2073
+ }
2074
+
2075
+ .t_light :where(
2076
+ [data-slot='fill'],
2077
+ [data-slot='thread'],
2078
+ [data-slot='sources-strip'],
2079
+ [data-slot='sidebar-scroll'],
2080
+ [data-slot='scroll-area-viewport'],
2081
+ [data-slot='textarea'],
2082
+ [data-slot='composer-field']
2083
+ )::-webkit-scrollbar-thumb {
2084
+ background: rgb(0 0 0 / 0.20);
2085
+ background-clip: content-box;
2086
+ }
2087
+
2088
+ /* The textarea's resize grip is the other platform artefact in the same family:
2089
+ a diagonal hatch in the corner of every Textarea and composer, drawn by the UA
2090
+ and matching nothing. A composer that grows with its content does not need a
2091
+ drag handle, and one that does not grow should not offer a broken one. */
2092
+ :where([data-slot='textarea'], [data-slot='composer-field']) {
2093
+ resize: none;
2094
+ }
2095
+
1956
2096
  ._ovs-contain {overscroll-behavior:contain;}
1957
2097
  .t_unmounted .is_View, .t_unmounted .is_Text { transition: none !important; }
1958
2098
  .is_View { display: flex; align-items: stretch; flex-direction: column; flex-basis: auto; box-sizing: border-box; min-height: 0; min-width: 0; flex-shrink: 0; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hanzo/ui",
3
- "version": "8.1.17",
3
+ "version": "8.1.19",
4
4
  "type": "module",
5
5
  "description": "Hanzo UI — the one canonical Hanzo component library, on @hanzo/gui + @hanzo/design. ONE substrate: every component renders through @hanzo/gui primitives, so the same import works on web, native (expo) and desktop (Tauri). Self-contained (theme.css), presentational, host-agnostic, clean-room.",
6
6
  "exports": {