Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/swift-cooks-write.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sanity/ui': patch
---

feat: add Tabs & subcomponents
3 changes: 2 additions & 1 deletion .oxlintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@
"react/todo": "error",
"typescript/no-deprecated": "error",
"unicorn/no-abusive-eslint-disable": "error",
// Not necessary since react compiler handles it
// Not necessary since react compiler handles these:
"react/jsx-no-constructed-context-values": "off",
"react-perf/jsx-no-new-array-as-prop": "off",
"react-perf/jsx-no-jsx-as-prop": "off",
"react-perf/jsx-no-new-object-as-prop": "off",
Expand Down
46 changes: 46 additions & 0 deletions apps/depth-testing/src/routes/ui3.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ import {
Radio,
Stack,
Switch,
Tab,
TabList,
TabPanel,
Text,
TextInput,
ThemeProvider,
Expand All @@ -22,6 +25,7 @@ const theme = buildTheme()

function Ui3() {
const [dialogOpen, setDialogOpen] = useState(false)
const [station, setStation] = useState('bridge')

return (
<ThemeProvider theme={theme}>
Expand Down Expand Up @@ -112,6 +116,48 @@ function Ui3() {
<Badge tone="critical">Warp core breach</Badge>
</Inline>
</Box>
<Box marginY={3}>
<TabList aria-label="Ship stations" gap={1}>
<Tab
id="tab-bridge"
aria-controls="panel-bridge"
label="Bridge"
selected={station === 'bridge'}
onClick={() => setStation('bridge')}
/>
<Tab
id="tab-engineering"
aria-controls="panel-engineering"
label="Engineering"
selected={station === 'engineering'}
onClick={() => setStation('engineering')}
/>
<Tab
id="tab-sickbay"
aria-controls="panel-sickbay"
label="Sickbay"
selected={station === 'sickbay'}
onClick={() => setStation('sickbay')}
/>
</TabList>
<TabPanel id="panel-bridge" aria-labelledby="tab-bridge" hidden={station !== 'bridge'}>
<Text>All stations report ready.</Text>
</TabPanel>
<TabPanel
id="panel-engineering"
aria-labelledby="tab-engineering"
hidden={station !== 'engineering'}
>
<Text>Dilithium matrix stable.</Text>
</TabPanel>
<TabPanel
id="panel-sickbay"
aria-labelledby="tab-sickbay"
hidden={station !== 'sickbay'}
>
<Text>No patients on the ward.</Text>
</TabPanel>
</Box>
</Card>
</Box>
</ThemeProvider>
Expand Down
46 changes: 46 additions & 0 deletions apps/depth-testing/src/routes/ui4.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import {
Radio,
Stack,
Switch,
Tab,
TabList,
TabPanel,
Text,
TextInput,
ThemeProvider,
Expand All @@ -23,6 +26,7 @@ const theme = buildTheme()

function Ui4() {
const [dialogOpen, setDialogOpen] = useState(false)
const [station, setStation] = useState('bridge')

return (
<ThemeProvider theme={theme}>
Expand Down Expand Up @@ -113,6 +117,48 @@ function Ui4() {
<Badge tone="critical">Warp core breach</Badge>
</Inline>
</Box>
<Box marginY={3}>
<TabList aria-label="Ship stations" gap={1}>
<Tab
id="tab-bridge"
aria-controls="panel-bridge"
label="Bridge"
selected={station === 'bridge'}
onClick={() => setStation('bridge')}
/>
<Tab
id="tab-engineering"
aria-controls="panel-engineering"
label="Engineering"
selected={station === 'engineering'}
onClick={() => setStation('engineering')}
/>
<Tab
id="tab-sickbay"
aria-controls="panel-sickbay"
label="Sickbay"
selected={station === 'sickbay'}
onClick={() => setStation('sickbay')}
/>
</TabList>
<TabPanel id="panel-bridge" aria-labelledby="tab-bridge" hidden={station !== 'bridge'}>
<Text>All stations report ready.</Text>
</TabPanel>
<TabPanel
id="panel-engineering"
aria-labelledby="tab-engineering"
hidden={station !== 'engineering'}
>
<Text>Dilithium matrix stable.</Text>
</TabPanel>
<TabPanel
id="panel-sickbay"
aria-labelledby="tab-sickbay"
hidden={station !== 'sickbay'}
>
<Text>No patients on the ward.</Text>
</TabPanel>
</Box>
</Card>
</Box>
</ThemeProvider>
Expand Down
20 changes: 20 additions & 0 deletions apps/depth-testing/src/routes/ui5.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
Link,
Radio,
Switch,
Tabs,
Text,
TextInput,
VStack,
Expand All @@ -22,6 +23,7 @@ import {useState} from 'react'

function Ui5() {
const [dialogOpen, setDialogOpen] = useState(false)
const [station, setStation] = useState('bridge')

return (
<Box margin={4}>
Expand Down Expand Up @@ -74,6 +76,24 @@ function Ui5() {
<Badge tone="critical" text="Warp core breach" />
</HStack>
</Box>
<Box marginY={3}>
<Tabs value={station} onValueChange={setStation}>
<Tabs.List aria-label="Ship stations">
<Tabs.Tab label="Bridge" value="bridge" />
<Tabs.Tab label="Engineering" value="engineering" />
<Tabs.Tab label="Sickbay" value="sickbay" />
</Tabs.List>
<Tabs.Panel value="bridge">
<Text>All stations report ready.</Text>
</Tabs.Panel>
<Tabs.Panel value="engineering">
<Text>Dilithium matrix stable.</Text>
</Tabs.Panel>
<Tabs.Panel value="sickbay">
<Text>No patients on the ward.</Text>
</Tabs.Panel>
</Tabs>
</Box>
</Card>
</Box>
)
Expand Down
50 changes: 50 additions & 0 deletions apps/inp-testing/src/routes/ui3.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import {
Radio,
Stack,
Switch,
Tab,
TabList,
TabPanel,
Text,
TextInput,
ThemeProvider,
Expand All @@ -32,6 +35,12 @@ const POPOVER_COUNT = 300
const BADGE_COUNT = 500
const AVATAR_COUNT = 300

const TABS = [
{value: 'overview', label: 'Overview'},
{value: 'activity', label: 'Activity'},
{value: 'settings', label: 'Settings'},
]

const scrollAreaStyle = {maxHeight: 260, overflow: 'auto'} as const

const theme = buildTheme()
Expand Down Expand Up @@ -364,6 +373,46 @@ function AvatarShuffleSection() {
)
}

/** One click on a tab shows its panel and hides the previous panel. */
function TabSwitchSection() {
const [selected, setSelected] = useState('overview')

return (
<Card tone="neutral" padding={4}>
<Stack gap={3}>
<Text size={1} weight="semibold">
7. Tab switch
</Text>
<Text size={1}>One click on a tab shows its panel and hides the previous panel.</Text>
<div>
<TabList aria-label="Tab switch" gap={1}>
{TABS.map((tab) => (
<Tab
key={tab.value}
id={`tab-${tab.value}`}
aria-controls={`panel-${tab.value}`}
label={tab.label}
selected={selected === tab.value}
onClick={() => setSelected(tab.value)}
/>
))}
</TabList>
{TABS.map((tab) => (
<TabPanel
key={tab.value}
id={`panel-${tab.value}`}
aria-labelledby={`tab-${tab.value}`}
hidden={selected !== tab.value}
>
<Text size={1}>{tab.label} panel</Text>
</TabPanel>
))}
</div>
</Stack>
</Card>
)
}

function Ui3() {
return (
<ThemeProvider theme={theme}>
Expand All @@ -378,6 +427,7 @@ function Ui3() {
<PopoverMountSection />
<BadgeToneToggleSection />
<AvatarShuffleSection />
<TabSwitchSection />
</Stack>
</ThemeProvider>
)
Expand Down
50 changes: 50 additions & 0 deletions apps/inp-testing/src/routes/ui4.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ import {
Radio,
Stack,
Switch,
Tab,
TabList,
TabPanel,
Text,
TextInput,
ThemeProvider,
Expand All @@ -33,6 +36,12 @@ const POPOVER_COUNT = 300
const BADGE_COUNT = 500
const AVATAR_COUNT = 300

const TABS = [
{value: 'overview', label: 'Overview'},
{value: 'activity', label: 'Activity'},
{value: 'settings', label: 'Settings'},
]

const scrollAreaStyle = {maxHeight: 260, overflow: 'auto'} as const

const theme = buildTheme()
Expand Down Expand Up @@ -365,6 +374,46 @@ function AvatarShuffleSection() {
)
}

/** One click on a tab shows its panel and hides the previous panel. */
function TabSwitchSection() {
const [selected, setSelected] = useState('overview')

return (
<Card tone="neutral" padding={4}>
<Stack gap={3}>
<Text size={1} weight="semibold">
7. Tab switch
</Text>
<Text size={1}>One click on a tab shows its panel and hides the previous panel.</Text>
<div>
<TabList aria-label="Tab switch" gap={1}>
{TABS.map((tab) => (
<Tab
key={tab.value}
id={`tab-${tab.value}`}
aria-controls={`panel-${tab.value}`}
label={tab.label}
selected={selected === tab.value}
onClick={() => setSelected(tab.value)}
/>
))}
</TabList>
{TABS.map((tab) => (
<TabPanel
key={tab.value}
id={`panel-${tab.value}`}
aria-labelledby={`tab-${tab.value}`}
hidden={selected !== tab.value}
>
<Text size={1}>{tab.label} panel</Text>
</TabPanel>
))}
</div>
</Stack>
</Card>
)
}

function Ui4() {
return (
<ThemeProvider theme={theme}>
Expand All @@ -379,6 +428,7 @@ function Ui4() {
<PopoverMountSection />
<BadgeToneToggleSection />
<AvatarShuffleSection />
<TabSwitchSection />
</Stack>
</ThemeProvider>
)
Expand Down
Loading
Loading