diff --git a/.changeset/stale-bags-study.md b/.changeset/stale-bags-study.md new file mode 100644 index 0000000000000..c57fb7bec10bd --- /dev/null +++ b/.changeset/stale-bags-study.md @@ -0,0 +1,8 @@ +--- +"@gradio/row": patch +"@gradio/tabitem": patch +"@gradio/tabs": patch +"gradio": patch +--- + +fix:Allow propogation of fill_height through Rows and Tabs, via scale diff --git a/demo/tabbed_interface_lite/run.ipynb b/demo/tabbed_interface_lite/run.ipynb index 26c5707d663ec..2b8ca0ee20c0d 100644 --- a/demo/tabbed_interface_lite/run.ipynb +++ b/demo/tabbed_interface_lite/run.ipynb @@ -1 +1 @@ -{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: tabbed_interface_lite"]}, {"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", "hello_world = gr.Interface(lambda name: \"Hello \" + name, \"text\", \"text\")\n", "bye_world = gr.Interface(lambda name: \"Bye \" + name, \"text\", \"text\")\n", "\n", "demo = gr.TabbedInterface([hello_world, bye_world], [\"Hello World\", \"Bye World\"])\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file +{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: tabbed_interface_lite"]}, {"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", "hello_world = gr.Interface(lambda name: \"Hello \" + name, \"text\", \"text\")\n", "bye_world = gr.Interface(lambda name: \"Bye \" + name, \"text\", \"text\")\n", "chat = gr.ChatInterface(lambda *args: \"Hello \" + args[0])\n", "\n", "demo = gr.TabbedInterface([hello_world, bye_world, chat], [\"Hello World\", \"Bye World\", \"Chat\"])\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5} \ No newline at end of file diff --git a/demo/tabbed_interface_lite/run.py b/demo/tabbed_interface_lite/run.py index d4bde163c758d..cfba160c21c5b 100644 --- a/demo/tabbed_interface_lite/run.py +++ b/demo/tabbed_interface_lite/run.py @@ -2,8 +2,9 @@ hello_world = gr.Interface(lambda name: "Hello " + name, "text", "text") bye_world = gr.Interface(lambda name: "Bye " + name, "text", "text") +chat = gr.ChatInterface(lambda *args: "Hello " + args[0]) -demo = gr.TabbedInterface([hello_world, bye_world], ["Hello World", "Bye World"]) +demo = gr.TabbedInterface([hello_world, bye_world, chat], ["Hello World", "Bye World", "Chat"]) if __name__ == "__main__": demo.launch() diff --git a/gradio/chat_interface.py b/gradio/chat_interface.py index cb729b11b7573..0770a9e156d78 100644 --- a/gradio/chat_interface.py +++ b/gradio/chat_interface.py @@ -260,7 +260,7 @@ def __init__( with Column(): self._render_header() if self.save_history: - with Row(): + with Row(scale=1): self._render_history_area() with Column(scale=6): self._render_chatbot_area( @@ -288,6 +288,7 @@ def _render_history_area(self): variant="primary", size="md", icon=utils.get_icon_path("plus.svg"), + # scale=0, ) self.chat_history_dataset = Dataset( components=[Textbox(visible=False)], diff --git a/gradio/interface.py b/gradio/interface.py index fe10d63fc662f..2d02671033491 100644 --- a/gradio/interface.py +++ b/gradio/interface.py @@ -971,6 +971,7 @@ def __init__( css=css, js=js, head=head, + fill_height=True, ) if tab_names is None: tab_names = [f"Tab {i}" for i in range(len(interface_list))] @@ -981,7 +982,10 @@ def __init__( ) with Tabs(): for interface, tab_name in zip(interface_list, tab_names, strict=False): - with Tab(label=tab_name): + with Tab( + label=tab_name, + scale=1 if interface.fill_height else 0, + ): interface.render() diff --git a/gradio/layouts/row.py b/gradio/layouts/row.py index 0bcc0e47e3f85..2d9d94d3ec34b 100644 --- a/gradio/layouts/row.py +++ b/gradio/layouts/row.py @@ -1,5 +1,6 @@ from __future__ import annotations +import warnings from typing import Literal from gradio_client.documentation import document @@ -30,6 +31,7 @@ def __init__( visible: bool = True, elem_id: str | None = None, elem_classes: list[str] | str | None = None, + scale: int = 0, render: bool = True, height: int | str | None = None, max_height: int | str | None = None, @@ -43,6 +45,7 @@ def __init__( visible: If False, row will be hidden. elem_id: An optional string that is assigned as the id of this component in the HTML DOM. Can be used for targeting CSS styles. elem_classes: An optional string or list of strings that are assigned as the class of this component in the HTML DOM. Can be used for targeting CSS styles. + scale: relative height compared to adjacent elements. 1 or greater indicates the Row will expand in height, and any child columns will also expand to fill the height. render: If False, this layout will not be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later. height: The height of the row, specified in pixels if a number is passed, or in CSS units if a string is passed. If content exceeds the height, the row will scroll vertically. If not set, the row will expand to fit the content. max_height: The maximum height of the row, specified in pixels if a number is passed, or in CSS units if a string is passed. If content exceeds the height, the row will scroll vertically. If content is shorter than the height, the row will shrink to fit the content. Will not have any effect if `height` is set and is smaller than `max_height`. @@ -58,6 +61,12 @@ def __init__( self.height = height self.max_height = max_height self.min_height = min_height + if scale != round(scale): + warnings.warn( + f"'scale' value should be an integer. Using {scale} will cause issues." + ) + + self.scale = scale BlockContext.__init__( self, diff --git a/gradio/layouts/tabs.py b/gradio/layouts/tabs.py index 726b4550b2671..20f5bf06ff8c0 100644 --- a/gradio/layouts/tabs.py +++ b/gradio/layouts/tabs.py @@ -67,6 +67,7 @@ def __init__( id: int | str | None = None, elem_id: str | None = None, elem_classes: list[str] | str | None = None, + scale: int = 0, render: bool = True, ): """ @@ -76,6 +77,7 @@ def __init__( elem_id: An optional string that is assigned as the id of the
containing the contents of the Tab layout. The same string followed by "-button" is attached to the Tab button. Can be used for targeting CSS styles. elem_classes: An optional string or list of strings that are assigned as the class of this component in the HTML DOM. Can be used for targeting CSS styles. render: If False, this layout will not be rendered in the Blocks context. Should be used if the intention is to assign event listeners now but render the component later. + scale: relative size compared to adjacent elements. 1 or greater indicates the Tab will expand in size. visible: If False, Tab will be hidden. interactive: If False, Tab will not be clickable. """ @@ -88,6 +90,7 @@ def __init__( self.label = label self.id = id self.visible = visible + self.scale = scale self.interactive = interactive def get_expected_parent(self) -> type[Tabs]: diff --git a/js/row/Index.svelte b/js/row/Index.svelte index 7a85a242af213..702f745639e36 100644 --- a/js/row/Index.svelte +++ b/js/row/Index.svelte @@ -14,6 +14,7 @@ export let height: number | string | undefined; export let min_height: number | string | undefined; export let max_height: number | string | undefined; + export let scale: number | null = null; const get_dimension = ( dimension_value: string | number | undefined @@ -35,9 +36,11 @@ class:unequal-height={equal_height === false} class:stretch={equal_height} class:hide={!visible} + class:grow-children={scale && scale >= 1} style:height={get_dimension(height)} style:max-height={get_dimension(max_height)} style:min-height={get_dimension(min_height)} + style:flex-grow={scale} id={elem_id} class="row {elem_classes.join(' ')}" > @@ -98,4 +101,8 @@ flex-wrap: wrap; min-width: min(160px, 100%); } + + .grow-children > :global(.column) { + align-self: stretch; + } diff --git a/js/tabitem/Index.svelte b/js/tabitem/Index.svelte index cd550bfe3d549..a71f2045b7d1c 100644 --- a/js/tabitem/Index.svelte +++ b/js/tabitem/Index.svelte @@ -18,6 +18,7 @@ export let visible = true; export let interactive = true; export let order: number; + export let scale: number; gradio?.dispatch("select", detail)} > diff --git a/js/tabitem/shared/TabItem.svelte b/js/tabitem/shared/TabItem.svelte index 8f4b8bbaa40ed..b54d68891bf9c 100644 --- a/js/tabitem/shared/TabItem.svelte +++ b/js/tabitem/shared/TabItem.svelte @@ -11,6 +11,7 @@ export let visible: boolean; export let interactive: boolean; export let order: number; + export let scale: number; const dispatch = createEventDispatcher<{ select: SelectData }>(); @@ -20,7 +21,7 @@ let tab_index: number; $: tab_index = register_tab( - { label, id, elem_id, visible, interactive }, + { label, id, elem_id, visible, interactive, scale }, order ); @@ -36,10 +37,12 @@
= 1} + style:display={$selected_tab === id && visible ? "flex" : "none"} + style:flex-grow={scale} role="tabpanel" > - + = 1 ? scale : null}>
@@ -48,7 +51,8 @@ diff --git a/js/tabs/Tabs.stories.svelte b/js/tabs/Tabs.stories.svelte index 90c6c555bda5a..25f25b398c10e 100644 --- a/js/tabs/Tabs.stories.svelte +++ b/js/tabs/Tabs.stories.svelte @@ -16,6 +16,7 @@ visible interactive elem_classes={["editor-tabitem"]} + scale={0} > Secret Tab
@@ -42,6 +44,7 @@ visible interactive elem_classes={["editor-tabitem"]} + scale={0} > Visible Tab diff --git a/js/tabs/shared/Tabs.svelte b/js/tabs/shared/Tabs.svelte index ee92dd1230509..ba25e866e5ff1 100644 --- a/js/tabs/shared/Tabs.svelte +++ b/js/tabs/shared/Tabs.svelte @@ -7,6 +7,7 @@ elem_id: string | undefined; visible: boolean; interactive: boolean; + scale: number | null; } @@ -60,6 +61,7 @@ if ($selected_tab === false && tab.visible && tab.interactive) { $selected_tab = tab.id; + $selected_tab_index = order; } return order; }, @@ -153,6 +155,9 @@ }); return tab_sizes; } + + $: tab_scale = + tabs[$selected_tab_index >= 0 ? $selected_tab_index : 0]?.scale; -
+
{#if has_tabs}