Skip to content

Commit 7d133bd

Browse files
joaquinhuiclaude
andcommitted
Fix Tab interactive property not updating from False to True
In Svelte, mutating an array element inside a closure (tabs[order] = tab) does not trigger reactivity. Adding `tabs = tabs` after mutation forces Svelte to recognize the change and re-render tab buttons with updated interactive/disabled state. Fixes #13033 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 735a6a6 commit 7d133bd

2 files changed

Lines changed: 32 additions & 0 deletions

File tree

js/tabs/shared/Tabs.svelte

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
setContext(TABS, {
6161
register_tab: (tab: Tab, order: number) => {
6262
tabs[order] = tab;
63+
tabs = tabs;
6364
6465
if ($selected_tab === false && tab.visible !== false && tab.interactive) {
6566
$selected_tab = tab.id;
@@ -72,6 +73,7 @@
7273
$selected_tab = tabs[0]?.id || false;
7374
}
7475
tabs[order] = null;
76+
tabs = tabs;
7577
},
7678
selected_tab,
7779
selected_tab_index

test/test_blocks.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -713,6 +713,36 @@ def generic_update():
713713
}
714714
assert output["data"][1] == {"__type__": "update", "interactive": True}
715715

716+
@pytest.mark.asyncio
717+
async def test_tab_interactive_update(self):
718+
"""Test that Tab interactive property can be toggled from False to True."""
719+
720+
def unlock():
721+
return gr.Tab(interactive=True)
722+
723+
def lock():
724+
return gr.Tab(interactive=False)
725+
726+
with gr.Blocks() as demo:
727+
with gr.Tab("tab1", id="tab1"):
728+
btn_unlock = gr.Button("Unlock")
729+
btn_lock = gr.Button("Lock")
730+
with gr.Tab("Locked", id="tab2", interactive=False) as tab2:
731+
gr.Markdown("Unlocked content")
732+
733+
btn_unlock.click(unlock, None, tab2)
734+
btn_lock.click(lock, None, tab2)
735+
736+
# Unlock: interactive=False -> True
737+
output = await demo.process_api(0, [], state=None)
738+
assert output["data"][0]["interactive"] is True
739+
assert output["data"][0]["__type__"] == "update"
740+
741+
# Lock: interactive=True -> False
742+
output = await demo.process_api(1, [], state=None)
743+
assert output["data"][0]["interactive"] is False
744+
assert output["data"][0]["__type__"] == "update"
745+
716746
@pytest.mark.asyncio
717747
async def test_error_raised_if_num_outputs_is_too_low(self):
718748
with gr.Blocks() as demo:

0 commit comments

Comments
 (0)