Files
opencode/packages/ui/src/components/tabs.tsx
2026-01-20 07:33:44 -06:00

119 lines
3.1 KiB
TypeScript

import { Tabs as Kobalte } from "@kobalte/core/tabs"
import { Show, splitProps, type JSX } from "solid-js"
import type { ComponentProps, ParentProps, Component } from "solid-js"
export interface TabsProps extends ComponentProps<typeof Kobalte> {
variant?: "normal" | "alt" | "settings"
orientation?: "horizontal" | "vertical"
}
export interface TabsListProps extends ComponentProps<typeof Kobalte.List> {}
export interface TabsTriggerProps extends ComponentProps<typeof Kobalte.Trigger> {
classes?: {
button?: string
}
hideCloseButton?: boolean
closeButton?: JSX.Element
onMiddleClick?: () => void
}
export interface TabsContentProps extends ComponentProps<typeof Kobalte.Content> {}
function TabsRoot(props: TabsProps) {
const [split, rest] = splitProps(props, ["class", "classList", "variant", "orientation"])
return (
<Kobalte
{...rest}
orientation={split.orientation}
data-component="tabs"
data-variant={split.variant || "normal"}
data-orientation={split.orientation || "horizontal"}
classList={{
...(split.classList ?? {}),
[split.class ?? ""]: !!split.class,
}}
/>
)
}
function TabsList(props: TabsListProps) {
const [split, rest] = splitProps(props, ["class", "classList"])
return (
<Kobalte.List
{...rest}
data-slot="tabs-list"
classList={{
...(split.classList ?? {}),
[split.class ?? ""]: !!split.class,
}}
/>
)
}
function TabsTrigger(props: ParentProps<TabsTriggerProps>) {
const [split, rest] = splitProps(props, [
"class",
"classList",
"classes",
"children",
"closeButton",
"hideCloseButton",
"onMiddleClick",
])
return (
<div
data-slot="tabs-trigger-wrapper"
classList={{
...(split.classList ?? {}),
[split.class ?? ""]: !!split.class,
}}
onAuxClick={(e) => {
if (e.button === 1 && split.onMiddleClick) {
e.preventDefault()
split.onMiddleClick()
}
}}
>
<Kobalte.Trigger
{...rest}
data-slot="tabs-trigger"
classList={{ "group/tab": true, [split.classes?.button ?? ""]: split.classes?.button }}
>
{split.children}
</Kobalte.Trigger>
<Show when={split.closeButton}>
{(closeButton) => (
<div data-slot="tabs-trigger-close-button" data-hidden={split.hideCloseButton}>
{closeButton()}
</div>
)}
</Show>
</div>
)
}
function TabsContent(props: ParentProps<TabsContentProps>) {
const [split, rest] = splitProps(props, ["class", "classList", "children"])
return (
<Kobalte.Content
{...rest}
data-slot="tabs-content"
classList={{
...(split.classList ?? {}),
[split.class ?? ""]: !!split.class,
}}
>
{split.children}
</Kobalte.Content>
)
}
const TabsSectionTitle: Component<ParentProps> = (props) => {
return <div data-slot="tabs-section-title">{props.children}</div>
}
export const Tabs = Object.assign(TabsRoot, {
List: TabsList,
Trigger: TabsTrigger,
Content: TabsContent,
SectionTitle: TabsSectionTitle,
})