InlineDrawer
An in-flow collapsible panel that expands and collapses along one axis, supporting sidebar navigation and persistent collapsed content.
Features
- In-flow collapsible panel with CSS transitions
minSizekeeps collapsed content visible (sidebar nav pattern)shouldDismissOnBlurwith portal-aware focus detection- Controlled and uncontrolled modes
hidden="until-found"for browser find-in-page supportprefers-reduced-motionsupport
Installation
npm install --save @godaddy/antaresProps
placement?InlineDrawerPlacement | undefined'left'Edge the drawer anchors to. Determines constrained axis. Unlike Drawer, InlineDrawer does not flip in RTL because CSS inline-size/block-size are already logical-direction-aware. The value is physical.
minSize?string | number | undefined—Size when collapsed. Panel stays visible at this size instead of hiding.
maxSize?string | number | undefined—Size when expanded.
animate?boolean | undefinedtrueCSS transition for expand/collapse. false disables animation.
shouldDismissOnBlur?boolean | undefined—Collapse when focus leaves the drawer. Does not collapse when focus moves to browser chrome.
className?string | undefined—Additional CSS class.
isDisabled?boolean | undefined—Whether the disclosure is disabled.
onExpandedChange?((isExpanded: boolean) => void) | undefined—Handler that is called when the disclosure's expanded state changes.
isExpanded?boolean | undefined—Whether the disclosure is expanded (controlled).
defaultExpanded?boolean | undefined—Whether the disclosure is expanded by default (uncontrolled).
id?Key | undefined—An id for the disclosure when used within a DisclosureGroup, matching the id used in `expandedKeys`.
render?DOMRenderFunction<"div", DisclosureRenderProps> | undefined—Overrides the default DOM element with a custom render function. This allows rendering existing components with built-in styles and behaviors such as router links, animation libraries, and pre-styled components. Requirements: - You must render the expected element type (e.g. if `<button>` is expected, you cannot render an `<a>`). - Only a single root DOM element can be rendered (no fragments). - You must pass through props and ref to the underlying DOM element, merging with your own prop as appropriate.
slot?string | null | undefined—A slot name for the component. Slots allow the component to receive props from a parent component. An explicit `null` value indicates that the local props completely override all props received from a parent.
Examples
Basic Usage
The panel toggles when the trigger is pressed, pushing adjacent content as it expands.
import { InlineDrawer, InlineDrawerTrigger, InlineDrawerPanel, Text } from '@godaddy/antares';export function DefaultExample() { return ( <InlineDrawer> <InlineDrawerTrigger>Toggle details</InlineDrawerTrigger> <InlineDrawerPanel> <Text>Collapsible content goes here.</Text> </InlineDrawerPanel> </InlineDrawer> );}Controlled
Use isExpanded and onExpandedChange to drive state externally, e.g. from a button outside the drawer.
import { useState } from 'react';import { InlineDrawer, InlineDrawerTrigger, InlineDrawerPanel, Button, Text } from '@godaddy/antares';export function ControlledExample() { const [expanded, setExpanded] = useState(false); return ( <> <Button variant="primary" onPress={() => setExpanded(!expanded)}> {expanded ? 'Collapse' : 'Expand'} </Button> <Text>Expanded: {String(expanded)}</Text> <InlineDrawer isExpanded={expanded} onExpandedChange={setExpanded}> <InlineDrawerTrigger>Details</InlineDrawerTrigger> <InlineDrawerPanel> <Text>Controlled panel content.</Text> </InlineDrawerPanel> </InlineDrawer> </> );}Sidebar Navigation
Combine minSize and maxSize to create a sidebar that collapses to an icon strip instead of disappearing completely.
import { InlineDrawer, InlineDrawerTrigger, InlineDrawerPanel, Flex, Text } from '@godaddy/antares';export function SidebarNavExample() { return ( <Flex direction="row" style={{ height: 300, border: '1px solid var(--bd-base)' }}> <InlineDrawer placement="left" defaultExpanded minSize={48} maxSize={220}> <InlineDrawerTrigger>Menu</InlineDrawerTrigger> <InlineDrawerPanel> <Flex as="nav" direction="column" gap="sm" padding="sm"> <Text>Home</Text> <Text>Settings</Text> <Text>Profile</Text> </Flex> </InlineDrawerPanel> </InlineDrawer> <Flex padding="md" style={{ flex: 1 }}> <Text>Main content area</Text> </Flex> </Flex> );}Vertical Placement
Set placement="top" or "bottom" to collapse vertically instead of horizontally.
import { InlineDrawer, InlineDrawerTrigger, InlineDrawerPanel, Flex, Text } from '@godaddy/antares';export function VerticalExample() { return ( <Flex direction="column" style={{ height: 400, border: '1px solid var(--bd-base)' }}> <InlineDrawer placement="top" defaultExpanded minSize={32} maxSize={120}> <InlineDrawerTrigger>Header</InlineDrawerTrigger> <InlineDrawerPanel> <Flex padding="sm"> <Text>Top drawer content, collapses vertically.</Text> </Flex> </InlineDrawerPanel> </InlineDrawer> <Flex padding="md" style={{ flex: 1 }}> <Text>Main content area</Text> </Flex> </Flex> );}Dismiss on Blur
Set shouldDismissOnBlur to auto-collapse when focus leaves the drawer. Tab from the inside button to the outside button to see it collapse. Focus moving to browser chrome (address bar, devtools) does not trigger collapse.
import { useState } from 'react';import { InlineDrawer, InlineDrawerTrigger, InlineDrawerPanel, Flex, Text, Button } from '@godaddy/antares';export function DismissOnBlurExample() { const [expanded, setExpanded] = useState(true); return ( <Flex direction="row" gap="md" style={{ height: 200 }}> <InlineDrawer placement="left" isExpanded={expanded} onExpandedChange={setExpanded} shouldDismissOnBlur maxSize={220} > <InlineDrawerTrigger>Panel</InlineDrawerTrigger> <InlineDrawerPanel> <Flex direction="column" gap="sm" padding="sm"> <Text>Focus here, then Tab out.</Text> <Button variant="secondary" onPress={() => undefined}> Inside button </Button> </Flex> </InlineDrawerPanel> </InlineDrawer> <Flex padding="md" direction="column" gap="sm" style={{ flex: 1 }}> <Text>Outside content</Text> <Button variant="secondary" onPress={() => undefined}> Outside button </Button> <Button variant="primary" onPress={() => setExpanded(true)}> Re-expand </Button> </Flex> </Flex> );}Focus Scope
Wrap panel content in <FocusScope> to trap focus while expanded. Tab cycles between Action A and Action B without escaping to main content. Use contain={isExpanded} so trapping only applies when open.
import { useState } from 'react';import { InlineDrawer, InlineDrawerTrigger, InlineDrawerPanel, FocusScope, Flex, Text, Button } from '@godaddy/antares';export function FocusScopeExample() { const [expanded, setExpanded] = useState(true); return ( <Flex direction="row" style={{ height: 200, border: '1px solid var(--bd-base)' }}> <InlineDrawer placement="left" isExpanded={expanded} onExpandedChange={setExpanded} maxSize={220}> <InlineDrawerTrigger>Sidebar</InlineDrawerTrigger> <InlineDrawerPanel> <FocusScope contain={expanded} restoreFocus> <Flex direction="column" gap="sm" padding="sm"> <Text>Focus is trapped when expanded.</Text> <Button variant="secondary" onPress={() => undefined}> Action A </Button> <Button variant="secondary" onPress={() => undefined}> Action B </Button> </Flex> </FocusScope> </InlineDrawerPanel> </InlineDrawer> <Flex padding="md" style={{ flex: 1 }}> <Text>Main content. Tab cannot reach here while sidebar is expanded.</Text> <Button variant="primary" onPress={() => setExpanded(true)}> Open sidebar </Button> </Flex> </Flex> );}Accessibility
Keyboard
| Key | Action |
|---|---|
Enter / Space | Toggle the drawer via the trigger button |
Tab | Move focus into/out of the panel (or trapped when using FocusScope) |
ARIA
aria-expandedon the trigger button reflects panel state (via RAC Disclosure)aria-controlslinks the trigger to the panelhidden="until-found"on collapsed panels (browser find-in-page support)- Panels with
minSizeoverridearia-hiddento keep collapsed content accessible
Best Practices
- Use
minSize+maxSizefor sidebar patterns where collapsed content stays visible. FocusScopeis opt-in. Don't combinecontain={true}withshouldDismissOnBlur(trapped focus can't leave to trigger blur).- Collapsed panels use
hidden="until-found"for browser find-in-page support. Panels withminSizeoverride this to keep content visible. - Don't nest InlineDrawers.