Tab select fix (#7470)

* changes

* add changeset

* changes

* changes

* changes

* Update js/tabs/shared/Tabs.svelte

Co-authored-by: Aarni Koskela <akx@iki.fi>

* changes

* changes

* changes

---------

Co-authored-by: Ali Abid <aliabid94@gmail.com>
Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
Co-authored-by: Aarni Koskela <akx@iki.fi>
This commit is contained in:
aliabid94 2024-02-21 17:27:58 -06:00 committed by GitHub
parent 98a2719bfb
commit ba3ec1300e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 121 additions and 3 deletions

View File

@ -0,0 +1,6 @@
---
"@gradio/tabs": patch
"gradio": patch
---
fix:Tab select fix

1
demo/tabs/run.ipynb Normal file
View File

@ -0,0 +1 @@
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: tabs"]}, {"cell_type": "code", "execution_count": null, "id": "272996653310673477252411125948039410165", "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": "288918539441861185822528903084949547379", "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "with gr.Blocks() as demo:\n", " with gr.Tabs():\n", " with gr.Tab(\"Set 1\"):\n", " with gr.Tabs() as tabs_1:\n", " tabset_1 = []\n", " textset_1 = []\n", " for i in range(10):\n", " with gr.Tab(f\"Tab {i+1}\") as tab:\n", " gr.Markdown(f\"Text {i+1}!\")\n", " textbox = gr.Textbox(label=f\"Input {i+1}\")\n", " tabset_1.append(tab)\n", " textset_1.append(textbox)\n", " with gr.Tab(\"Set 2\"):\n", " tabset_2 = []\n", " textset_2 = []\n", " for i in range(10):\n", " with gr.Tab(f\"Tab {i+11}\") as tab:\n", " gr.Markdown(f\"Text {i+11}!\")\n", " textbox = gr.Textbox(label=f\"Input {i+11}\")\n", " tabset_2.append(tab)\n", " textset_2.append(textbox)\n", "\n", " for text1, text2 in zip(textset_1, textset_2):\n", " text1.submit(lambda x: x, text1, text2)\n", "\n", " selected = gr.Textbox(label=\"Selected Tab\")\n", " with gr.Row():\n", " hide_odd_btn = gr.Button(\"Hide Odd Tabs\")\n", " show_all_btn = gr.Button(\"Show All Tabs\")\n", " make_even_uninteractive_btn = gr.Button(\"Make Even Tabs Uninteractive\")\n", " make_all_interactive_btn = gr.Button(\"Make All Tabs Interactive\")\n", "\n", " hide_odd_btn.click(lambda: [gr.Tab(visible=i % 2 == 1) for i, _ in enumerate(tabset_1 + tabset_2)], outputs=(tabset_1 + tabset_2))\n", " show_all_btn.click(lambda: [gr.Tab(visible=True) for tab in tabset_1 + tabset_2], outputs=(tabset_1 + tabset_2))\n", " make_even_uninteractive_btn.click(lambda: [gr.Tab(interactive=i % 2 == 0) for i, _ in enumerate(tabset_1 + tabset_2)], outputs=(tabset_1 + tabset_2))\n", " make_all_interactive_btn.click(lambda: [gr.Tab(interactive=True) for tab in tabset_1 + tabset_2], outputs=(tabset_1 + tabset_2))\n", "\n", " def get_selected_index(evt: gr.SelectData):\n", " return evt.value\n", " gr.on([tab.select for tab in tabset_1 + tabset_2], get_selected_index, outputs=selected)\n", "\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}

46
demo/tabs/run.py Normal file
View File

@ -0,0 +1,46 @@
import gradio as gr
with gr.Blocks() as demo:
with gr.Tabs():
with gr.Tab("Set 1"):
with gr.Tabs() as tabs_1:
tabset_1 = []
textset_1 = []
for i in range(10):
with gr.Tab(f"Tab {i+1}") as tab:
gr.Markdown(f"Text {i+1}!")
textbox = gr.Textbox(label=f"Input {i+1}")
tabset_1.append(tab)
textset_1.append(textbox)
with gr.Tab("Set 2"):
tabset_2 = []
textset_2 = []
for i in range(10):
with gr.Tab(f"Tab {i+11}") as tab:
gr.Markdown(f"Text {i+11}!")
textbox = gr.Textbox(label=f"Input {i+11}")
tabset_2.append(tab)
textset_2.append(textbox)
for text1, text2 in zip(textset_1, textset_2):
text1.submit(lambda x: x, text1, text2)
selected = gr.Textbox(label="Selected Tab")
with gr.Row():
hide_odd_btn = gr.Button("Hide Odd Tabs")
show_all_btn = gr.Button("Show All Tabs")
make_even_uninteractive_btn = gr.Button("Make Even Tabs Uninteractive")
make_all_interactive_btn = gr.Button("Make All Tabs Interactive")
hide_odd_btn.click(lambda: [gr.Tab(visible=i % 2 == 1) for i, _ in enumerate(tabset_1 + tabset_2)], outputs=(tabset_1 + tabset_2))
show_all_btn.click(lambda: [gr.Tab(visible=True) for tab in tabset_1 + tabset_2], outputs=(tabset_1 + tabset_2))
make_even_uninteractive_btn.click(lambda: [gr.Tab(interactive=i % 2 == 0) for i, _ in enumerate(tabset_1 + tabset_2)], outputs=(tabset_1 + tabset_2))
make_all_interactive_btn.click(lambda: [gr.Tab(interactive=True) for tab in tabset_1 + tabset_2], outputs=(tabset_1 + tabset_2))
def get_selected_index(evt: gr.SelectData):
return evt.value
gr.on([tab.select for tab in tabset_1 + tabset_2], get_selected_index, outputs=selected)
if __name__ == "__main__":
demo.launch()

63
js/app/test/tabs.spec.ts Normal file
View File

@ -0,0 +1,63 @@
import { test, expect } from "@gradio/tootils";
test("clicking through tabs shows correct content", async ({ page }) => {
await page.getByRole("tab", { name: "Tab 2" }).click();
await expect(page.getByText("Text 1!")).toBeHidden();
await expect(page.getByText("Text 2!")).toBeVisible();
await page.getByRole("tab", { name: "Tab 4" }).click();
await expect(page.getByText("Text 2!")).toBeHidden();
await expect(page.getByText("Text 4!")).toBeVisible();
await page.getByRole("tab", { name: "Set 2" }).click();
await page.getByRole("tab", { name: "Tab 12" }).click();
await expect(page.getByText("Text 2!")).toBeHidden();
await expect(page.getByText("Text 12!")).toBeVisible();
});
test("correct selected tab shown", async ({ page }) => {
await page.getByRole("tab", { name: "Tab 2" }).click();
await expect(page.getByLabel("Selected Tab")).toHaveValue("Tab 2");
await page.getByRole("tab", { name: "Tab 5" }).click();
await expect(page.getByLabel("Selected Tab")).toHaveValue("Tab 5");
await page
.getByRole("button", { name: "Make Even Tabs Uninteractive" })
.click();
await page.waitForTimeout(1000);
await expect(page.getByRole("tab", { name: "Tab 2" })).toBeDisabled();
await page.getByRole("button", { name: "Make All Tabs Interactive" }).click();
await page.waitForTimeout(1000);
await page.getByRole("tab", { name: "Tab 2" }).click();
await expect(page.getByLabel("Selected Tab")).toHaveValue("Tab 2");
await page.getByRole("button", { name: "Hide Odd Tabs" }).click();
await page.waitForTimeout(1000);
await page.getByRole("tab", { name: "Tab 4" }).click();
await page.getByRole("button", { name: "Show All Tabs" }).click();
await page.waitForTimeout(1000);
await page.getByRole("tab", { name: "Tab 9" }).click();
await expect(page.getByLabel("Selected Tab")).toHaveValue("Tab 9");
});
test("output from one tab to another works", async ({ page }) => {
await page.getByRole("tab", { name: "Tab 4" }).click();
await page.getByLabel("Input 4").fill("hi");
await page.getByLabel("Input 4").press("Enter");
await page.getByRole("tab", { name: "Set 2" }).click();
await page.getByRole("tab", { name: "Tab 13" }).click();
await expect(page.getByLabel("Input 13")).toHaveValue("");
await expect(page.getByLabel("Input 13")).toBeVisible();
await expect(page.getByLabel("Input 14")).toBeHidden();
await page.getByRole("tab", { name: "Tab 14" }).click();
await expect(page.getByLabel("Input 14")).toBeVisible();
await expect(page.getByLabel("Input 14")).toHaveValue("hi");
});

View File

@ -31,11 +31,12 @@
setContext(TABS, {
register_tab: (tab: Tab) => {
let index: number;
let existingTab = tabs.find((t) => t.id === tab.id);
if (existingTab) {
// update existing tab with newer values
let i = tabs.findIndex((t) => t.id === tab.id);
tabs[i] = { ...tabs[i], ...tab };
index = tabs.findIndex((t) => t.id === tab.id);
tabs[index] = { ...tabs[index], ...tab };
} else {
tabs.push({
name: tab.name,
@ -44,6 +45,7 @@
visible: tab.visible,
interactive: tab.interactive
});
index = tabs.length - 1;
}
selected_tab.update((current) => {
if (current === false && tab.visible && tab.interactive) {
@ -54,7 +56,7 @@
return nextTab ? nextTab.id : current;
});
tabs = tabs;
return tabs.length - 1;
return index;
},
unregister_tab: (tab: Tab) => {
const i = tabs.findIndex((t) => t.id === tab.id);