# Tamagui Complete Documentation > Tamagui is a complete UI solution for React Native and Web, with a fully-featured UI kit, styling engine, and optimizing compiler. ## components/accordion/1.0.0 --- title: Accordion description: A vertically stacked set of interactive headings with content. name: accordion component: Accordion package: accordion --- ```tsx hero template=Accordion ``` ## Installation Accordion is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/accordion ``` ## Anatomy Import all parts and piece them together. ```jsx import { Accordion } from 'tamagui' // or '@tamagui/accordion' export default () => ( ) ``` ## API Reference ### Accordion Contains all the parts of an accordion. Determines whether one or multiple items can be opened at the same time. ), }, { name: 'value', required: false, type: 'string', description: ( The controlled value of the item to expand when type is{' '} "single". Must be used in conjunction with{' '} onValueChange. ), }, { name: 'defaultValue', required: false, type: 'string', description: ( The value of the item to expand when initially rendered and type is{' '} "single". Use when you do not need to control the state of the items. ), }, { name: 'onValueChange', required: false, type: '(value: string) => void', typeSimple: 'function', description: ( Event handler called when the expanded state of an item changes and{' '} type is "single". ), }, { name: 'value', required: false, default: '[]', type: 'string[]', description: ( The controlled value of the item to expand when type is{' '} "multiple". Must be used in conjunction with{' '} onValueChange. ), }, { name: 'defaultValue', required: false, default: '[]', type: 'string[]', description: ( The value of the item to expand when initially rendered when type{' '} is "multiple". Use when you do not need to control the state of the items. ), }, { name: 'onValueChange', required: false, type: '(value: string[]) => void', typeSimple: 'function', description: ( Event handler called when the expanded state of an item changes and{' '} type is "multiple". ), }, { name: 'collapsible', required: false, default: 'false', type: 'boolean', description: ( When type is "single", allows closing content when clicking trigger for an open item. ), }, { name: 'disabled', required: false, type: 'boolean', default: 'false', description: ( When true, prevents the user from interacting with the accordion and all its items. ), }, { name: 'dir', required: false, type: '"ltr" | "rtl"', typeSimple: 'enum', default: '"ltr"', description: 'The reading direction of the accordion when applicable. If omitted, assumes LTR (left-to-right) reading mode.', }, ]} /> ### Item Contains all the parts of a collapsible section. When true, prevents the user from interacting with the item. ), }, { name: 'value', required: true, type: 'string', description: 'A unique value for the item.', }, ]} /> ### Header Wraps an `Accordion.Trigger`. Use the `asChild` prop to update it to the appropriate heading level for your page. ### Trigger Toggles the collapsed state of its associated item. It should be nested inside of an `Accordion.Header`. ### Content Contains the collapsible content for an item. Used to force mounting when more control is needed. Useful when controlling animation with React animation libraries. ), }, ]} /> ## Examples ### Expanded by default Use the `defaultValue` prop to define the open item by default. ```jsx line=1 ``` ### Allow collapsing all items Use the `collapsible` prop to allow all items to close. ```jsx line=1 ``` ### Multiple items open at the same time Set the `type` prop to `multiple` to enable opening multiple items at once. ```jsx line=1 ``` ## Accessibility Adheres to the [Accordion WAI-ARIA design pattern](https://www.w3.org/TR/wai-aria-practices-1.1/#accordion). ## components/accordion/2.0.0 --- title: Accordion description: A vertically stacked set of interactive headings with content name: accordion component: Accordion package: accordion demoName: Accordion --- ```tsx hero template=Accordion ``` ## Installation Accordion is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/accordion ``` ## Anatomy Import all parts and piece them together. ```jsx import { Accordion } from 'tamagui' // or '@tamagui/accordion' export default () => ( ) ``` ## API Reference ### Accordion Contains all the parts of an accordion. Determines whether one or multiple items can be opened at the same time. ), }, { name: 'value', required: false, type: 'string', description: ( The controlled value of the item to expand when type is{' '} "single". Must be used in conjunction with{' '} onValueChange. ), }, { name: 'defaultValue', required: false, type: 'string', description: ( The value of the item to expand when initially rendered and type is{' '} "single". Use when you do not need to control the state of the items. ), }, { name: 'onValueChange', required: false, type: '(value: string) => void', typeSimple: 'function', description: ( Event handler called when the expanded state of an item changes and{' '} type is "single". ), }, { name: 'value', required: false, default: '[]', type: 'string[]', description: ( The controlled value of the item to expand when type is{' '} "multiple". Must be used in conjunction with{' '} onValueChange. ), }, { name: 'defaultValue', required: false, default: '[]', type: 'string[]', description: ( The value of the item to expand when initially rendered when type{' '} is "multiple". Use when you do not need to control the state of the items. ), }, { name: 'onValueChange', required: false, type: '(value: string[]) => void', typeSimple: 'function', description: ( Event handler called when the expanded state of an item changes and{' '} type is "multiple". ), }, { name: 'collapsible', required: false, default: 'false', type: 'boolean', description: ( When type is "single", allows closing content when clicking trigger for an open item. ), }, { name: 'disabled', required: false, type: 'boolean', default: 'false', description: ( When true, prevents the user from interacting with the accordion and all its items. ), }, { name: 'dir', required: false, type: '"ltr" | "rtl"', typeSimple: 'enum', default: '"ltr"', description: 'The reading direction of the accordion when applicable. If omitted, assumes LTR (left-to-right) reading mode.', }, ]} /> ### Accordion.Item Contains all the parts of a collapsible section. When true, prevents the user from interacting with the item. ), }, { name: 'value', required: true, type: 'string', description: 'A unique value for the item.', }, ]} /> ### Accordion.Header Wraps an `Accordion.Trigger`. Use the `asChild` prop to update it to the appropriate heading level for your page. ### Accordion.Trigger Toggles the collapsed state of its associated item. It should be nested inside of an `Accordion.Header`. ### Accordion.Content Contains the collapsible content for an item. Used to force mounting when more control is needed. Useful when controlling animation with React animation libraries. ), }, ]} /> ## Examples ### Expanded by default Use the `defaultValue` prop to define the open item by default. ```jsx line=1 ``` ### Allow collapsing all items Use the `collapsible` prop to allow all items to close. ```jsx line=1 ``` ### Multiple items open at the same time Set the `type` prop to `multiple` to enable opening multiple items at once. ```jsx line=1 ``` ## Accessibility Adheres to the [Accordion WAI-ARIA design pattern](https://www.w3.org/TR/wai-aria-practices-1.1/#accordion). ## components/alert-dialog/1.0.0 --- title: AlertDialog description: Show an alert prompt in a dialog name: alertDialog component: AlertDialog package: alert-dialog demoName: AlertDialog --- ```tsx hero template=AlertDialog ``` ## Installation Alert Dialog is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/alert-dialog ``` In order to use this component independently of `tamagui`, you'll first need to install the `@tamagui/portal` package: ```bash npm install @tamagui/portal ``` Then add `PortalProvider` to the root of your app: ```tsx fileName="App.tsx" import { PortalProvider } from '@tamagui/portal' import YourApp from './components/YourApp' function App() { return ( ) } export default App ``` ## Anatomy ```tsx import { AlertDialog } from 'tamagui' // or '@tamagui/alert-dialog' export default () => ( {/* ... */} ) ``` ## API Reference ### AlertDialog Contains every component for the AlertDialog. Shares all [Dialog Props](/docs/components/dialog#api), except modal which is on by default. Adds: ### AlertDialog.Trigger Just [Tamagui Props](/docs/intro/props). ### AlertDialog.Portal Renders AlertDialog into appropriate container. Beyond [Tamagui Props](/docs/intro/props), adds: ### AlertDialog.Content Main container for AlertDialog content, this is where you should apply animations. Beyond [Tamagui Props](/docs/intro/props), adds: ### AlertDialog.Overlay Displays behind Content. Beyond [Tamagui Props](/docs/intro/props), adds: ### AlertDialog.Title Required. Can wrap in VisuallyHidden to hide. Defaults to H2, see [Headings](/docs/components/headings). ### AlertDialog.Description Required. Can wrap in VisuallyHidden to hide. Defaults to Paragraph, see [Paragraph](/docs/components/text). ### AlertDialog.Cancel Closes the AlertDialog, accepts all YStack props. Recommended to use with your own component and `asChild`. ### PortalProvider ## Examples ### Inside native modals If you're using native modals (maybe from react-navigation), you'll notice the Dialogs won't show up inside the modal. To get around this, you should wrap your screen inside `PortalProvider`, like so: ```tsx import { PortalProvider } from 'tamagui' // this component used in react-navigation/expo-router with `presentation: "modal"` export function Page() { return ( {/* rest of your page, including the Dialog... */} ) } ``` ## components/alert-dialog/2.0.0 --- title: Alert Dialog description: Show an alert prompt in a dialog name: alert-dialog component: AlertDialog package: alert-dialog demoName: AlertDialog --- ```tsx hero template=AlertDialog ``` AlertDialog is a modal dialog that interrupts the user with important content and expects a response. It's built on Dialog with stricter accessibility requirements, and [automatically stacks](/ui/z-index) above other content. ## Installation Alert Dialog is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/alert-dialog ``` ## Anatomy ```tsx import { AlertDialog } from 'tamagui' // or '@tamagui/alert-dialog' export default () => ( {/* ... */} ) ``` ## API Reference ### AlertDialog Contains every component for the AlertDialog. Shares all [Dialog Props](/docs/components/dialog#api), except modal which is on by default. Adds: ### AlertDialog.Trigger Just [Tamagui Props](/docs/intro/props). ### AlertDialog.Portal Renders AlertDialog into appropriate container. Beyond [Tamagui Props](/docs/intro/props), adds: ### AlertDialog.Content Main container for AlertDialog content, this is where you should apply animations. Beyond [Tamagui Props](/docs/intro/props), adds: ### AlertDialog.Overlay Displays behind Content. Beyond [Tamagui Props](/docs/intro/props), adds: ### AlertDialog.Title Required. Can wrap in VisuallyHidden to hide. Defaults to H2, see [Headings](/docs/components/headings). ### AlertDialog.Description Required. Can wrap in VisuallyHidden to hide. Defaults to Paragraph, see [Paragraph](/docs/components/text). ### AlertDialog.Cancel Closes the AlertDialog, accepts all YStack props. Recommended to use with your own component and `asChild`. ### AlertDialog.Action Confirms the AlertDialog action, accepts all YStack props. Recommended to use with your own component and `asChild`. ### AlertDialog.Destructive A destructive action button for the AlertDialog. When using `native` mode on iOS, this renders with the native red destructive button style. Accepts all YStack props. ```tsx Delete Account? This action cannot be undone. ``` ### PortalProvider ## components/anchor/1.0.0 --- title: Anchor description: Link to external websites. name: html component: Anchor --- ## Usage The Anchor component provides a way to link to external websites. It extends [SizableText](/docs/components/text#sizable-text), adding the `href`, `target`, and `rel` attributes. On native, it will use React Native `Linking.openURL`, on web it will render to an `a` element with `href` set appropriately. ## API Reference ### Anchor Inherits [Tamagui props](/docs/intro/props) as well as: ## components/anchor/2.0.0 --- title: Anchor description: Link to external websites name: anchor component: Anchor package: html --- ## Installation Anchor is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/html ``` ## Usage The Anchor component provides a way to link to external websites. It extends [SizableText](/docs/components/text#sizable-text), adding the `href`, `target`, and `rel` attributes. On native, it uses React Native `Linking.openURL`. On web, it renders an `a` element with `href` set appropriately. ## API Reference ### Anchor Inherits [Tamagui props](/docs/intro/props) as well as: ## components/avatar/1.0.0 --- title: Avatar description: Display aspect-fixed images with a fallback while loading name: avatar component: Avatar package: avatar demoName: Avatar --- ```tsx hero template=Avatar ``` ## Installation Avatar is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/avatar ``` ## Usage ```tsx import { Avatar } from 'tamagui' export default () => ( ) ``` ## API Reference ### Avatar Avatar extends [Square](/docs/components/shapes#shape-props), giving it all the [Tamagui standard props](/docs/intro/props) as well as `size` and `circular`. ### Avatar.Fallback Avatar.Fallback extends [YStack](/docs/components/stacks), plus: ### Avatar.Image Avatar.Image extends [Image](/docs/components/image). ## components/avatar/2.0.0 --- title: Avatar description: Display aspect-ratio-fixed images with a fallback while loading name: avatar component: Avatar package: avatar demoName: Avatar --- ```tsx hero template=Avatar ``` ## Installation Avatar is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/avatar ``` ## Usage ```tsx import { Avatar } from 'tamagui' export default () => ( ) ``` ## API Reference ### Avatar Avatar extends [Square](/docs/components/shapes#shape-props), giving it all the [Tamagui standard props](/docs/intro/props) as well as `size` and `circular`. ### Avatar.Fallback Avatar.Fallback extends [YStack](/docs/components/stacks), plus: ### Avatar.Image Avatar.Image extends [Image](/docs/components/image). ## components/button/1.0.0-alpha --- title: Button description: A simple button component name: button component: Button demoName: Button --- # Button A simple, sizable button. ```tsx hero template=Button ``` ### Usage ```tsx import { Button } from 'tamagui' export default () => ``` ### 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. Tamagui supports adjusting the padding, border radius, font size and icons sizes all in one with the `size` prop. ```tsx import { Button } from 'tamagui' export default () => ``` 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. ### Icon Theming You can pass icons as either elements or components. If passing components, Tamagui will automatically pass the `size` and `color` prop to them based on your theme. ### Button props Button extends View, inheriting all the [Tamagui standard props](/docs/intro/props), adding: ## components/button/1.0.0-beta.0 --- title: Button description: A simple button component name: button component: Button demoName: Button --- # Button A simple, sizable button. ```tsx hero template=Button ``` ### Usage ```tsx import { Button } from 'tamagui' export default () => ``` ### 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. Tamagui supports adjusting the padding, border radius, font size and icons sizes all in one with the `size` prop. ```tsx import { Button } from 'tamagui' export default () => ``` 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. ### Icon Theming You can pass icons as either elements or components. If passing components, Tamagui will automatically pass the `size` and `color` prop to them based on your theme. ### Button props Button extends View, inheriting all the [Tamagui standard props](/docs/intro/props), plus: ## components/button/1.0.0 --- title: Button description: A simple button component name: button component: Button package: button demoName: Button --- # Button A simple, sizable button. ```tsx hero template=Button ``` ### Usage ```tsx import { Button } from 'tamagui' export default () => ``` ### 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. Tamagui supports adjusting the padding, border radius, font size and icons sizes all in one with the `size` prop. ```tsx import { Button } from 'tamagui' export default () => ``` 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. ### Icon Theming You can pass icons as either elements or components. If passing components, Tamagui will automatically pass the `size` and `color` prop to them based on your theme. You can [use the source of Button itself](https://github.com/tamagui/tamagui/blob/v2/code/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. ### Customization (Advanced) Button only supports a limited subset of text props directly, and doesn't accept `hoverStyle` text props. If you need more control, you can do a simple customization using some exported helpers. Please note that this pattern is a bit antithetical to the multiple-components APIs that Tamagui generally prefers. In a future release we hope to fix this, but that change should be easy to migrate to. ```tsx import { forwardRef } from 'react' import { ButtonFrame, ButtonText, GetProps, ButtonProps as TamaguiButtonProps, styled, themeable, useButton, } from 'tamagui' const CustomButtonFrame = styled(ButtonFrame, { // ... }) const CustomButtonText = styled(ButtonText, { // ... }) // to capture the custom variant types you define type CustomButtonFrameProps = GetProps type CustomButtonTextProps = GetProps export type CustomButtonProps = TamaguiButtonProps & CustomButtonFrameProps & CustomButtonTextProps export const Button = CustomButtonFrame.styleable((propsIn, ref) => { const { props } = useButton(propsIn, { Text: CustomButtonText }) return }) ``` ### Button props Buttons extend Stack views inheriting all the [Tamagui standard props](/docs/intro/props), plus: ## components/button/1.28.0 --- title: Button description: An incredibly flexible button. name: button component: Button package: button demoName: Button --- ```tsx hero template=Button ``` ## Usage When using the simple Button API, it's as simple as this: ```tsx import { Button } from 'tamagui' export default () => ``` ### 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. Tamagui supports adjusting the padding, border radius, font size and icons sizes all in one with the `size` prop. ```tsx import { Button } from 'tamagui' export default () => ``` 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. ### Icon Theming You can pass icons as either elements or components. If passing components, Tamagui will automatically pass the `size` and `color` prop to them based on your theme. You can [use the source of Button itself](https://github.com/tamagui/tamagui/blob/main/code/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. ### Creating your own Button Tamagui 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). The previous `useButton` API is deprecated and will be removed in a future version. It's brittle and is easily replaced with the new compound component APIs as described in the guide. ## API Reference ### Button Buttons extend Stack views inheriting all the [Tamagui standard props](/docs/intro/props), plus: ## components/button/2.0.0 --- title: Button description: A simple button component name: button component: Button package: button demoName: Button --- ```tsx hero template=Button ``` ## Installation Button is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/button ``` ## Usage ```tsx import { Button } from 'tamagui' export default () => ``` ## 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. Tamagui supports adjusting the padding, border radius, font size and icons sizes all in one with the `size` prop. ```tsx import { Button } from 'tamagui' export default () => ``` 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 'tamagui' export default () => ( ) ``` 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, Tamagui 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, Tamagui automatically adds spacing between the icon and the button's text. This space is calculated as 40% of the icon's final computed size (after considering `size`, `iconSize`, and `scaleIcon`). This margin is applied to the right of an `icon` and to the left of an `iconAfter`. ```tsx import { Button, Star } from 'tamagui' export default () => ( <> ) ``` You can [use the source of Button itself](https://github.com/tamagui/tamagui/blob/v2/code/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 'tamagui' export default () => ( ) ``` ## Web Form Props Button supports all standard HTML ` {/* Override form attributes */} ) ``` Button defaults to `type="button"` to prevent unintended form submissions. Use `type="submit"` explicitly when you want form submission behavior. ## Text Styling Button does not support a `color` prop directly. Instead, use `Button.Text` for full control over text styling. Combine it with the `group` prop on Button to coordinate interactive styles between the frame and its children: ```tsx import { Button } from 'tamagui' export default () => ( ) ``` 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 Tamagui 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 [Tamagui standard props](/docs/intro/props), plus: ', 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 Tamagui 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 Tamagui 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: '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: '---', }, ]} /> ## components/card/1.0.0 --- title: Card description: Sizable, themeable cards with a flexible API. name: card component: Card package: card demoName: Card --- ```tsx hero template=Card ``` ## Installation Card is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/card ``` ## Anatomy ```tsx import { Card } from 'tamagui' // or '@tamagui/card' export default () => ( {/* any other components */} ) ``` ## API Reference ### Card Frame of the card, extends [ThemeableStack props](/docs/components/stacks#themeablestack), adding: ### Card.Header Extends [ThemeableStack](/docs/components/stacks#themeablestack), adding: ### Card.Footer Extends [ThemeableStack](/docs/components/stacks#themeablestack), adding: ### Card.Background Extends [YStack](/docs/components/stacks), set to `fullscreen` and zIndex below Header/Footer. ## components/card/2.0.0 --- title: Card description: Sizable, themeable cards with a flexible API name: card component: Card package: card demoName: Card --- ```tsx hero template=Card ``` ## Installation Card is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/card ``` ## Anatomy ```tsx import { Card } from 'tamagui' // or '@tamagui/card' export default () => ( {/* any other components */} ) ``` ## API Reference ### Card Frame of the card, extends [ThemeableStack props](/docs/components/stacks#themeablestack), adding: ### Card.Header Extends [ThemeableStack](/docs/components/stacks#themeablestack), adding: ### Card.Footer Extends [ThemeableStack](/docs/components/stacks#themeablestack), adding: ### Card.Background Extends [YStack](/docs/components/stacks), set to `fullscreen` and `zIndex` below Header/Footer. ## components/checkbox/1.3.0 --- title: Checkbox description: A simple checkbox component name: checkbox component: Checkbox package: checkbox demoName: Checkbox --- # Checkbox Use in forms to toggle between two states. ```tsx hero template=Checkbox ``` ## Installation Checkbox is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/checkbox ``` ## Usage ```tsx import { Check } from '@tamagui/lucide-icons' import { Checkbox } from 'tamagui' export default () => ( ) ``` ## API Reference ### Checkbox `Checkbox` extend ThemeableStack inheriting all the [props](/docs/components/stacks#themeablestack), plus: void', description: 'Callback that fires when the checkbox state is changed.', }, { name: 'sizeAdjust', type: 'number', description: `Adjust the checkbox size scaling by this number.`, }, { name: 'scaleIcon', type: 'number', description: `Scale the indicator icon more than usual by this number.`, }, { name: 'scaleSize', type: 'number', default: '0.5', description: `The Tamagui size tokens should map to the height of a button at any given step. This means you want somewhat smaller checkboxes typically.`, }, { name: 'unstyled', required: false, type: `boolean`, description: `Removes all default Tamagui styles.`, }, ]} /> ### Checkbox.Indicator `Checkbox.Indicator` extend ThemeableStack inheriting all the [props](/docs/components/stacks#themeablestack), plus: ## components/checkbox/1.85.0 --- title: Checkbox description: A simple checkbox component name: checkbox component: Checkbox package: checkbox demoName: Checkbox --- # Checkbox Toggle state in forms. Styled Unstyled Headless ```tsx hero template=Checkbox ```` ```tsx hero template=CheckboxUnstyled ```` ```tsx hero template=CheckboxHeadless ```` ## Installation Checkbox is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/checkbox ```` Checkbox is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/checkbox ``` To use the headless switch, you want to import it from the `@tamagui/switch-headless` package. This package has no dependency on `@tamagui/core`, but still works off the react-native APIs. This means can bring your own style library. ```bash npm install @tamagui/switch-headless ``` ## Usage ```tsx import { Check } from '@tamagui/lucide-icons' import { Checkbox } from 'tamagui' export default () => ( ) ``` Use the `createCheckbox` export to create a fully custom checkbox that still uses the Tamagui styling system. This is similar to setting `unstyled`, but goes a bit further. It doesn't add any types for `size` or `unstyled`, and it won't automatically apply the `active` theme. If does pass the `checked` prop down as indicated in the types of `createCheckbox`. ```tsx template=CheckboxUnstyled ``` Using the `useCheckbox` API, you can make your own Checkbox from scratch. ```tsx template=CheckboxHeadless ``` ## API Reference ### Checkbox `Checkbox` extend ThemeableStack inheriting all the [props](/docs/components/stacks#themeablestack), plus: void', description: 'Callback that fires when the checkbox state is changed.', }, { name: 'sizeAdjust', type: 'number', description: `Adjust the checkbox size scaling by this number.`, }, { name: 'scaleIcon', type: 'number', description: `Scale the indicator icon more than usual by this number.`, }, { name: 'scaleSize', type: 'number', default: '0.5', description: `The Tamagui size tokens should map to the height of a button at any given step. This means you want somewhat smaller checkboxes typically.`, }, { name: 'unstyled', required: false, type: `boolean`, description: `Removes all default Tamagui styles.`, }, ]} /> ### Checkbox.Indicator `Checkbox.Indicator` extend ThemeableStack inheriting all the [props](/docs/components/stacks#themeablestack), plus: ## components/checkbox/1.89.0 --- title: Checkbox description: Toggle state in forms. name: checkbox component: Checkbox package: checkbox demoName: Checkbox --- Styled Unstyled Headless ```tsx hero template=Checkbox ```` ```tsx hero template=CheckboxUnstyled ```` ```tsx hero template=CheckboxHeadless ```` ## Installation Checkbox is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/checkbox ```` Checkbox is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/checkbox ``` To use the headless checkbox, you want to import it from the `@tamagui/checkbox-headless` package. This package has no dependency on `@tamagui/core`, but still works off the react-native APIs. This means you can bring your own style library. ```bash npm install @tamagui/checkbox-headless ``` ## Usage ```tsx import { Check } from '@tamagui/lucide-icons' import { Checkbox } from 'tamagui' export default () => ( ) ``` Use the `createCheckbox` export to create a fully custom checkbox that still uses the Tamagui styling system. This is similar to setting `unstyled`, but goes a bit further. It doesn't add any types for `size` or `unstyled`, and it won't automatically apply the `active` theme. It does pass the `checked` prop down as indicated in the types of `createCheckbox`. ```tsx template=CheckboxUnstyled ``` Using the `useCheckbox` API, you can make your own Checkbox from scratch. ```tsx template=CheckboxHeadless ``` ## API Reference ### Checkbox `Checkbox` extend ThemeableStack inheriting all the [props](/docs/components/stacks#themeablestack), plus: void', description: 'Callback that fires when the checkbox state is changed.', }, { name: 'sizeAdjust', type: 'number', description: `Adjust the checkbox size scaling by this number.`, }, { name: 'scaleIcon', type: 'number', description: `Scale the indicator icon more than usual by this number.`, }, { name: 'scaleSize', type: 'number', default: '0.5', description: `The Tamagui size tokens should map to the height of a button at any given step. This means you want somewhat smaller checkboxes typically.`, }, { name: 'unstyled', required: false, type: `boolean`, description: `Removes all default Tamagui styles.`, }, ]} /> ### Checkbox.Indicator `Checkbox.Indicator` extend ThemeableStack inheriting all the [props](/docs/components/stacks#themeablestack), plus: ## components/checkbox/2.0.0 --- title: Checkbox description: Toggle state in forms name: checkbox component: Checkbox package: checkbox demoName: Checkbox --- Styled Unstyled Headless ```tsx hero template=Checkbox ```` ```tsx hero template=CheckboxUnstyled ```` ```tsx hero template=CheckboxHeadless ```` ## Installation Checkbox is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/checkbox ```` Checkbox is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/checkbox ``` To use the headless checkbox, you want to import it from the `@tamagui/checkbox-headless` package. This package has no dependency on `@tamagui/core`, but still works off the react-native APIs. This means you can bring your own style library. ```bash npm install @tamagui/checkbox-headless ``` ## Usage ```tsx import { Check } from '@tamagui/lucide-icons' import { Checkbox } from 'tamagui' export default () => ( ) ``` Use the `createCheckbox` export to create a fully custom checkbox that still uses the Tamagui styling system. This is similar to setting `unstyled`, but goes a bit further. It doesn't add any types for `size` or `unstyled`, and it won't automatically apply the `active` theme. It does pass the `checked` prop down as indicated in the types of `createCheckbox`. ```tsx template=CheckboxUnstyled ``` The `useCheckbox` hook provides all the state and accessibility props needed to build a custom checkbox with any styling solution. ```tsx template=CheckboxHeadless ``` ### Basic Usage ```tsx import { useCheckbox } from '@tamagui/checkbox-headless' import { useState } from 'react' import { Pressable, View } from 'react-native' function MyCheckbox({ defaultChecked, onCheckedChange, ...props }) { const [checked, setChecked] = useState(defaultChecked || false) const { checkboxProps, checkboxRef, bubbleInput } = useCheckbox( props, [checked, setChecked], null ) return ( <> {checked && } {bubbleInput} ) } ``` ## API Reference ### Checkbox `Checkbox` extends ThemeableStack inheriting all the [props](/docs/components/stacks#themeablestack), plus: void', description: 'Callback that fires when the checkbox state is changed.', }, { name: 'sizeAdjust', type: 'number', description: `Adjust the checkbox size scaling by this number.`, }, { name: 'scaleIcon', type: 'number', description: `Scale the indicator icon more than usual by this number.`, }, { name: 'scaleSize', type: 'number', default: '0.5', description: `The Tamagui size tokens should map to the height of a button at any given step. This means you want somewhat smaller checkboxes typically.`, }, { name: 'unstyled', required: false, type: `boolean`, description: `Removes all default Tamagui styles.`, }, { name: 'activeStyle', required: false, type: `StyleProp`, description: `Styles to apply when the checkbox is checked.`, }, { name: 'activeTheme', required: false, type: `string | null`, description: `Theme to apply when the checkbox is checked. Set to null for no theme change.`, }, ]} /> ### Checkbox.Indicator `Checkbox.Indicator` extends ThemeableStack inheriting all the [props](/docs/components/stacks#themeablestack), plus: ### useCheckbox The `useCheckbox` hook accepts three arguments: ```tsx const { checkboxProps, checkboxRef, bubbleInput } = useCheckbox( props, // CheckboxProps state, // [checked: CheckedState, setChecked: (checked: CheckedState) => void] ref // React.Ref ) ``` #### CheckedState The checkbox supports three states: - `true` - checked - `false` - unchecked - `'indeterminate'` - indeterminate/mixed state (useful for "select all" patterns) #### Props (first argument) ## components/context-menu/2.0.0 --- title: Context Menu description: A menu component triggered by right-click on web and long press on touch devices name: context-menu component: ContextMenu package: context-menu demoName: ContextMenu --- ```tsx hero template=ContextMenu ``` ContextMenu displays a menu triggered by right-click on web or long-press on mobile. It supports submenus, native platform menus with iOS previews, and [automatically stacks](/ui/z-index) above other content. ## Installation ContextMenu is already installed in `tamagui`, or you can install it independently: ```bash yarn add @tamagui/context-menu ``` If you want to use native menus, add these dependencies: ```sh yarn add @react-native-menu/menu yarn add react-native-ios-context-menu yarn add react-native-ios-utilities yarn add zeego yarn add sf-symbols-typescript ``` Then add the setup import at your app entry point: ```tsx import '@tamagui/native/setup-zeego' ``` **Expo Router users:** This import must run _before_ `expo-router/entry`. Create an `index.js` at your project root that imports the setup first, then expo-router, and update your `package.json` main field to `"index.js"`. See the [upgrade guide](/docs/guides/how-to-upgrade#expo-router-entry-point) for details. ## Anatomy Import all parts and piece them together. ```jsx import { ContextMenu } from 'tamagui' // or '@tamagui/context-menu' export default () => ( Right Click or longPress About Notes Settings {/* when title is nested inside a React element then you need to use `textValue` */} Calendar Actions Note settings Create note Delete all notes Sync notes ) ``` ## API Reference ### ContextMenu Contains every component for the ContextMenu. void }) => void', required: false, description: 'Called when the menu opens or closes. Call event.preventDefault() to cancel and allow the native context menu to show instead.', }, { name: 'onOpenWillChange', type: '(open: boolean) => void', required: false, platform: 'ios', description: 'Called before the open/close animation begins.', }, { name: 'modal', type: 'boolean', default: 'true', required: false, description: 'When true, traps focus inside the menu and blocks outside scroll/interactions.', }, { name: 'stayInFrame', type: 'ShiftProps | boolean', required: false, default: '{ padding: 10 }', description: 'Shifts the menu horizontally to stay within viewport bounds. Pass an object to customize shift behavior (mainAxis, crossAxis, padding).', }, { name: 'allowFlip', type: 'FlipProps | boolean', required: false, description: 'Flips the menu to the opposite side if there is insufficient space.', }, { name: 'offset', type: 'OffsetOptions', required: false, description: 'Distance between the menu and its trigger.', }, { name: 'unstyled', required: false, type: 'boolean', description: 'Removes all default Tamagui styles.', }, ]} /> #### Allowing Native Context Menu You can call `event.preventDefault()` in `onOpenChange` to prevent the Tamagui menu from opening and allow the native browser context menu to appear instead: ```tsx { if (someCondition) { // prevent Tamagui menu, let native context menu show event?.preventDefault() } }} > {/* ... */} ``` ### ContextMenu.Portal This is necessary for the ContextMenu. ### ContextMenu.Trigger The ContextMenu will only be triggered when the user right-clicks or long-presses within the Trigger area. ### ContextMenu.Content Contains the content of the ContextMenu. void', required: false, description: 'Called when focus returns to the trigger after closing.', }, { name: 'onEscapeKeyDown', type: '(event: KeyboardEvent) => void', required: false, description: 'Called when the escape key is pressed. Can be prevented.', }, { name: 'onPointerDownOutside', type: '(event: PointerEvent) => void', required: false, description: 'Called when a pointer event occurs outside the content.', }, { name: 'onInteractOutside', type: '(event: Event) => void', required: false, description: 'Called when any interaction occurs outside the content.', }, ]} /> ### ContextMenu.Item A selectable menu item that triggers an action when selected. void', required: false, description: 'Called when the item is selected via click or keyboard.', }, { name: 'onFocus', type: '() => void', required: false, description: 'Called when the item receives focus.', }, { name: 'onBlur', type: '() => void', required: false, description: 'Called when the item loses focus.', }, { name: 'textValue', type: 'string', required: false, platform: 'ios/android', description: 'Text used for typeahead and native menus. Required when ItemTitle contains a React node instead of a string.', }, ]} /> ### ContextMenu.ItemTitle Renders the title of the menu item. You can directly pass a text node to the ItemTitle. However, if you use a nested React node like ``, you need to pass `textValue` to the `` so that it works with native menus. ### ContextMenu.ItemIcon A component to render an icon. For non-native menus, you can pass an icon component. For native menus, you can pass platform-specific icons to the `android`/`ios` props. On iOS, it renders the native [SF Symbols](https://github.com/andrewtavis/sf-symbols-online) icons. ```jsx line=1 ``` ### ContextMenu.ItemImage A component to render an item image. For native menus, it only works on iOS. It takes the same properties as `@tamagui/image`. ### ContextMenu.ItemSubtitle A component to render a subtitle for the menu item. For native menus, it only works on iOS. ### ContextMenu.Group A component that groups multiple menu items together. ### ContextMenu.CheckboxItem A menu item with a checkbox that can be toggled on/off. void', required: false, description: 'Called when the item receives focus.', }, { name: 'onBlur', type: '() => void', required: false, description: 'Called when the item loses focus.', }, { name: 'textValue', type: 'string', required: false, platform: 'ios/android', description: 'Text for native menus. Required when ItemTitle contains a React node.', }, { name: 'value', type: "'on' | 'off' | 'mixed'", required: false, platform: 'ios/android', description: 'Controlled checked state for native menus.', }, { name: 'onValueChange', type: '(state, prevState) => void', required: false, platform: 'ios/android', description: 'Called when checked state changes on native menus.', }, { name: 'checked', type: 'boolean', required: false, description: 'Controlled checked state for web menus.', }, { name: 'onCheckedChange', type: '(checked: boolean) => void', required: false, description: 'Called when checked state changes on web.', }, ]} /> ### ContextMenu.ItemIndicator Use inside `CheckboxItem` or `RadioItem` to indicate when an item is checked. This allows you to conditionally render a checkmark. ```jsx line=1 {/* This does not work with the native prop. */} ``` ### ContextMenu.Label Renders a non-focusable label for a group of items. On native menus, only one label is supported per menu and submenu. ### ContextMenu.Arrow Renders an arrow pointing to the trigger. ### ContextMenu.Separator Renders a visual divider between menu items. Web only. ### ContextMenu.Sub A container for nested sub-menu components. void', required: false, description: 'Called when the sub-menu opens or closes.', }, ]} /> ### ContextMenu.SubContent Renders the content of a sub-menu. Same props as `Content`, excluding `side` and `align`. ### ContextMenu.SubTrigger A menu item that opens a sub-menu on hover/focus. Accepts the same props as `Item`. ### ContextMenu.Preview When the ContextMenu is visible, this renders a custom preview component. Only works with native iOS menus. Should be rendered as a child of `ContextMenu.Content`. React.ReactNode)', required: true, platform: 'ios', description: 'The preview content to render. Can be a function for lazy rendering.', }, { name: 'size', type: '{ width?: number, height?: number }', required: false, platform: 'ios', description: 'Dimensions of the preview.', }, { name: 'onPress', type: '() => void', required: false, platform: 'ios', description: 'Called when the preview is pressed.', }, { name: 'backgroundColor', type: 'string | { dark: string, light: string }', required: false, platform: 'ios', description: 'Background color of the preview.', }, { name: 'borderRadius', type: 'number', required: false, platform: 'ios', description: 'Border radius of the preview.', }, { name: 'preferredCommitStyle', type: "'pop' | 'dismiss'", required: false, default: "'dismiss'", platform: 'ios', description: "Exit transition when preview is tapped. Use 'pop' when navigating to another screen.", }, ]} /> ```jsx line=1 {() => } ``` ## components/dialog/1.0.0 --- title: Dialog description: Show a modal with configurable layout and accessible actions. name: dialog component: Dialog package: dialog demoName: Dialog --- ```tsx hero template=Dialog ``` Dialog does not work on native, instead you can Adapt it to a Sheet as shown in the demo code above. ## Installation Dialog is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/dialog ``` In order to use this component independently of `tamagui`, you'll first need to install the `@tamagui/portal` package: ```bash npm install @tamagui/portal ``` Then add `PortalProvider` to the root of your app: ```tsx fileName="App.tsx" import { PortalProvider } from '@tamagui/portal' import YourApp from './components/YourApp' function App() { return ( ) } export default App ``` ## Anatomy ```tsx import { Dialog } from 'tamagui' // or '@tamagui/dialog' export default () => ( {/* ... */} {/* Optional: Control focus behavior */} {/* Focus scope will be applied to children */} ) ``` ## API Reference ### Dialog Contains every component for the dialog. Beyond [Tamagui Props](/docs/intro/props), adds: void', }, { name: 'modal', type: 'boolean', default: 'true', description: `Renders into root of app instead of inline`, }, { name: 'disableRemoveScroll', type: 'boolean', required: false, description: `Used to disable the automatic removal of scrolling from the page when open.`, }, ]} /> ### Dialog.Trigger Just [Tamagui Props](/docs/intro/props). ### Dialog.Portal Renders Dialog into appropriate container. Beyond [Tamagui Props](/docs/intro/props), adds: ### Dialog.Content Main container for Dialog content, this is where you should apply animations. Beyond [Tamagui Props](/docs/intro/props), adds: ### Dialog.Overlay Displays behind Content. Beyond [Tamagui Props](/docs/intro/props), adds: ### Dialog.Title Required. Can wrap in VisuallyHidden to hide. Defaults to H2, see [Headings](/docs/components/headings). ### Dialog.Description Required. Can wrap in VisuallyHidden to hide. Defaults to Paragraph, see [Paragraph](/docs/components/text). ### Dialog.Close Closes the Dialog, accepts the same props as YStack. Recommended to use with your own component and `asChild`. Just [Tamagui Props](/docs/intro/props). ### Dialog.FocusScope Provides access to the underlying FocusScope component used by Dialog for focus management. Can be used to control focus behavior from a parent component. void', description: `Event handler called when auto-focusing on mount. Can be prevented`, }, { name: 'onUnmountAutoFocus', type: '(event: Event) => void', description: `Event handler called when auto-focusing on unmount. Can be prevented`, }, ]} /> ### Dialog.Sheet When used with `Adapt`, Dialog will render as a sheet when that breakpoint is active. See [Sheet](/docs/components/sheet) for more props. Must use `Adapt.Contents` inside the `Dialog.Sheet.Frame` to insert the contents given to `Dialog.Content` ```tsx import { Dialog } from 'tamagui' // or '@tamagui/dialog' export default () => ( {/* ... */} {/* optionally change to sheet when small screen */} ) ``` Note that Dialog.Sheet currently doesn't preserve state of the contents when it transitions between Sheet and Portal. In the future, we can do this on the web using react-reparenting. ### PortalProvider ## Examples ### Inside native modals If you're using native modals (maybe from react-navigation), you'll notice the Dialogs won't show up inside the modal. To get around this, you should wrap your screen inside `PortalProvider`, like so: ```tsx import { PortalProvider } from 'tamagui' // this component used in react-navigation/expo-router with `presentation: "modal"` export function Page() { return ( {/* rest of your page, including the Dialog... */} ) } ``` ## components/dialog/1.131.0 --- title: Dialog description: Show a modal with configurable layout and accessible actions. name: dialog component: Dialog package: dialog demoName: Dialog --- ```tsx hero template=Dialog ``` Dialog is a great way to show content inside a new floating window above content. Be sure to open the code example above for a copy-paste implementation. ## Installation Dialog is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/dialog ``` If you aren't using `tamagui` and instead using the `@tamagui/dialog` package separately, you'll first need to install the `@tamagui/portal` package: ```bash npm install @tamagui/portal ``` Then add `PortalProvider` to the root of your app: ```tsx fileName="App.tsx" import { PortalProvider } from '@tamagui/portal' import YourApp from './components/YourApp' function App() { return ( ) } export default App ``` ## Anatomy ```tsx import { Dialog } from 'tamagui' // or '@tamagui/dialog' export default () => ( {/* ... */} {/* Optional: Control focus behavior */} {/* Focus scope will be applied to children */} ) ``` ## Scoping Dialog supports scoping which lets you mount one or more Dialog instances at the root of your app, while having a deeply nested child Trigger or Content attach to the proper parent Dialog instance. In performance sensitive areas you may want to take advantage of this, it allows you to only need to render the Dialog.Trigger inside the sensitive area as Dialogs aren't the cheapest component - they have a lot of functionality. Here's the basic anatomy of using `scope` and placing your Dialog higher up for performance: ```tsx fileName=_layout.tsx import { Dialog } from 'tamagui' // in your root layout: export default ({ children }) => ( {/* ... */} {/* the rest of your app, note that it's inside of Dialog */} {children} ) ``` ```tsx fileName=UserProfile.tsx export default () => ( ) ``` Note that the `Trigger` scope ties to the `Dialog` scope. ## Dismissal Behavior By default, dialogs can be dismissed by: - Clicking outside the dialog content (on the overlay) - Pressing the Escape key - Clicking a Dialog.Close element ### Modal vs Non-Modal Dialogs - **Modal dialogs** (`modal={true}`, which is the default): - In v1, have `disableOutsidePointerEvents` set to `true` by default - Still dismiss on outside click, but prevent interaction with elements behind the dialog - Prevent right-click dismissal (right-clicks on the overlay are ignored) - **Non-modal dialogs** (`modal={false}`): - Allow interaction with elements behind the dialog - Dismiss on any outside click - Do not trap focus ### Preventing Outside Dismissal To prevent a dialog from closing when clicking outside: ```tsx { event.preventDefault() }} > {/* Dialog contents */} ``` ## API Reference ### Dialog Contains every component for the dialog. Beyond [Tamagui Props](/docs/intro/props), adds: void', }, { name: 'modal', type: 'boolean', default: 'true', description: `Renders into root of app instead of inline`, }, { name: 'disableRemoveScroll', type: 'boolean', required: false, description: `Used to disable the automatic removal of scrolling from the page when open.`, }, ]} /> ### Dialog.Trigger Just [Tamagui Props](/docs/intro/props). ### Dialog.Portal Renders Dialog into appropriate container. Beyond [Tamagui Props](/docs/intro/props), adds: ### Dialog.Content Main container for Dialog content, this is where you should apply animations. Beyond [Tamagui Props](/docs/intro/props), adds: ### Dialog.Overlay Displays behind Content. Beyond [Tamagui Props](/docs/intro/props), adds: ### Dialog.Title Required. Can wrap in VisuallyHidden to hide. Defaults to H2, see [Headings](/docs/components/headings). ### Dialog.Description Required. Can wrap in VisuallyHidden to hide. Defaults to Paragraph, see [Paragraph](/docs/components/text). ### Dialog.Close Closes the Dialog, accepts the same props as YStack. Recommended to use with your own component and `asChild`. Just [Tamagui Props](/docs/intro/props). ### Dialog.FocusScope Provides access to the underlying FocusScope component used by Dialog for focus management. Can be used to control focus behavior from a parent component. void', description: `Event handler called when auto-focusing on mount. Can be prevented`, }, { name: 'onUnmountAutoFocus', type: '(event: Event) => void', description: `Event handler called when auto-focusing on unmount. Can be prevented`, }, ]} /> ### Dialog.Sheet When used with `Adapt`, Dialog will render as a sheet when that breakpoint is active. See [Sheet](/docs/components/sheet) for more props. Must use `Adapt.Contents` inside the `Dialog.Sheet.Frame` to insert the contents given to `Dialog.Content` ```tsx import { Dialog } from 'tamagui' // or '@tamagui/dialog' export default () => ( {/* ... */} {/* optionally change to sheet when small screen */} ) ``` Note that Dialog.Sheet currently doesn't preserve state of the contents when it transitions between Sheet and Portal. In the future, we can do this on the web using react-reparenting. ### PortalProvider ## Examples ### Inside native modals If you're using native modals (maybe from react-navigation), you'll notice the Dialogs won't show up inside the modal. To get around this, you should wrap your screen inside `PortalProvider`, like so: ```tsx import { PortalProvider } from 'tamagui' // this component used in react-navigation/expo-router with `presentation: "modal"` export function Page() { return ( {/* rest of your page, including the Dialog... */} ) } ``` ## components/dialog/2.0.0 --- title: Dialog description: Show a modal with configurable layout and accessible actions name: dialog component: Dialog package: dialog demoName: Dialog --- ```tsx hero template=Dialog ``` Dialog is a great way to show content inside a new floating window above content. Dialogs [automatically stack](/ui/z-index) above other overlays. Be sure to open the code example above for a copy-paste implementation. ## Installation Dialog is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/dialog ``` For native apps, we recommend [setting up native portals](/docs/components/portal#native-portal-setup-recommended) to preserve React context inside Dialog content. ## Anatomy ```tsx import { Dialog } from 'tamagui' // or '@tamagui/dialog' export default () => ( {/* ... */} {/* Optional: Control focus behavior */} {/* Focus scope will be applied to children */} ) ``` ## Scoping Dialog supports scoping which lets you mount one or more Dialog instances at the root of your app, while having a deeply nested child Trigger or Content attach to the proper parent Dialog instance. In performance sensitive areas you may want to take advantage of this, it allows you to only need to render the Dialog.Trigger inside the sensitive area as Dialogs aren't the cheapest component - they have a lot of functionality. Here's the basic anatomy of using `scope` and placing your Dialog higher up for performance: ```tsx fileName=_layout.tsx import { Dialog } from 'tamagui' // in your root layout: export default ({ children }) => ( {/* ... */} {/* the rest of your app, note that it's inside of Dialog */} {children} ) ``` ```tsx fileName=UserProfile.tsx export default () => ( ) ``` Note that the `Trigger` scope ties to the `Dialog` scope. ## Dismissal Behavior By default, dialogs can be dismissed by: - Clicking outside the dialog content (on the overlay) - Pressing the Escape key - Clicking a Dialog.Close element ### Modal vs Non-Modal Dialogs - **Modal dialogs** (`modal={true}`, which is the default): - In v1, have `disableOutsidePointerEvents` set to `true` by default - Still dismiss on outside click, but prevent interaction with elements behind the dialog - Prevent right-click dismissal (right-clicks on the overlay are ignored) - **Non-modal dialogs** (`modal={false}`): - Allow interaction with elements behind the dialog - Dismiss on any outside click - Do not trap focus ### Preventing Outside Dismissal To prevent a dialog from closing when clicking outside: ```tsx { event.preventDefault() }} > {/* Dialog contents */} ``` ## API Reference ### Dialog Contains every component for the dialog. Beyond [Tamagui Props](/docs/intro/props), adds: void', description: `Called when the dialog opens or closes.`, }, { name: 'modal', type: 'boolean', default: 'true', description: `Renders into root of app instead of inline.`, }, { name: 'keepChildrenMounted', type: 'boolean', default: 'false', description: `When true, dialog content stays mounted in the DOM even when closed. Useful for preserving state across open/close cycles or when you need faster re-opening.`, }, { name: 'disableRemoveScroll', type: 'boolean', required: false, description: `Used to disable the automatic removal of scrolling from the page when open.`, }, ]} /> ### Dialog.Trigger Just [Tamagui Props](/docs/intro/props). ### Dialog.Portal Renders Dialog into appropriate container. Beyond [Tamagui Props](/docs/intro/props), adds: ### Dialog.Content Main container for Dialog content, this is where you should apply animations. Beyond [Tamagui Props](/docs/intro/props), adds: ### Dialog.Overlay Displays behind Content. Beyond [Tamagui Props](/docs/intro/props), adds: ### Dialog.Title Required. Can wrap in VisuallyHidden to hide. Defaults to H2, see [Headings](/docs/components/headings). ### Dialog.Description Required. Can wrap in VisuallyHidden to hide. Defaults to Paragraph, see [Paragraph](/docs/components/text). ### Dialog.Close Closes the Dialog, accepts the same props as YStack. Recommended to use with your own component and `asChild`. Just [Tamagui Props](/docs/intro/props). ### Dialog.FocusScope Provides access to the underlying FocusScope component used by Dialog for focus management. Can be used to control focus behavior from a parent component. void', description: `Event handler called when auto-focusing on mount. Can be prevented`, }, { name: 'onUnmountAutoFocus', type: '(event: Event) => void', description: `Event handler called when auto-focusing on unmount. Can be prevented`, }, ]} /> ### Dialog.Sheet When used with `Adapt`, Dialog will render as a sheet when that breakpoint is active. See [Sheet](/docs/components/sheet) for more props. Must use `Adapt.Contents` inside the `Dialog.Sheet.Frame` to insert the contents given to `Dialog.Content` ```tsx import { Dialog } from 'tamagui' // or '@tamagui/dialog' export default () => ( {/* ... */} {/* optionally change to sheet when small screen */} ) ``` Note that Dialog.Sheet currently doesn't preserve state of the contents when it transitions between Sheet and Portal. In the future, we can do this on the web using react-reparenting. ## components/focus-scope/1.128.0 --- title: FocusScope description: Manage focus behavior within elements accessibly. name: focus-scope component: FocusScope package: focus-scope --- A utility component for managing keyboard focus within a container. Controls focus trapping, auto-focus behavior, and focus cycling for accessible interactive components. Note that this is a web-only component, on native it is a no-op. ## Installation FocusScope is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/focus-scope ``` ## Usage Wrap any content that needs focus management: ```tsx import { Button, FocusScope, XStack } from 'tamagui' export default () => ( ) ``` ## Focus Trapping Use `trapped` to prevent focus from escaping the scope: ```tsx import { Button, Dialog, FocusScope, XStack, YStack } from 'tamagui' export default () => ( {/* key used by AnimatePresence to animate */} Focused Content ) ``` ## Focus Looping Enable `loop` to cycle focus between first and last elements: ```tsx import { Button, FocusScope, XStack } from 'tamagui' export default () => ( {/* Tab from "Last" goes to "First" */} ) ``` ## Animation-Friendly Focusing Use `focusOnIdle` to prevent reflows during animations: ```tsx import { Button, FocusScope, XStack } from 'tamagui' export default () => ( ) ``` ## Advanced Control with FocusScopeController Use the controller pattern for managing focus from parent components: ```tsx import { Button, FocusScope, XStack, YStack } from 'tamagui' import { useState } from 'react' export default () => { const [trapped, setTrapped] = useState(false) return ( ) } ``` ## Function as Children For advanced use cases, pass a function to get access to focus props: ```tsx import { FocusScope, View } from 'tamagui' export default () => ( {({ onKeyDown, tabIndex, ref }) => ( Custom focus container )} ) ``` ## API Reference ### FocusScope void', description: 'Event handler called when auto-focusing on mount. Can be prevented', }, { name: 'onUnmountAutoFocus', type: '(event: Event) => void', description: 'Event handler called when auto-focusing on unmount. Can be prevented', }, { name: 'forceUnmount', type: 'boolean', default: 'false', description: 'If unmount is animated, you want to force re-focus at start of animation not after', }, { name: 'children', type: 'React.ReactNode | ((props: FocusProps) => React.ReactNode)', description: 'Content to apply focus management to, or function that receives focus props', }, ]} /> ### FocusScope.Controller Provides context-based control over FocusScope behavior: void', description: 'Override onMountAutoFocus handler for all child FocusScope.Controller.Scope components', }, { name: 'onUnmountAutoFocus', type: '(event: Event) => void', description: 'Override onUnmountAutoFocus handler for all child FocusScope.Controller.Scope components', }, { name: 'forceUnmount', type: 'boolean', description: 'Override forceUnmount behavior for all child FocusScope.Controller.Scope components', }, ]} /> The FocusScope component automatically inherits props from the nearest FocusScope.Controller, with controller props taking precedence over direct props. ## Usage in Other Components Many Tamagui components export FocusScope for advanced focus control: ```tsx import { Dialog, Popover, Select } from 'tamagui' // Available on: // And more... ``` ## Accessibility FocusScope follows accessibility best practices: - Manages `tabindex` appropriately for focus flow - Respects user's reduced motion preferences - Maintains focus visible indicators - Provides proper ARIA support when used with other components - Handles edge cases like disabled elements and hidden content FocusScope is primarily designed for web platforms. On React Native, it renders children without focus management since native platforms handle focus differently. ## Examples ### Modal Focus Management ```tsx import { Button, Dialog, FocusScope, Input, XStack, YStack } from 'tamagui' export default () => ( User Details ) ``` ### Custom Focus Container ```tsx import { Button, FocusScope, styled, XStack } from 'tamagui' const FocusContainer = styled(XStack, { borderWidth: 2, borderColor: 'transparent', borderRadius: '$4', padding: '$4', variants: { focused: { true: { borderColor: '$blue10', shadowColor: '$blue10', shadowRadius: 10, shadowOpacity: 0.3, }, }, }, }) export default () => ( {({ onKeyDown, tabIndex, ref }) => ( )} ) ``` ## components/focus-scope/2.0.0 --- title: FocusScope description: Manage focus behavior within elements accessibly. name: focus-scope component: FocusScope package: focus-scope --- A utility component for managing keyboard focus within a container. Controls focus trapping, auto-focus behavior, and focus cycling for accessible interactive components. Note that this is a web-only component, on native it is a no-op. ## Installation FocusScope is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/focus-scope ``` ## Usage Wrap any content that needs focus management: ```tsx import { Button, FocusScope, XStack } from 'tamagui' export default () => ( ) ``` ## Focus Trapping Use `trapped` to prevent focus from escaping the scope: ```tsx import { Button, Dialog, FocusScope, XStack, YStack } from 'tamagui' export default () => ( {/* key used by AnimatePresence to animate */} Focused Content ) ``` ## Focus Looping Enable `loop` to cycle focus between first and last elements: ```tsx import { Button, FocusScope, XStack } from 'tamagui' export default () => ( {/* Tab from "Last" goes to "First" */} ) ``` ## Animation-Friendly Focusing Use `focusOnIdle` to prevent reflows during animations: ```tsx import { Button, FocusScope, XStack } from 'tamagui' export default () => ( ) ``` ## Advanced Control with FocusScopeController Use the controller pattern for managing focus from parent components: ```tsx import { Button, FocusScope, XStack, YStack } from 'tamagui' import { useState } from 'react' export default () => { const [trapped, setTrapped] = useState(false) return ( ) } ``` ## Function as Children For advanced use cases, pass a function to get access to focus props: ```tsx import { FocusScope, View } from 'tamagui' export default () => ( {({ onKeyDown, tabIndex, ref }) => ( Custom focus container )} ) ``` ## API Reference ### FocusScope void', description: 'Event handler called when auto-focusing on mount. Can be prevented', }, { name: 'onUnmountAutoFocus', type: '(event: Event) => void', description: 'Event handler called when auto-focusing on unmount. Can be prevented', }, { name: 'forceUnmount', type: 'boolean', default: 'false', description: 'If unmount is animated, you want to force re-focus at start of animation not after', }, { name: 'children', type: 'React.ReactNode | ((props: FocusProps) => React.ReactNode)', description: 'Content to apply focus management to, or function that receives focus props', }, ]} /> ### FocusScope.Controller Provides context-based control over FocusScope behavior: void', description: 'Override onMountAutoFocus handler for all child FocusScope.Controller.Scope components', }, { name: 'onUnmountAutoFocus', type: '(event: Event) => void', description: 'Override onUnmountAutoFocus handler for all child FocusScope.Controller.Scope components', }, { name: 'forceUnmount', type: 'boolean', description: 'Override forceUnmount behavior for all child FocusScope.Controller.Scope components', }, ]} /> The FocusScope component automatically inherits props from the nearest FocusScope.Controller, with controller props taking precedence over direct props. ## Usage in Other Components Many Tamagui components export FocusScope for advanced focus control: ```tsx import { Dialog, Popover, Select } from 'tamagui' // Available on: // And more... ``` ## Accessibility FocusScope follows accessibility best practices: - Manages `tabindex` appropriately for focus flow - Respects user's reduced motion preferences - Maintains focus visible indicators - Provides proper ARIA support when used with other components - Handles edge cases like disabled elements and hidden content FocusScope is primarily designed for web platforms. On React Native, it renders children without focus management since native platforms handle focus differently. ## Examples ### Modal Focus Management ```tsx import { Button, Dialog, FocusScope, Input, XStack, YStack } from 'tamagui' export default () => ( User Details ) ``` ### Custom Focus Container ```tsx import { Button, FocusScope, styled, XStack } from 'tamagui' const FocusContainer = styled(XStack, { borderWidth: 2, borderColor: 'transparent', borderRadius: '$4', padding: '$4', variants: { focused: { true: { borderColor: '$blue10', shadowColor: '$blue10', shadowRadius: 10, shadowOpacity: 0.3, }, }, }, }) export default () => ( {({ onKeyDown, tabIndex, ref }) => ( )} ) ``` ## components/form/1.3.0 --- title: Form description: A simple form component for native and web. name: form component: Form package: form demoName: Form --- ```tsx hero template=Forms ``` ## Installation Form is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/form ``` ## Anatomy ```tsx import { Form } from 'tamagui' // or '@tamagui/form' export default () => (
{/* ... */} ) ``` For a simpler use case and backwards compat, you can also use it without `Group.Item`, which will just apply borders and spacing based on direct children. Note that Group will detect if any `Group.Item` is inside it, and automatically switch modes. If no Item, it spaces direct children: ```tsx import { Button, XGroup } from 'tamagui' // usage without Item: export default () => ( ) ``` ## Sizing The `size` property will use your tokens to grab the appropriate radius for borderRadius values which it will pass to the first and last child as style props for borderRadius. ```tsx import { Button, XGroup } from 'tamagui' export default () => ( ) ``` ## Disabled The `disabled` property will pass to children ## Group API ### Group `XGroup` and `YGroup` extend [YStack](/docs/components/stacks), getting [Tamagui standard props](/docs/intro/props), plus: ### Group.Item Wrap each of `XGroup` or `YGroup`'s children in one of these. It lets Tamagui apply the needed styles to them. Accepts only a `children` prop. ## components/group/1.11.2 --- title: Group description: Render horizontal or vertical groups easily. name: group component: Group demoName: Group --- # Group Layout buttons and more with groups ```tsx hero template=Group ``` ## Usage You can use `Group` by itself with the `orientation` property determining the direction it assumes. By default, Groups will control the border radius of their children automatically - the first and last children will get their start/end radius set to match group radius. If it's a `YGroup`, it will adjust top/bottom radius. `XGroup` adjusts the left/right radius. You can use Groups with or without `Group.Item`, depending on if you want to spacing and separators to be handled based on direct children, or on each Item rendered. ```tsx import { Button, XGroup } from 'tamagui' // usage with Item: export default () => ( ) ``` For a simpler use case and backwards compat, you can also use it without `Group.Item`, which will just apply borders and spacing based on direct children. Note that Group will detect if any `Group.Item` is inside it, and automatically switch modes. If no Item, it spaces direct children: ```tsx import { Button, XGroup } from 'tamagui' // usage without Item: export default () => ( ) ``` ## Sizing The `size` property will use your tokens to grab the appropriate radius for borderRadius values which it will pass to the first and last child as style props for borderRadius. ```tsx import { Button, XGroup } from 'tamagui' export default () => ( ) ``` ## Disabled The `disabled` property will pass to children ## API Reference ### Group `Group`, `XGroup` and `YGroup` extend [YStack](/docs/components/stacks), getting [Tamagui standard props](/docs/intro/props), plus: ### Group.Item Wrap each of `XGroup` or `YGroup`'s children in one of these. It lets Tamagui apply the needed styles to them. Accepts only a `children` prop. ## components/group/1.56.1 --- title: Group description: Render horizontal or vertical groups easily. name: group component: Group demoName: Group --- ```tsx hero template=Group ``` ## Installation Group is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/group ``` ## Usage You can use `Group` by itself with the `orientation` property determining the direction it assumes. By default, Groups will control the border radius of their children automatically - the first and last children will get their start/end radius set to match group radius. If it's a `YGroup`, it will adjust top/bottom radius. `XGroup` adjusts the left/right radius. You can use Groups with or without `Group.Item`, depending on if you want to spacing and separators to be handled based on direct children, or on each Item rendered. ```tsx import { Button, XGroup } from 'tamagui' // usage with Item: export default () => ( ) ``` For a simpler use case and backwards compat, you can also use it without `Group.Item`, which will just apply borders and spacing based on direct children. Note that Group will detect if any `Group.Item` is inside it, and automatically switch modes. If no Item, it spaces direct children: ```tsx import { Button, XGroup } from 'tamagui' // usage without Item: export default () => ( ) ``` ## Sizing The `size` property will use your tokens to grab the appropriate radius for borderRadius values which it will pass to the first and last child as style props for borderRadius. ```tsx import { Button, XGroup } from 'tamagui' export default () => ( ) ``` ## Disabled The `disabled` property will pass to children ## API Reference ### Group `Group`, `XGroup` and `YGroup` extend [YStack](/docs/components/stacks), getting [Tamagui standard props](/docs/intro/props), plus: ### Group.Item Wrap each of `XGroup` or `YGroup`'s children in one of these. It lets Tamagui apply the needed styles to them. It accepts the following props: ## components/group/1.6.0 --- title: Group description: Render horizontal or vertical groups easily. name: group component: Group demoName: Group --- # Group Layout buttons and more with groups. ```tsx hero template=Group ``` ## Usage You can use `Group` by itself with the `axis` property determining the direction it assumes. By default, Groups will control the border radius of their children automatically - the first and last children will get their start/end radius set to match group radius. If it's a `YGroup`, it will adjust top/bottom radius. `XGroup` adjusts the left/right radius. You can use Groups with or without `Group.Item`, depending on if you want to spacing and separators to be handled based on direct children, or on each Item rendered. ```tsx import { Button, XGroup } from 'tamagui' // usage with Item: export default () => ( ) ``` For a simpler use case and backwards compat, you can also use it without `Group.Item`, which will just apply borders and spacing based on direct children. Note that Group will detect if any `Group.Item` is inside it, and automatically switch modes. If no Item, it spaces direct children: ```tsx import { Button, XGroup } from 'tamagui' // usage without Item: export default () => ( ) ``` ## Sizing The `size` property will use your tokens to grab the appropriate radius for borderRadius values which it will pass to the first and last child as style props for borderRadius. ```tsx import { Button, XGroup } from 'tamagui' export default () => ( ) ``` ## Disabled The `disabled` property will pass to children ## Group API ### Group `Group`, `XGroup`and`YGroup` extend [YStack](/docs/components/stacks), getting [Tamagui standard props](/docs/intro/props), plus: ### Group.Item Wrap each of `XGroup` or `YGroup`'s children in one of these. It lets Tamagui apply the needed styles to them. Accepts only a `children` prop. ## components/group/1.7.0 --- title: Group description: Render horizontal or vertical groups easily. name: group component: Group demoName: Group --- # Group Layout buttons and more with groups. ```tsx hero template=Group ``` ## Usage You can use `Group` by itself with the `axis` property determining the direction it assumes. By default, Groups will control the border radius of their children automatically - the first and last children will get their start/end radius set to match group radius. If it's a `YGroup`, it will adjust top/bottom radius. `XGroup` adjusts the left/right radius. You can use Groups with or without `Group.Item`, depending on if you want to spacing and separators to be handled based on direct children, or on each Item rendered. ```tsx import { Button, XGroup } from 'tamagui' // usage with Item: export default () => ( ) ``` For a simpler use case and backwards compat, you can also use it without `Group.Item`, which will just apply borders and spacing based on direct children. Note that Group will detect if any `Group.Item` is inside it, and automatically switch modes. If no Item, it spaces direct children: ```tsx import { Button, XGroup } from 'tamagui' // usage without Item: export default () => ( ) ``` ## Sizing The `size` property will use your tokens to grab the appropriate radius for borderRadius values which it will pass to the first and last child as style props for borderRadius. ```tsx import { Button, XGroup } from 'tamagui' export default () => ( ) ``` ## Disabled The `disabled` property will pass to children ## Group API ### Group `Group`, `XGroup`and`YGroup` extend [YStack](/docs/components/stacks), getting [Tamagui standard props](/docs/intro/props), plus: ### Group.Item Wrap each of `XGroup` or `YGroup`'s children in one of these. It lets Tamagui apply the needed styles to them. Accepts only a `children` prop. ## components/group/2.0.0 --- title: Group description: Render horizontal or vertical groups easily name: group component: Group package: group demoName: Group --- ```tsx hero template=Group ``` ## Installation Group is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/group ``` ## Usage Use `Group` with `Group.Item` wrapping each child. The `orientation` property determines the layout direction. Group zeros out the border radius on connecting sides of children - the first child keeps its start radius, the last keeps its end radius, and middle items have no radius on connecting sides. For `YGroup`, this affects top/bottom radius. For `XGroup`, left/right radius. ```tsx import { Button, XGroup } from 'tamagui' export default () => ( ) ``` ## Sizing In v2, children control their own sizing. Apply size props directly to the child components. For responsive sizing, use media queries on the children: ```tsx import { Activity, Airplay } from '@tamagui/lucide-icons' import { Button, XGroup } from 'tamagui' export default () => ( ) ``` The `size` prop on Group itself only affects the border radius of the group container: ```tsx import { Button, XGroup } from 'tamagui' export default () => ( ) ``` ## Separators Add separators manually between items: ```tsx import { ListItem, Separator, YGroup } from 'tamagui' export default () => ( ) ``` ## Disabled The `disabled` property will pass to children. ## Custom Components & Nested Items Automatic index detection only works when `Group.Item` is a **direct child** of `Group`. If you wrap `Group.Item` inside a custom component, the automatic first/last detection won't work. You have a few options: ### Option 1: Use `forcePlacement` If you know the position ahead of time, use the `forcePlacement` prop: ```tsx function MyFirstItem({ children }) { return {children} } export default () => ( ) ``` ### Option 2: Use `useGroupItem` hook For full control, use the `useGroupItem` hook directly in your custom component: ```tsx import { useGroupItem } from '@tamagui/group' function MyItem({ children, forcePlacement }) { const groupItemProps = useGroupItem({ disabled: false }, forcePlacement) return React.cloneElement(children, groupItemProps) } ``` ### Option 3: Pass placement from parent Calculate positions in the parent and pass them down: ```tsx const items = ['First', 'Second', 'Third'] export default () => ( {items.map((item, i) => ( ))} ) ``` ## API Reference ### Group `Group`, `XGroup` and `YGroup` extend [YStack](/docs/components/stacks), getting [Tamagui standard props](/docs/intro/props), plus: ### Group.Item Wrap each of `XGroup` or `YGroup`'s children in one of these. It lets Tamagui apply the needed styles to them. It accepts the following props: ## components/headings/1.0.0 --- title: Headings description: Heading components that mimic HTML equivalents name: html component: Headings package: text demoName: Headings --- ```tsx hero template=Headings ``` ## Installation Headings is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/text ``` ```tsx import { H1, H2, H3, H4, H5, H6, Heading } from 'tamagui' export default () => ( <>

