mirror of
https://github.com/hanzoai/gui.git
synced 2026-10-25 02:31:41 +00:00
923 lines
29 KiB
Plaintext
923 lines
29 KiB
Plaintext
---
|
||
title: Gui 1.0 🎉
|
||
publishedAt: '2022-12-29'
|
||
description: Ship cross-platform React apps in ½ the time with 2x performance.
|
||
by: nate
|
||
poster: banner-one.jpg
|
||
---
|
||
|
||
<IntroParagraph large>
|
||
React Native is amazing for building mobile apps, but sharing components between web and
|
||
native [sacrifices performance, productivity and UX](/docs/intro/why-a-compiler).
|
||
</IntroParagraph>
|
||
|
||
<IntroParagraph>
|
||
Gui introduces a novel optimizing compiler for React that evaluates your code at
|
||
build-time, turning heavy JS into flatter trees and much faster CSS. The result is more
|
||
code share %, less dev time, and lighter, faster apps.
|
||
</IntroParagraph>
|
||
|
||
Gui's optimizing compiler makes advanced optimizations using partial
|
||
evaluation, CSS extraction, and ultimately tree-flattening. Where it optimizes,
|
||
things get a lot faster:
|
||
|
||
<Spacer />
|
||
<Spacer />
|
||
<BenchmarkChartWeb />
|
||
<Aside>Rendering between groups of styles conditionally</Aside>
|
||
<Spacer />
|
||
<Spacer />
|
||
|
||
Gui comes in three parts:
|
||
|
||
[**Gui Core**](#overview-of-hanzoguicore) (`@hanzogui/core`) is a style
|
||
library for React Native and web that supports 100% of the React Native API
|
||
surface in a library that only depends on React. It adds all the
|
||
[goodies of modern style libraries](#overview) into a cohesive package.
|
||
|
||
[**Gui Static**](#overview-of-hanzoguistatic) (`@hanzogui/static`) is an
|
||
optimizing compiler on top of Core, turning even inline styles sprinkled with
|
||
logic into atomic CSS and minimal JS, flattening your view tree for maximum
|
||
performance.
|
||
|
||
[**Gui UI**](#overview-of-hanzogui) (`hanzogui`) is a component kit built on
|
||
top of the incredibly powerful theme primitives of `core`. That, alongside
|
||
compound-component APIs and complete size control enables a new level of control
|
||
not seen before in a UI kit.
|
||
|
||
---
|
||
|
||
## Overview
|
||
|
||
Lets get familiar with both `@hanzogui/core` (the styling library) and
|
||
`@hanzogui/static` (the compiler), and how the latter optimizes the former.
|
||
|
||
<Spacer />
|
||
<Wide>
|
||
<GuiExamplesCode />
|
||
</Wide>
|
||
|
||
The key to Gui's performance gains lie in **view flattening** or
|
||
tree-flattening: the compiler analyzes code (even across module boundaries) and
|
||
evaluates styled components away using both the AST and Node VM code evaluation.
|
||
It will fully flatten custom styled components (like `<Circle />`) into plain
|
||
old `<div />` (or `<View />` on native).
|
||
|
||
---
|
||
|
||
<Spacer />
|
||
<SponsorNotice />
|
||
<Spacer />
|
||
|
||
---
|
||
|
||
## Overview of `@hanzogui/core`
|
||
|
||
**Core is a complete cross-platform style library**. It allows creating typed
|
||
design systems that work with a `styled` factory on both React Native and web:
|
||
|
||
##### Highlights
|
||
|
||
- Works **100% the same across Native and Web**.
|
||
- **Works completely at runtime**, no compiler necessary, but optimizes away at
|
||
compile-time.
|
||
- Size of 22Kb `@hanzogui/web` to 31Kb `@hanzogui/core` (gzip, excluding react).
|
||
- SSR, React Server Component, Concurrent mode support for 100% of the features.
|
||
- Custom typed design systems.
|
||
- Powerful typed variants, including functional variants.
|
||
- Prop-order based styling means no more CSS specificity fights!
|
||
- Inline styles with tokens, media and pseudo styles that all optimize away.
|
||
- Typed shorthands.
|
||
- Pluggable animation drivers, allows swapping JS-based animations to pure CSS
|
||
on the web.
|
||
|
||
One novel feature is **deterministic, easy to reason about style merging**. Core
|
||
_always merges styles based on the order received rather than arcane CSS
|
||
definition-order + specificity rules_, no matter if those styles come through
|
||
nested `styled` calls, or via inline props. This resolves limitations in both
|
||
CSS and CSS-in-JS systems as they largely exist today.
|
||
|
||
### styled()
|
||
|
||
Here's an example of the `styled` function with a few variants:
|
||
|
||
```tsx
|
||
import { Stack, styled } from '@hanzo/gui' // or '@hanzogui/core'
|
||
|
||
export const Circle = styled(Stack, {
|
||
// access your tokens and theme values easily with $ props
|
||
backgroundColor: '$background',
|
||
borderRadius: '$4',
|
||
|
||
// media and pseudo styles - this would take 15+ lines of brittle JS in RN
|
||
$gtSm: {
|
||
pressStyle: {
|
||
borderRadius: '$6',
|
||
},
|
||
},
|
||
|
||
variants: {
|
||
// define variants <Circle pin="top" />
|
||
// these will flatten, even when nesting multiple styled() calls
|
||
pin: {
|
||
top: {
|
||
position: 'absolute',
|
||
top: 0,
|
||
},
|
||
},
|
||
|
||
size: {
|
||
// functional variants give incredible power and save bundle size
|
||
'...size': (size, { tokens }) => {
|
||
return {
|
||
width: tokens.size[size] ?? size,
|
||
height: tokens.size[size] ?? size,
|
||
}
|
||
},
|
||
},
|
||
} as const,
|
||
})
|
||
```
|
||
|
||
For more, see the [configuration](/docs/core/configuration),
|
||
[styling](/docs/core/styled), and [variants](/docs/core/variants) docs.
|
||
|
||
### Design system
|
||
|
||
Using [createGui](/docs/core/configuration) you generate a fully-typed
|
||
design system with colors, tokens, spacing, sizing, fonts, themes, shorthands,
|
||
animations, and more.
|
||
|
||
It works with well-optimized and easy to use hooks like
|
||
[useMedia](/docs/core/use-media) and [useTheme](/docs/core/use-theme) that save
|
||
a ton of time over rolling these yourself.
|
||
|
||
Here's a stripped down configuration:
|
||
|
||
```tsx
|
||
import { createFont, createGui, createTokens } from '@hanzo/gui' // or '@hanzogui/core'
|
||
|
||
const zenFont = createFont({
|
||
family: "'Zen', Helvetica, Arial, sans-serif",
|
||
size: { 1: 12, 2: 14 /* ... */ },
|
||
// ... lineHeight, weight, letterSpacing, transform, style, color, face
|
||
})
|
||
|
||
const size = { 0: 0, 1: 5, 2: 10 /* ... */ }
|
||
|
||
const tokens = createTokens({
|
||
size,
|
||
space: { ...size, '-1': -5, '-2': -10 },
|
||
radius: { 0: 0, 1: 3 },
|
||
zIndex: { 0: 0, 1: 100, 2: 200 },
|
||
color: { white: '#fff', black: '#000' },
|
||
})
|
||
|
||
export default createGui({
|
||
fonts: {
|
||
heading: zenFont,
|
||
body: zenFont,
|
||
},
|
||
tokens,
|
||
themes: {
|
||
light: { bg: '#f2f2f2', color: tokens.color.black },
|
||
dark: { bg: '#111', color: tokens.color.white },
|
||
},
|
||
media: {
|
||
sm: { maxWidth: 860 },
|
||
gtSm: { minWidth: 860 + 1 },
|
||
},
|
||
shorthands: {
|
||
px: 'paddingHorizontal',
|
||
f: 'flex',
|
||
} as const,
|
||
})
|
||
```
|
||
|
||
### Stack and Text
|
||
|
||
<HeroContainer tinted>
|
||
<StacksDemo />
|
||
</HeroContainer>
|
||
|
||
Finally, the [Stack and Text components](/docs/core/view-and-text) work with
|
||
`styled()` and provide lot of nice features like hover, press, and focus styles,
|
||
typed inline style props with theme and token values, shorthands, media queries,
|
||
animations, and more.
|
||
|
||
---
|
||
|
||
## What's new in `@hanzogui/core`
|
||
|
||
Over a thousand bugfixes since beta with large performance and memory
|
||
improvements, much higher test coverage, and compatibility with the latest and
|
||
greatest in React and React Native.
|
||
|
||
### Compatibility
|
||
|
||
Across all of Gui, we've bumped support to the latest versions. Due to
|
||
improvements in react-native-web 18, we were also able to dramatically simplify
|
||
setup, no longer having to patch the library to support classnames.
|
||
|
||
Gui supports React Native 0.70, React 18, React Native Web 18. It's the only
|
||
Native UI library that fully supports concurrent mode on the web as well.
|
||
|
||
### Big gains for web-only use cases
|
||
|
||
Early in the beta for web-only use cases, Core had the downside of requiring you
|
||
to bundle all of `react-native-web` in your app, not to mention the always
|
||
tricky problem of configuring your bundler to alias `react-native` to
|
||
`react-native-web`.
|
||
|
||
For 1.0, we've made the difficult steps to get `@hanzogui/core` to have no
|
||
dependency at all on `react-native` (and therefore no need to setup anything in
|
||
your bundler), while still maintaining 100% compatibility with the React Native
|
||
APIs.
|
||
|
||
This unlocks a few things:
|
||
|
||
- Much easier setup: no need to touch your bundler.
|
||
- Save ~30Kb of bundle size by avoiding `react-native-web` entirely for web-only
|
||
use cases.
|
||
|
||
You can get all the benefits of unified APIs across native and web plus an
|
||
optimizing compiler and full-featured design system, yet actually save bundle
|
||
size vs React Native Web.
|
||
|
||
### Bundle size reduction
|
||
|
||
De-coupling core from `react-native` is a big win for web bundle size, allowing
|
||
you to leave out 35Kb of size if just using `core`. We've shaved nearly ~12Kb
|
||
beyond that during the betas by iteratively improving code and reducing
|
||
dependencies. Today core is ~20Kb, gzipped, but can get down to ~10Kb fairly
|
||
straightforwardly.
|
||
|
||
Beyond that, we have landed refactors now that allow releasing a web-specific
|
||
core which will drop a few Native-specific APIs and bring the total runtime size
|
||
cost down to below 8Kb.
|
||
|
||
### Performance improvements
|
||
|
||
We've greatly optimized render performance during the beta across the board.
|
||
Some of the more interesting improvements are:
|
||
|
||
#### `useTheme`
|
||
|
||
The `useTheme` hook is used by every Gui component, and is smart about
|
||
re-renders by tracking which keys are accessed by your styles to only re-render
|
||
when their values change. But it wasn't as smart about memory usage and avoiding
|
||
work up front, and was also re-parenting the React tree too often.
|
||
|
||
We saw 8% improvements in Lighthouse scores on the website homepage just by
|
||
optimizing this.
|
||
|
||
#### `useMedia`
|
||
|
||
Supporting SSR often means you need to hydrate using an initial value, and then
|
||
re-render after hydration with the "real" media query value. We've moved over to
|
||
use React's
|
||
[useSyncExternalStore hook](https://beta.reactjs.org/apis/react/useSyncExternalStore),
|
||
which greatly reduced code and helps avoid re-renders and hooks used
|
||
per-component. It also clears us to remove the double-render that SSR based apps
|
||
typically do on hydration.
|
||
|
||
#### Avoiding work generating styles
|
||
|
||
Previously, Core used `react-native-web` to handle the final steps of taking
|
||
styles and converting them into CSS. In profiling and reading over the code, we
|
||
found this to be a large bottleneck to performance as it would iterate over
|
||
objects many times, and generate many intermediate objects in the process.
|
||
|
||
`@hanzogui/core` is now entirely dependency-free and generates it's own styles.
|
||
In total, de-coupling saved us 4-5 loops over the generated style objects
|
||
per-component.
|
||
|
||
### `styled` upgrades
|
||
|
||
The `styled` factory has undergone a number of improvements. It now supports
|
||
wrapping any component you give it, so long as that component accepts a `style`
|
||
prop.
|
||
|
||
#### A note on `styled` types
|
||
|
||
We now recommend using `as const` after your `variants` object definition to fix
|
||
some tricky issues related to some
|
||
[outstanding Typescript limitations around inferring const generics]().
|
||
|
||
### Fonts
|
||
|
||
##### <FontLanguage />
|
||
|
||
Supporting fonts per-language is now possible with <FontLanguage />, like
|
||
so. First, you can specify language-specific fonts with a suffix in your
|
||
configuration, much like a sub-theme:
|
||
|
||
```tsx
|
||
const bodyFontEn = createFont({
|
||
family: '"Helvetica"',
|
||
// ... per-font design tokens
|
||
})
|
||
|
||
const bodyFontMandarin = createFont({
|
||
family: '"Helvetica Mandarin"',
|
||
// ... per-font design tokens
|
||
})
|
||
|
||
export const config = createGui({
|
||
fonts: {
|
||
body: bodyFontEn,
|
||
body_mandarin: bodyFontMandarin,
|
||
},
|
||
})
|
||
```
|
||
|
||
Then you can change the family to Mandarin at any point in your React tree, with
|
||
types working as expected:
|
||
|
||
```tsx
|
||
import { FontLanguage, Text } from '@hanzo/gui' // or '@hanzogui/core'
|
||
|
||
export default () => (
|
||
<FontLanguage body="mandarin">
|
||
<Text fontFamily="$body">{/* TODO hello world in mandarin */}</Text>
|
||
</FontLanguage>
|
||
)
|
||
```
|
||
|
||
#### `config.fonts.[fontname].face`
|
||
|
||
React Native makes loading fonts a bit trickier than the web, and the easiest
|
||
way to do it involved naming your font family differently per-weight. On the web
|
||
you'd have `Helvetica` and just change `font-weight`, but on Native you set the
|
||
family from `Helvetica` to `Helvetica Bold` instead of the weight.
|
||
|
||
Gui added support for this through
|
||
[the `face` option on font configurations]().
|
||
|
||
### The `themeShallow` prop
|
||
|
||
The `theme` prop in Gui by default will re-theme all sub-component. Gui
|
||
now supports the boolean `themeShallow` prop on any Gui component, which
|
||
will _only_ theme that exact component, leaving all children components with the
|
||
same theme as their parent.
|
||
|
||
### Helpers
|
||
|
||
#### The `loadTheme` and `updateTheme` helpers
|
||
|
||
Themes load in a large variety of tokens for spacing, sizing, radius, colors,
|
||
and more. They are incredibly powerful, but they also have some cost in bundle
|
||
size.
|
||
|
||
The `loadTheme` utility function means you can only load the default themes you
|
||
want to serve, saving on bundle size, and then add in alternative themes later
|
||
on.
|
||
|
||
Meanwhile `updateTheme` gives you the ability to dynamically modify themes on
|
||
the fly, changing any of their values. On the web, themes work through CSS
|
||
variables, meaning `updateTheme` is incredibly fast as it avoids all React
|
||
re-rendering if no theme values are currently being relied on for dynamic
|
||
styles.
|
||
|
||
#### The `useMediaPropsActive` hook
|
||
|
||
This hook is useful for authoring your own custom components built on Gui.
|
||
The Gui UI kit makes use of this hook extensively. Gui has a philosophy
|
||
that everything Just Works™️ at runtime as well as compile-time. The
|
||
compile-time side just makes it all a lot faster. By working fully at runtime,
|
||
it means you have more flexiblity (no need to use any plugins at all), but also
|
||
lots of power. For example, if Gui didn't work fully runtime, you couldn't
|
||
support animations with your design system at all.
|
||
|
||
The `useMediaPropsActive` is an important part of that functionality, making it
|
||
easy to properly access the "currently active" set of styles given the current
|
||
screen size. Here's an example:
|
||
|
||
```tsx
|
||
import { Stack, StackProps, useMediaPropsActive } from '@hanzo/gui' // or '@hanzogui/core'
|
||
|
||
const CustomWidget = (props: StackProps) => {
|
||
const activeProps = useMediaPropsActive(props)
|
||
|
||
console.log(`The current color for this screen size is`, activeProps.backgroundColor)
|
||
|
||
return <Stack {...modifyProps(activeProps)} />
|
||
}
|
||
|
||
export default () => (
|
||
<CustomWidget
|
||
backgroundColor="red"
|
||
$large={{
|
||
backgroundColor: 'green',
|
||
}}
|
||
/>
|
||
)
|
||
```
|
||
|
||
---
|
||
|
||
## Overview of `@hanzogui/static`
|
||
|
||
[Static](/docs/intro/why-a-compiler) is a babel and node-based optimizing
|
||
compiler, specifically for frontend React code. It supports web and native
|
||
through a plugin interface that has adapters for Webpack, Vite, Next, React
|
||
Native, and Expo. Over a dozen major improvements to the compiler have made
|
||
their way in since beta. Some of the highlights are:
|
||
|
||
On the web, render performance is much improved, especially for interactive
|
||
(pseudo) and responsive (media query) styles. It improves Lighthouse scores
|
||
10-25%.
|
||
|
||
<Image
|
||
title="The compiler improves the Lighthouse score of the homepage of https://hanzogui.dev from 85 to 96"
|
||
src="/banner-lighthouse.jpg"
|
||
size="hero"
|
||
height={325}
|
||
width={761}
|
||
resizeMode="contain"
|
||
mt="$2"
|
||
mb="$4"
|
||
/>
|
||
|
||
For more information on how it works and why it's important, read our
|
||
[introduction to the compiler article](/docs/intro/why-a-compiler).
|
||
|
||
---
|
||
|
||
## What's new in `@hanzogui/static`
|
||
|
||
### Performance
|
||
|
||
The compiler uses `babel` to parse and optimize components, which it can get
|
||
away with for performance largely because it only needs to parse a subset of
|
||
your files, and it only needs to look for a few areas - namely JSX elements and
|
||
`styled()` functions.
|
||
|
||
During the beta we landed many performance improvements bringing average parse
|
||
time down to below 6ms for a longer file on a modern laptop. By default now
|
||
Gui avoids parsing many more files through quick heuristics. It's now also
|
||
fully thread-safe, uses more caching, and has been fine-tuned for memory usage.
|
||
|
||
### Coverage
|
||
|
||
Previously, Gui Static only knew how to optimize components found in your
|
||
separated design system package. But it's both common and desirable to have
|
||
one-off `styled()` definitions that are just used for small areas of your app
|
||
that live alongside those areas, outside your design system.
|
||
|
||
The compiler now supports analyzing components outside of just your design
|
||
system, allowing for even less friction when writing apps. It means you can put
|
||
your `styled()` definitions _anywhere_ without worrying, and Gui Static will
|
||
load and optimize those components as it discovers them.
|
||
|
||
### Vite support
|
||
|
||
Gui now fully works [with Vite 3 and 4](/docs/guides/vite), both with the
|
||
compiler and without. A simple `vite.config.js` would look like this:
|
||
|
||
```tsx
|
||
import { hanzoguiPlugin } from '@hanzogui/vite-plugin'
|
||
import react from '@vitejs/plugin-react-swc'
|
||
import { defineConfig } from 'vite'
|
||
|
||
export default defineConfig({
|
||
clearScreen: false,
|
||
plugins: [
|
||
react(),
|
||
hanzoguiPlugin({
|
||
components: ['@hanzo/gui'],
|
||
config: 'hanzogui.config.ts',
|
||
}),
|
||
],
|
||
})
|
||
```
|
||
|
||
### Correctness
|
||
|
||
Most of the work during beta focused on correctness. We've increased testing to
|
||
cover many more areas, and landed a number of important correctness fixes
|
||
alongside the ones in `core`.
|
||
|
||
---
|
||
|
||
## Overview of Gui
|
||
|
||
Gui UI is a suite of React components and hooks that adapt nicely to both
|
||
Native and Web.
|
||
|
||
- Every component works on Native and Web and adapts properly to each platform.
|
||
- Lightweight default styles included but completely customizable.
|
||
- **Complete theme control** - totally transform the look and feel down to
|
||
individual components without fuss, even avoiding re-renders on theme changes
|
||
(web).
|
||
- **Complete size control** - every component can be scaled up/down based on
|
||
your custom design system tokens.
|
||
- **Compound Component APIs** - enabling much more control over styling.
|
||
- A novel **Adapt** component allows for completely changing UI based on
|
||
platform and media query.
|
||
|
||
---
|
||
|
||
## What's new in Gui
|
||
|
||
### A whole lot of new components 🎁
|
||
|
||
We've seen the addition of seven new components. Each comes with compound
|
||
component API for much more complete control over each piece of the components
|
||
visuals and behavior.
|
||
|
||
We owe thanks to both [Radix](https://www.radix-ui.com) and
|
||
[Floating UI](https://floating-ui.com) for making these much easier to build.
|
||
|
||
Like the existing components in Gui, every new component is sizable,
|
||
themeable, and able to be automatically styled using your design system.
|
||
|
||
The new components are:
|
||
|
||
#### Sheet
|
||
|
||
<HeroContainer tinted>
|
||
<SheetDemo />
|
||
</HeroContainer>
|
||
|
||
This was an excellent test of the unified animation drivers on Gui, and
|
||
unified interaction primitives of React Native, and we're happy with how it's
|
||
turned out.
|
||
|
||
Internally, we've come up with some helpers for each animation driver to support
|
||
a consistent API for taking a number value and interpolating it with some style
|
||
properties. Each driver handles this quite differently on the surface, but the
|
||
Gui drivers now give a consistent interface across them all.
|
||
|
||
#### Select
|
||
|
||
<HeroContainer tinted>
|
||
<SelectDemo />
|
||
</HeroContainer>
|
||
|
||
#### Dialog
|
||
|
||
[Show content in a Dialog](/docs/components/dialog) that can adapt to another
|
||
component depending on the screen size.
|
||
|
||
<HeroContainer tinted>
|
||
<DialogDemo />
|
||
</HeroContainer>
|
||
|
||
```tsx hero template=Dialog
|
||
|
||
```
|
||
|
||
#### AlertDialog
|
||
|
||
Show a Dialog specialized for confirming or denying an action
|
||
[with AlertDialog](/docs/components/alert-dialog).
|
||
|
||
<HeroContainer tinted>
|
||
<AlertDialogDemo />
|
||
</HeroContainer>
|
||
|
||
```tsx hero template=AlertDialog
|
||
|
||
```
|
||
|
||
AlertDialog is the first of our components to include the `native` prop. When
|
||
set to true, it adapts the element to use platform native visual containers when
|
||
possible. For AlertDialog, this means that on iOS and Android, you'll see a
|
||
native Alert dialog prompt.
|
||
|
||
#### Slider
|
||
|
||
A [draggable Slider](/docs/components/slider) allows users to input values
|
||
within a range.
|
||
|
||
<HeroContainer tinted>
|
||
<SliderDemo />
|
||
</HeroContainer>
|
||
|
||
```tsx hero template=Slider
|
||
|
||
```
|
||
|
||
#### Label
|
||
|
||
Label has been updated to work with all the new form inputs.
|
||
|
||
<HeroContainer tinted>
|
||
<LabelDemo />
|
||
</HeroContainer>
|
||
|
||
```tsx hero template=Label
|
||
|
||
```
|
||
|
||
#### Card
|
||
|
||
Display content with a header, footer, background image, title, subtitle and
|
||
description [using Card](/docs/components/card).
|
||
|
||
<HeroContainer tinted>
|
||
<CardDemo />
|
||
</HeroContainer>
|
||
|
||
```tsx hero template=Card
|
||
|
||
```
|
||
|
||
#### ListItem
|
||
|
||
[ListItem](/docs/components/list-item) allows you to display content with a
|
||
title, subtitle, before and after images or icons, and more.
|
||
|
||
<HeroContainer tinted>
|
||
<ListItemDemo />
|
||
</HeroContainer>
|
||
|
||
```tsx hero template=ListItem
|
||
|
||
```
|
||
|
||
#### Avatar
|
||
|
||
<HeroContainer tinted>
|
||
<AvatarDemo />
|
||
</HeroContainer>
|
||
|
||
```tsx hero template=Avatar
|
||
|
||
```
|
||
|
||
#### Spinner
|
||
|
||
<HeroContainer tinted>
|
||
<SpinnerDemo />
|
||
</HeroContainer>
|
||
|
||
```tsx hero template=Spinner
|
||
|
||
```
|
||
|
||
#### Progress
|
||
|
||
<HeroContainer tinted>
|
||
<ProgressDemo />
|
||
</HeroContainer>
|
||
|
||
```tsx hero template=Progress
|
||
|
||
```
|
||
|
||
#### XGroup and YGroup
|
||
|
||
<HeroContainer tinted>
|
||
<GroupDemo />
|
||
</HeroContainer>
|
||
|
||
The `Group` component has been split into
|
||
[XGroup and YGroup](/docs/components/group) to match Stacks. It's been upgraded
|
||
across the board with the ability to be scrollable and to better handle passing
|
||
children styles.
|
||
|
||
#### ScrollView
|
||
|
||
Gui [now exports ScrollView](/docs/components/scroll-view), the exact same
|
||
as React Native ScrollView but with all Gui props supported.
|
||
|
||
---
|
||
|
||
## What else is new
|
||
|
||
### Apps
|
||
|
||
#### The Kitchen Sink
|
||
|
||
The monorepo now includes `apps/kitchen-sink`, a native app that demos every
|
||
component that comes in Gui. This has helped us quickly iterate and improve
|
||
components and their correctness across Android and iOS. Android especially
|
||
received a wide variety of fixes during the betas.
|
||
|
||
#### Starter repos
|
||
|
||
`create-gui` underwent some big improvements that will set it up to be much
|
||
more useful going forward. We moved starters into the monorepo, which was tricky
|
||
but lets us iterate much more rapidly on them and test them e2e for each
|
||
release. We're using a custom `~/.hanzogui` home directory and git clone that
|
||
gives us a much smoother upgrade experience, especially in future versions. The
|
||
`starer-free` starter repo has had extensive polish as well, simplifying the
|
||
setup, removing the need for watch commands, and properly building to production
|
||
across all features for web, iOS and Android.
|
||
|
||
### Features
|
||
|
||
#### React Native Animation Driver
|
||
|
||
We added a new animation driver, `@hanzogui/animations-react-native` that works
|
||
with the built-in Animation API of React Native. This is in addition to the
|
||
existing `@hanzogui/animations-css` and `@hanzogui/animations-reanimated` drivers.
|
||
The advantages of this driver are that you pay no extra cost for spring
|
||
animations on the web when you're already using `react-native-web`, and a
|
||
simpler setup compared to Reanimated.
|
||
|
||
#### SSR and React Server Components
|
||
|
||
During the beta we landed a wide variety of correctness fixes, tests and runtime
|
||
safeguards for SSR and landed early support for React Server Components. We've
|
||
tested them in early versions of Hydrogen and Next.js and they should generally
|
||
work when the environment variable `ENABLE_RSC` is set.
|
||
|
||
#### Vite Plugin + Vite Compiler
|
||
|
||
We've landed Vite support. Check out [the Vite guide](/docs/guides/vite) for how
|
||
to install Gui with Vite.
|
||
|
||
#### react-native-web-lite
|
||
|
||
As a temporary measure, we released a modernized version of `react-native-web`.
|
||
It improves tree shaking, lands complete concurrent support for React 18, and
|
||
strips out a few deprecated areas.
|
||
|
||
#### Concurrent Mode Support
|
||
|
||
We've updated Gui's base React version to be 18, and landed a large amount
|
||
of fixes relating to concurrent mode. Every feature in Gui now fully
|
||
supports concurrent mode, and with `react-native-web-lite`, so does every
|
||
feature in the React Native API surface for web.
|
||
|
||
#### `@hanzogui/next-theme`
|
||
|
||
See the [Next.js guide](/docs/guides/next-js) for more on how to use this
|
||
helpful library that automatically handles light/dark/system color scheme
|
||
preferences.
|
||
|
||
#### `@hanzogui/theme-base` upgrades
|
||
|
||
The default theme package now includes `_active` sub-themes, paving the way for
|
||
a consistent way to style all active states across every component in `hanzogui`.
|
||
|
||
It also now includes theme values for `color1` => `color12` as part of each
|
||
theme. This gives you granular access outside of the more specific color values
|
||
like `background`, or `borderColor`.
|
||
|
||
#### Usage in production
|
||
|
||
Gui now has several apps in production in both app stores. One larger one
|
||
built by a household name company is currently under NDA, but we can announce
|
||
soon. We're proud of how active the Discord has become with users building high
|
||
quality apps!
|
||
|
||
### Polish
|
||
|
||
#### Correctness
|
||
|
||
More than any other section in this release, the biggest amount of effort for
|
||
1.0 went into correctness. Gui has steadily landed fixes across every
|
||
feature and component since Beta, and the difference between early this year and
|
||
now is astounding, with a ton of edge cases handled automatically now.
|
||
|
||
#### Community
|
||
|
||
We've been building a great community,
|
||
[especially on Discord](https://discord.gg/4qh6tdcVDa). Check out
|
||
[the Community page](/community) for more information including diverse
|
||
community-maintained starter kits and Figma files.
|
||
|
||
#### Documentation
|
||
|
||
The docs have undergone continuous improvements. The compiler now has
|
||
[an extensive article breaking down the whys and hows of how it works](/docs/intro/why-a-compiler).
|
||
And all the guides have been iterated on and tested from scratch to verify they
|
||
work.
|
||
|
||
#### Testing
|
||
|
||
We've expanded our testing signficantly: 10x more tests, package.json linting,
|
||
full CI/CD, stricter linting in general, and a few big integration tests.
|
||
|
||
---
|
||
|
||
## Going forward
|
||
|
||
Gui is stable and free of all blocking bugs across every feature, but
|
||
there's a so much more to go to make every part of it simpler, lighter, faster,
|
||
and more correct both in types and behavior.
|
||
|
||
Writing about what comes after 1.0 is a blog post to itself. For now,
|
||
[next.md](https://github.com/hanzoai/gui/blob/main/next.md) is a living
|
||
document of upcoming features and fixes.
|
||
|
||
The next few minor releases will focus on improving types, accessibility,
|
||
animations, test coverage, and solidifying the newer components. We'll be
|
||
setting up stricter release processes, and improving contributor experience.
|
||
|
||
There are many exciting features on the table as well, including:
|
||
|
||
- Improving dynamic inline evaluation.
|
||
- Container queries.
|
||
- Descendent styling ala `a:hover p`.
|
||
- `hanzogui build` - build to plain css and JS for compatibility with any
|
||
bundler.
|
||
- Adding the `native` prop for platform-specific output on Select, Dialog,
|
||
Popover, Sheet and more.
|
||
- `<Theme />` custom tokens.
|
||
- `<Debug />` to show nice visualizations of what's happening inside an entire
|
||
tree of components.
|
||
- `<Skeleton />` to automatically render skeleton variants for every component
|
||
in a tree.
|
||
- `<Menu />`, `<Radio />` or `<Toggle />` equivalent, `<Tabs />`,
|
||
`<Accordion />`, `<Autocomplete />` and more.
|
||
- Adding pseudo `focusWithinStyle`.
|
||
- Breakpoints as token values allowing `height="$lg"`.
|
||
|
||
---
|
||
|
||
## Sponsors
|
||
|
||
<IntroParagraph>Gui is fully funded by GitHub Sponsors.</IntroParagraph>
|
||
|
||
I love working on Gui, and there's a wealth of concrete and interesting ways
|
||
for it to mature. The motivation is to take things slowly, do them right, and
|
||
stay fully OSS.
|
||
|
||
<IntroParagraph>
|
||
In order to make this work, I'll need sponsors, and I want to make that worth it. I'm
|
||
setting up a range of pretty cool **Sponsor Benefits** going forward:
|
||
</IntroParagraph>
|
||
|
||
- New features as they are being developed.
|
||
- Early access to source code.
|
||
- Nightlies, access to a private npm org.
|
||
- Private chat at higher levels.
|
||
- **Early access to upcoming Studio, Docs** and other apps:
|
||
|
||
<Spacer />
|
||
<XStack space ai="stretch" maw="100%" $sm={{ fd: 'column' }}>
|
||
<Card flex={1} title="📚 Docs">
|
||
Your design system and UI auto-generates a beautiful docs site, just like
|
||
hanzogui.dev.
|
||
</Card>
|
||
<Card flex={1} title="🖼️ Studio">
|
||
A frontend realtime editor for colors, themes, tokens, default styles and more.
|
||
</Card>
|
||
<Card flex={1} title="❓·····">
|
||
A simpler way to build universal apps.
|
||
</Card>
|
||
</XStack>
|
||
<Spacer />
|
||
|
||
<XStack space my="$-4">
|
||
<Image
|
||
linked
|
||
resizeMode="contain"
|
||
width={420}
|
||
height={350}
|
||
src="/screen-studio-colors.webp"
|
||
/>
|
||
<Image linked resizeMode="contain" width={420} height={350} src="/screen-studio.webp" />
|
||
</XStack>
|
||
<Aside>The Gui Studio, early beta</Aside>
|
||
<Spacer />
|
||
|
||
Docs can run alongside Studio in the future as part of a suite of tools for your
|
||
frontend. Studio will have realtime collaboration and allows you to edit your
|
||
apps themes live with HMR. Tweak colors, themes, tokens, styles, icons, fonts,
|
||
and more across every pseudo state on every component.
|
||
|
||
Studio hooks into your app at runtime to achieve this thanks to the big work
|
||
we've aleady done pre-analyzing your components and their types and props.
|
||
|
||
It will also export and import between JSON and Figma.
|
||
|
||
Please do consider sponsoring!
|
||
|
||
<Spacer />
|
||
<SponsorButton />
|
||
|
||
---
|
||
|
||
## Acknowledgements
|
||
|
||
We've had 38 new contributors since early this year, exponentially increasing!
|
||
Thanks to all of them, and also to the many QA testers that join in our Discord
|
||
chat every day :).
|
||
|
||
Early sponsors have made a huge difference: I owe a large thank you to
|
||
[Vercel](https://vercel.com), [Codingscape](https://codingscape.com),
|
||
[QuestPortal](https://www.questportal.com) and [BeatGig](https://beatgig.com),
|
||
the first corporate sponsors ❤️.
|
||
|
||
Gui draws inspiration and small areas of code from some incredible other
|
||
libraries: [Radix](https://www.radix-ui.com/) provided much of the compound
|
||
component APIs, [Floating UI](https://floating-ui.com/) handles all of the
|
||
floating elements positioning, [Moti](https://moti.fyi) which served as a start
|
||
point for the animation drivers, and
|
||
[Framer Motion](https://github.com/framer/motion) for the nifty AnimatePresence
|
||
functionality.
|
||
|
||
---
|
||
|
||
### Join the community
|
||
|
||
<Wide>
|
||
<SocialLinksRow />
|
||
</Wide>
|