@hanzo/ui 8.3.2 → 8.3.3

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/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.3.2</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.3.3</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
  *
@@ -840,33 +840,72 @@
840
840
  }
841
841
 
842
842
  /* ── tokens/fonts.css ─────────────────────────────────────── */
843
- /* Geist Sans + Geist Mono — the only two faces on Hanzo surfaces.
843
+ /* Zen — the only family on Hanzo surfaces, sans and mono.
844
844
  SELF-HOSTED. The faces ship inside this package (assets/fonts/*.woff2, two
845
- variable files, 141 KB total, SIL OFL-1.1 — see assets/fonts/LICENSE-Geist.txt).
846
-
847
- Why self-hosted rather than @import from fonts.googleapis.com:
845
+ variable files, 141 KB total, SIL OFL-1.1 — see assets/fonts/LICENSE-Zen.txt).
846
+
847
+ Zen is our own family, under the SIL Open Font License. The licence file
848
+ beside the binaries carries every copyright the OFL requires; nothing else in
849
+ this repository restates them, which is the whole of what §2 asks for.
850
+
851
+ SHIPPED here rather than @import-ed from `@hanzo/font`, and that is load
852
+ bearing. `@hanzo/ui` composes this file into the MIDDLE of its theme.css, and
853
+ CSS drops an @import that does not precede every other rule — measured, in
854
+ Chromium, on the built sheet: zero faces loaded and not one woff2 requested.
855
+ An @font-face has no such ordering rule, so declaring the faces is the only
856
+ form that survives being flattened into a larger stylesheet. `@hanzo/font`
857
+ remains the one place the faces are AUTHORED; this is a copy of its output,
858
+ the same way the colour tokens are copied rather than fetched.
859
+
860
+ Why self-hosted rather than a third-party CDN:
848
861
  - A sign-in page must not make a third-party request. hanzoai/id refused to
849
862
  import this file for exactly that reason, which split the token layer: id
850
863
  took the colours and not the typeface. Self-hosting removes the reason, so
851
864
  every surface can import styles.css unchanged.
852
- - The @import was a render-blocking request to a host we do not control, on
853
- the critical path of every surface, and it broke offline/air-gapped dev.
865
+ - It was a render-blocking request to a host we do not control, on the
866
+ critical path of every surface, and it broke offline/air-gapped dev.
854
867
  - One variable file per family replaces nine static weights, and it is fewer
855
- bytes than the CSS-then-woff2 round trip Google served.
868
+ bytes than the CSS-then-woff2 round trip.
856
869
 
857
870
  The url()s are relative to THIS file, so they resolve wherever the package is
858
- mounted — node_modules, a CDN, a copied dist — with no configuration. */
871
+ mounted — node_modules, a CDN, a copied dist — with no configuration.
872
+
873
+ `font-display: block`, NOT swap, and the difference is the whole brand. `swap`
874
+ paints the fallback IMMEDIATELY and repaints when the face lands, so every first
875
+ visit shows the platform's own sans for as long as the download takes — on Ubuntu
876
+ that is DejaVu, which looks nothing like us and is the single most common way a
877
+ Hanzo surface renders wrong. `block` holds the text invisible for a short period
878
+ (~3s) and then paints Zen, so the fallback is only ever reached when the face
879
+ genuinely fails to arrive. A held word is a moment; the wrong typeface is the
880
+ brand. The generic tail below stays for exactly that real-failure case. */
859
881
 
860
882
 
861
883
 
862
884
 