Heading 1

Heading 2

Heading 3

Heading 4

Heading 5
Heading 6
Heading ) ``` The headings all extend from the base `Heading` component. Note, this is just our own theme for Inter headings, but you can change the styles for any font completely. Tamagui expects for your [font.size](/docs/core/configuration#font-tokens) to have the keys 1-10 so headings work with your font tokens automatically. ## How it works The `Heading` component is defined as follows: ```tsx export const Heading = styled(Paragraph, { tag: 'span', name: 'Heading', accessibilityRole: 'header', fontFamily: '$heading', size: '$8', margin: 0, }) ``` Note that Heading, and H1-H6 all default to the `heading` font family that must be defined in your tamagui.config.ts. Because [Paragraph](/docs/components/text#paragraph) extends [SizableText](/docs/components/text#sizabletext), you get automatic styles based on your font theme. Let's see how `SizableText` defines the size variant, roughly, which gives a good idea of how Tamagui works, and how you could create or change your own headings at a lower level. ```tsx import { Text } from 'tamagui' // or '@tamagui/core' const SizableText = styled(Text, { name: 'SizableText', fontFamily: '$body', color: '$color', variants: { size: { '...fontSize': (val, { font, props }) => { const fontSize = font.size[val] const lineHeight = font.lineHeight[val] const fontWeight = font.weight[val] const letterSpacing = font.letterSpacing[val] const fontStyle = font.style?.[val] const textTransform = font.transform?.[val] return { fontStyle, textTransform, fontWeight, letterSpacing, fontSize, lineHeight, } }, }, }, defaultVariants: { // note tamagui uses a generic "true" token that your sizes should set to be the same as the default on your scale size: '$true', }, }) ``` ## API Reference ### Heading Headings extend [SizableText props](/docs/components/text#sizabletext) inheriting all the [Tamagui standard props](/docs/intro/props). ## components/headings/2.0.0 --- title: Headings description: Heading components that mirror HTML equivalents name: headings component: Headings package: text demoName: Headings --- ```tsx hero template=Headings ``` ## Installation Headings is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/text ``` ```tsx import { H1, H2, H3, H4, H5, H6, Heading } from 'tamagui' export default () => ( <>

