Files
zeekayandHanzo Dev bfe539744a Type the tab wrappers and variant spreads as the packages declare them
React passes ref as a prop, and a forwardRef over props with an index
signature drops every named prop through Omit; the font extras are
optional in a spread function's config.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-04 21:34:25 -07:00

107 lines
2.3 KiB
TypeScript

import { useStore, useStoreSelector } from '@hanzogui/use-store'
import type { TabsProps, TabsTabProps } from '@hanzo/gui'
import { Paragraph, Tabs, XStack, styled, withStaticProperties } from '@hanzo/gui'
import { type Href, useLocalSearchParams, useRouter } from 'one'
class TabsStore {
active = 'styled'
}
function TabsComponent(props: TabsProps) {
const router = useRouter()
const store = useStore(TabsStore)
const params = useLocalSearchParams()
const id = props.id || 'value'
const updateUrl = (newValue: string) => {
store.active = newValue
const url = new URL(location.href)
url.searchParams.set(id, newValue)
url.hash = '' // having this set messes with the scroll
router.replace(url as Href, {
scroll: false,
})
}
const value =
typeof params[id] === 'string' ? (params[id] as string) : (props.defaultValue ?? '')
return (
<Tabs
onValueChange={updateUrl}
unstyled
orientation="horizontal"
flexDirection="column"
borderWidth={0}
{...props}
value={value}
/>
)
}
const Tab = (props: TabsTabProps) => {
const isActive = useStoreSelector(TabsStore, (x) => x.active === props.value)
return (
<Tabs.Tab
// disableActiveTheme
size="$3"
flex={1}
px="$5"
pointerEvents="auto"
{...props}
focusStyle={{
outlineColor: '$outlineColor',
outlineWidth: 2,
outlineStyle: 'solid',
}}
{...(isActive && {
backgroundColor: '$color7',
hoverStyle: {
backgroundColor: '$color7',
},
focusStyle: {
backgroundColor: '$color7',
},
})}
>
<Paragraph size="$3">{props.children}</Paragraph>
</Tabs.Tab>
)
}
const TabsListFrame = styled(XStack, {
pointerEvents: 'none',
maxW: '50%',
mt: -30,
justify: 'flex-end',
self: 'flex-end',
t: 70,
mr: 0,
mb: 0,
z: 10000,
position: 'sticky' as any,
r: 0,
$sm: {
minW: '100%',
self: 'stretch',
mt: 0,
},
})
const TabsList = (props) => {
return (
<TabsListFrame className="sticky">
<Tabs.List size="$4" width="100%" {...props} />
</TabsListFrame>
)
}
export const MDXTabs = withStaticProperties(TabsComponent, {
List: TabsList,
Tab,
Content: Tabs.Content,
})