# Tamagui Complete Documentation ## 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'; 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/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/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/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/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/master/packages/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/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/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 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/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 has 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 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/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/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/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/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/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/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