Heading 1

Heading 2

Heading 3

Heading 4

Heading 5
Heading 6
Heading ) ``` The headings all extend from the base `Heading` component. Note, this is just our own theme for Inter headings, but you can change the styles for any font completely. Tamagui expects for your [font.size](/docs/core/configuration#font-tokens) to have the keys 1-10 so headings work with your font tokens automatically. ## How it works The `Heading` component is defined as follows: ```tsx export const Heading = styled(Paragraph, { tag: 'span', name: 'Heading', accessibilityRole: 'header', fontFamily: '$heading', size: '$8', margin: 0, }) ``` Note that Heading, and H1-H6 all default to the `heading` font family that must be defined in your tamagui.config.ts. Because [Paragraph](/docs/components/text#paragraph) extends [SizableText](/docs/components/text#sizabletext), you get automatic styles based on your font theme. Let's see how `SizableText` defines the size variant, roughly, which gives a good idea of how Tamagui works, and how you could create or change your own headings at a lower level. ```tsx import { Text } from 'tamagui' // or '@tamagui/core' const SizableText = styled(Text, { name: 'SizableText', fontFamily: '$body', color: '$color', variants: { size: { '...fontSize': (val, { font, props }) => { const fontSize = font.size[val] const lineHeight = font.lineHeight[val] const fontWeight = font.weight[val] const letterSpacing = font.letterSpacing[val] const fontStyle = font.style?.[val] const textTransform = font.transform?.[val] return { fontStyle, textTransform, fontWeight, letterSpacing, fontSize, lineHeight, } }, }, }, defaultVariants: { // note tamagui uses a generic "true" token that your sizes should set to be the same as the default on your scale size: '$true', }, }) ``` ## API Reference ### Heading Headings extend [SizableText props](/docs/components/text#sizabletext) inheriting all the [Tamagui standard props](/docs/intro/props). ## components/html-elements/1.0.0 --- title: HTML Elements description: Render semantic HTML with these elements. name: html-elements component: Layouts --- To assist in creating accessible web apps, the following components are exported, all mapping directly to DOM elements of the lowercase names: - `Section` (`section`) - `Article` (`article`) - `Main` (`main`) - `Header` (`header`) - `Aside` (`aside`) - `Footer` (`footer`) - `Nav` (`nav`) ## Installation It's exported by `tamagui`, or: ```bash npm install @tamagui/elements ``` ## HTML element props All HTML components extend View, inheriting all the [Tamagui standard props](/docs/intro/props). ## components/html-elements/2.0.0 --- title: HTML Elements description: Render semantic HTML with these elements name: html-elements component: Layouts package: elements --- To assist in creating accessible web apps, the following components are exported, all mapping directly to DOM elements of the lowercase names: - `Section` (`section`) - `Article` (`article`) - `Main` (`main`) - `Header` (`header`) - `Aside` (`aside`) - `Footer` (`footer`) - `Nav` (`nav`) ## Installation It's exported by `tamagui`, or: ```bash npm install @tamagui/elements ``` ## API Reference All HTML components extend View, inheriting all the [Tamagui standard props](/docs/intro/props). ## components/image/1.0.0 --- title: Image description: React Native Web Image + Tamagui style props. name: html component: Image package: image demoName: Image --- # Image React Native Web Image + Tamagui style props. ```tsx hero template=Image ``` ### Props [Tamagui props](/docs/intro/props) + [React Native Web Image props](https://necolas.github.io/react-native-web/docs/image/). ## components/image/1.13.0 --- title: Image description: React Native Web Image + Tamagui style props. name: html component: Image package: image demoName: Image --- ```tsx hero template=Image ``` ## Installation Image is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/image ``` ## Usage Note that you need to set `source` like so - the `width` and `height` properties apply as styles around the image, but the actual image needs `source.width` and `source.height` for React Native: ```tsx export default () => ( ) ``` ## API Reference ### Image [Tamagui props](/docs/intro/props) + [React Native Web Image props](https://necolas.github.io/react-native-web/docs/image/). ## components/image/2.0.0 --- title: Image description: A pure, lightweight Image component with Tamagui style props name: image component: Image package: image demoName: Image --- ```tsx hero template=Image ``` ## Installation Image is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/image ``` ## Usage Use the `src` prop for the image URL: ```tsx import { Image } from 'tamagui' export default () => ( ) ``` You can also use `objectFit` to control how the image fits its container: ```tsx ``` ## Using with expo-image For better performance and features like blurhash placeholders and transitions, you can use `createImage` to create a custom Image component with expo-image: ```tsx import { Image as ExpoImage } from 'expo-image' import { createImage } from '@tamagui/image' export const Image = createImage({ Component: ExpoImage, resizeModePropName: 'contentFit', objectPositionPropName: 'contentPosition', }) ``` Now you can use all expo-image props alongside Tamagui's unified API: ```tsx const blurhash = '|rF?hV%2WCj[ayj[a|j[az...' export default () => ( ) ``` ### createImage Options ## Accessibility Always provide an `alt` attribute describing the image content. For decorative images, use an empty string (`alt=""`). ```tsx // meaningful image The Tamagui team at React Conf 2024 // decorative image ``` On React Native, use `accessible` and `accessibilityLabel` for screen reader support. See the [React Native Accessibility docs](https://reactnative.dev/docs/accessibility) for details. ```tsx ``` ## API Reference ### Image Extends View with [Tamagui props](/docs/intro/props), plus: ### Web-only Props These props pass through to the native `` element on web: ### Accessibility Props Web props like `loading`, `srcSet`, and `fetchPriority` only apply on web. On native, use expo-image via `createImage` for advanced features like blurhash placeholders and priority loading. ## components/inputs/1.0.0 --- title: Input & Textarea name: inputs description: Flexible form fields in styled and unstyled forms. component: Input demoName: Inputs --- ```tsx hero template=Inputs ``` Using the same base component TextInput, from [React Native](https://reactnative.dev/docs/textinput) or [React Native Web](https://necolas.github.io/react-native-web/docs/text-input/), Tamagui simply wraps these components to allow the full set of style props, as well as scaling all the styles up or down using the `size` property, much like Button. ## Installation Input is already installed in `tamagui`, or you can install it independently: ```bash npm install @tamagui/input ``` ## Input A one-line input field: ```tsx import { Input } from 'tamagui' export const App = () => ( // Accepts size and style properties directly ) ``` ## TextArea For multi-line inputs: ```tsx import { TextArea } from 'tamagui' export const App = () => ( // Accepts size and style properties directly