Allow propogation of fill_height through Rows and Tabs, via scale (#10372)

* changes

* add changeset

* changes

* add changeset

* 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: Abubakar Abid <abubakar@huggingface.co>
This commit is contained in:
aliabid94 2025-01-17 14:54:24 -08:00 committed by GitHub
parent b10f5e150a
commit 96bbde277e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 64 additions and 9 deletions

View File

@ -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

View File

@ -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}
{"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}

View File

@ -2,8 +2,9 @@ import gradio as gr
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()

View File

@ -260,7 +260,7 @@ class ChatInterface(Blocks):
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 @@ class ChatInterface(Blocks):
variant="primary",
size="md",
icon=utils.get_icon_path("plus.svg"),
# scale=0,
)
self.chat_history_dataset = Dataset(
components=[Textbox(visible=False)],

View File

@ -971,6 +971,7 @@ class TabbedInterface(Blocks):
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 @@ class TabbedInterface(Blocks):
)
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()

View File

@ -1,5 +1,6 @@
from __future__ import annotations
import warnings
from typing import Literal
from gradio_client.documentation import document
@ -30,6 +31,7 @@ class Row(BlockContext, metaclass=ComponentMeta):
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 @@ class Row(BlockContext, metaclass=ComponentMeta):
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 @@ class Row(BlockContext, metaclass=ComponentMeta):
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,

View File

@ -67,6 +67,7 @@ class Tab(BlockContext, metaclass=ComponentMeta):
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 @@ class Tab(BlockContext, metaclass=ComponentMeta):
elem_id: An optional string that is assigned as the id of the <div> 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 @@ class Tab(BlockContext, metaclass=ComponentMeta):
self.label = label
self.id = id
self.visible = visible
self.scale = scale
self.interactive = interactive
def get_expected_parent(self) -> type[Tabs]:

View File

@ -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;
}
</style>

View File

@ -18,6 +18,7 @@
export let visible = true;
export let interactive = true;
export let order: number;
export let scale: number;
</script>
<TabItem
@ -28,6 +29,7 @@
{interactive}
{id}
{order}
{scale}
on:select={({ detail }) => gradio?.dispatch("select", detail)}
>
<slot />

View File

@ -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 @@
<div
id={elem_id}
class="tabitem {elem_classes.join(' ')}"
style:display={$selected_tab === id && visible ? "block" : "none"}
class:grow-children={scale >= 1}
style:display={$selected_tab === id && visible ? "flex" : "none"}
style:flex-grow={scale}
role="tabpanel"
>
<Column>
<Column scale={scale >= 1 ? scale : null}>
<slot />
</Column>
</div>
@ -48,7 +51,8 @@
<style>
div {
display: block;
display: flex;
flex-direction: column;
position: relative;
border: none;
border-radius: var(--radius-sm);
@ -56,4 +60,7 @@
width: 100%;
box-sizing: border-box;
}
.grow-children > :global(.column > .column) {
flex-grow: 1;
}
</style>

View File

@ -16,6 +16,7 @@
visible
interactive
elem_classes={["editor-tabitem"]}
scale={0}
>
<img
style="width: 200px;"
@ -31,6 +32,7 @@
visible={false}
interactive
elem_classes={["editor-tabitem"]}
scale={0}
>
Secret Tab
</TabItem>
@ -42,6 +44,7 @@
visible
interactive
elem_classes={["editor-tabitem"]}
scale={0}
>
Visible Tab
</TabItem>

View File

@ -7,6 +7,7 @@
elem_id: string | undefined;
visible: boolean;
interactive: boolean;
scale: number | null;
}
</script>
@ -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;
</script>
<svelte:window
@ -160,7 +165,12 @@
on:click={handle_outside_click}
/>
<div class="tabs {elem_classes.join(' ')}" class:hide={!visible} id={elem_id}>
<div
class="tabs {elem_classes.join(' ')}"
class:hide={!visible}
id={elem_id}
style:flex-grow={tab_scale}
>
{#if has_tabs}
<div class="tab-wrapper">
<div class="tab-container visually-hidden" aria-hidden="true">