Skip to content

Commit

Permalink
Fix type on Tabs component Vue (#912)
Browse files Browse the repository at this point in the history
* add `tabs` example to Vue

* use useResolveButtonType for Tabs

* update changelog
  • Loading branch information
RobinMalfait authored Nov 5, 2021
1 parent 2599655 commit 39b1646
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Allow to click on elements inside a `DialogOverlay` ([#816](https://github.com/tailwindlabs/headlessui/pull/816))
- Fix SSR crash because of `useWindowEvent` ([#817](https://github.com/tailwindlabs/headlessui/pull/817))
- Improve tree shaking ([#859](https://github.com/tailwindlabs/headlessui/pull/859))
- Add `type="button"` to `Tabs` component ([#912](https://github.com/tailwindlabs/headlessui/pull/912))

## [@headlessui/react@v1.4.1] - 2021-08-30

Expand Down
81 changes: 81 additions & 0 deletions packages/@headlessui-vue/examples/src/components/tabs/tabs.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<template>
<div class="flex flex-col items-start w-screen h-full p-12 bg-gray-50 space-y-12">
<SwitchGroup as="div" class="flex items-center space-x-4">
<SwitchLabel>Manual keyboard activation</SwitchLabel>

<Switch as="button" v-model="manual" :className="resolveSwitchClass" v-slot="{ checked }">
<span
class="inline-block w-5 h-5 transition duration-200 ease-in-out transform bg-white rounded-full"
:class="{ 'translate-x-5': checked, 'translate-x-0': !checked }"
/>
</Switch>
</SwitchGroup>

<TabGroup class="flex flex-col max-w-3xl w-full" as="div" :manual="manual">
<TabList class="relative z-0 rounded-lg shadow flex divide-x divide-gray-200">
<Tab
v-for="(tab, tabIdx) in tabs"
key="tab.name"
:disabled="tab.disabled"
class="group relative min-w-0 flex-1 overflow-hidden bg-white py-4 px-4 text-sm font-medium text-center hover:bg-gray-50 focus:z-10"
:class="{
'text-gray-900': selected,
'text-gray-500 hover:text-gray-700': !selected,
'rounded-l-lg': tabIdx === 0,
'rounded-r-lg': tabIdx === tabs.length - 1,
'opacity-50': tab.disabled,
}"
v-slot="{ selected }"
>
<span>{{tab.name}}</span>
<small v-if="tab.disabled" class="inline-block px-4 text-xs">(disabled)</small>
<span
aria-hidden="true"
class="absolute inset-x-0 bottom-0 h-0.5"
:class="{'bg-indigo-500': selected, 'bg-transparent':!selected}"
/>
</Tab>
</TabList>

<TabPanels class="mt-4">
<TabPanel v-for="tab in tabs" class="bg-white rounded-lg p-4 shadow" key="tab.name">
{{tab.content}}
</TabPanel>
</TabPanels>
</TabGroup>
</div>
</template>

<script>
import { defineComponent, h, ref, onMounted, watchEffect, watch } from 'vue'
import { SwitchGroup, Switch, SwitchLabel, TabGroup, TabList, Tab, TabPanels, TabPanel } from '@headlessui/vue'
function classNames(...classes) {
return classes.filter(Boolean).join(' ')
}
let tabs = [
{ name: 'My Account', content: 'Tab content for my account' },
{ name: 'Company', content: 'Tab content for company', disabled: true },
{ name: 'Team Members', content: 'Tab content for team members' },
{ name: 'Billing', content: 'Tab content for billing' },
]
export default {
components: { SwitchGroup, Switch, SwitchLabel, TabGroup, TabList, Tab, TabPanels, TabPanel },
setup(props, context) {
let manual = ref(false)
return {
tabs: ref(tabs),
manual,
resolveSwitchClass({ checked }) {
return classNames(
'relative inline-flex flex-shrink-0 h-6 transition-colors duration-200 ease-in-out border-2 border-transparent rounded-full cursor-pointer w-11 focus:outline-none focus:shadow-outline',
checked ? 'bg-indigo-600' : 'bg-gray-200'
)
},
}
},
}
</script>
11 changes: 11 additions & 0 deletions packages/@headlessui-vue/examples/src/routes.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,17 @@
}
]
},
{
"name": "Tabs",
"path": "/tabs",
"children": [
{
"name": "Tabs (basic)",
"path": "/tabs/tabs",
"component": "./components/tabs/tabs.vue"
}
]
},
{
"name": "Focus Trap",
"path": "/focus-trap",
Expand Down
7 changes: 5 additions & 2 deletions packages/@headlessui-vue/src/components/tabs/tabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { Keys } from '../../keyboard'
import { dom } from '../../utils/dom'
import { match } from '../../utils/match'
import { focusIn, Focus } from '../../utils/focus-management'
import { useResolveButtonType } from '../../hooks/use-resolve-button-type'

type StateDefinition = {
// State
Expand Down Expand Up @@ -217,7 +218,6 @@ export let Tab = defineComponent({

let myIndex = computed(() => api.tabs.value.indexOf(tabRef))
let selected = computed(() => myIndex.value === api.selectedIndex.value)
let type = computed(() => attrs.type ?? (props.as === 'button' ? 'button' : undefined))

function handleKeyDown(event: KeyboardEvent) {
let list = api.tabs.value.map(tab => dom(tab)).filter(Boolean) as HTMLElement[]
Expand Down Expand Up @@ -276,7 +276,10 @@ export let Tab = defineComponent({
id,
selected,
myIndex,
type,
type: useResolveButtonType(
computed(() => ({ as: props.as, type: attrs.type })),
tabRef
),
handleKeyDown,
handleFocus,
handleSelection,
Expand Down

0 comments on commit 39b1646

Please sign in to comment.