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]>
381 lines
11 KiB
Plaintext
381 lines
11 KiB
Plaintext
---
|
|
title: Button
|
|
description: A simple button component
|
|
name: button
|
|
component: Button
|
|
package: button
|
|
demoName: Button
|
|
---
|
|
|
|
<HeroContainer demoMultiple>
|
|
<ButtonDemo />
|
|
</HeroContainer>
|
|
|
|
```tsx hero template=Button
|
|
|
|
```
|
|
|
|
<Highlights
|
|
features={[
|
|
'Size prop that works on all styles.',
|
|
'Place an icon before or after.',
|
|
'Control icon size explicitly with `iconSize`.',
|
|
'Theme groups of buttons with `Button.Apply`.',
|
|
]}
|
|
/>
|
|
|
|
## Installation
|
|
|
|
Button is already installed in `hanzogui`, or you can install it independently:
|
|
|
|
```bash
|
|
npm install @hanzogui/button
|
|
```
|
|
|
|
## Usage
|
|
|
|
```tsx
|
|
import { Button } from '@hanzo/gui'
|
|
|
|
export default () => <Button>Lorem ipsum</Button>
|
|
```
|
|
|
|
## Sizing
|
|
|
|
Sizing buttons provides a unique challenge especially for a compiler, because
|
|
you need to adjust many different properties - not just on the outer frame, but
|
|
on the text wrapped inside. Gui supports adjusting the padding, border
|
|
radius, font size and icons sizes all in one with the `size` prop.
|
|
|
|
```tsx
|
|
import { Button } from '@hanzo/gui'
|
|
|
|
export default () => <Button size="$6">Lorem ipsum</Button>
|
|
```
|
|
|
|
Given your theme defines a size `6`, the button will adjust all of the
|
|
properties appropriately. You can also pass a plain number to get an arbitrary
|
|
size.
|
|
|
|
## Variants
|
|
|
|
The Button component supports different visual styles through the `variant`
|
|
prop. Currently, the primary available variant is `"outlined"`.
|
|
|
|
```tsx
|
|
import { Button, XStack } from '@hanzo/gui'
|
|
|
|
export default () => (
|
|
<XStack gap="$2">
|
|
<Button>Default</Button>
|
|
<Button variant="outlined">Outlined</Button>
|
|
</XStack>
|
|
)
|
|
```
|
|
|
|
When `variant="outlined"` is applied, the button typically has a transparent
|
|
background with a visible border. The exact appearance (border color,
|
|
hover/press states) is determined by your theme's definitions for an outlined
|
|
button.
|
|
|
|
## Icon Theming
|
|
|
|
You can pass icons as either elements or components. If passing components,
|
|
Gui will automatically theme them (passing `size`). The icon size is
|
|
determined by the Button's `size` prop by default.
|
|
|
|
You can also explicitly set the icon size using the `iconSize` prop, which
|
|
accepts a `SizeTokens` value (e.g., `"$2"`). The `scaleIcon` prop can be used to
|
|
further adjust the size relative to the determined or explicitly set icon size.
|
|
|
|
When an icon is present, Gui automatically adds spacing between the icon and
|
|
the button's text using the CSS `gap` property on the Button frame. The gap is
|
|
derived from the Button's `size` token value, keeping spacing consistent with
|
|
the overall button dimensions.
|
|
|
|
```tsx
|
|
import { Button, Star } from '@hanzo/gui'
|
|
|
|
export default () => (
|
|
<>
|
|
<Button icon={Star} size="$5">
|
|
Icon sized by Button
|
|
</Button>
|
|
<Button icon={Star} iconSize="$2" size="$5">
|
|
Icon sized explicitly
|
|
</Button>
|
|
</>
|
|
)
|
|
```
|
|
|
|
You can
|
|
[use the source of Button itself](https://github.com/hanzoai/gui/blob/v2/pkgs/ui/button/src/Button.tsx)
|
|
to see in more detail what variants you can override, and how we use this
|
|
pattern internally to create our Button component.
|
|
|
|
## Group Theming
|
|
|
|
You can use `Button.Apply` to theme a group of Buttons using a shared context.
|
|
This is useful for applying consistent sizing or variants to multiple buttons
|
|
without passing props to each one individually.
|
|
|
|
```tsx
|
|
import { Button, ButtonDemo, YStack } from '@hanzo/gui'
|
|
|
|
export default () => (
|
|
<YStack gap="$4">
|
|
<Button.Apply size="$2" variant="outlined">
|
|
<Button>Small Outlined 1</Button>
|
|
<Button>Small Outlined 2</Button>
|
|
<Button icon={Star}>With Icon</Button>
|
|
</Button.Apply>
|
|
|
|
<Button.Apply size="$5">
|
|
<Button>Large 1</Button>
|
|
<Button theme="blue">Large Themed</Button>
|
|
</Button.Apply>
|
|
</YStack>
|
|
)
|
|
```
|
|
|
|
## Web Form Props
|
|
|
|
Button supports all standard HTML `<button>` attributes for form integration.
|
|
These props are web-only and ignored on native:
|
|
|
|
```tsx
|
|
import { Button, Form } from '@hanzo/gui'
|
|
|
|
export default () => (
|
|
<Form action="/submit">
|
|
<Button type="submit">Submit Form</Button>
|
|
<Button type="reset">Reset</Button>
|
|
<Button type="button">Regular Button (default)</Button>
|
|
|
|
{/* Override form attributes */}
|
|
<Button type="submit" formAction="/alternative-endpoint" formMethod="post">
|
|
Submit to Different Endpoint
|
|
</Button>
|
|
</Form>
|
|
)
|
|
```
|
|
|
|
<Notice>
|
|
Button defaults to `type="button"` to prevent unintended form submissions. Use
|
|
`type="submit"` explicitly when you want form submission behavior.
|
|
</Notice>
|
|
|
|
## Text Styling
|
|
|
|
**Changed from v1:** In v1, you could pass text style props like `color`,
|
|
`fontSize`, `fontWeight`, `fontFamily`, and `letterSpacing` directly to
|
|
`<Button>` and they would be forwarded to the button's text via context. In v2,
|
|
this is no longer supported — Button's frame is a `View` and text style props
|
|
passed to it are ignored.
|
|
|
|
To customize text appearance, use `Button.Text` explicitly:
|
|
|
|
```tsx
|
|
import { Button } from '@hanzo/gui'
|
|
|
|
export default () => (
|
|
<Button>
|
|
<Button.Text color="blue" fontSize="$5" fontWeight="bold">
|
|
Styled text
|
|
</Button.Text>
|
|
</Button>
|
|
)
|
|
```
|
|
|
|
### Interactive Text Styles
|
|
|
|
Combine `Button.Text` with the `group` prop on Button to coordinate text
|
|
styles across hover, press, and focus states:
|
|
|
|
```tsx
|
|
import { Button } from '@hanzo/gui'
|
|
|
|
export default () => (
|
|
<Button group="btn" bg="pink">
|
|
<Button.Text color="blue" $group-btn-hover={{ color: 'red' }}>
|
|
Hello world
|
|
</Button.Text>
|
|
</Button>
|
|
)
|
|
```
|
|
|
|
The `group` prop lets any child reference interactive states like
|
|
`$group-btn-hover`, `$group-btn-press`, and `$group-btn-focus` for
|
|
precise styling per interaction state.
|
|
|
|
## Creating Your Own Button
|
|
|
|
Gui now has all the features necessary to make creating a custom Button easy
|
|
enough that you may want to roll your own button. Learn how to do it with our
|
|
dedicated guide, [How to Build a Button](/docs/guides/how-to-build-a-button).
|
|
|
|
## API Reference
|
|
|
|
Buttons extend Stack views inheriting all the
|
|
[Gui standard props](/docs/intro/props), plus:
|
|
|
|
<PropsTable
|
|
data={[
|
|
{
|
|
name: 'size',
|
|
required: false,
|
|
type: 'SizeTokens | number',
|
|
description: `Set a size from your theme's size tokens (e.g., "$4") or a specific number. Adjusts padding, font size, and icon sizes.`,
|
|
},
|
|
{
|
|
name: 'variant',
|
|
required: false,
|
|
type: '"outlined" | undefined',
|
|
description: 'Applies the "outlined" button style.',
|
|
},
|
|
{
|
|
name: 'elevation',
|
|
required: false,
|
|
type: 'SizeTokens | number',
|
|
description: `Adds a shadow/elevation effect to the button. Accepts a size token or number.`,
|
|
},
|
|
{
|
|
name: 'disabled',
|
|
required: false,
|
|
type: 'boolean',
|
|
description:
|
|
'If true, the button will be non-interactive and visually disabled. Sets `pointerEvents: "none"`.',
|
|
},
|
|
{
|
|
name: 'theme',
|
|
required: false,
|
|
type: 'string',
|
|
description: `Apply a theme just to the button and its children.`,
|
|
},
|
|
{
|
|
name: 'icon',
|
|
required: false,
|
|
type: 'React.ReactNode | React.ComponentType<{ color?: string, size?: number }>',
|
|
description: `Pass any React element or a component. Appears before the text. If a component is passed, 'color' and 'size' props are passed to it.`,
|
|
},
|
|
{
|
|
name: 'iconAfter',
|
|
required: false,
|
|
type: 'React.ReactNode | React.ComponentType<{ color?: string, size?: number }>',
|
|
description: `Pass any React element or a component. Appears after the text. If a component is passed, 'color' and 'size' props are passed to it.`,
|
|
},
|
|
{
|
|
name: 'iconSize',
|
|
required: false,
|
|
type: 'SizeTokens',
|
|
description: `Explicitly set the size of the icon, overriding the default size derived from the Button's 'size' prop. Uses theme size tokens (e.g., "$2").`,
|
|
},
|
|
{
|
|
name: 'scaleIcon',
|
|
required: false,
|
|
type: 'number',
|
|
description: `Scale the icon by this factor. Default is 1. Applied after 'iconSize' or the default size calculation.`,
|
|
},
|
|
{
|
|
name: 'circular',
|
|
required: false,
|
|
type: `boolean`,
|
|
description: `Forces a circular button. Applies border radius to make the button a circle.`,
|
|
},
|
|
{
|
|
name: 'chromeless',
|
|
required: false,
|
|
type: 'boolean | "all"',
|
|
description:
|
|
'Removes default Gui visual styles (background, border) for a more minimal appearance, while keeping layout and interactions. If "all", removes hover/press/focus styles too.',
|
|
},
|
|
{
|
|
name: 'unstyled',
|
|
required: false,
|
|
type: `boolean`,
|
|
description: `Removes all Gui default styles, including layout, interactions, and accessibility attributes. Prefer 'chromeless' for removing only visual styles.`,
|
|
},
|
|
// Web-only form props
|
|
{
|
|
name: '// Web Form Props',
|
|
description:
|
|
'The following props are web-only and provide full HTML button form semantics. They are ignored on native.',
|
|
type: '---',
|
|
},
|
|
{
|
|
name: 'type',
|
|
required: false,
|
|
type: '"button" | "submit" | "reset"',
|
|
description:
|
|
'Web-only. The button type. Defaults to "button" to prevent unintended form submissions.',
|
|
},
|
|
{
|
|
name: 'form',
|
|
required: false,
|
|
type: 'string',
|
|
description: 'Web-only. The ID of the form element the button is associated with.',
|
|
},
|
|
{
|
|
name: 'formAction',
|
|
required: false,
|
|
type: 'string',
|
|
description: "Web-only. URL for form submission, overrides the form's action.",
|
|
},
|
|
{
|
|
name: 'formMethod',
|
|
required: false,
|
|
type: '"get" | "post"',
|
|
description: 'Web-only. HTTP method for form submission.',
|
|
},
|
|
{
|
|
name: 'formEncType',
|
|
required: false,
|
|
type: 'string',
|
|
description: 'Web-only. Encoding type for form data.',
|
|
},
|
|
{
|
|
name: 'formNoValidate',
|
|
required: false,
|
|
type: 'boolean',
|
|
description: 'Web-only. Bypass form validation when submitting.',
|
|
},
|
|
{
|
|
name: 'formTarget',
|
|
required: false,
|
|
type: 'string',
|
|
description: 'Web-only. Where to display form response (_self, _blank, etc).',
|
|
},
|
|
{
|
|
name: 'name',
|
|
required: false,
|
|
type: 'string',
|
|
description: 'Web-only. Name submitted with form data.',
|
|
},
|
|
{
|
|
name: 'value',
|
|
required: false,
|
|
type: 'string',
|
|
description: 'Web-only. Value submitted with form data.',
|
|
},
|
|
{
|
|
name: 'popoverTarget',
|
|
required: false,
|
|
type: 'string',
|
|
description: 'Web-only. ID of popover element to control.',
|
|
},
|
|
{
|
|
name: 'popoverTargetAction',
|
|
required: false,
|
|
type: '"hide" | "show" | "toggle"',
|
|
description: 'Web-only. Action to perform on the popover.',
|
|
},
|
|
// Note about text styling
|
|
{
|
|
name: '// Text Styling',
|
|
description:
|
|
'Button does not support `color` directly. To style text color, use `Button.Text` with the `group` prop for interactive states. See the Text Styling section above.',
|
|
type: '---',
|
|
},
|
|
]}
|
|
/>
|