Change sidebar position (#10582)

* position

* position

* add changeset

* fixes

---------

Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com>
This commit is contained in:
Dawood Khan 2025-02-14 02:33:11 -05:00 committed by GitHub
parent b640df2517
commit 1299267a8a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 62 additions and 13 deletions

View File

@ -0,0 +1,6 @@
---
"@gradio/sidebar": minor
"gradio": minor
---
feat:Change sidebar position

View File

@ -1 +1 @@
{"cells": [{"cell_type": "markdown", "id": "302934307671667531413257853548643485645", "metadata": {}, "source": ["# Gradio Demo: blocks_sidebar"]}, {"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", "import random\n", "\n", "def generate_pet_name(animal_type, personality):\n", " cute_prefixes = [\"Fluffy\", \"Ziggy\", \"Bubbles\", \"Pickle\", \"Waffle\", \"Mochi\", \"Cookie\", \"Pepper\"]\n", " animal_suffixes = {\n", " \"Cat\": [\"Whiskers\", \"Paws\", \"Mittens\", \"Purrington\"],\n", " \"Dog\": [\"Woofles\", \"Barkington\", \"Waggins\", \"Pawsome\"],\n", " \"Bird\": [\"Feathers\", \"Wings\", \"Chirpy\", \"Tweets\"],\n", " \"Rabbit\": [\"Hops\", \"Cottontail\", \"Bouncy\", \"Fluff\"]\n", " }\n", "\n", " prefix = random.choice(cute_prefixes)\n", " suffix = random.choice(animal_suffixes[animal_type])\n", "\n", " if personality == \"Silly\":\n", " prefix = random.choice([\"Sir\", \"Lady\", \"Captain\", \"Professor\"]) + \" \" + prefix\n", " elif personality == \"Royal\":\n", " suffix += \" the \" + random.choice([\"Great\", \"Magnificent\", \"Wise\", \"Brave\"])\n", "\n", " return f\"{prefix} {suffix}\"\n", "\n", "with gr.Blocks(theme=gr.themes.Soft()) as demo:\n", " with gr.Sidebar():\n", " gr.Markdown(\"# \ud83d\udc3e Pet Name Generator\")\n", " gr.Markdown(\"Use the options below to generate a unique pet name!\")\n", "\n", " animal_type = gr.Dropdown(\n", " choices=[\"Cat\", \"Dog\", \"Bird\", \"Rabbit\"],\n", " label=\"Choose your pet type\",\n", " value=\"Cat\"\n", " )\n", " personality = gr.Radio(\n", " choices=[\"Normal\", \"Silly\", \"Royal\"],\n", " label=\"Personality type\",\n", " value=\"Normal\"\n", " )\n", "\n", " name_output = gr.Textbox(label=\"Your pet's fancy name:\", lines=2)\n", " generate_btn = gr.Button(\"Generate Name! \ud83c\udfb2\", variant=\"primary\")\n", " generate_btn.click(\n", " fn=generate_pet_name,\n", " inputs=[animal_type, personality],\n", " outputs=name_output\n", " )\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: blocks_sidebar"]}, {"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", "import random\n", "\n", "def generate_pet_name(animal_type, personality):\n", " cute_prefixes = [\"Fluffy\", \"Ziggy\", \"Bubbles\", \"Pickle\", \"Waffle\", \"Mochi\", \"Cookie\", \"Pepper\"]\n", " animal_suffixes = {\n", " \"Cat\": [\"Whiskers\", \"Paws\", \"Mittens\", \"Purrington\"],\n", " \"Dog\": [\"Woofles\", \"Barkington\", \"Waggins\", \"Pawsome\"],\n", " \"Bird\": [\"Feathers\", \"Wings\", \"Chirpy\", \"Tweets\"],\n", " \"Rabbit\": [\"Hops\", \"Cottontail\", \"Bouncy\", \"Fluff\"]\n", " }\n", "\n", " prefix = random.choice(cute_prefixes)\n", " suffix = random.choice(animal_suffixes[animal_type])\n", "\n", " if personality == \"Silly\":\n", " prefix = random.choice([\"Sir\", \"Lady\", \"Captain\", \"Professor\"]) + \" \" + prefix\n", " elif personality == \"Royal\":\n", " suffix += \" the \" + random.choice([\"Great\", \"Magnificent\", \"Wise\", \"Brave\"])\n", "\n", " return f\"{prefix} {suffix}\"\n", "\n", "with gr.Blocks(theme=gr.themes.Soft()) as demo:\n", " with gr.Sidebar(position=\"left\"):\n", " gr.Markdown(\"# \ud83d\udc3e Pet Name Generator\")\n", " gr.Markdown(\"Use the options below to generate a unique pet name!\")\n", "\n", " animal_type = gr.Dropdown(\n", " choices=[\"Cat\", \"Dog\", \"Bird\", \"Rabbit\"],\n", " label=\"Choose your pet type\",\n", " value=\"Cat\"\n", " )\n", " personality = gr.Radio(\n", " choices=[\"Normal\", \"Silly\", \"Royal\"],\n", " label=\"Personality type\",\n", " value=\"Normal\"\n", " )\n", "\n", " name_output = gr.Textbox(label=\"Your pet's fancy name:\", lines=2)\n", " generate_btn = gr.Button(\"Generate Name! \ud83c\udfb2\", variant=\"primary\")\n", " generate_btn.click(\n", " fn=generate_pet_name,\n", " inputs=[animal_type, personality],\n", " outputs=name_output\n", " )\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}

View File

@ -21,7 +21,7 @@ def generate_pet_name(animal_type, personality):
return f"{prefix} {suffix}"
with gr.Blocks(theme=gr.themes.Soft()) as demo:
with gr.Sidebar():
with gr.Sidebar(position="left"):
gr.Markdown("# 🐾 Pet Name Generator")
gr.Markdown("Use the options below to generate a unique pet name!")

View File

@ -1,5 +1,7 @@
from __future__ import annotations
from typing import Literal
from gradio_client.documentation import document
from gradio.blocks import BlockContext
@ -31,6 +33,7 @@ class Sidebar(BlockContext, metaclass=ComponentMeta):
elem_classes: list[str] | str | None = None,
render: bool = True,
width: int | str = 320,
position: Literal["left", "right"] = "left",
):
"""
Parameters:
@ -40,10 +43,12 @@ class Sidebar(BlockContext, metaclass=ComponentMeta):
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.
width: The width of the sidebar, specified in pixels if a number is passed, or in CSS units if a string is passed.
position: The position of the sidebar in the layout, either "left" or "right". Defaults to "left".
"""
self.label = label
self.open = open
self.width = width
self.position = position
BlockContext.__init__(
self,
visible=visible,

View File

@ -5,6 +5,7 @@
import type { Gradio } from "@gradio/utils";
import Column from "@gradio/column";
export let open = true;
export let position: "left" | "right" = "left";
export let loading_status: LoadingStatus;
export let gradio: Gradio<{
expand: never;
@ -21,6 +22,7 @@
<Sidebar
bind:open
bind:position
{width}
on:expand={() => gradio.dispatch("expand")}
on:collapse={() => gradio.dispatch("collapse")}

View File

@ -7,6 +7,7 @@
export let open = true;
export let width: number | string;
export let position: "left" | "right" = "left";
// Using a temporary variable to animate the sidebar opening at the start
let mounted = false;
@ -22,7 +23,10 @@
const parent_rect = sidebar_div.closest(".wrap")?.getBoundingClientRect();
if (!parent_rect) return;
const sidebar_rect = sidebar_div.getBoundingClientRect();
const available_space = parent_rect.left;
const available_space =
position === "left"
? parent_rect.left
: window.innerWidth - parent_rect.right;
overlap_amount = Math.max(0, sidebar_rect.width - available_space + 30);
}
@ -30,7 +34,6 @@
sidebar_div.closest(".wrap")?.classList.add("sidebar-parent");
check_overlap();
window.addEventListener("resize", check_overlap);
const update_parent_overlap = (): void => {
document.documentElement.style.setProperty(
"--overlap-amount",
@ -39,7 +42,9 @@
};
update_parent_overlap();
mounted = true;
return () => window.removeEventListener("resize", check_overlap);
return () => {
window.removeEventListener("resize", check_overlap);
};
});
// We need to wait for the component to be mounted before we can set the open state
@ -50,8 +55,9 @@
<div
class="sidebar"
class:open={_open}
class:right={position === "right"}
bind:this={sidebar_div}
style="width: {width_css}; left: calc({width_css} * -1)"
style="width: {width_css}; {position}: calc({width_css} * -1)"
>
<button
on:click={() => {
@ -94,13 +100,20 @@
:global(.sidebar-parent) {
display: flex !important;
padding-left: 0;
transition: padding-left 0.3s ease-in-out;
padding-right: 0;
transition:
padding-left 0.3s ease-in-out,
padding-right 0.3s ease-in-out;
}
:global(.sidebar-parent:has(.sidebar.open)) {
:global(.sidebar-parent:has(.sidebar.open:not(.right))) {
padding-left: var(--overlap-amount);
}
:global(.sidebar-parent:has(.sidebar.open.right)) {
padding-right: var(--overlap-amount);
}
.sidebar {
display: flex;
flex-direction: column;
@ -108,20 +121,24 @@
top: 0;
height: 100%;
background-color: var(--background-fill-secondary);
box-shadow: var(--size-1) 0 var(--size-2) rgba(100, 89, 89, 0.1);
transform: translateX(0%);
transition: transform 0.3s ease-in-out;
z-index: 1000;
}
.sidebar.open {
.sidebar.open:not(.right) {
transform: translateX(100%);
box-shadow: var(--size-1) 0 var(--size-2) rgba(100, 89, 89, 0.1);
}
.sidebar.open.right {
transform: translateX(-100%);
box-shadow: calc(var(--size-1) * -1) 0 var(--size-2) rgba(100, 89, 89, 0.1);
}
.toggle-button {
position: absolute;
top: var(--size-4);
right: calc(var(--size-8) * -1);
background: none;
border: none;
cursor: pointer;
@ -129,17 +146,32 @@
display: flex;
align-items: center;
justify-content: center;
transition: right 0.3s ease-in-out;
transition: all 0.3s ease-in-out;
width: var(--size-8);
height: var(--size-8);
z-index: 1001;
}
.open .toggle-button {
.sidebar:not(.right) .toggle-button {
right: calc(var(--size-8) * -1);
}
.sidebar.right .toggle-button {
left: calc(var(--size-8) * -1);
transform: rotate(180deg);
}
.open:not(.right) .toggle-button {
right: var(--size-2-5);
transform: rotate(180deg);
}
.open.right .toggle-button {
left: auto;
right: var(--size-2-5);
transform: rotate(0deg);
}
.chevron {
width: 100%;
height: 100%;
@ -163,4 +195,8 @@
padding-right: var(--size-8);
overflow-y: auto;
}
.sidebar.right .sidebar-content {
padding-left: var(--size-8);
}
</style>