@luxfi/ui 5.5.5 → 5.5.6

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 (65) hide show
  1. package/commerce/ui/context.tsx +13 -16
  2. package/components/access-code-input.tsx +3 -4
  3. package/components/analytics.tsx +8 -17
  4. package/components/auth/login-panel.tsx +7 -6
  5. package/components/auth/login.tsx +1 -1
  6. package/components/auth/widget.tsx +1 -1
  7. package/components/back-button.tsx +4 -7
  8. package/components/chat-widget.tsx +5 -6
  9. package/components/commerce/bag-button.tsx +8 -7
  10. package/components/commerce/buy-button.tsx +2 -3
  11. package/components/commerce/checkout-button.tsx +12 -10
  12. package/components/commerce/checkout-panel/cart-accordian.tsx +3 -4
  13. package/components/commerce/checkout-panel/desktop-cp.tsx +5 -6
  14. package/components/commerce/checkout-panel/index.tsx +1 -1
  15. package/components/commerce/checkout-panel/mobile-cp.tsx +4 -4
  16. package/components/commerce/checkout-panel/policy-links.tsx +7 -12
  17. package/components/commerce/checkout-panel/steps-indicator.tsx +1 -1
  18. package/components/commerce/desktop-bag-popup.tsx +1 -1
  19. package/components/commerce/drawer/micro.tsx +30 -30
  20. package/components/commerce/drawer/shell.tsx +3 -5
  21. package/components/contact-dialog/contact-form.tsx +6 -13
  22. package/components/contact-dialog/index.tsx +2 -2
  23. package/components/copyright.tsx +3 -2
  24. package/components/drawer-margin.tsx +2 -2
  25. package/components/footer.tsx +6 -7
  26. package/components/header/desktop-nav-menu.tsx +6 -6
  27. package/components/header/desktop.tsx +5 -5
  28. package/components/header/index.tsx +1 -1
  29. package/components/header/mobile-bag-drawer.tsx +1 -1
  30. package/components/header/mobile-menu-toggle-button.tsx +5 -6
  31. package/components/header/mobile-nav-menu-ai.tsx +13 -12
  32. package/components/header/mobile-nav-menu-item.tsx +12 -11
  33. package/components/header/mobile-nav-menu.tsx +17 -16
  34. package/components/header/mobile.tsx +7 -8
  35. package/components/icons/social-icon.tsx +1 -1
  36. package/components/logo.tsx +3 -2
  37. package/components/main.tsx +3 -4
  38. package/components/mini-chart/mini-chart.tsx +2 -1
  39. package/next/font/font-desc.ts +18 -0
  40. package/next/font/fonts.ts +40 -0
  41. package/next/font/get-app-router-font-classes.ts +14 -12
  42. package/next/font/load-and-return-lux-next-fonts-on-import.ts +16 -24
  43. package/next/font/local/Zen-Variable.woff2 +0 -0
  44. package/next/font/next-font-desc.ts +18 -17
  45. package/next/head-metadata/index.tsx +7 -6
  46. package/next/head-metadata/next-metadata.ts +49 -0
  47. package/package.json +9 -10
  48. package/root-layout/index.tsx +39 -19
  49. package/style/fonts/Zen-Variable.woff2 +0 -0
  50. package/style/lux-colors.css +0 -1
  51. package/style/lux-fonts.css +5 -11
  52. package/style/lux-global-non-next.css +9 -9
  53. package/style/lux-global.css +56 -21
  54. package/tsconfig.json +8 -0
  55. package/next/font/local/Druk-Wide-Bold.ttf +0 -0
  56. package/next/font/local/Druk-Wide-Medium.ttf +0 -0
  57. package/next/head-metadata/from-next/metadata-types.ts +0 -158
  58. package/next/head-metadata/from-next/opengraph-types.ts +0 -267
  59. package/next/head-metadata/from-next/twitter-types.ts +0 -92
  60. package/style/fonts/Druk-Wide-Bold.ttf +0 -0
  61. package/style/fonts/Druk-Wide-Medium.ttf +0 -0
  62. package/tailwind/fontFamily.tailwind.lux.ts +0 -18
  63. package/tailwind/index.ts +0 -2
  64. package/tailwind/lux-tw-fonts.ts +0 -40
  65. package/tailwind/tailwind.config.lux-preset.ts +0 -10
