From 76d68eabfe9df40fff2cd2e564566b0a3c718399 Mon Sep 17 00:00:00 2001 From: Robin Malfait Date: Mon, 5 Dec 2022 18:52:12 +0100 Subject: [PATCH] improve SSR for Tabs in Vue --- .../src/components/tabs/tabs.ts | 48 ++++++++++++++++++- 1 file changed, 46 insertions(+), 2 deletions(-) diff --git a/packages/@headlessui-vue/src/components/tabs/tabs.ts b/packages/@headlessui-vue/src/components/tabs/tabs.ts index 4cc35ed10b..fbbb881650 100644 --- a/packages/@headlessui-vue/src/components/tabs/tabs.ts +++ b/packages/@headlessui-vue/src/components/tabs/tabs.ts @@ -58,6 +58,10 @@ function useTabsContext(component: string) { return context } +let TabsSSRContext = Symbol('TabsSSRContext') as InjectionKey< + Ref<{ tabs: string[]; panels: string[] } | null> +> + // --- export let TabGroup = defineComponent({ @@ -116,6 +120,16 @@ export let TabGroup = defineComponent({ provide(TabsContext, api) + let SSRCounter = ref({ tabs: [], panels: [] }) + let mounted = ref(false) + onMounted(() => { + mounted.value = true + }) + provide( + TabsSSRContext, + computed(() => (mounted.value ? SSRCounter.value : null)) + ) + watchEffect(() => { if (api.tabs.value.length <= 0) return if (props.selectedIndex === null && selectedIndex.value !== null) return @@ -231,7 +245,22 @@ export let Tab = defineComponent({ onMounted(() => api.registerTab(internalTabRef)) onUnmounted(() => api.unregisterTab(internalTabRef)) - let myIndex = computed(() => api.tabs.value.indexOf(internalTabRef)) + let SSRContext = inject(TabsSSRContext)! + let mySSRIndex = computed(() => { + if (SSRContext.value) { + let mySSRIndex = SSRContext.value.tabs.indexOf(props.id) + if (mySSRIndex === -1) return SSRContext.value.tabs.push(props.id) - 1 + return mySSRIndex + } + + return -1 + }) + + let myIndex = computed(() => { + let myIndex = api.tabs.value.indexOf(internalTabRef) + if (myIndex === -1) return mySSRIndex.value + return myIndex + }) let selected = computed(() => myIndex.value === api.selectedIndex.value) function activateUsing(cb: () => FocusResult) { @@ -391,7 +420,22 @@ export let TabPanel = defineComponent({ onMounted(() => api.registerPanel(internalPanelRef)) onUnmounted(() => api.unregisterPanel(internalPanelRef)) - let myIndex = computed(() => api.panels.value.indexOf(internalPanelRef)) + let SSRContext = inject(TabsSSRContext)! + let mySSRIndex = computed(() => { + if (SSRContext.value) { + let mySSRIndex = SSRContext.value.panels.indexOf(props.id) + if (mySSRIndex === -1) return SSRContext.value.panels.push(props.id) - 1 + return mySSRIndex + } + + return -1 + }) + + let myIndex = computed(() => { + let myIndex = api.panels.value.indexOf(internalPanelRef) + if (myIndex === -1) return mySSRIndex.value + return myIndex + }) let selected = computed(() => myIndex.value === api.selectedIndex.value) return () => {