mirror of
https://github.com/hanzoai/gui.git
synced 2026-10-25 02:31:41 +00:00
Both old names are owned by a different npm account (artemis-prime), so publishing them returns 403 — which is how this surfaced: the 8.0.0 run shipped @hanzogui/logo and @hanzogui/demos depending on [email protected], a version that cannot be published and therefore does not exist. Those two were uninstallable. @hanzo/gui and @hanzogui/* are ours, so the framework now carries the name it is imported by everywhere downstream, and the loader moves under the scope we control. The rewrite is limited to package references. `DEBUG?.startsWith('hanzogui')` is a log-namespace filter and join(dir, 'hanzogui') is a path — rewriting either would change behaviour, so both are untouched. Co-authored-by: Hanzo Dev <[email protected]>
372 lines
8.2 KiB
Plaintext
372 lines
8.2 KiB
Plaintext
Gui is a style library `@hanzogui/core`, and a separate UI kit `hanzogui`. 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 `hanzogui` 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 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 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.GUI_TARGET === 'web' && {
|
|
outlineColor: true,
|
|
caretColor: true,
|
|
}),
|
|
},
|
|
}
|
|
```
|
|
|
|
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 GuiThemes = typeof generatedThemes
|
|
|
|
/**
|
|
* This is an optional production optimization: themes JS can get to 20Kb or more.
|
|
* Gui has ~1Kb of logic to hydrate themes from CSS, so you can remove the JS.
|
|
* So long as you server render your Gui CSS, this will save you bundle size:
|
|
*/
|
|
export const themes: GuiThemes =
|
|
process.env.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.
|