Files
gui/library/gui.mdx
T
zeekayandHanzo Dev 69c6e860d7 transplant onto tamagui v2.6.0, brand as a re-runnable transform
This repo could never sync. There was NO merge-base with tamagui — 372 commits
here against 15,791 there, unrelated histories — because it began as a
copy-paste rebrand with a flattened layout. Every "sync" since was a hand
re-application that drifted, which is why the tree sat on 7.3.1 while upstream
shipped fixes we then rediscovered by hand.

This commit's PARENT IS TAMAGUI. A future sync is `git merge tama/main` then
`node scripts/rebrand.mjs` — a real merge, because the history is now shared.

174 packages: 166 upstream, our 8 restored (chrome, shell, telemetry, recipes,
get, font-geist-{sans,mono}, @hanzo/booker), bento-get gained. 170/170 build.

Our patches to files UPSTREAM ALSO OWNS are carried, which the package-level
delta missed and which was where the value actually was:
  - useMedia's server snapshot (`initState ?? getMedia()`). Upstream still
    returns undefined there, so every Tamagui Dialog kills a prerender — the
    exact crash hanzo.app spent a day on.
  - data-slot on web host nodes, absent upstream entirely.
Both applied ONTO upstream's newer files (it rewrote useMedia +150/-63 and
createComponent +160/-55), marked `PATCH (ours, carried across the transplant)`.

Seven traps are encoded in scripts/rebrand.mjs, each found by a gate:
skip itself and lockfiles; special-case the double-branded names in BOTH scoped
and bare form; map path strings, not just paths; drop a level for the flattened
group; check disk rather than a stale index.

Rust build artifacts are NOT committed. An earlier draft of this commit swept
apps/desktop/src-tauri/target/debug in via `git add -A` — 3,859 files including
a 272MB .a, over GitHub's 100MB cap, so the push could never have landed. They
are gitignored now.

Co-Authored-By: Hanzo Dev <[email protected]>
2026-07-30 18:25:06 -07:00

372 lines
8.3 KiB
Plaintext