863
885
  :root{
864
- --font-sans:"Geist","Geist Sans",ui-sans-serif,system-ui,sans-serif;
886
+ --font-sans:"Zen",ui-sans-serif,system-ui,sans-serif;
865
887
  --font-display:var(--font-sans);
866
- --font-mono:"Geist Mono",ui-monospace,SFMono-Regular,monospace;
888
+ --font-mono:"Zen Mono",ui-monospace,SFMono-Regular,monospace;
867
889
  --font-serif:Georgia,serif;
868
- /* hanzo.ai sets these OpenType features on <body>. */
869
- --font-feature-settings:"ss01","ss02","cv01","cv02","cv03";
890
+ /* The default is Zen as drawn, and that is a decision rather than an omission.
891
+ `base.css` puts this on <body>, so whatever is here is the voice of every
892
+ surface in the estate — which is exactly why it should not carry a brand's.
893
+
894
+ It used to read `"ss01","ss02","cv01","cv02","cv03"`, of which FOUR did
895
+ nothing: Zen has no cv01/cv02/cv03 at all, and ss01 and ss02 both remap `a`,
896
+ so ss01 substitutes first and ss02 never matches the glyph it was written
897
+ for. The one that did work quietly gave Lux and Zoo the single-storey `a`
898
+ that belongs to Hanzo.
899
+
900
+ A brand sets its own voice by overriding THIS token — one knob, one place:
901
+ Hanzo "ss01" single-storey a, the neo-grotesque register
902
+ Lux "ss04" straight-leg R, to sit under the wordmark
903
+ Zoo normal the humanist default, the warmest of the three
904
+ Zen ships eleven sets; ss03 is a tailed l, ss05 a serifed I, ss06 an
905
+ alternate G and ss09 a slashed zero with a serif one. Kerning, ligatures and
906
+ contextual alternates are on by default in every browser and do not belong
907
+ in this list. */
908
+ --font-feature-settings:normal;
870
909
  }
871
910
 
872
911
  /* ── tokens/base.css ─────────────────────────────────────── */
@@ -1089,6 +1128,13 @@
1089
1128
  :where(*)::-webkit-scrollbar-thumb{background:var(--white-15);border-radius:var(--radius-full)}
1090
1129
  :where(*)::-webkit-scrollbar-thumb:hover{background:var(--white-30)}
1091
1130
  :where(*)::-webkit-scrollbar-corner{background:transparent}
1131
+ /* The stepper arrows, and they are a LINUX defect specifically. Chromium on
1132
+ macOS draws no buttons, so styling the track and thumb looks finished there
1133
+ and ships a classic GTK scrollbar — a boxed arrow at each end of every
1134
+ scroller, on both axes — to everyone on Ubuntu. Styling the other pseudos
1135
+ does not suppress them; only this does. Zero width AND height because the
1136
+ horizontal and vertical bars each read one of them. */
1137
+ :where(*)::-webkit-scrollbar-button{display:none;width:0;height:0}
1092
1138
  .light :where(*)::-webkit-scrollbar-thumb{background:rgb(0 0 0 / .18)}
1093
1139
  .light :where(*)::-webkit-scrollbar-thumb:hover{background:rgb(0 0 0 / .32)}
1094
1140
  }
package/dist/styles.css CHANGED
@@ -840,33 +840,72 @@
840
840
  }
841
841
 
842
842
  /* ── tokens/fonts.css ─────────────────────────────────────── */