@@ -3,8 +3,7 @@ import React, { useState, useEffect } from 'react'
3
3
  import { useRouter } from 'next/navigation'
4
4
 
5
5
  import type { LinkDef } from '@hanzo/ui/types'
6
- import { cn } from '@hanzo/ui/util'
7
-
6
+ import { Box, cn } from '@hanzo/ui'
8
7
  import { CartPanel, useCommerce } from '@hanzo/commerce'
9
8
  import Login from '../auth/login'
10
9
  import sendGAEvent from '../../next/analytics/google-analytics'
@@ -89,7 +88,7 @@ const MobileHeader: React.FC<{
89
88
  }
90
89
  // header element MUST be fixed, and NOT sticky. Or else drawer breaks on mobile browsers
91
90
  return (<>
92
- <header id='MOBILE_HEADER' className={cn(
91
+ <Box tag="header" id='MOBILE_HEADER' className={cn(
93
92
  `bg-background fixed z-header top-0 left-0 w-full ${menuOpen() ? 'hidden' : 'block'}`,
94
93
  className
95
94
  )}>
@@ -99,12 +98,12 @@ const MobileHeader: React.FC<{
99
98
  {/* Not that key to the cross-fade effect
100
99
  is that this is **on top of** the logo. */}
101
100
  {menuOpen() && (
102
- <div className={'absolute left-0 top-0 bottom-0 right-0 pl-8 ' +
101
+ <Box className={'absolute left-0 top-0 bottom-0 right-0 pl-8 ' +
103
102
  'flex flex-row ' +
104
103
  'bg-background animate-mobile-menu-open'
105
104
  }>
106
105
  <Avatar className='self-center ' />
107
- </div>
106
+ </Box>
108
107
  )}
109
108
  <div className='flex gap-0 flex-row'>
110
109
  <BagButton className='text-primary -mr-[3px]' onClick={openBag} />
@@ -112,7 +111,7 @@ const MobileHeader: React.FC<{
112
111
  </div>
113
112
 
114
113
  </div>
115
- </header>
114
+ </Box>
116
115
  {!noCommerce && (
117
116
  <MobileBagDrawer
118
117
  className=''
@@ -123,7 +122,7 @@ const MobileHeader: React.FC<{
123
122
  )}
124
123
 
125
124
  {menuOpen() && (
126
- <div className={
125
+ <Box className={
127
126
  'fixed top-0 left-0 w-full h-full ' +
128
127
  // z must below header itself
129
128
  'flex flex-column bg-background z-below-header animate-mobile-menu-open'
@@ -162,7 +161,7 @@ const MobileHeader: React.FC<{
162
161
  />
163
162
  )
164
163
  )}
165
- </div>
164
+ </Box>
166
165
  ) /* menuOpen */}
167
166
  </>)
168
167
  }
@@ -2,7 +2,7 @@ import React from 'react'
2
2
 
3
3
  import { SocialIcon as BaseSocialIcon } from 'react-social-icons'
4
4
 
5
- import { cn } from '@hanzo/ui/util'
5
+ import { cn } from '@hanzo/ui'
6
6
  import './social-svg.css'
7
7
 
8
8
  interface SocialIconProps {
@@ -1,4 +1,5 @@
1
1
  import React from 'react'
2
+ import { Box, css } from '@hanzo/ui'
2
3
  import Link from 'next/link'
3
4
 
4
5
  import { type TShirtSize } from '@hanzo/ui/types'
@@ -52,9 +53,9 @@ const Logo: React.FC<{
52
53
  </>)
53
54
 
54
55
  return href ? (
55
- <Link href={href} className={clx} onClick={onClick}>{art}</Link>
56
+ <Link href={href} style={css(clx)} onClick={onClick}>{art}</Link>
56
57
  ) : (
57
- <span className={clx} onClick={onClick}>{art}</span>
58
+ <Box tag="span" className={clx} onClick={onClick}>{art}</Box>
58
59
  )
59
60
  }
60
61
 
@@ -1,6 +1,5 @@
1
1
  import React, { type PropsWithChildren } from 'react'
2
- import { cn } from '@hanzo/ui/util'
3
-
2
+ import { Box, cn } from '@hanzo/ui'
4
3
  const Main: React.FC<PropsWithChildren & {
5
4
  id?: string
6
5
  className?: string
@@ -13,7 +12,7 @@ const Main: React.FC<PropsWithChildren & {
13
12
  standardWidth=true,
14
13
  id
15
14
  }) => (
16
- <main id={id ?? 'LUX_UI_MAIN'} className={cn(
15
+ <Box tag="main" id={id ?? 'LUX_UI_MAIN'} className={cn(
17
16
  'flex flex-col justify-start items-center',
18
17
  'px-4 md:px-6 lg:px-8',
19
18
  standardWidth ? 'max-w-screen-2xl w-full lg:mx-auto' : '',
@@ -21,7 +20,7 @@ const Main: React.FC<PropsWithChildren & {
21
20
  className
22
21
  )}>
23
22
  {children}
24
- </main>
23
+ </Box>
25
24
  )
26
25
 
27
26
  export default Main
@@ -1,6 +1,7 @@
1
1
  'use client'
2
2
 
3
3
  import React, { useEffect, useRef } from 'react'
4
+ import { Box } from '@hanzo/ui'
4
5
  import { type MiniChartProps } from './mini-chart-props'
5
6
 
6
7
  const MiniChart: React.FC<MiniChartProps> = ({
@@ -77,7 +78,7 @@ const MiniChart: React.FC<MiniChartProps> = ({
77
78
  <div style={containerStyles} className='tradingview-widget-container h-[150px]' ref={containerRef} />
78
79
  <div className='tradingview-widget-copyright border-t w-full invisible'>
79
80
  <a href={`https://www.tradingview.com/symbols/${symbol}${exchange ? `/?exchange=${exchange}` : '' }`} rel="noopener" target="_blank">
80
- <span className="text-[--hz-ui-primary]">{symbol} quotes</span></a>&nbsp;by TradingView
81
+ <Box tag="span" className="text-[--hz-ui-primary]">{symbol} quotes</Box></a>&nbsp;by TradingView
81
82
  </div>
82
83
  </>)
83
84
  }
@@ -0,0 +1,18 @@
1
+ /**
2
+ * A font in this site's vocabulary.
3
+ *
4
+ * `name` is the ROLE the font plays — `sans`, `nav`, `heading`, `serif`, `mono`
5
+ * — not a file and not a family. The stack is what the browser resolves, and
6
+ * `cssVar` is the custom property the next/font loader publishes the loaded
7
+ * face under, so the stack can point at it.
8
+ *
9
+ * It lived in a Tailwind preset and was called `TwFontDesc`, which named the
10
+ * engine that happened to read it rather than what it is. The engine is gone;
11
+ * the fonts are not.
12
+ */
13
+ export type FontDesc = {
14
+ /** The role: `sans`, `nav`, `heading`, `serif`, `mono`. */
15
+ name: string
16
+ fontFamily: string[]
17
+ cssVar?: string
18
+ }
@@ -0,0 +1,40 @@
1
+ import type { FontDesc } from './font-desc'
2
+
3
+
4
+ /* Read by ./load-and-return-lux-next-fonts-on-import.ts */
5
+
6
+ export default [
7
+ {
8
+ fontFamily: ['var(--font-inter)'], // do not provide fall-backs due to next bug
9
+ cssVar: '--font-inter',
10
+ name: 'sans'
11
+ },
12
+ {
13
+ fontFamily: ['var(--font-inter)'], // do not provide fall-backs due to next bug
14
+ cssVar: '--font-inter',
15
+ name: 'nav'
16
+ },
17
+ {
18
+ fontFamily: ['var(--font-zen-sans)'], // do not provide fall-backs due to next bug
19
+ cssVar: '--font-zen-sans',
20
+ name: 'heading'
21
+ },
22
+ {
23
+ name: 'serif',
24
+ fontFamily: ['ui-serif', 'Georgia', 'Cambria', '"Times New Roman"', 'Times']
25
+ },
26
+ {
27
+ name: 'mono',
28
+ fontFamily: [
29
+ 'ui-monospace',
30
+ 'SFMono-Regular',
31
+ 'Menlo',
32
+ 'Monaco',
33
+ 'Consolas',
34
+ '"Liberation Mono"',
35
+ '"Courier New"',
36
+ 'monospace',
37
+ ]
38
+ }
39
+
40
+ ] as FontDesc[]
@@ -1,17 +1,19 @@
1
1
  import nextFonts from './load-and-return-lux-next-fonts-on-import'
2
2
  import type NextFontDesc from './next-font-desc'
3
3
 
4
- // These will be injected for <body> in app router app that uses our RootLayout
5
-
6
- // First is assumed to be mapped to the default font and is injected into <body>
7
- // as a normal tw font family class.
4
+ /**
5
+ * next/font's own generated class names, for <body> in an app-router app using
6
+ * our RootLayout.
7
+ *
8
+ * Each one DEFINES a custom property holding the face it loaded, so they have
9
+ * to land on an element before anything can name `var(--font-inter)`.
10
+ *
11
+ * It used to append `font-<role>` for the default face as well. That was a
12
+ * utility class, and with no engine generating it the body had a name no sheet
13
+ * served — the family is set on `body` in lux-global.css instead, where it can
14
+ * point at the property these classes define.
15
+ */
8
16
  export default () => {
9
- let nf = nextFonts.map((desc: NextFontDesc) => (desc.nextFont!.variable))
10
- // dedupe
11
- nf = nf.filter(
12
- (str, i, arr) => (
13
- arr.indexOf(str) === i
14
- )
15
- )
16
- return nf.join(' ') + ` font-${nextFonts[0].twName}`
17
+ const named = nextFonts.map((desc: NextFontDesc) => desc.nextFont!.variable)
18
+ return [...new Set(named)].join(' ')
17
19
  }
@@ -1,13 +1,13 @@
1
1
  // import { Inter } from 'next/font/google'
2
2
  import localFont from 'next/font/local'
3
3
 
4
- import type { TwFontDesc } from '@hanzo/ui/tailwind' // TODO
4
+ import type { FontDesc } from './font-desc'
5
5
  import type NextFontDesc from './next-font-desc'
6
6
 
7
- import twFonts from '../../tailwind/lux-tw-fonts'
7
+ import fonts from './fonts'
8
8
 
9
9
  /*
10
- Creating NextFontDesc's and TwFontDesc's has to be seperated because they are needed
10
+ Creating NextFontDesc's and FontDesc's has to be seperated because they are needed
11
11
  at different times during the next compile / build. Otherwise a nasty
12
12
  race condition happens!
13
13
 
@@ -15,21 +15,11 @@ import twFonts from '../../tailwind/lux-tw-fonts'
15
15
 
16
16
  */
17
17
 
18
- const drukWide = localFont({
19
- src: [
20
- {
21
- path: './local/Druk-Wide-Bold.ttf',
22
- weight: '700',
23
- style: 'normal'
24
- },
25
- {
26
- path: './local/Druk-Wide-Medium.ttf',
27
- weight: '500',
28
- style: 'normal',
29
- },
30
- ],
18
+ const zen = localFont({
19
+ src: './local/Zen-Variable.woff2',
20
+ weight: '100 900',
31
21
  display: 'swap',
32
- variable: '--font-druk-wide',
22
+ variable: '--font-zen-sans',
33
23
  })
34
24
 
35
25
  const inter = localFont({
@@ -41,25 +31,27 @@ const inter = localFont({
41
31
  export default [
42
32
  {
43
33
  font: inter,
44
- twName: 'sans'
34
+ name: 'sans'
45
35
  },
46
36
  {
47
37
  font: inter,
48
- twName: 'nav'
38
+ name: 'nav'
49
39
  },
50
40
  {
51
- font: drukWide,
52
- twName: 'heading'
41
+ // Zen is one variable face over 100-900, so the display cut is weight and
42
+ // tracking in CSS rather than a second file: '.font-heading' in style/lux-global.css.
43
+ font: zen,
44
+ name: 'heading'
53
45
  }
54
46
  ].map (
55
47
  (el) => {
56
- const twFont: TwFontDesc | undefined = twFonts.find((twf: TwFontDesc) => (el.twName === twf.twName))
57
- if (!twFont) {
48
+ const font: FontDesc | undefined = fonts.find((f: FontDesc) => (el.name === f.name))
49
+ if (!font) {
58
50
  throw new Error('lux-next-fonts: Next font is not paired to a TW font!')
59
51
  }
60
52
 
61
53
  return ({
62
- ...twFont,
54
+ ...font,
63
55
  nextFont: el.font,
64
56
  })
65
57
  }
@@ -1,28 +1,29 @@
1
- import type { TwFontDesc } from '@hanzo/ui/tailwind'
1
+ import type localFont from 'next/font/local'
2
2
 
3
- // from next repo
4
- type NextFont = {
5
- className: string
6
- style: { fontFamily: string; fontWeight?: number; fontStyle?: string }
7
- }
8
-
9
- // from next repo
10
- type NextFontWithVariable = NextFont & {
11
- variable: string
12
- }
3
+ import type { FontDesc } from './font-desc'
13
4
 
5
+ /**
6
+ * What a next/font loader hands back, DERIVED from the loader.
7
+ *
8
+ * These were two hand-copied declarations marked "from next repo" — a copy of a
9
+ * type that keeps moving, which is how the OpenGraph types in ../head-metadata
10
+ * went stale and failed as "two different types with this name exist, but they
11
+ * are unrelated". `ReturnType` names the position and lets Next say what lives
12
+ * there. The loader answers with a union — a font is only given a variable
13
+ * when it was asked for one — so `Extract` picks the half that has it.
14
+ */
15
+ export type NextFontWithVariable = Extract<ReturnType<typeof localFont>, { variable: string }>
14
16
 
15
17
  /*
16
- NextFontDesc and TwFontDesc have to be seperate because they are needed
17
- at different times during the next compile / build. Otherwise a nasty
18
+ NextFontDesc and FontDesc have to be seperate because they are needed
19
+ at different times during the next compile / build. Otherwise a nasty
18
20
  race condition happens! That's why they are in different files.
19
21
  */
20
22
 
21
- interface NextFontDesc extends TwFontDesc {
22
- nextFont: NextFontWithVariable
23
+ interface NextFontDesc extends FontDesc {
24
+ nextFont: NextFontWithVariable
23
25
  }
24
26
 
25
27
  export {
26
28
  type NextFontDesc as default,
27
- type NextFontWithVariable,
28
- }
29
+ }
@@ -4,14 +4,15 @@ import type { Metadata } from 'next'
4
4
  import Head from "next/head"
5
5
 
6
6
  import type {
7
+ Author,
7
8
  IconDescriptor,
9
+ OGImage,
10
+ OpenGraph,
8
11
  TemplateString,
9
- Author,
10
- ThemeColorDescriptor
11
- } from './from-next/metadata-types'
12
-
13
- import type { OpenGraph, OGImage } from './from-next/opengraph-types'
14
- import type { Twitter, TwitterImage } from './from-next/twitter-types'
12
+ ThemeColorDescriptor,
13
+ Twitter,
14
+ TwitterImage,
15
+ } from './next-metadata'
15
16
 
16
17
  /*
17
18
  NOTE: This is ONLY for sites that use the pages router in next.
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Next's metadata vocabulary, DERIVED from Next's own `Metadata` type.
3
+ *
4
+ * These were three files of hand-copied declarations under `from-next/`, which
5
+ * is a copy of a type that keeps moving: Next 16 changed `OpenGraph` and the
6
+ * copy stayed where it was, so passing `metadata.openGraph` into a component
7
+ * typed against the copy failed with
8
+ *
9
+ * Two different types with this name exist, but they are unrelated.
10
+ *
11
+ * — a message that reads like a duplicate package rather than a stale copy.
12
+ *
13
+ * Derivation cannot drift. Nothing here restates a shape; each line names a
14
+ * position inside `Metadata` and lets Next say what lives there.
15
+ */
16
+ import type { Metadata } from 'next'
17
+
18
+ /** The element type of an array, or the type itself when it is not one. */
19
+ type Item<T> = T extends readonly (infer E)[] ? E : T
20
+
21
+ /** Metadata fields are nullable by convention; this is the value half. */
22
+ type Set<T> = Exclude<T, null | undefined>
23
+
24
+ export type OpenGraph = Set<Metadata['openGraph']>
25
+ export type OGImage = Item<Set<OpenGraph['images']>>
26
+
27
+ export type Twitter = Set<Metadata['twitter']>
28
+ export type TwitterImage = Item<Set<Twitter['images']>>
29
+
30
+ export type Author = Item<Set<Metadata['authors']>>
31
+ /**
32
+ * A theme colour with its media query. `Metadata['themeColor']` also admits a
33
+ * bare colour string; this is the form with fields, picked out by the one it
34
+ * always has.
35
+ */
36
+ export type ThemeColorDescriptor = Extract<Item<Set<Metadata['themeColor']>>, { color: unknown }>
37
+
38
+ /**
39
+ * The title's object form. `Metadata['title']` is that OR a plain string, and
40
+ * the string is the case with nothing to read.
41
+ */
42
+ export type TemplateString = Exclude<Set<Metadata['title']>, string>
43
+
44
+ /**
45
+ * One icon, in its descriptor form. `Metadata['icons']` also admits a bare url
46
+ * and a grouping object (`{ icon, shortcut, apple }`); this is the one that
47
+ * describes a single icon, picked out by the field only it has.
48
+ */
49
+ export type IconDescriptor = Extract<Item<Set<Metadata['icons']>>, { url: unknown }>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@luxfi/ui",
3
- "version": "5.5.5",
3
+ "version": "5.5.6",
4
4
  "description": "Library that contains shared UI primitives, support for a common design system, and other boilerplate support.",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org/",
@@ -27,7 +27,6 @@
27
27
  "./next": "./next/index.ts",
28
28
  "./style/": "./style/",
29
29
  "./site-def": "./site-def/index.ts",
30
- "./tailwind": "./tailwind/index.ts",
31
30
  "./util": "./util/index.ts"
32
31
  },
33
32
  "dependencies": {
@@ -41,21 +40,22 @@
41
40
  "react-social-icons": "^6.4.0",
42
41
  "react-tooltip": "^5.26.4",
43
42
  "request": "^2.88.2",
44
- "usehooks-ts": "^3.1.0"
43
+ "usehooks-ts": "^3.1.0",
44
+ "react-native-web": "^0.21.2"
45
45
  },
46
46
  "peerDependencies": {
47
47
  "@hanzo/iam": "0.21.9",
48
- "@hanzo/commerce": "7.6.4",
49
- "@hanzo/ui": "5.3.34",
48
+ "@hanzo/commerce": "7.7.0",
49
+ "@hanzo/ui": "8.23.2",
50
50
  "@luxfi/menu-icons": "^1.0.2",
51
51
  "@hookform/resolvers": "^3.3.2",
52
52
  "lucide-react": "0.470.0",
53
53
  "mobx": "^6.12.3",
54
54
  "mobx-react-lite": "^4.0.7",
55
- "next": "16.1.0",
55
+ "next": "16.3.3",
56
56
  "next-themes": "^0.4.0",
57
- "react": "19.2.0",
58
- "react-dom": "19.2.0",
57
+ "react": "19.2.8",
58
+ "react-dom": "19.2.8",
59
59
  "react-hook-form": "7.54.2",
60
60
  "validator": "^13.11.0",
61
61
  "zod": "3.23.8"
@@ -71,8 +71,7 @@
71
71
  "@types/react": "19.0.2",
72
72
  "@types/react-dom": "19.0.2",
73
73
  "@types/validator": "^13.12.1",
74
- "tailwindcss": "3.4.17",
75
- "typescript": "5.7.3"
74
+ "typescript": "7.0.2"
76
75
  },
77
76
  "scripts": {
78
77
  "lat": "npm show @luxfi/ui version",
@@ -2,6 +2,7 @@ import React, { type PropsWithChildren } from 'react'
2
2
  import type { Viewport } from 'next'
3
3
 
4
4
  import { Toaster } from '@hanzo/ui/primitives'
5
+ import { Hanzo } from '@hanzo/ui'
5
6
  import { CommerceProvider } from '@hanzo/commerce'
6
7
 
7
8
  import getAppRouterBodyFontClasses from '../next/font/get-app-router-font-classes'
@@ -14,6 +15,13 @@ import CommerceDrawer from '../components/commerce/drawer'
14
15
 
15
16
  import type SiteDef from '../types/site-def'
16
17
 
18
+ // BY NAME, and before the Lux sheets so those can override. Next does not
19
+ // follow a CSS import out of node_modules on a consumer's behalf, so naming
20
+ // these here is what actually puts the reset and the token scale on the page —
21
+ // a site that omits them renders with browser defaults and no palette.
22
+ import '@hanzo/ui/theme.css'
23
+ import '@hanzo/ui/styles.css'
24
+
17
25
  import '../style/lux-global.css'
18
26
  import '../style/cart-animation.css'
19
27
  import '../style/checkout-animation.css'
@@ -28,21 +36,20 @@ const viewport = {
28
36
  } satisfies Viewport
29
37
 
30
38
  /*
31
- These '.variable' fields are actually autogenerate css classnames that *define* the actual
32
- css variables ('--<ugly-name>') that one asks for in the tailwind classes.
33
- They are what make them available in the global scope. So this MUST
34
- be done like this for the tailwind font classes to work.
35
-
36
- (...not to be confused with the css var itself. This field should be named something else!)
37
- */
38
-
39
- /*
40
- re body: overflow-y-hidden overflow-x-hidden, h-full
41
- We cannot have these on body tag for scroll-snap to work on iOS!
39
+ The only classes left on <body> are next/font's own generated ones. Each
40
+ DEFINES a custom property (`--font-inter`, `--font-zen-sans`) holding the face
41
+ it loaded, and they have to be on an element for the rest of the sheet to
42
+ resolve those names which is why they are classes and not a stylesheet.
43
+
44
+ The ground, the ink and the family that used to sit here as utility classes
45
+ are in lux-global.css, on `body` itself. They were `bg-background
46
+ text-foreground flex flex-col min-h-full`, and with no engine generating them
47
+ they were four names no sheet served.
48
+
49
+ re body: not overflow-hidden and not h-full scroll-snap does not work on iOS
50
+ with those on the body tag.
42
51
  */
43
- const bodyClasses =
44
- 'bg-background text-foreground flex flex-col min-h-full ' +
45
- getAppRouterBodyFontClasses()
52
+ const bodyClasses = getAppRouterBodyFontClasses()
46
53
 
47
54
  function RootLayout({
48
55
  showHeader = false,
@@ -75,11 +82,23 @@ function RootLayout({
75
82
  <FacebookPixelHead/>
76
83
  </head>
77
84
 
78
- <body suppressHydrationWarning className={bodyClasses} style={{
79
-
80
- // As noted above: 'overflow: hidden' on the <body> tag breaks scroll snap!
81
- display: 'none', // see analytics.tsx
82
- }}>
85
+ {/* No inline style. The body's layout is stated once, in lux-global.css,
86
+ where it applies whether or not any script runs.
87
+
88
+ It used to render `display: none` here and a mount effect in
89
+ analytics.tsx set it back — hiding the page until React had hydrated.
90
+ That trades a flash for a site that is blank to anything without
91
+ JavaScript, and it silently outranked the sheet: the effect wrote
92
+ `flex`, so the `display: grid` the sheet asks for never once applied
93
+ on any of these sites.
94
+
95
+ Note the other half of that comment, still true: `overflow: hidden` on
96
+ <body> breaks scroll-snap on iOS, so it does not go here either. */}
97
+ <body suppressHydrationWarning className={bodyClasses}>
98
+ {/* The root every @hanzo/ui component reads its config from. Without it
99
+ a prerender throws `Err0` from inside gui — a message that names
100
+ neither the component nor the missing provider. */}
101
+ <Hanzo theme='dark'>
83
102
  <Analytics/>
84
103
  <Auth app={siteDef.app}>
85
104
  {siteDef?.commerce ? (
@@ -94,6 +113,7 @@ function RootLayout({
94
113
  )}
95
114
  </Auth>
96
115
  <Toaster position='top-center' duration={3000}/>
116
+ </Hanzo>
97
117
  </body>
98
118
  </html>
99
119
  )
Binary file
@@ -1,4 +1,3 @@
1
- @tailwind base;
2
1
  /* see https://stackoverflow.com/questions/69746121/using-nextjs-how-can-you-import-in-css-using-tailwind-css */
3
2
 
4
3
  @layer base {
@@ -1,16 +1,10 @@
1
- @tailwind base;
2
-
1
+ /* Both faces are served from the app's own /fonts. The Next path (../next/font)
2
+ emits the same two through next/font instead. */
3
3
  @layer base {
4
4
  @font-face {
5
- font-family: "DrukWide";
6
- src: url("/fonts/Druk-Wide-Medium.ttf");
7
- font-weight: 500;
8
- font-style: normal;
9
- }
10
- @font-face {
11
- font-family: "DrukWide";
12
- src: url("/fonts/Druk-Wide-Bold.ttf");
13
- font-weight: 700;
5
+ font-family: "Zen";
6
+ src: url("/fonts/Zen-Variable.woff2") format("woff2");
7
+ font-weight: 100 900;
14
8
  font-style: normal;
15
9
  }
16
10
  @font-face {
@@ -1,22 +1,22 @@
1
1
  /* Note, preflight is applied first:
2
2
  https://unpkg.com/tailwindcss@3.3.5/src/css/preflight.css
3
3
  */
4
- @import "tailwindcss/base";
5
-
6
4
  /* see https://stackoverflow.com/questions/69746121/using-nextjs-how-can-you-import-in-css-using-tailwind-css */
7
5
  /* @import "@hanzo/ui/style/hanzo-common"; */
8
- @import "lux-colors";
9
- @import "lux-fonts";
10
-
11
- @import "tailwindcss/components";
12
- @import "tailwindcss/utilities";
13
-
6
+ @import "./lux-colors.css";
7
+ @import "./lux-fonts.css";
14
8
  div.nextjs-toast-errors-parent[data-nextjs-toast="true"] {
15
9
  display: none;
16
10
  }
17
11
 
12
+ /* Headings are Zen cut wide: the '.zen-wide' preset from @hanzo/font, fitted
13
+ against Druk Wide Bold. The preset's scaleX(1.56) is left out on purpose -- a
14
+ transform does not reflow, and these land on block h1-h4 that would overrun
15
+ their container. Use the class itself where a word has room to be monumental. */
18
16
  .font-heading {
19
- @apply uppercase;
17
+ text-transform: uppercase;
18
+ font-variation-settings: 'wght' 845;
19
+ letter-spacing: -0.04em;
20
20
  }
21
21
 
22
22
  /* Specific style fixes for react-square-web-payments-sdk -