From d0b2ce8c0f150f0b636ad7d2226f7c8c61401996 Mon Sep 17 00:00:00 2001 From: pngwn Date: Wed, 16 Oct 2024 21:11:17 +0100 Subject: [PATCH] Ensure tabs render in SSR mode and reduce time it takes for them to render. (#9728) * fix tabs in SSR * format * add changeset * remove log * add changeset * more ifx * fix more * more fix * types --------- Co-authored-by: gradio-pr-bot --- .changeset/lazy-houses-repair.md | 7 ++++++ js/core/src/init.ts | 20 +++++++++++++++++ js/tabs/Index.svelte | 10 +++++++++ js/tabs/shared/Tabs.svelte | 38 ++++++++++++++++++++++---------- 4 files changed, 63 insertions(+), 12 deletions(-) create mode 100644 .changeset/lazy-houses-repair.md diff --git a/.changeset/lazy-houses-repair.md b/.changeset/lazy-houses-repair.md new file mode 100644 index 0000000000..f89f24ef26 --- /dev/null +++ b/.changeset/lazy-houses-repair.md @@ -0,0 +1,7 @@ +--- +"@gradio/core": patch +"@gradio/tabs": patch +"gradio": patch +--- + +fix:Ensure tabs render in SSR mode and reduce time it takes for them to render. diff --git a/js/core/src/init.ts b/js/core/src/init.ts index 471abba704..7882e0769e 100644 --- a/js/core/src/init.ts +++ b/js/core/src/init.ts @@ -290,6 +290,26 @@ export function create_components(initial_layout: ComponentMeta | undefined): { ); } + if (instance.type === "tabs") { + instance.children = + instance?.children?.map((c) => ({ + ...c, + props: { + ...c.props, + id: c.props.id || c.id + } + })) || []; + const child_tab_items = instance.children?.filter( + (child) => child.type === "tabitem" + ); + instance.props.inital_tabs = child_tab_items?.map((child) => ({ + label: child.props.label, + id: child.props.id, + visible: child.props.visible, + interactive: child.props.interactive + })); + } + return instance; } diff --git a/js/tabs/Index.svelte b/js/tabs/Index.svelte index b5b261f7e1..189bbbb54f 100644 --- a/js/tabs/Index.svelte +++ b/js/tabs/Index.svelte @@ -9,10 +9,19 @@ const dispatch = createEventDispatcher(); + interface Tab { + name: string; + id: string | number; + elem_id: string | undefined; + visible: boolean; + interactive: boolean; + } + export let visible = true; export let elem_id = ""; export let elem_classes: string[] = []; export let selected: number | string; + export let inital_tabs: Tab[]; export let gradio: Gradio<{ change: never; select: SelectData; @@ -28,6 +37,7 @@ bind:selected on:change={() => gradio.dispatch("change")} on:select={(e) => gradio.dispatch("select", e.detail)} + {inital_tabs} > diff --git a/js/tabs/shared/Tabs.svelte b/js/tabs/shared/Tabs.svelte index 9e8458d489..76f895d7a3 100644 --- a/js/tabs/shared/Tabs.svelte +++ b/js/tabs/shared/Tabs.svelte @@ -7,7 +7,8 @@ setContext, createEventDispatcher, onMount, - onDestroy + onDestroy, + tick } from "svelte"; import OverflowIcon from "./OverflowIcon.svelte"; import { writable } from "svelte/store"; @@ -15,7 +16,7 @@ interface Tab { name: string; - id: object; + id: string | number; elem_id: string | undefined; visible: boolean; interactive: boolean; @@ -24,9 +25,10 @@ export let visible = true; export let elem_id = ""; export let elem_classes: string[] = []; - export let selected: number | string | object; + export let selected: number | string; + export let inital_tabs: Tab[]; - let tabs: Tab[] = []; + let tabs: Tab[] = inital_tabs; let overflow_menu_open = false; let overflow_menu: HTMLElement; @@ -35,8 +37,12 @@ let tab_nav_el: HTMLElement; let overflow_nav: HTMLElement; - const selected_tab = writable(false); - const selected_tab_index = writable(0); + const selected_tab = writable( + selected || tabs[0]?.id || false + ); + const selected_tab_index = writable( + tabs.findIndex((t) => t.id === selected) || 0 + ); const dispatch = createEventDispatcher<{ change: undefined; select: SelectData; @@ -72,20 +78,19 @@ selected_tab_index }); - function change_tab(id: object | string | number): void { + function change_tab(id: string | number): void { const tab_to_activate = tabs.find((t) => t.id === id); if ( tab_to_activate && tab_to_activate.interactive && - tab_to_activate.visible + tab_to_activate.visible && + $selected_tab !== tab_to_activate.id ) { selected = id; $selected_tab = id; $selected_tab_index = tabs.findIndex((t) => t.id === id); dispatch("change"); overflow_menu_open = false; - } else { - console.warn("Attempted to select a non-interactive or hidden tab."); } } @@ -149,10 +154,19 @@ nav_items.forEach((item) => tab_nav_el.appendChild(item)); overflow_items.forEach((item) => overflow_nav.appendChild(item)); + overflow_has_selected_tab = handle_overflow_has_selected_tab($selected_tab); + } - overflow_has_selected_tab = tabs.some( + $: overflow_has_selected_tab = + handle_overflow_has_selected_tab($selected_tab); + + function handle_overflow_has_selected_tab( + selected_tab: number | string | false + ): boolean { + if (selected_tab === false || !overflow_nav) return false; + return tabs.some( (t) => - t.id === $selected_tab && + t.id === selected_tab && overflow_nav.contains(document.querySelector(`[data-tab-id="${t.id}"]`)) ); }