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]>
447 lines
12 KiB
Plaintext
447 lines
12 KiB
Plaintext
---
|
|
title: Quick Config
|
|
description: Easy config and themes with @hanzogui/config/v4
|
|
---
|
|
|
|
<IntroParagraph>
|
|
Config v4 simplifies configuration, generates much more useful themes, and adds a new
|
|
helper function for generating your own theme suite called `createThemes`.
|
|
</IntroParagraph>
|
|
|
|
Gui is incredibly customizable, but if you want to get started faster and
|
|
enjoy using a configuration that is standardized and has been tested in many
|
|
apps, we recommend our `@hanzogui/config` package.
|
|
|
|
First you'll want to add it:
|
|
|
|
```bash
|
|
npm install @hanzogui/config
|
|
```
|
|
|
|
Using the new `defaultConfig` is the easiest way to start:
|
|
|
|
```tsx fileName="hanzogui.config.ts"
|
|
import { defaultConfig } from '@hanzogui/config/v4'
|
|
import { createGui } from '@hanzo/gui'
|
|
|
|
export const config = createGui(defaultConfig)
|
|
|
|
type CustomConfig = typeof config
|
|
|
|
// ensure types work
|
|
declare module 'hanzogui' {
|
|
interface GuiCustomConfig extends CustomConfig {}
|
|
}
|
|
```
|
|
|
|
It gives you a robust suite of themes, a few shorthands that mostly align with
|
|
Tailwind, and default settings that prevent bugs.
|
|
|
|
If you like it but want to make some changes, you can
|
|
[copy and paste the source code](https://github.com/hanzoai/gui/blob/5b0c075e92688ac85737fe97c98cd77322f034b0/pkgs/core/config/src/v4.ts)
|
|
into your app and customize to your taste.
|
|
|
|
<Notice theme="green" title="Custom Themes">
|
|
If you want to learn to create your own custom theme suite rather than use the included
|
|
defaults, check out the [Creating Custom Themes Guide](/docs/guides/theme-builder).
|
|
</Notice>
|
|
|
|
We recommend adding `settings.styleCompat` to the default config, setting it to
|
|
be "react-native". This will align the default flexBasis of `flex` to be `0`,
|
|
not `auto`, matching the default in React Native. This setting will become the
|
|
default in the upcoming Gui v2 release. We left it out of Config v4 because
|
|
we wanted an easier transition for existing users, but if you are a new user, we
|
|
recommend this setting.
|
|
|
|
---
|
|
|
|
### Default Configuration
|
|
|
|
You can take or leave as much of the default configuration as you please. Each
|
|
part is exported separately, or all together as `defaultConfig`.
|
|
|
|
#### Themes
|
|
|
|
Config v4 has a new helper function `createThemes`, an opinionated way to
|
|
generate a suite of themes. It also comes with default themes that include
|
|
minimal grayscale light and dark themes, and an inverted "accent" theme.
|
|
|
|
It's easiest to get a feel for both createThemes and the default themes by reading
|
|
the source for how `defaultThemes` are defined:
|
|
|
|
```tsx fileName=themes.ts
|
|
import * as Colors from '@hanzogui/colors'
|
|
import { createThemes, defaultComponentThemes } from '@hanzogui/config/v4'
|
|
|
|
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 =
|
|
// we define this in our bundler plugins, but you can also use your framework/bundlers
|
|
// built in environment variables to ensure this is shaken away on client js bundles
|
|
process.env.GUI_ENVIRONMENT === 'client' && process.env.NODE_ENV === 'production'
|
|
? {}
|
|
: (generatedThemes as any)
|
|
```
|
|
|
|
So what have we done?
|
|
|
|
- `base` will always generate `light` and `dark` as your root themes. We plan to
|
|
add support for generating just one base theme, but you can manually remove
|
|
either light or dark if you please.
|
|
- Our `base` themes are grayscale, defined by their palettes.
|
|
- The `accent` option is an opinionated way to have a "contrasting theme". When
|
|
set, it generates a few things:
|
|
- `light_accent` and `dark_accent` themes
|
|
- `$accent1` through `$accent12` on the base themes
|
|
- `childrenThemes` allows us to set up some sub-themes easily, this is
|
|
especially useful for when you want to make an area look like an error,
|
|
success, or warning state. That's why we default to setting `green`, `yellow`,
|
|
and `red`. Of course, you can swap these out for whatever you like.
|
|
- We also are setting `componentThemes` to `defaultComponentThemes`, which will
|
|
generate for us default styling for the Gui UI components. If you prefer
|
|
to not have default component themes, you can leave this out.
|
|
- You can use the `getTheme` callback to customize any generated theme. See the
|
|
[theme-builder guide](/docs/guides/theme-builder#customizing-themes-with-gettheme)
|
|
for details.
|
|
|
|
#### Settings
|
|
|
|
<PropsTable
|
|
data={[
|
|
{ name: 'mediaQueryDefaultActive', description: 'See Media' },
|
|
{ name: 'defaultFont', description: '"body"' },
|
|
{
|
|
name: 'fastSchemeChange',
|
|
description:
|
|
'true - On iOS, leverages DynamicColorIOS for fast light/dark theme changes.',
|
|
},
|
|
{
|
|
name: 'shouldAddPrefersColorThemes',
|
|
description:
|
|
'true - Generates CSS for prefers-color-scheme, so even with JS off you have proper light/dark styling.',
|
|
},
|
|
{
|
|
name: 'allowedStyleValues',
|
|
description:
|
|
'"somewhat-strict-web" - More strict than just a string, but still allows web-only style values like vh, vw.',
|
|
},
|
|
{
|
|
name: 'themeClassNameOnRoot',
|
|
description:
|
|
'true - Defaults to putting your root theme className onto the root html tag so you can use your CSS variables on your body tag.',
|
|
},
|
|
{
|
|
name: 'onlyAllowShorthands',
|
|
description: 'true - For any shorthand defined, remove the types for the longhand.',
|
|
},
|
|
]}
|
|
/>
|
|
|
|
#### Media
|
|
|
|
The new media queries in v4 are also more simplified and aligned to Tailwind:
|
|
|
|
<PropsTable
|
|
data={[
|
|
{ name: '2xl', description: `minWidth: 1536` },
|
|
{ name: 'xl', description: `minWidth: 1280` },
|
|
{ name: 'lg', description: `minWidth: 1024` },
|
|
{ name: 'md', description: `minWidth: 768` },
|
|
{ name: 'sm', description: `minWidth: 640` },
|
|
{ name: 'xs', description: `minWidth: 460` },
|
|
{ name: '2xs', description: `minWidth: 340` },
|
|
]}
|
|
/>
|
|
|
|
On the server, only xs and 2xs default to `true` to align generally give you a
|
|
[mobile-first design](https://en.wikipedia.org/wiki/Responsive_web_design)
|
|
setup, but of course you can change that. This only really affects `useMedia()`,
|
|
as Gui generates proper SSR-safe CSS for media queries on the server for any
|
|
style properties.
|
|
|
|
#### Shorthands
|
|
|
|
Config v4 has fewer shorthands, and aligns shorthands to Tailwind for
|
|
familiarity:
|
|
|
|
<PropsTable
|
|
data={[
|
|
{ name: 'text', description: 'textAlign' },
|
|
{ name: 'b', description: 'bottom' },
|
|
{ name: 'bg', description: 'backgroundColor' },
|
|
{ name: 'content', description: 'alignContent' },
|
|
{ name: 'flex', description: 'flexDirection' },
|
|
{ name: 'grow', description: 'flexGrow' },
|
|
{ name: 'items', description: 'alignItems' },
|
|
{ name: 'justify', description: 'justifyContent' },
|
|
{ name: 'l', description: 'left' },
|
|
{ name: 'm', description: 'margin' },
|
|
{ name: 'maxH', description: 'maxHeight' },
|
|
{ name: 'maxW', description: 'maxWidth' },
|
|
{ name: 'mb', description: 'marginBottom' },
|
|
{ name: 'minH', description: 'minHeight' },
|
|
{ name: 'minW', description: 'minWidth' },
|
|
{ name: 'ml', description: 'marginLeft' },
|
|
{ name: 'mr', description: 'marginRight' },
|
|
{ name: 'mt', description: 'marginTop' },
|
|
{ name: 'mx', description: 'marginHorizontal' },
|
|
{ name: 'my', description: 'marginVertical' },
|
|
{ name: 'p', description: 'padding' },
|
|
{ name: 'pb', description: 'paddingBottom' },
|
|
{ name: 'pl', description: 'paddingLeft' },
|
|
{ name: 'pr', description: 'paddingRight' },
|
|
{ name: 'pt', description: 'paddingTop' },
|
|
{ name: 'px', description: 'paddingHorizontal' },
|
|
{ name: 'py', description: 'paddingVertical' },
|
|
{ name: 'r', description: 'right' },
|
|
{ name: 'rounded', description: 'borderRadius' },
|
|
{ name: 'select', description: 'userSelect' },
|
|
{ name: 'self', description: 'alignSelf' },
|
|
{ name: 'shrink', description: 'flexShrink' },
|
|
{ name: 't', description: 'top' },
|
|
{ name: 'z', description: 'zIndex' },
|
|
]}
|
|
/>
|
|
|
|
#### Tokens
|
|
|
|
Default tokens are defined as:
|
|
|
|
```tsx
|
|
export const size = {
|
|
$0: 0,
|
|
'$0.25': 2,
|
|
'$0.5': 4,
|
|
'$0.75': 8,
|
|
$1: 20,
|
|
'$1.5': 24,
|
|
$2: 28,
|
|
'$2.5': 32,
|
|
$3: 36,
|
|
'$3.5': 40,
|
|
$4: 44,
|
|
$true: 44,
|
|
'$4.5': 48,
|
|
$5: 52,
|
|
$6: 64,
|
|
$7: 74,
|
|
$8: 84,
|
|
$9: 94,
|
|
$10: 104,
|
|
$11: 124,
|
|
$12: 144,
|
|
$13: 164,
|
|
$14: 184,
|
|
$15: 204,
|
|
$16: 224,
|
|
$17: 224,
|
|
$18: 244,
|
|
$19: 264,
|
|
$20: 284,
|
|
}
|
|
|
|
export const space = {
|
|
// ... space is the same as size, but also defines "negative" values for every size, like:
|
|
'$-1': -20,
|
|
}
|
|
|
|
export const zIndex = {
|
|
0: 0,
|
|
1: 100,
|
|
2: 200,
|
|
3: 300,
|
|
4: 400,
|
|
5: 500,
|
|
}
|
|
|
|
export const radius = {
|
|
0: 0,
|
|
1: 3,
|
|
2: 5,
|
|
3: 7,
|
|
4: 9,
|
|
true: 9,
|
|
5: 10,
|
|
6: 16,
|
|
7: 19,
|
|
8: 22,
|
|
9: 26,
|
|
10: 34,
|
|
11: 42,
|
|
12: 50,
|
|
}
|
|
```
|
|
|
|
Note that `color` tokens aren't defined, instead we are just using themes.
|
|
|
|
Also note that the "true" value on tokens is the "default" - Gui UI for now
|
|
uses defaults to determine how to size various things out of the box. This isn't
|
|
mandatory, and in version 2 of Gui we are working on a more clear solution.
|
|
|
|
#### Fonts
|
|
|
|
Only a `body` and `heading` font are exported, which both use "system" font
|
|
families:
|
|
|
|
<PropsTable
|
|
data={[
|
|
{
|
|
name: 'web',
|
|
description:
|
|
'-apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',
|
|
},
|
|
{ name: 'native', description: 'System' },
|
|
]}
|
|
/>
|
|
|
|
You can create your own system font using the exported `createSystemFont`
|
|
helper, or of course swap out your own fonts altogether.
|