Tabs
The tabs widget is primarily a navigation control, where we switch between sections.
We show a tab bar with Tabs.List:
<Tabs> {/* container */}
<Tabs.List> {/* header, horizontal or vertical */}
<Tabs.Tab> {/* tab */}
<Tabs.Tab> {/* tab */}
<Tabs.Tab> {/* tab */}
</Tabs.Tab>
<Tabs.Panel> {/* tab panel */}
<Tabs.Panel> {/* tab panel */}
<Tabs.Panel> {/* tab panel */}
uncontrolled mode
- We select the initial tab with
defaultValue. - Pairs of matching
Tabs.TabandTabs.Panelshare the samevalue. - (optional) We make the list mobile-friendly with
Scroller: we wrap the.Tabcomponents with it.
<Tabs defaultValue="first" color="dimmed">
<Tabs.List>
<Scroller>
<Tabs.Tab value="first">Proteins</Tabs.Tab>
<Tabs.Tab value="second">Workouts</Tabs.Tab>
</Scroller>
</Tabs.List>
<Tabs.Panel value="first">{/* Proteins */}</Tabs.Panel>
<Tabs.Panel value="second">{/* Workouts */}</Tabs.Panel>
</Tabs>
controlled mode
Note: In controlled mode, the selected tab derives from state. The state is subscribed to through value, while onChange handles tentative tab changes:
const [authMode, setAuthMode] = useState("login")
;<Tabs value={authMode} onChange={(v) => setAuthMode(v!)}>
<Tabs.Tab value="login">Login</Tabs.Tab>
<Tabs.Tab value="signup">Sign up</Tabs.Tab>
</Tabs>
Tabs.Panel are optional in control mode
A Tabs.Panel wraps its content as a div and doesn't bring style by default
When its value is not matched, it uses display:none to hide its content.
We technically don't need a Tabs.Panel: we can do the conditional display manually based on state, or use an always-on component whose data derives from the selected tab name (do not use).
panels default to lazy-mounted, and sticking around when unselected
A given panel mounts the first time it is selected.
-
By default, it doesn't unmount when unselected. It uses the React
<Activity>hidden feature to hide itself:- Its state is preserved.
- The Effects are destroyed, aka the effect cleanup functions run just the same as if the component had unmounted, and the effects run again when the tab is selected back. (the default is
keepMountedMode="activity")
-
We can ask a "real" unmount with
keepMounted={false}which adds thedisplay=noneHMTL attribute. -
The
keepMountedMode="display-none"option is special because, when combined with the defaultkeepMounted={true}, all tabs mount immediately (not lazily), and their effect all run at the same time. Since they stay mounted, the cleanup effect doesn't run when switching tabs and the one-time effect doesn't run when switching to a tab. They appear hidden only through CSS.