Files
2026-09-04 09:04:51 -07:00

700 lines
28 KiB
Plaintext

---
title: Gui 2
publishedAt: '2025-12-29'
description: More stable, easy, documented, fast, and feature-complete.
by: nate
image: /blog/version-two.jpg
---
<IntroParagraph large>
Gui brings high performing, consistent, typed inline styles to React Native and React
Web, plus composable UI components, a novel theme system and an optimizing compiler.
</IntroParagraph>
We're excited to announce **the first release candidate for Gui v2 is
here**!
We'll do a little housekeeping first, so if you want to,
[skip to what's new](#new-in-v2).
### What makes it great
Gui brings many style features from CSS to native. Every style it supports
works on both native and web, at both run-time and compile-time, and server-side
as well as client-side.
In comparison to other solutions, Gui is especially strong at:
- **Many features, high performance everywhere.** Other solutions prioritize one
platform, and bail out of the hard parts of web performance that require a
compiler _and_ a lot of careful work to get right. Some examples of large
areas Gui does well - SSR safe spring animations, SSR safe light-dark
themes, SSR safe media queries and Container all the above features working
with CSS or springs, and so on.
- **Top tier performance everywhere.** A small example - you can choose from 4
animation drivers (CSS, Reanimated, Motion, React Native), per-platform, yet
no matter which you choose you get proper SSR support—even media queries and
dark mode render and hydrate without jumps or flickers.
- **Type-safe inline styling that merges and optimizes.** Inline styles are
productivity boosts, but Gui adds type safety, easy/controllable merging,
and an optimizing compiler that does partial analysis to optimize even
logic-filled styling. It's an underrated boost to productivity.
- **Refined, styled and unstyled composable components.** Great on web and
native thanks to composable components, native adaptation, the Adapt
primitive, and a lot of iteration.
- **Robust.** Gui has been developed actively for years, proven in
[large apps](https://uniswap.org), and has more than tripled test coverage
just in the last year.
### During v1
- **8,500+ commits** over 2 years (~330/month).
- **900+ issues closed**.
- **136 new contributors** (from 46 to 182 total).
- **289 test files** with kitchen-sink tests running across all 4 animation
drivers, plus many new deeper native integration tests with both Detox and
Maestro.
- Released
[`@hanzogui/build`](https://github.com/hanzoai/gui/blob/v2/pkgs/build/README.md),
which makes it trivial to publish npm packages that support CommonJS and
ESModules, native and web without requiring any configuration at all when
importing - whether it's Metro, Node, Vite, or otherwise.
- Platform, theme, and container queries, plus combined container and media
queries.
- New compound components [Tabs](/docs/components/tabs),
[Accordion](/docs/components/accordion),
[ToggleGroup](/docs/components/toggle-group).
- New unstyled versions of most components.
- A lot of low level work on performance, documentation, our CLI, and more.
- Improved theme generation packages, and the powerful
[free and paid theme builder](/theme).
[![Theme Generator examples](/blog/theme-generator-showcase.webp)](/theme/37/nike-neon)
## New in v2
Version 2 is a huge release but the migration from v1 should only be moderate.
We removed mostly deprecated APIs, aligned to web and modern React Native,
improved performance and native library integrations, and dropped a few new
features and components.
Find a [list of breaking changes at the bottom of the post](#breaking-changes).
<Notice>Give this blog post URL to your favorite coding agent to help upgrade!</Notice>
### Features
#### Config v5
The default Gui configuration has been upgraded to v5 with a more complete
design system and easier customization. See the
[Config v5 docs](/docs/core/config-v5) for full details.
**More color themes** - V5 adds gray, orange, pink, purple, teal, and neutral to
the existing blue, red, yellow, and green palettes, all using Radix Colors v3
for improved accessibility.
**Opacity tokens** - New foreground and background opacity variants make subtle
overlays and borders easy: `$color01`, `$color0075`, `$color005`,
`$background01`, and more.
**Shadow colors** - Pre-tuned shadow opacities (`$shadow1` through `$shadow6`)
that work well in both light and dark modes.
**Expanded media queries** - Height-based queries (`$height-xs`, `$height-sm`,
etc.), a `$pointerTouch` query for touch detection, and renamed size queries
(`$xxl`, `$xxs`, `$xxxs`). The `$sm` through `$xxl` breakpoints now match
Tailwind CSS exactly (640, 768, 1024, 1280, 1536), making it easier to work
across both ecosystems. The smaller breakpoints (`$xxxs`, `$xxs`, `$xs`) are
designed for container queries where you need finer control below 640px.
**Easy customization** - The new `createV5Theme` helper lets you add or override
color themes with minimal boilerplate, working directly with `@hanzogui/colors`.
**Subtle variant** - Import from `@hanzogui/config/v5-subtle` for a more muted,
desaturated color palette. Or use `adjustPalette` and `adjustPalettes` to create
your own custom color transformations.
#### New Styles
See the [Style API docs](/docs/intro/styles) for the full reference, some
highlights:
- **`backgroundImage`** - CSS `linear-gradient` and `radial-gradient` syntax
with token support.
- **`boxShadow`** - Full CSS box-shadow support including multiple shadows,
spread, and inset. Accepts strings with your tokens.
- **`filter`** - Graphical filters like `brightness`, `opacity`, `blur`.
- **`mixBlendMode`** - Blend modes like `multiply`, `screen`, `overlay`, etc.
- **`isolation`** - Creates a new stacking context (`auto` | `isolate`)
- **`boxSizing`** - Box model (`border-box` | `content-box`).
- **`display`** - Pass-through with `contents`.
- **`position`** - Now accepts `fixed`, automatically converted to `absolute` on
native. For easier media queries like `$md={{ position: 'fixed' }}`.
- **`borderCurve`** - Corner curve style (`circular` | `continuous` for Apple's
"squircle"). iOS 13+ only.
- **`cursor`** - Cursor style. Full CSS values on web; `auto` | `pointer` on iOS
17+ (trackpad/stylus).
- **`textShadow`** - CSS text-shadow shorthand with token support:
`textShadow="2px 2px 4px $shadowColor"`. On native, only single shadows
supported.
- **`border`** - CSS border shorthand with token support:
`border="1px solid $borderColor"`. On native, expands to individual width,
style, and color properties.
- **`outline`** - CSS outline shorthand with token support:
`outline="2px solid $outlineColor"`. On native, expands to `outlineWidth`,
`outlineStyle`, and `outlineColor`.
### New Components
#### Menu
[Menu](/docs/components/menu) provides dropdown menus with full keyboard
navigation, submenus, checkbox items, and animations. On iOS and Android, it
automatically renders using native platform menus.
<HeroContainer>
<MenuDemo />
</HeroContainer>
```tsx hero template=Menu
```
#### ContextMenu
[ContextMenu](/docs/components/context-menu) works like Menu but activates on
right-click (web) or long-press (native). It includes support for preview
content on iOS.
<HeroContainer>
<ContextMenuDemo />
</HeroContainer>
```tsx hero template=ContextMenu
```
#### Input & TextArea
<HeroContainer demoMultiple>
<NewInputsDemo />
</HeroContainer>
```tsx hero template=Inputs
```
Input has been rewritten from scratch with a web-first approach - you write
standard HTML input attributes and Gui automatically converts them to React
Native equivalents on native platforms:
```tsx
// Web-standard API that works everywhere
<Input type="email" enterKeyHint="send" />
<Input type="password" />
<Input type="tel" />
```
This replaces the React Native-style props like `keyboardType`,
`secureTextEntry`, and `returnKeyType` with their web equivalents. The old props
still work but are deprecated. See the [Input docs](/docs/components/inputs) for
the full migration guide.
#### Image
The [Image](/docs/components/image) component follows the same web-first
philosophy as Input. It uses standard HTML `<img>` attributes like `src`, `alt`,
`loading`, and `decoding` as the primary API, with automatic conversion to React
Native equivalents on native.
On native, you can choose your image loading adapter - use the built-in React
Native Image, or integrate with optimized libraries like `expo-image` or
`react-native-fast-image` for better caching and performance.
#### Sheet, Button, ListItem, Select
All were re-written internally to retain much the same API surface, but align
better to the web, and run dramatically faster and better.
Select on web and Sheet on native got big upgrades.
### Motion Animation Driver
![Motion animation library banner](/blog/motion-banner.webp)
The all powerful [Motion animation library](https://motion.dev) comes to Gui
as an [animation driver](/docs/core/animations-motion), bringing real innovation
to web aimations.
The driver is still somewhat experimental, we're still working through some very
subtle issues with sending updates rapidly, and are working them to isolate it.
What makes this even more interesting is that Gui completely re-wrote the
internal component logic to allow a new `avoidReRenders` path option for
animation drivers. When true, all group, media, pseudo, and some theme styles
all move out of React.
Combined with Motion's support of the off-thread
[Web Animations API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Animations_API),
and it makes for really incredibly smooth feeling apps.
We noticed a large gain in performance in a large app by just swapping to the
driver, and the animations feel great — see them for yourself on this site. Just
note, there's a can be occasionally hiccups with some enter styles. There's a
way to work around this, but then you de-opt other parts. We're sure we'll get
Motion out of beta soon, and even in it's current state it's worth considering.
### Reanimated Driver
The [Reanimated](https://docs.swmansion.com/react-native-reanimated/) driver
comes back in style with `worklet` and `avoidReRenders` support. This means
animations run entirely on the UI thread without triggering React re-renders,
giving you much better performance for complex animations on both web and
native.
The Moti driver (`@hanzogui/animations-moti`) is now deprecated in favor of the
[Reanimated driver](/docs/core/animations-reanimated)
(`@hanzogui/animations-reanimated`). This removes a dependency and fixes some
compatibility issues. If you're using `@hanzogui/animations-moti`, switch to
`@hanzogui/animations-reanimated` - the API is the same.
#### Swap Animation Drivers Inline
You can now configure multiple animation drivers and select per-component using
the new `animatedBy` prop. This serves two important purposes: it allows mixing
drivers more granularly, and it enables the compiler to better optimize. See the
[animation drivers docs](/docs/core/animation-drivers#multiple-drivers) for full
details.
```tsx
// Config with multiple drivers up front
createGui({
animations: {
default: cssDriver,
spring: reanimatedDriver,
},
})
// Select per-component - compiler can optimize knowing the driver
<View animatedBy="spring" transition="bouncy" />
```
The compiler can optimize better with this pattern, and you can now lazy load a
driver with a function:
```tsx
import { loadAnimationDriver } from '@hanzo/gui'
loadAnimationDriver('spring', reanimatedDriver)
```
#### Transition Delay
All animation drivers now support delays:
```tsx
<View transition={['bouncy', { delay: 200 }]} />
```
This works with CSS, React Native Animated, Reanimated, and Motion drivers.
#### Enter/Exit Transition Control
The `transition` prop now supports different animations for enter and exit. This
is useful for creating asymmetric animations where elements enter slowly but
exit quickly, or vice versa:
```tsx
// slow enter, fast exit
<View
transition={{ enter: 'lazy', exit: 'quick' }}
enterStyle={{ opacity: 0 }}
exitStyle={{ opacity: 0 }}
/>
// with a default for property changes while mounted
<View
transition={{ enter: 'lazy', exit: 'quick', default: 'bouncy' }}
/>
// array syntax with delay and per-property config
<View
transition={['bouncy', { enter: 'lazy', exit: 'quick', delay: 200 }]}
/>
```
This works on all four animation drivers. See the
[animation docs](/docs/core/animations#enterexittransitions) for more details.
#### Pseudo-Style Transitions
Pseudo-style props (`hoverStyle`, `pressStyle`, `focusStyle`) now support their
own `transition` property. This enables CSS-like semantics where entering a
state uses that state's transition, and exiting uses the base transition:
```tsx
<Square
transition="1000ms" // slow exit (back to base)
hoverStyle={{
transition: '200ms', // fast enter
backgroundColor: 'red',
}}
/>
```
This pattern creates snappy, responsive interactions where elements react
quickly to user input but settle back smoothly. Works with group pseudo states
too (`$group-card-hover`). See the
[animation docs](/docs/core/animations#pseudo-style-transitions) for details.
#### Popover `transform-origin`
[Popover](/docs/components/popover) and [Tooltip](/docs/components/tooltip) now
automatically calculate the correct CSS `transform-origin` based on placement
and arrow position. This means scale animations naturally "grow" from the anchor
point where the content connects to the trigger.
The transform origin adjusts automatically based on the final placement - if the
popover flips from `bottom` to `top`, the origin updates accordingly. This
creates polished, native-feeling animations without any manual configuration.
#### Consistent Active Styling
Components with toggle/selection states now support consistent `activeStyle` and
`activeTheme` props for styling their active states:
- [**Switch**](/docs/components/switch) - Styles applied when the switch is on
- [**Checkbox**](/docs/components/checkbox) - Styles applied when checked
- [**ToggleGroup.Item**](/docs/components/toggle-group) - Styles applied when
the item is selected
- [**Tabs.Tab**](/docs/components/tabs) - Styles applied when the tab is active
```tsx
// Apply custom styles when active
<Switch activeStyle={{ backgroundColor: '$green8' }} />
// Or apply a theme when active
<Checkbox activeTheme="green" />
// Works inline or via styled()
const GreenTab = styled(Tabs.Tab, {
activeStyle: {
backgroundColor: '$green9',
},
})
```
This replaces a variety of inconsistent APIs in v1.
#### Faster, Lighter, more Consistent Components
Several components have been significantly simplified:
[**Button**](/docs/components/button) - Rewritten from scratch with ~60% less
code. No longer uses the slow `useProps` hook internally. Now supports all
web-standard HTML button attributes (`type`, `formAction`, `formMethod`, `name`,
`value`, `popoverTarget`, etc.). Defaults to `type="button"` to prevent
accidental form submissions.
[**ListItem**](/docs/components/list-item) - Rebuilt with context-based styling.
Removed text style props (`fontFamily`, `fontSize`, etc.) and internal spacing
props (`spaceFlex`, `scaleSpace`) for composable component API. Much faster
rendering.
[**Select**](/docs/components/select) - SelectItem is based on ListItem so is
likewise much faster, and gains an optional floating indicator. SelectLabel is
now a simpler SizableText-based component instead of depending on ListItem.
**Icons** - Themed icons now use a fast path that skips the heavy style
resolution when no media queries are used, significantly reducing re-renders in
apps with many icons.
[**Progress**](/docs/components/progress) - Now SSR-friendly with
percentage-based transforms on web that render correctly without client-side
hydration. Bouncy animations no longer overshoot past the container edges.
[**Tabs**](/docs/components/tabs) - `activeStyle` and `activeTheme` props
replace the old `Theme` wrapper approach. `activationMode` now defaults to
`'manual'` (click/Enter to activate) matching web standards.
[**Group**](/docs/components/group) - Dramatically simplified. No more magic
child cloning.
#### Headless and Unstyled Components
We're expanding headless components in v2. Many components now have three
variants:
- **Styled** - Full Gui components with default styles
- **Unstyled** - Uses a `createX` factory allowing fully custom styling
- **Headless** - Zero dependency on `@hanzogui/core`, just hooks
The headless packages (`@hanzogui/switch-headless`, `@hanzogui/checkbox-headless`,
`@hanzogui/radio-headless`, `@hanzogui/tabs-headless`) provide hooks like
`useSwitch`, `useCheckbox`, `useRadioGroup`, and `useTabs` that handle all the
state management, accessibility, and keyboard navigation - letting you bring
your own styling solution.
This makes Gui components usable even if you're not using Gui for
styling. For now it's a subset, but we plan to continue expanding headless
exports throughout v2.
#### @hanzogui/react-native-web-lite
React Native Web has slowed down development and has various issues in modern JS
projects. We built `@hanzogui/react-native-web-lite` by translating
`react-native-web` to TypeScript, moving to a modern ESModule setup, and
enabling tree shaking.
If you're using Gui for most styling, you can save a significant amount of
bundled JS on web by aliasing to this package. It's not perfectly compatible
with `react-native-web` - it strips out the style system to share Gui
internals - but for Gui-first apps, it's a nice optimization.
#### Component Scope
[Dialog](/docs/components/dialog), [Popover](/docs/components/popover),
[Sheet](/docs/components/sheet), and [Tooltip](/docs/components/tooltip) now
support a `scope` prop that lets you mount a single instance at your app's root
while placing triggers anywhere in your tree. **This is a significant
performance win** - in testing with large apps, we found it greatly improved UX
by eliminating the overhead of mounting full overlay components inline.
Instead of each Tooltip or Popover in a list rendering its own portal, content,
and animation logic, you mount one instance at the root and scatter lightweight
triggers throughout your app. The triggers are just simple components that
communicate with the shared instance via context.
```tsx
// _layout.tsx - mount once at root with your providers
<GuiProvider>
<Tooltip scope="global">
<Tooltip.Content>
<Tooltip.Arrow />
<Paragraph>{/* label set by trigger */}</Paragraph>
</Tooltip.Content>
{/* rest of your app */}
<Slot />
</Tooltip>
</GuiProvider>
// anywhere in your app - just the trigger
<Tooltip.Trigger scope="global" aria-label="Settings">
<Button icon={Settings} />
</Tooltip.Trigger>
```
This pattern is especially valuable for data-heavy views like tables, lists, or
dashboards where you might have dozens or hundreds of interactive elements that
need tooltips or popovers.
### New Colors
`@hanzogui/colors` has been updated to Radix v3, old colors are available at
`@hanzogui/colors/legacy`. See the [Colors docs](/docs/intro/colors) for full
details.
### Compiler Improvements
The [compiler](/docs/intro/compiler-install) has been significantly improved in
v2, especially for native. Most notably, the experimental theme optimization
setting is now on by default, and stable. This means better performance on
native without any configuration needed.
### Native Portals
Gui's portal-based components (Sheet, Dialog, Popover, Select, and Toast)
now support true native portals via
[react-native-teleport](https://github.com/nicksrandall/react-native-teleport).
Native doesn't support portals. Gui v1 worked around this by abusing private
APIs and automatically re-propagating its own contexts, but your custom contexts
would break. This also added lots of overhead.
In v2 you can now add `react-native-teleport`, then import:
```tsx
import '@hanzogui/native/setup-teleport'
```
Now all components that portal work better and faster. See the
[Portal docs](/docs/components/portal) for details and alternative approaches
like component scoping.
### Native Sheet Gestures
[Sheet](/docs/components/sheet) now has optional integration with
`react-native-gesture-handler` for much smoother performance on native. Install
`react-native-gesture-handler` and add the setup import before any Gui
imports.
See the [`@hanzogui/native` docs](/ui/native) or
[Sheet docs](/docs/components/sheet) for full details.
### Cross-Platform Pointer Events
Pointer events (`onPointerDown`, `onPointerUp`, `onPointerMove`,
`onPointerEnter`, `onPointerLeave`, `onPointerCancel`) now work cross-platform.
On native, they're mapped to touch events with a normalized event shape matching
the web API: The `setPointerCapture` and `releasePointerCapture` APIs are
supported for drag scenarios where you need move events to continue firing even
after the pointer leaves the element bounds.
### CLI Improvements and Agent Prompt Generation
The [Gui CLI](/docs/guides/cli) has new commands for building and working
with your design system:
- **`hanzogui build`** - Pre-compile components in-place for production. Works
with any bundler and supports wrapping your build command to automatically
restore files after.
- **`hanzogui generate`** - Build your full Gui configuration and output CSS.
Validates your config and pre-generates your design system.
- **`hanzogui generate-css`** - Generate the `hanzogui.generated.css` file from your config.
Use `--output` to specify a custom output path.
- **`hanzogui generate-prompt`** - Generate an LLM-friendly markdown file from
your config, documenting all tokens, themes, components, and shorthands for
use with AI assistants.
- **`hanzogui check`** - Scan for inconsistent dependency versions across your
project.
We recommend generating your prompt and committing to your repo, even before you
do your full upgrade to version 2, as it will help agents understand your
Gui config better.
### Smaller Bundle Size
The `@hanzogui/core` bundle has been reduced by ~32% (from ~37KB to ~25KB
gzipped). This was achieved through several optimizations to color parsing,
expensive gesture handling, and automatically trimming optional theme generation
code.
### Breaking Changes
- **Shadow colors** output opacities using `color-mix()` which may break
snapshot tests or any code testing the expected parsed format.
- **Removed `@hanzogui/react-native-use-responder-events`.** If you were using
`onResponderGrant`, `onResponderMove`, `onResponderRelease`, or
`onResponderTerminate` props on web, switch to standard pointer events
(`onPointerDown`, `onPointerMove`, `onPointerUp`) or touch events. On native,
use React Native's built-in responder system.
- **Config v5 changes from v4.** Media query names change (`2xl` → `xxl`, `2xs`
→ `xxs`), style defaults align with React Native. See
[Config v5 docs](/docs/core/config-v5).
- **React Native 0.81+, React 19+, and TypeScript 5+ required.** Gui 2
targets React Native 0.81, React 19, and TypeScript 5 and above with New
Architecture support. This enables significant new style features, improved
type inference, and simplified internals.
- Default flex and position styles align with the latest React Native versions,
(you can change settings to keep the legacy behavior).
- Button and ListItem lose direct text style props for better performance and
consistency.
- useTheme no longer takes props; use the Theme component instead.
- Removed web-only `onHoverIn` and `onHoverOut` in favor of standard web events
(`onMouseEnter` or `onPointerEnter`).
- Added comprehensive web event handler support including keyboard, pointer,
drag and drop, clipboard, and scroll events.
- Moved from ThemeableStack to View for most base components in UI.
- Removed deprecated `Stack` for the identical `View`.
- Renamed the `animation` prop to `transition` for clarity and consistency.
- Removed `<Theme inverse />` and `themeInverse` prop - see
[inverse themes guide](/docs/guides/theme-builder#inverse-themes).
- Removed the `maxDarkLightNesting` and `cssStyleSeparator` settings.
- Removed `space` and `spaceDirection` props - use `gap` instead.
- Tabs `activationMode` now defaults to `'manual'` instead of `'automatic'`.
This means focusing a tab no longer changes the active tab - you must click or
press Enter/Space. This matches web standards.
- Group component simplified: `Group.Item` is now required (no more auto-cloning
direct children). Removed props: `space`, `separator`, `scrollable`,
`showScrollIndicator`, `disablePassBorderRadius`, `forceUseItem`. Children now
control their own sizing - apply size/responsive props directly to child
components. Add `<Separator />` manually between items when needed.
- Moved `<Spacer />` from core to `@hanzogui/spacer`.
- Moved all settings on `createGui` to the `settings` object.
- Native portals no longer auto-import React internals hack. If you want native
portals for better context preservation, add
`import '@hanzogui/native/setup-teleport'` at app startup. See
[Portal docs](/docs/components/portal).
- LinearGradient on native now requires setup import. Add
`import '@hanzogui/native/setup-expo-linear-gradient'` at app startup. See
[LinearGradient docs](/docs/components/linear-gradient).
- Removed React Native accessibility props in favor of web-standard props:
- `accessibilityLabel` → `aria-label`
- `accessibilityRole` → `role`
- `accessibilityHint` → `aria-describedby`
- `accessibilityState` → `aria-disabled`, `aria-selected`, `aria-checked`,
`aria-busy`, `aria-expanded`
- `accessibilityValue` → `aria-valuemin`, `aria-valuemax`, `aria-valuenow`,
`aria-valuetext`
- `accessibilityElementsHidden` → `aria-hidden`
- `accessibilityViewIsModal` → `aria-modal`
- `accessibilityLiveRegion` → `aria-live`
- `accessible` → `tabIndex={0}`
- `focusable` → `tabIndex`
- `nativeID` → `id`
### Goals
Our main goal with version two is **stability**. Gui started as a side
project with incredible scope and maintained an ambitious stance towards landing
large features and internal improvements.
Speaking for myself now: I personally pushed releases too fast, and as a result
burned too many of our users with regressions. We generally fast-followed with
fixes, but that isn't good enough.
I'd like to apologize for that, sincerely. We had a v2 nearly ready over a year
ago, but it felt right to push back the release until we felt confident we'd
fixed nearly every major issue, and overhauled our testing setup.
React Native is difficult to test, so it took us a while to build it out, but
I'm incredibly happy with where we're at now. On every commit we're running
integration tests on iOS and Android across every complex component, alongside a
few thousand web and core tests.
#### Testing
The testing infrastructure has been completely rebuilt since v1. At the v1.0
release we had 13 test files and a single CI workflow. Today we have 127 test
files across 5 testing frameworks with dedicated native testing infrastructure.
**Frameworks added:**
- **Playwright** for E2E and integration tests
- **Vitest** for unit and integration tests
- **Jest + Detox** for iOS and Android native E2E testing
- **Maestro** for iOS flow-based testing
**Multi-driver testing:** Every Playwright UI test runs four times, once for
each animation driver. This catches driver-specific regressions that would
otherwise slip through.
### What's next
Gui is quite mature in terms of features, foundation, and performance. AI
Agents generate its code exceptionally well because it's been in wide use and
well documented for years. For this reason, we are avoiding large syntax or
theme changes, for now.
We're going to deprecate a variety of things in 2.1 that will be planned for
3.0, and will follow with 3.0 a lot quicker than this major took.
There's still some work to do in terms of simplifying internals, we'd like to
move both our built-in styles and standardized sizing to be done in a more clear
way where it's easy to unplug either. Other broad goals include better alignment
to the web, simpler onboarding, more components, better components, and more
native component integrations.
### Thanks
A huge thanks is owed to our amazing team, which has persisted through this
giant release and throughout the last two years fixing issues.
Special thanks to [Quan Nguyen](https://github.com/anhquan291) for extensive
work on documentation, Radix v3 color updates, and theme improvements. And to
[Dave Mkpa-Eke](https://github.com/DaveyEke)
([@1804davey](https://x.com/1804davey)) for numerous bug fixes across Progress,
Input, ContextMenu, and other components, as well as the new Select.Indicator
feature and blog improvements.