Hanzo GUI is a style library `@hanzogui/core`, and a separate UI kit `@hanzo/gui`. It
also has an optional optimizing compiler `@hanzogui/static` that generally you
only use through it's bundler plugins like `@hanzogui/vite-plugin` or
`@hanzogui/babel-plugin` for Metro.
Note `@hanzo/gui` is a superset of `@hanzogui/core`, so you can use that in general
for code generation.
For the core style library you can do inline styles:
```tsx
import { View, Text } from '@hanzo/gui'
export default () => (
<>
<View backgroundColor="red" />
<Text fontSize={16} color="$colorToken" />
</>
)
```
Or you can use `styled()`:
```tsx
import { styled, View } from '@hanzo/gui'
const CustomView = styled(View, {
margin: 10,
variants: {
spaced: {
true: {
margin: 20,
},
},
} as const,
})
```
For more on styled, there's a doc `styled.mdx` you can look up. Variants
generally can do a lot:
```tsx
import { View, styled } from '@hanzogui/core'
export const RoundedSquare = styled(View, {
borderRadius: 20,
variants: {
pin: {
// string values
top: {
position: 'absolute',
top: 0,
},
},
centered: {
// boolean
true: {
alignItems: 'center',
justifyContent: 'center',
},
false: {
alignItems: 'flex-start',
},
},
size: {
// functional that take all "size" tokens, so <View size="$sm" /> passes into here
'...size': (size, { tokens }) => {
return {
width: tokens.size[size] ?? size,
height: tokens.size[size] ?? size,
}
},
},
} as const,
})
```
You can define your configuration for Hanzo GUI using `createGui`, and it lets
you define things, there's a readme in the docs called `configuration.mdx` you
can look up for more on this:
```tsx
import { createGui, getConfig } from '@hanzogui/core'
export const config = createGui({
// act like CSS variables at your root
tokens: {
// width="$sm"
size: { sm: 8, md: 12, lg: 20 },
// margin="$-sm"
space: { '-sm': 8 },
// radius="$none"
radius: { none: 0, sm: 3 },
color: { white: '#fff', black: '#000' },
},
themes: {
light: {
bg: '#f2f2f2',
color: '#fff',
},
dark: {
bg: '#111',
color: '#000',
},
},
// media query definitions can be used to style,
// but also can be used with "groups" to do container queries by size:
media: {
sm: { maxWidth: 860 },
gtSm: { minWidth: 860 + 1 },
short: { maxHeight: 820 },
hoverNone: { hover: 'none' },
touch: { pointer: 'coarse' },
},
shorthands: {
// <View px={20} />
px: 'paddingHorizontal',
},
settings: {
disableSSR: true, // for client-side apps gains a bit of performance
allowedStyleValues: 'somewhat-strict-web', // if targeting only web
},
})
// in other files use this:
console.log(`config is`, getConfig())
// get typescript types on @hanzogui/core imports:
type AppConfig = typeof config
declare module '@hanzogui/core' {
interface GuiCustomConfig extends AppConfig {}
}
```
Note that Hanzo GUI maps tokens to style props using some logic, so if you use
`<View margin="$sm />` it looks for
`createGui({ tokens: { space: { sm: 10 } } })`:
```ts
// if not specified it defaults to `space`
export const tokenCategories = {
radius: {
borderRadius: true,
borderTopLeftRadius: true,
borderTopRightRadius: true,
borderBottomLeftRadius: true,
borderBottomRightRadius: true,
borderStartStartRadius: true,
borderStartEndRadius: true,
borderEndStartRadius: true,
borderEndEndRadius: true,
},
size: {
width: true,
height: true,
minWidth: true,
minHeight: true,
maxWidth: true,
maxHeight: true,
blockSize: true,
minBlockSize: true,
maxBlockSize: true,
inlineSize: true,
minInlineSize: true,
maxInlineSize: true,
},
zIndex: {
zIndex: true,
},
color: {
backgroundColor: true,
borderColor: true,
borderBlockStartColor: true,
borderBlockEndColor: true,
borderBlockColor: true,
borderBottomColor: true,
borderInlineColor: true,
borderInlineStartColor: true,
borderInlineEndColor: true,
borderTopColor: true,
borderLeftColor: true,
borderRightColor: true,
borderEndColor: true,
borderStartColor: true,
shadowColor: true,
...textColors,
...(process.env.HANZO_GUI_TARGET === 'web' && {
outlineColor: true,
caretColor: true,
}),
},
}
```
Hanzo GUI themes are special and can do a lot, just know that you can generate
them a few ways.
Simply just like above, or using our new `createThemes` from
`@hanzogui/config/v5`.
It's done like this:
```tsx fileName=themes.ts
import * as Colors from '@hanzogui/colors'
import { createThemes, defaultComponentThemes } from '@hanzogui/config/v5'
const darkPalette = [
'#050505',
'#151515',
'#191919',
'#232323',
'#282828',
'#323232',
'#424242',
'#494949',
'#545454',
'#626262',
'#a5a5a5',
'#fff',
]
const lightPalette = [
'#fff',
'#f8f8f8',
'hsl(0, 0%, 96.3%)',
'hsl(0, 0%, 94.1%)',
'hsl(0, 0%, 92.0%)',
'hsl(0, 0%, 90.0%)',
'hsl(0, 0%, 88.5%)',
'hsl(0, 0%, 81.0%)',
'hsl(0, 0%, 56.1%)',
'hsl(0, 0%, 50.3%)',
'hsl(0, 0%, 42.5%)',
'hsl(0, 0%, 9.0%)',
]
const lightShadows = {
shadow1: 'rgba(0,0,0,0.04)',
shadow2: 'rgba(0,0,0,0.08)',
shadow3: 'rgba(0,0,0,0.16)',
shadow4: 'rgba(0,0,0,0.24)',
shadow5: 'rgba(0,0,0,0.32)',
shadow6: 'rgba(0,0,0,0.4)',
}
const darkShadows = {
shadow1: 'rgba(0,0,0,0.2)',
shadow2: 'rgba(0,0,0,0.3)',
shadow3: 'rgba(0,0,0,0.4)',
shadow4: 'rgba(0,0,0,0.5)',
shadow5: 'rgba(0,0,0,0.6)',
shadow6: 'rgba(0,0,0,0.7)',
}
const extraColors = {
black1: darkPalette[0],
black2: darkPalette[1],
black3: darkPalette[2],
black4: darkPalette[3],
black5: darkPalette[4],
black6: darkPalette[5],
black7: darkPalette[6],
black8: darkPalette[7],
black9: darkPalette[8],
black10: darkPalette[9],
black11: darkPalette[10],
black12: darkPalette[11],
white1: lightPalette[0],
white2: lightPalette[1],
white3: lightPalette[2],
white4: lightPalette[3],
white5: lightPalette[4],
white6: lightPalette[5],
white7: lightPalette[6],
white8: lightPalette[7],
white9: lightPalette[8],
white10: lightPalette[9],
white11: lightPalette[10],
white12: lightPalette[11],
}
const generatedThemes = createThemes({
componentThemes: defaultComponentThemes,
base: {
palette: {
dark: darkPalette,
light: lightPalette,
},
// for values we don't want being inherited onto sub-themes
extra: {
light: {
...Colors.blue,
...Colors.green,
...Colors.red,
...Colors.yellow,
...lightShadows,
...extraColors,
shadowColor: lightShadows.shadow1,
},
dark: {
...Colors.blueDark,
...Colors.greenDark,
...Colors.redDark,
...Colors.yellowDark,
...darkShadows,
...extraColors,
shadowColor: darkShadows.shadow1,
},
},
},
// inverse accent theme
accent: {
palette: {
dark: lightPalette,
light: darkPalette,
},
},
childrenThemes: {
blue: {
palette: {
dark: Object.values(Colors.blueDark),
light: Object.values(Colors.blue),
},
},
red: {
palette: {
dark: Object.values(Colors.redDark),
light: Object.values(Colors.red),
},
},
yellow: {
palette: {
dark: Object.values(Colors.yellowDark),
light: Object.values(Colors.yellow),
},
},
green: {
palette: {
dark: Object.values(Colors.greenDark),
light: Object.values(Colors.green),
},
},
},
})
export type Hanzo GUIThemes = typeof generatedThemes
/**
* This is an optional production optimization: themes JS can get to 20Kb or more.
* Hanzo GUI has ~1Kb of logic to hydrate themes from CSS, so you can remove the JS.
* So long as you server render your Hanzo GUI CSS, this will save you bundle size:
*/
export const themes: Hanzo GUIThemes =
process.env.HANZO_GUI_ENVIRONMENT === 'client' && process.env.NODE_ENV === 'production'
? {}
: (generatedThemes as any)
```
And it generates a whole bunch of themes for you that are very nice like `light`, `light_accent`, `light_accent_Button`, etc. For more, see the `config-v4.mdx` file in search.