843
- /* Geist Sans + Geist Mono — the only two faces on Hanzo surfaces.
843
+ /* Zen — the only family on Hanzo surfaces, sans and mono.
844
844
  SELF-HOSTED. The faces ship inside this package (assets/fonts/*.woff2, two
845
- variable files, 141 KB total, SIL OFL-1.1 — see assets/fonts/LICENSE-Geist.txt).
846
-
847
- Why self-hosted rather than @import from fonts.googleapis.com:
845
+ variable files, 141 KB total, SIL OFL-1.1 — see assets/fonts/LICENSE-Zen.txt).
846
+
847
+ Zen is our own family, under the SIL Open Font License. The licence file
848
+ beside the binaries carries every copyright the OFL requires; nothing else in
849
+ this repository restates them, which is the whole of what §2 asks for.
850
+
851
+ SHIPPED here rather than @import-ed from `@hanzo/font`, and that is load
852
+ bearing. `@hanzo/ui` composes this file into the MIDDLE of its theme.css, and
853
+ CSS drops an @import that does not precede every other rule — measured, in
854
+ Chromium, on the built sheet: zero faces loaded and not one woff2 requested.
855
+ An @font-face has no such ordering rule, so declaring the faces is the only
856
+ form that survives being flattened into a larger stylesheet. `@hanzo/font`
857
+ remains the one place the faces are AUTHORED; this is a copy of its output,
858
+ the same way the colour tokens are copied rather than fetched.
859
+
860
+ Why self-hosted rather than a third-party CDN:
848
861
  - A sign-in page must not make a third-party request. hanzoai/id refused to
849
862
  import this file for exactly that reason, which split the token layer: id
850
863
  took the colours and not the typeface. Self-hosting removes the reason, so
851
864
  every surface can import styles.css unchanged.
852
- - The @import was a render-blocking request to a host we do not control, on
853
- the critical path of every surface, and it broke offline/air-gapped dev.
865
+ - It was a render-blocking request to a host we do not control, on the
866
+ critical path of every surface, and it broke offline/air-gapped dev.
854
867
  - One variable file per family replaces nine static weights, and it is fewer
855
- bytes than the CSS-then-woff2 round trip Google served.
868
+ bytes than the CSS-then-woff2 round trip.
856
869
 
857
870
  The url()s are relative to THIS file, so they resolve wherever the package is
858
- mounted — node_modules, a CDN, a copied dist — with no configuration. */
871
+ mounted — node_modules, a CDN, a copied dist — with no configuration.
872
+
873
+ `font-display: block`, NOT swap, and the difference is the whole brand. `swap`
874
+ paints the fallback IMMEDIATELY and repaints when the face lands, so every first
875
+ visit shows the platform's own sans for as long as the download takes — on Ubuntu
876
+ that is DejaVu, which looks nothing like us and is the single most common way a
877
+ Hanzo surface renders wrong. `block` holds the text invisible for a short period
878
+ (~3s) and then paints Zen, so the fallback is only ever reached when the face
879
+ genuinely fails to arrive. A held word is a moment; the wrong typeface is the
880
+ brand. The generic tail below stays for exactly that real-failure case. */
859
881
 
860
882
 
861
883
 
862
884
 
863
885
  :root{
864
- --font-sans:"Geist","Geist Sans",ui-sans-serif,system-ui,sans-serif;
886
+ --font-sans:"Zen",ui-sans-serif,system-ui,sans-serif;
865
887
  --font-display:var(--font-sans);
866
- --font-mono:"Geist Mono",ui-monospace,SFMono-Regular,monospace;
888
+ --font-mono:"Zen Mono",ui-monospace,SFMono-Regular,monospace;
867
889
  --font-serif:Georgia,serif;
868
- /* hanzo.ai sets these OpenType features on <body>. */
869
- --font-feature-settings:"ss01","ss02","cv01","cv02","cv03";
890
+ /* The default is Zen as drawn, and that is a decision rather than an omission.
891
+ `base.css` puts this on <body>, so whatever is here is the voice of every
892
+ surface in the estate — which is exactly why it should not carry a brand's.
893
+
894
+ It used to read `"ss01","ss02","cv01","cv02","cv03"`, of which FOUR did
895
+ nothing: Zen has no cv01/cv02/cv03 at all, and ss01 and ss02 both remap `a`,
896
+ so ss01 substitutes first and ss02 never matches the glyph it was written
897
+ for. The one that did work quietly gave Lux and Zoo the single-storey `a`
898
+ that belongs to Hanzo.
899
+
900
+ A brand sets its own voice by overriding THIS token — one knob, one place:
901
+ Hanzo "ss01" single-storey a, the neo-grotesque register
902
+ Lux "ss04" straight-leg R, to sit under the wordmark
903
+ Zoo normal the humanist default, the warmest of the three
904
+ Zen ships eleven sets; ss03 is a tailed l, ss05 a serifed I, ss06 an
905
+ alternate G and ss09 a slashed zero with a serif one. Kerning, ligatures and
906
+ contextual alternates are on by default in every browser and do not belong
907
+ in this list. */
908
+ --font-feature-settings:normal;
870
909
  }
871
910
 
872
911
  /* ── tokens/base.css ─────────────────────────────────────── */
@@ -1089,6 +1128,13 @@
1089
1128
  :where(*)::-webkit-scrollbar-thumb{background:var(--white-15);border-radius:var(--radius-full)}
1090
1129
  :where(*)::-webkit-scrollbar-thumb:hover{background:var(--white-30)}
1091
1130
  :where(*)::-webkit-scrollbar-corner{background:transparent}
