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
2 changes: 1 addition & 1 deletion ui/src/components/ui/tabs/Tabs.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const forwarded = useForwardPropsEmits(delegatedProps, emits)
data-slot="tabs"
:data-orientation="forwarded.orientation || 'horizontal'"
v-bind="forwarded"
:class="cn('gap-2 group/tabs flex data-horizontal:flex-col', props.class)"
:class="cn('gap-2 group/tabs flex data-[orientation=horizontal]:flex-col', props.class)"
>
<slot v-bind="slotProps" />
</TabsRoot>
Expand Down
4 changes: 2 additions & 2 deletions ui/src/components/ui/tabs/TabsTrigger.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ const forwardedProps = useForwardProps(delegatedProps)
<TabsTrigger
data-slot="tabs-trigger"
:class="cn(
'gap-1.5 rounded-md border border-transparent px-1.5 py-0.5 text-sm font-medium group-data-[variant=default]/tabs-list:data-active:shadow-sm group-data-[variant=line]/tabs-list:data-active:shadow-none [&_svg:not([class*=size-])]:size-4 has-data-[icon=inline-end]:pr-1 has-data-[icon=inline-start]:pl-1 relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center whitespace-nowrap text-foreground/60 transition-all group-data-vertical/tabs:w-full group-data-vertical/tabs:justify-start hover:text-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:outline-1 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50 dark:text-muted-foreground dark:hover:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0',
'gap-1.5 rounded-md border border-transparent px-1.5 py-0.5 text-sm font-medium group-data-[variant=default]/tabs-list:data-active:shadow-sm group-data-[variant=line]/tabs-list:data-active:shadow-none [&_svg:not([class*=size-])]:size-4 has-data-[icon=inline-end]:pr-1 has-data-[icon=inline-start]:pl-1 relative inline-flex h-[calc(100%-1px)] flex-1 items-center justify-center whitespace-nowrap text-foreground/60 transition-all group-data-[orientation=vertical]/tabs:w-full group-data-[orientation=vertical]/tabs:justify-start hover:text-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 focus-visible:outline-1 focus-visible:outline-ring disabled:pointer-events-none disabled:opacity-50 dark:text-muted-foreground dark:hover:text-foreground [&_svg]:pointer-events-none [&_svg]:shrink-0',
'group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-active:bg-transparent dark:group-data-[variant=line]/tabs-list:data-active:border-transparent dark:group-data-[variant=line]/tabs-list:data-active:bg-transparent',
'data-active:bg-background data-active:text-foreground dark:data-active:border-input dark:data-active:bg-input/30 dark:data-active:text-foreground',
'after:absolute after:bg-foreground after:opacity-0 after:transition-opacity group-data-horizontal/tabs:after:inset-x-0 group-data-horizontal/tabs:after:bottom-[-5px] group-data-horizontal/tabs:after:h-0.5 group-data-vertical/tabs:after:inset-y-0 group-data-vertical/tabs:after:-right-1 group-data-vertical/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100',
'after:absolute after:bg-foreground after:opacity-0 after:transition-opacity group-data-[orientation=horizontal]/tabs:after:inset-x-0 group-data-[orientation=horizontal]/tabs:after:bottom-[-5px] group-data-[orientation=horizontal]/tabs:after:h-0.5 group-data-[orientation=vertical]/tabs:after:inset-y-0 group-data-[orientation=vertical]/tabs:after:-right-1 group-data-[orientation=vertical]/tabs:after:w-0.5 group-data-[variant=line]/tabs-list:data-active:after:opacity-100',
props.class,
)"
v-bind="forwardedProps"
Expand Down
2 changes: 1 addition & 1 deletion ui/src/components/ui/tabs/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export { default as TabsList } from './TabsList.vue'
export { default as TabsTrigger } from './TabsTrigger.vue'

export const tabsListVariants = cva(
'rounded-lg p-0.75 group-data-horizontal/tabs:h-8 data-[variant=line]:rounded-none group/tabs-list inline-flex w-fit items-center justify-center text-muted-foreground group-data-vertical/tabs:h-fit group-data-vertical/tabs:flex-col',
'rounded-lg p-0.75 group-data-[orientation=horizontal]/tabs:h-8 data-[variant=line]:rounded-none group/tabs-list inline-flex w-fit items-center justify-center text-muted-foreground group-data-[orientation=vertical]/tabs:h-fit group-data-[orientation=vertical]/tabs:flex-col',
{
variants: {
variant: {
Expand Down
46 changes: 46 additions & 0 deletions ui/src/components/ui/tabs/tabs.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { mount } from '@vue/test-utils'
import { describe, expect, it } from 'vitest'
import { defineComponent } from 'vue'
import { tabsListVariants } from '.'
import Tabs from './Tabs.vue'
import TabsContent from './TabsContent.vue'
import TabsList from './TabsList.vue'
import TabsTrigger from './TabsTrigger.vue'

describe('tabs orientation classes', () => {
it('matches data-orientation on the tabs group, not boolean data-horizontal', () => {
const classes = tabsListVariants()
expect(classes).toContain('group-data-[orientation=horizontal]/tabs:h-8')
expect(classes).toContain('group-data-[orientation=vertical]/tabs:h-fit')
expect(classes).toContain('group-data-[orientation=vertical]/tabs:flex-col')
expect(classes).not.toContain('group-data-horizontal/tabs:')
expect(classes).not.toContain('group-data-vertical/tabs:')
})

it('stacks the tab list above content for the default horizontal orientation', () => {
const Harness = defineComponent({
components: { Tabs, TabsList, TabsTrigger, TabsContent },
template: `
<Tabs default-value="a">
<TabsList>
<TabsTrigger value="a">A</TabsTrigger>
</TabsList>
<TabsContent value="a">panel</TabsContent>
</Tabs>
`
})
const wrapper = mount(Harness)
const root = wrapper.get('[data-slot="tabs"]')
expect(root.attributes('data-orientation')).toBe('horizontal')
expect(root.classes()).toContain('data-[orientation=horizontal]:flex-col')
expect(root.classes()).not.toContain('data-horizontal:flex-col')

const list = wrapper.get('[data-slot="tabs-list"]')
expect(list.classes()).toContain('group-data-[orientation=horizontal]/tabs:h-8')

const trigger = wrapper.get('[data-slot="tabs-trigger"]')
expect(trigger.classes()).toContain('group-data-[orientation=horizontal]/tabs:after:h-0.5')
expect(trigger.classes()).toContain('group-data-[orientation=vertical]/tabs:w-full')
expect(wrapper.text()).toContain('panel')
})
})
Loading