1131
+ /* The stepper arrows, and they are a LINUX defect specifically. Chromium on
1132
+ macOS draws no buttons, so styling the track and thumb looks finished there
1133
+ and ships a classic GTK scrollbar — a boxed arrow at each end of every
1134
+ scroller, on both axes — to everyone on Ubuntu. Styling the other pseudos
1135
+ does not suppress them; only this does. Zero width AND height because the
1136
+ horizontal and vertical bars each read one of them. */
1137
+ :where(*)::-webkit-scrollbar-button{display:none;width:0;height:0}
1092
1138
  .light :where(*)::-webkit-scrollbar-thumb{background:rgb(0 0 0 / .18)}
1093
1139
  .light :where(*)::-webkit-scrollbar-thumb:hover{background:rgb(0 0 0 / .32)}
1094
1140
  }
package/dist/theme.css CHANGED
@@ -838,33 +838,72 @@
838
838
  }
839
839
 
840
840
  /* ── tokens/fonts.css ─────────────────────────────────────── */
841
- /* Geist Sans + Geist Mono — the only two faces on Hanzo surfaces.
841
+ /* Zen — the only family on Hanzo surfaces, sans and mono.
842
842
  SELF-HOSTED. The faces ship inside this package (assets/fonts/*.woff2, two
843
- variable files, 141 KB total, SIL OFL-1.1 — see assets/fonts/LICENSE-Geist.txt).
844
-
845
- Why self-hosted rather than @import from fonts.googleapis.com:
843
+ variable files, 141 KB total, SIL OFL-1.1 — see assets/fonts/LICENSE-Zen.txt).
844
+
845
+ Zen is our own family, under the SIL Open Font License. The licence file
846
+ beside the binaries carries every copyright the OFL requires; nothing else in
847
+ this repository restates them, which is the whole of what §2 asks for.
848
+
849
+ SHIPPED here rather than @import-ed from `@hanzo/font`, and that is load
850
+ bearing. `@hanzo/ui` composes this file into the MIDDLE of its theme.css, and
851
+ CSS drops an @import that does not precede every other rule — measured, in
852
+ Chromium, on the built sheet: zero faces loaded and not one woff2 requested.
853
+ An @font-face has no such ordering rule, so declaring the faces is the only
854
+ form that survives being flattened into a larger stylesheet. `@hanzo/font`
855
+ remains the one place the faces are AUTHORED; this is a copy of its output,
856
+ the same way the colour tokens are copied rather than fetched.
857
+
858
+ Why self-hosted rather than a third-party CDN:
846
859
  - A sign-in page must not make a third-party request. hanzoai/id refused to
847
860
  import this file for exactly that reason, which split the token layer: id
848
861
  took the colours and not the typeface. Self-hosting removes the reason, so
849
862
  every surface can import styles.css unchanged.
850
- - The @import was a render-blocking request to a host we do not control, on
851
- the critical path of every surface, and it broke offline/air-gapped dev.
863
+ - It was a render-blocking request to a host we do not control, on the
864
+ critical path of every surface, and it broke offline/air-gapped dev.
852
865
  - One variable file per family replaces nine static weights, and it is fewer
853
- bytes than the CSS-then-woff2 round trip Google served.
866
+ bytes than the CSS-then-woff2 round trip.
854
867
 
855
868
  The url()s are relative to THIS file, so they resolve wherever the package is
856
- mounted — node_modules, a CDN, a copied dist — with no configuration. */
869
+ mounted — node_modules, a CDN, a copied dist — with no configuration.
870
+
871
+ `font-display: block`, NOT swap, and the difference is the whole brand. `swap`
872
+ paints the fallback IMMEDIATELY and repaints when the face lands, so every first
873
+ visit shows the platform's own sans for as long as the download takes — on Ubuntu
874
+ that is DejaVu, which looks nothing like us and is the single most common way a
875
+ Hanzo surface renders wrong. `block` holds the text invisible for a short period
876
+ (~3s) and then paints Zen, so the fallback is only ever reached when the face
877
+ genuinely fails to arrive. A held word is a moment; the wrong typeface is the
878
+ brand. The generic tail below stays for exactly that real-failure case. */
857
879
 
858
880
 
859
881
 
860
882
 
861
883
  :root{
862
- --font-sans:"Geist","Geist Sans",ui-sans-serif,system-ui,sans-serif;
884
+ --font-sans:"Zen",ui-sans-serif,system-ui,sans-serif;
863
885
  --font-display:var(--font-sans);
864
- --font-mono:"Geist Mono",ui-monospace,SFMono-Regular,monospace;
886
+ --font-mono:"Zen Mono",ui-monospace,SFMono-Regular,monospace;
865
887
  --font-serif:Georgia,serif;
866
- /* hanzo.ai sets these OpenType features on <body>. */
867
- --font-feature-settings:"ss01","ss02","cv01","cv02","cv03";
888
+ /* The default is Zen as drawn, and that is a decision rather than an omission.
889
+ `base.css` puts this on <body>, so whatever is here is the voice of every
890
+ surface in the estate — which is exactly why it should not carry a brand's.
891
+
892
+ It used to read `"ss01","ss02","cv01","cv02","cv03"`, of which FOUR did
893
+ nothing: Zen has no cv01/cv02/cv03 at all, and ss01 and ss02 both remap `a`,
894
+ so ss01 substitutes first and ss02 never matches the glyph it was written
895
+ for. The one that did work quietly gave Lux and Zoo the single-storey `a`
896
+ that belongs to Hanzo.
897
+
898
+ A brand sets its own voice by overriding THIS token — one knob, one place:
899
+ Hanzo "ss01" single-storey a, the neo-grotesque register
900
+ Lux "ss04" straight-leg R, to sit under the wordmark
901
+ Zoo normal the humanist default, the warmest of the three
902
+ Zen ships eleven sets; ss03 is a tailed l, ss05 a serifed I, ss06 an
903
+ alternate G and ss09 a slashed zero with a serif one. Kerning, ligatures and
904
+ contextual alternates are on by default in every browser and do not belong
905
+ in this list. */
906
+ --font-feature-settings:normal;
868
907
  }
869
908
 
870
909
  /* ── tokens/base.css ─────────────────────────────────────── */
@@ -1087,6 +1126,13 @@
1087
1126
  :where(*)::-webkit-scrollbar-thumb{background:var(--white-15);border-radius:var(--radius-full)}
1088
1127
  :where(*)::-webkit-scrollbar-thumb:hover{background:var(--white-30)}
1089
1128
  :where(*)::-webkit-scrollbar-corner{background:transparent}
1129
+ /* The stepper arrows, and they are a LINUX defect specifically. Chromium on
1130
+ macOS draws no buttons, so styling the track and thumb looks finished there
1131
+ and ships a classic GTK scrollbar — a boxed arrow at each end of every
1132
+ scroller, on both axes — to everyone on Ubuntu. Styling the other pseudos
1133
+ does not suppress them; only this does. Zero width AND height because the
1134
+ horizontal and vertical bars each read one of them. */
1135
+ :where(*)::-webkit-scrollbar-button{display:none;width:0;height:0}
1090
1136
  .light :where(*)::-webkit-scrollbar-thumb{background:rgb(0 0 0 / .18)}
1091
1137
  .light :where(*)::-webkit-scrollbar-thumb:hover{background:rgb(0 0 0 / .32)}
1092
1138
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hanzo/ui",
3
- "version": "8.3.2",
3
+ "version": "8.3.3",
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": {
@@ -211,11 +211,11 @@
211
211
  "dependencies": {
212
212
  "@hanzo/appearance": "^0.2.2",
213
213
  "@hanzo/brand": "^1.4.5",
214
- "@hanzo/design": "^0.5.18",
214
+ "@hanzo/design": "^0.5.21",
215
+ "@hanzo/font": "^1.8.2",
215
216
  "@hanzo/logo": "^1.0.13",
216
217
  "@hanzo/products": "^0.2.0",
217
- "clsx": "^2.1.1",
218
- "@hanzo/font": "^1.8.1"
218
+ "clsx": "^2.1.1"
219
219
  },
220
220
  "peerDependencies": {
221
221
  "@hanzo/canvas": ">=0.1.0",