hugging-face-gradio
Build Gradio web UIs and demos in Python. Use when creating or editing Gradio apps, components, event listeners, layouts, or chatbots.
Install
npx skills add https://github.com/sickn33/agentic-awesome-skills/tree/main/skills/hugging-face-gradio
claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install sickn33-agentic-awesome-skills@llmmart
git clone https://github.com/sickn33/agentic-awesome-skills.git
The skills CLI installs just this skill, for any of its supported agents. Claude Code installs the whole sickn33/agentic-awesome-skills collection as a plugin from our marketplace. Git is the plain clone.
Skill manifest
Gradio
When to Use
Use this skill when you need build Gradio web UIs and demos in Python. Use when creating or editing Gradio apps, components, event listeners, layouts, or chatbots.
Gradio is a Python library for building interactive web UIs and ML demos. This skill covers the core API, patterns, and examples.
Guides
Detailed guides on specific topics (read these when relevant):
- Quickstart
- The Interface Class
- Blocks and Event Listeners
- Controlling Layout
- More Blocks Features
- Custom CSS and JS
- Streaming Outputs
- Streaming Inputs
- Sharing Your App
- Custom HTML Components
- Getting Started with the Python Client
- Getting Started with the JS Client
Core Patterns
Interface (high-level): wraps a function with input/output components.
import gradio as gr
def greet(name):
return f"Hello {name}!"
gr.Interface(fn=greet, inputs="text", outputs="text").launch()
Blocks (low-level): flexible layout with explicit event wiring.
import gradio as gr
with gr.Blocks() as demo:
name = gr.Textbox(label="Name")
output = gr.Textbox(label="Greeting")
btn = gr.Button("Greet")
btn.click(fn=lambda n: f"Hello {n}!", inputs=name, outputs=output)
demo.launch()
ChatInterface: high-level wrapper for chatbot UIs.
import gradio as gr
def respond(message, history):
return f"You said: {message}"
gr.ChatInterface(fn=respond).launch()
Key Component Signatures
Textbox(value: str | I18nData | Callable | None = None, type: Literal['text', 'password', 'email'] = "text", lines: int = 1, max_lines: int | None = None, placeholder: str | I18nData | None = None, label: str | I18nData | None = None, info: str | I18nData | None = None, every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, show_label: bool | None = None, container: bool = True, scale: int | None = None, min_width: int = 160, interactive: bool | None = None, visible: bool | Literal['hidden'] = True, elem_id: str | None = None, autofocus: bool = False, autoscroll: bool = True, elem_classes: list[str] | str | None = None, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", text_align: Literal['left', 'right'] | None = None, rtl: bool = False, buttons: list[Literal['copy'] | Button] | None = None, max_length: int | None = None, submit_btn: str | bool | None = False, stop_btn: str | bool | None = False, html_attributes: InputHTMLAttributes | None = None)
Creates a textarea for user to enter string input or display string output..
Number(value: float | Callable | None = None, label: str | I18nData | None = None, placeholder: str | I18nData | None = None, info: str | I18nData | None = None, every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, show_label: bool | None = None, container: bool = True, scale: int | None = None, min_width: int = 160, interactive: bool | None = None, visible: bool | Literal['hidden'] = True, elem_id: str | None = None, elem_classes: list[str] | str | None = None, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", buttons: list[Button] | None = None, precision: int | None = None, minimum: float | None = None, maximum: float | None = None, step: float = 1)
Creates a numeric field for user to enter numbers as input or display numeric output..
Slider(minimum: float = 0, maximum: float = 100, value: float | Callable | None = None, step: float | None = None, precision: int | None = None, label: str | I18nData | None = None, info: str | I18nData | None = None, every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, show_label: bool | None = None, container: bool = True, scale: int | None = None, min_width: int = 160, interactive: bool | None = None, visible: bool | Literal['hidden'] = True, elem_id: str | None = None, elem_classes: list[str] | str | None = None, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", randomize: bool = False, buttons: list[Literal['reset']] | None = None)
Creates a slider that ranges from to with a step size of ..
Checkbox(value: bool | Callable = False, label: str | I18nData | None = None, info: str | I18nData | None = None, every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, show_label: bool | None = None, container: bool = True, scale: int | None = None, min_width: int = 160, interactive: bool | None = None, visible: bool | Literal['hidden'] = True, elem_id: str | None = None, elem_classes: list[str] | str | None = None, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", buttons: list[Button] | None = None)
Creates a checkbox that can be set to True or False.
Dropdown(choices: Sequence[str | int | float | tuple[str, str | int | float]] | None = None, value: str | int | float | Sequence[str | int | float] | Callable | DefaultValue | None = DefaultValue(), type: Literal['value', 'index'] = "value", multiselect: bool | None = None, allow_custom_value: bool = False, max_choices: int | None = None, filterable: bool = True, label: str | I18nData | None = None, info: str | I18nData | None = None, every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, show_label: bool | None = None, container: bool = True, scale: int | None = None, min_width: int = 160, interactive: bool | None = None, visible: bool | Literal['hidden'] = True, elem_id: str | None = None, elem_classes: list[str] | str | None = None, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", buttons: list[Button] | None = None)
Creates a dropdown of choices from which a single entry or multiple entries can be selected (as an input component) or displayed (as an output component)..
Radio(choices: Sequence[str | int | float | tuple[str, str | int | float]] | None = None, value: str | int | float | Callable | None = None, type: Literal['value', 'index'] = "value", label: str | I18nData | None = None, info: str | I18nData | None = None, every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, show_label: bool | None = None, container: bool = True, scale: int | None = None, min_width: int = 160, interactive: bool | None = None, visible: bool | Literal['hidden'] = True, elem_id: str | None = None, elem_classes: list[str] | str | None = None, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", rtl: bool = False, buttons: list[Button] | None = None)
Creates a set of (string or numeric type) radio buttons of which only one can be selected..
Image(value: str | PIL.Image.Image | np.ndarray | Callable | None = None, format: str = "webp", height: int | str | None = None, width: int | str | None = None, image_mode: Literal['1', 'L', 'P', 'RGB', 'RGBA', 'CMYK', 'YCbCr', 'LAB', 'HSV', 'I', 'F'] | None = "RGB", sources: list[Literal['upload', 'webcam', 'clipboard']] | Literal['upload', 'webcam', 'clipboard'] | None = None, type: Literal['numpy', 'pil', 'filepath'] = "numpy", label: str | I18nData | None = None, every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, show_label: bool | None = None, buttons: list[Literal['download', 'share', 'fullscreen'] | Button] | None = None, container: bool = True, scale: int | None = None, min_width: int = 160, interactive: bool | None = None, visible: bool | Literal['hidden'] = True, streaming: bool = False, elem_id: str | None = None, elem_classes: list[str] | str | None = None, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", webcam_options: WebcamOptions | None = None, placeholder: str | None = None, watermark: WatermarkOptions | None = None)
Creates an image component that can be used to upload images (as an input) or display images (as an output)..
Audio(value: str | Path | tuple[int, np.ndarray] | Callable | None = None, sources: list[Literal['upload', 'microphone']] | Literal['upload', 'microphone'] | None = None, type: Literal['numpy', 'filepath'] = "numpy", label: str | I18nData | None = None, every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, show_label: bool | None = None, container: bool = True, scale: int | None = None, min_width: int = 160, interactive: bool | None = None, visible: bool | Literal['hidden'] = True, streaming: bool = False, elem_id: str | None = None, elem_classes: list[str] | str | None = None, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", format: Literal['wav', 'mp3'] | None = None, autoplay: bool = False, editable: bool = True, buttons: list[Literal['download', 'share'] | Button] | None = None, waveform_options: WaveformOptions | dict | None = None, loop: bool = False, recording: bool = False, subtitles: str | Path | list[dict[str, Any]] | None = None, playback_position: float = 0)
Creates an audio component that can be used to upload/record audio (as an input) or display audio (as an output)..
Video(value: str | Path | Callable | None = None, format: str | None = None, sources: list[Literal['upload', 'webcam']] | Literal['upload', 'webcam'] | None = None, height: int | str | None = None, width: int | str | None = None, label: str | I18nData | None = None, every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, show_label: bool | None = None, container: bool = True, scale: int | None = None, min_width: int = 160, interactive: bool | None = None, visible: bool | Literal['hidden'] = True, elem_id: str | None = None, elem_classes: list[str] | str | None = None, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", webcam_options: WebcamOptions | None = None, include_audio: bool | None = None, autoplay: bool = False, buttons: list[Literal['download', 'share'] | Button] | None = None, loop: bool = False, streaming: bool = False, watermark: WatermarkOptions | None = None, subtitles: str | Path | list[dict[str, Any]] | None = None, playback_position: float = 0)
Creates a video component that can be used to upload/record videos (as an input) or display videos (as an output).
File(value: str | list[str] | Callable | None = None, file_count: Literal['single', 'multiple', 'directory'] = "single", file_types: list[str] | None = None, type: Literal['filepath', 'binary'] = "filepath", label: str | I18nData | None = None, every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, show_label: bool | None = None, container: bool = True, scale: int | None = None, min_width: int = 160, height: int | str | float | None = None, interactive: bool | None = None, visible: bool | Literal['hidden'] = True, elem_id: str | None = None, elem_classes: list[str] | str | None = None, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", allow_reordering: bool = False, buttons: list[Button] | None = None)
Creates a file component that allows uploading one or more generic files (when used as an input) or displaying generic files or URLs for download (as output).
Chatbot(value: list[MessageDict | Message] | Callable | None = None, label: str | I18nData | None = None, every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, show_label: bool | None = None, container: bool = True, scale: int | None = None, min_width: int = 160, visible: bool | Literal['hidden'] = True, elem_id: str | None = None, elem_classes: list[str] | str | None = None, autoscroll: bool = True, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", height: int | str | None = 400, resizable: bool = False, max_height: int | str | None = None, min_height: int | str | None = None, editable: Literal['user', 'all'] | None = None, latex_delimiters: list[dict[str, str | bool]] | None = None, rtl: bool = False, buttons: list[Literal['share', 'copy', 'copy_all'] | Button] | None = None, watermark: str | None = None, avatar_images: tuple[str | Path | None, str | Path | None] | None = None, sanitize_html: bool = True, render_markdown: bool = True, feedback_options: list[str] | tuple[str, ...] | None = ('Like', 'Dislike'), feedback_value: Sequence[str | None] | None = None, line_breaks: bool = True, layout: Literal['panel', 'bubble'] | None = None, placeholder: str | None = None, examples: list[ExampleMessage] | None = None, allow_file_downloads: <class 'inspect._empty'> = True, group_consecutive_messages: bool = True, allow_tags: list[str] | bool = True, reasoning_tags: list[tuple[str, str]] | None = None, like_user_message: bool = False)
Creates a chatbot that displays user-submitted messages and responses.
Button(value: str | I18nData | Callable = "Run", every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, variant: Literal['primary', 'secondary', 'stop', 'huggingface'] = "secondary", size: Literal['sm', 'md', 'lg'] = "lg", icon: str | Path | None = None, link: str | None = None, link_target: Literal['_self', '_blank', '_parent', '_top'] = "_self", visible: bool | Literal['hidden'] = True, interactive: bool = True, elem_id: str | None = None, elem_classes: list[str] | str | None = None, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", scale: int | None = None, min_width: int | None = None)
Creates a button that can be assigned arbitrary .click() events.
Markdown(value: str | I18nData | Callable | None = None, label: str | I18nData | None = None, every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, show_label: bool | None = None, rtl: bool = False, latex_delimiters: list[dict[str, str | bool]] | None = None, visible: bool | Literal['hidden'] = True, elem_id: str | None = None, elem_classes: list[str] | str | None = None, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", sanitize_html: bool = True, line_breaks: bool = False, header_links: bool = False, height: int | str | None = None, max_height: int | str | None = None, min_height: int | str | None = None, buttons: list[Literal['copy']] | None = None, container: bool = False, padding: bool = False)
Used to render arbitrary Markdown output.
`HTML(value: Any | Callable | None = None, label: str | I18nData | None = None, html_template: str = "$
Creates a component with arbitrary HTML.
Custom HTML Components
If a task requires significant customization of an existing component or a component that doesn't exist in Gradio, you can create one with gr.HTML. It supports html_template (with ${} JS expressions and {{}} Handlebars syntax), css_template for scoped styles, and js_on_load for interactivity — where props.value updates the component value and trigger('event_name') fires Gradio events. For reuse, subclass gr.HTML and define api_info() for API/MCP support. See the full guide.
Here's an example that shows how to create and use these kinds of components:
import gradio as gr
class StarRating(gr.HTML):
def __init__(self, label, value=0, **kwargs):
html_template = """
<h2>${label} rating:</h2>
${Array.from({length: 5}, (_, i) => `<img class='${i < value ? '' : 'faded'}' src='https://upload.wikimedia.org/wikipedia/commons/d/df/Award-star-gold-3d.svg'>`).join('')}
"""
css_template = """
img { height: 50px; display: inline-block; cursor: pointer; }
.faded { filter: grayscale(100%); opacity: 0.3; }
"""
js_on_load = """
const imgs = element.querySelectorAll('img');
imgs.forEach((img, index) => {
img.addEventListener('click', () => {
props.value = index + 1;
});
});
"""
super().__init__(value=value, label=label, html_template=html_template, css_template=css_template, js_on_load=js_on_load, **kwargs)
def api_info(self):
return {"type": "integer", "minimum": 0, "maximum": 5}
with gr.Blocks() as demo:
gr.Markdown("# Restaurant Review")
food_rating = StarRating(label="Food", value=3)
service_rating = StarRating(label="Service", value=3)
ambience_rating = StarRating(label="Ambience", value=3)
average_btn = gr.Button("Calculate Average Rating")
rating_output = StarRating(label="Average", value=3)
def calculate_average(food, service, ambience):
return round((food + service + ambience) / 3)
average_btn.click(
fn=calculate_average,
inputs=[food_rating, service_rating, ambience_rating],
outputs=rating_output
)
demo.launch()
Event Listeners
All event listeners share the same signature:
component.event_name(
fn: Callable | None | Literal["decorator"] = "decorator",
inputs: Component | Sequence[Component] | set[Component] | None = None,
outputs: Component | Sequence[Component] | set[Component] | None = None,
api_name: str | None = None,
api_description: str | None | Literal[False] = None,
scroll_to_output: bool = False,
show_progress: Literal["full", "minimal", "hidden"] = "full",
show_progress_on: Component | Sequence[Component] | None = None,
queue: bool = True,
batch: bool = False,
max_batch_size: int = 4,
preprocess: bool = True,
postprocess: bool = True,
cancels: dict[str, Any] | list[dict[str, Any]] | None = None,
trigger_mode: Literal["once", "multiple", "always_last"] | None = None,
js: str | Literal[True] | None = None,
concurrency_limit: int | None | Literal["default"] = "default",
concurrency_id: str | None = None,
api_visibility: Literal["public", "private", "undocumented"] = "public",
time_limit: int | None = None,
stream_every: float = 0.5,
key: int | str | tuple[int | str, ...] | None = None,
validator: Callable | None = None,
) -> Dependency
Supported events per component:
- AnnotatedImage: select
- Audio: stream, change, clear, play, pause, stop, pause, start_recording, pause_recording, stop_recording, upload, input
- BarPlot: select, double_click
- BrowserState: change
- Button: click
- Chatbot: change, select, like, retry, undo, example_select, option_select, clear, copy, edit
- Checkbox: change, input, select
- CheckboxGroup: change, input, select
- ClearButton: click
- Code: change, input, focus, blur
- ColorPicker: change, input, submit, focus, blur
- Dataframe: change, input, select, edit
- Dataset: click, select
- DateTime: change, submit
- DeepLinkButton: click
- Dialogue: change, input, submit
- DownloadButton: click
- Dropdown: change, input, select, focus, blur, key_up
- DuplicateButton: click
- File: change, select, clear, upload, delete, download
- FileExplorer: change, input, select
- Gallery: select, upload, change, delete, preview_close, preview_open
- HTML: change, input, click, double_click, submit, stop, edit, clear, play, pause, end, start_recording, pause_recording, stop_recording, focus, blur, upload, release, select, stream, like, example_select, option_select, load, key_up, apply, delete, tick, undo, retry, expand, collapse, download, copy
- HighlightedText: change, select
- Image: clear, change, stream, select, upload, input
- ImageEditor: clear, change, input, select, upload, apply
- ImageSlider: clear, change, stream, select, upload, input
- JSON: change
- Label: change, select
- LinePlot: select, double_click
- LoginButton: click
- Markdown: change, copy
- Model3D: change, upload, edit, clear
- MultimodalTextbox: change, input, select, submit, focus, blur, stop
- Navbar: change
- Number: change, input, submit, focus, blur
- ParamViewer: change, upload
- Plot: change
- Radio: select, change, input
- ScatterPlot: select, double_click
- SimpleImage: clear, change, upload
- Slider: change, input, release
- State: change
- Textbox: change, input, select, submit, focus, blur, stop, copy
- Timer: tick
- UploadButton: click, upload
- Video: change, clear, start_recording, stop_recording, stop, play, pause, end, upload, input
Prediction CLI
The gradio CLI includes info and predict commands for interacting with Gradio apps programmatically. These are especially useful for coding agents that need to use Spaces in their workflows.
gradio info — Discover endpoints and parameters
gradio info <space_id_or_url>
Returns a JSON payload describing all endpoints, their parameters (with types and defaults), and return values.
gradio info gradio/calculator
# {
# "/predict": {
# "parameters": [
# {"name": "num1", "required": true, "default": null, "type": {"type": "number"}},
# {"name": "operation", "required": true, "default": null, "type": {"enum": ["add", "subtract", "multiply", "divide"], "type": "string"}},
# {"name": "num2", "required": true, "default": null, "type": {"type": "number"}}
# ],
# "returns": [{"name": "output", "type": {"type": "number"}}],
# "description": ""
# }
# }
File-type parameters show "type": "filepath" with instructions to include "meta": {"_type": "gradio.FileData"} — this signals the file will be uploaded to the remote server.
gradio predict — Send predictions
gradio predict <space_id_or_url> <endpoint> <json_payload>
Returns a JSON object with named output keys.
# Simple numeric prediction
gradio predict gradio/calculator /predict '{"num1": 5, "operation": "multiply", "num2": 3}'
# {"output": 15}
# Image generation
gradio predict black-forest-labs/FLUX.2-dev /infer '{"prompt": "A majestic dragon"}'
# {"Result": "/tmp/gradio/.../image.webp", "Seed": 1117868604}
# File upload (must include meta key)
gradio predict gradio/image_mod /predict '{"image": {"path": "/path/to/image.png", "meta": {"_type": "gradio.FileData"}}}'
# {"output": "/tmp/gradio/.../output.png"}
Both commands accept --token for accessing private Spaces.
Additional Reference
- End-to-End Examples — complete working apps
Limitations
- Use this skill only when the task clearly matches its upstream product or API scope.
- Verify commands, API behavior, pricing, quotas, credentials, and deployment effects against current official documentation before making changes.
- Do not treat generated examples as a substitute for environment-specific tests, security review, or user approval for destructive or costly actions.
Files (agentic-awesome-skills)
-
examples.md 14.1 KB
# Gradio End-to-End Examples Complete working Gradio apps for reference. ## Blocks Essay Simple ```python import gradio as gr def change_textbox(choice): if choice == "short": return gr.Textbox(lines=2, visible=True) elif choice == "long": return gr.Textbox(lines=8, visible=True, value="Lorem ipsum dolor sit amet") else: return gr.Textbox(visible=False) with gr.Blocks() as demo: radio = gr.Radio( ["short", "long", "none"], label="What kind of essay would you like to write?" ) text = gr.Textbox(lines=2, interactive=True, buttons=["copy"]) radio.change(fn=change_textbox, inputs=radio, outputs=text) demo.launch() ``` ## Blocks Flipper ```python import numpy as np import gradio as gr def flip_text(x): return x[::-1] def flip_image(x): return np.fliplr(x) with gr.Blocks() as demo: gr.Markdown("Flip text or image files using this demo.") with gr.Tab("Flip Text"): text_input = gr.Textbox() text_output = gr.Textbox() text_button = gr.Button("Flip") with gr.Tab("Flip Image"): with gr.Row(): image_input = gr.Image() image_output = gr.Image() image_button = gr.Button("Flip") with gr.Accordion("Open for More!", open=False): gr.Markdown("Look at me...") temp_slider = gr.Slider( 0, 1, value=0.1, step=0.1, interactive=True, label="Slide me", ) text_button.click(flip_text, inputs=text_input, outputs=text_output) image_button.click(flip_image, inputs=image_input, outputs=image_output) demo.launch() ``` ## Blocks Form ```python import gradio as gr with gr.Blocks() as demo: name_box = gr.Textbox(label="Name") age_box = gr.Number(label="Age", minimum=0, maximum=100) symptoms_box = gr.CheckboxGroup(["Cough", "Fever", "Runny Nose"]) submit_btn = gr.Button("Submit") with gr.Column(visible=False) as output_col: diagnosis_box = gr.Textbox(label="Diagnosis") patient_summary_box = gr.Textbox(label="Patient Summary") def submit(name, age, symptoms): return { submit_btn: gr.Button(visible=False), output_col: gr.Column(visible=True), diagnosis_box: "covid" if "Cough" in symptoms else "flu", patient_summary_box: f"{name}, {age} y/o", } submit_btn.click( submit, [name_box, age_box, symptoms_box], [submit_btn, diagnosis_box, patient_summary_box, output_col], ) demo.launch() ``` ## Blocks Hello ```python import gradio as gr def welcome(name): return f"Welcome to Gradio, {name}!" with gr.Blocks() as demo: gr.Markdown( """ # Hello World! Start typing below to see the output. """) inp = gr.Textbox(placeholder="What is your name?") out = gr.Textbox() inp.change(welcome, inp, out) demo.launch() ``` ## Blocks Layout ```python import gradio as gr demo = gr.Blocks() with demo: with gr.Row(): gr.Image(interactive=True, scale=2) gr.Image() with gr.Row(): gr.Textbox(label="Text") gr.Number(label="Count", scale=2) gr.Radio(choices=["One", "Two"]) with gr.Row(): gr.Button("500", scale=0, min_width=500) gr.Button("A", scale=0) gr.Button("grow") with gr.Row(): gr.Textbox() gr.Textbox() gr.Button() with gr.Row(): with gr.Row(): with gr.Column(): gr.Textbox(label="Text") gr.Number(label="Count") gr.Radio(choices=["One", "Two"]) gr.Image() with gr.Column(): gr.Image(interactive=True) gr.Image() gr.Image() gr.Textbox(label="Text") gr.Number(label="Count") gr.Radio(choices=["One", "Two"]) demo.launch() ``` ## Calculator ```python import gradio as gr def calculator(num1, operation, num2): if operation == "add": return num1 + num2 elif operation == "subtract": return num1 - num2 elif operation == "multiply": return num1 * num2 elif operation == "divide": if num2 == 0: raise gr.Error("Cannot divide by zero!") return num1 / num2 demo = gr.Interface( calculator, [ "number", gr.Radio(["add", "subtract", "multiply", "divide"]), "number" ], "number", examples=[ [45, "add", 3], [3.14, "divide", 2], [144, "multiply", 2.5], [0, "subtract", 1.2], ], title="Toy Calculator", description="Here's a sample toy calculator.", api_name="predict" ) demo.launch() ``` ## Chatbot Simple ```python import gradio as gr import random import time with gr.Blocks() as demo: chatbot = gr.Chatbot() msg = gr.Textbox() clear = gr.ClearButton([msg, chatbot]) def respond(message, chat_history): bot_message = random.choice(["How are you?", "Today is a great day", "I'm very hungry"]) chat_history.append({"role": "user", "content": message}) chat_history.append({"role": "assistant", "content": bot_message}) time.sleep(2) return "", chat_history msg.submit(respond, [msg, chatbot], [msg, chatbot]) demo.launch() ``` ## Chatbot Streaming ```python import gradio as gr import random import time with gr.Blocks() as demo: chatbot = gr.Chatbot() msg = gr.Textbox() clear = gr.Button("Clear") def user(user_message, history: list): return "", history + [{"role": "user", "content": user_message}] def bot(history: list): bot_message = random.choice(["How are you?", "I love you", "I'm very hungry"]) history.append({"role": "assistant", "content": ""}) for character in bot_message: history[-1]['content'] += character time.sleep(0.05) yield history msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False).then( bot, chatbot, chatbot ) clear.click(lambda: None, None, chatbot, queue=False) demo.launch() ``` ## Custom Css ```python import gradio as gr with gr.Blocks() as demo: with gr.Column(elem_classes="cool-col"): gr.Markdown("### Gradio Demo with Custom CSS", elem_classes="darktest") gr.Markdown( elem_classes="markdown", value="Resize the browser window to see the CSS media query in action.", ) if __name__ == "__main__": demo.launch(css_paths=["demo/custom_css/custom_css.css"]) ``` ## Fake Diffusion ```python import gradio as gr import numpy as np import time def fake_diffusion(steps): rng = np.random.default_rng() for i in range(steps): time.sleep(1) image = rng.random(size=(600, 600, 3)) yield image image = np.ones((1000,1000,3), np.uint8) image[:] = [255, 124, 0] yield image demo = gr.Interface(fake_diffusion, inputs=gr.Slider(1, 10, 3, step=1), outputs="image", api_name="predict") demo.launch() ``` ## Hello World ```python import gradio as gr def greet(name): return "Hello " + name + "!" demo = gr.Interface(fn=greet, inputs="textbox", outputs="textbox", api_name="predict") demo.launch() ``` ## Image Editor ```python import gradio as gr import time def sleep(im): time.sleep(5) return [im["background"], im["layers"][0], im["layers"][1], im["composite"]] def predict(im): return im["composite"] with gr.Blocks() as demo: with gr.Row(): im = gr.ImageEditor( type="numpy", ) im_preview = gr.Image() n_upload = gr.Number(0, label="Number of upload events", step=1) n_change = gr.Number(0, label="Number of change events", step=1) n_input = gr.Number(0, label="Number of input events", step=1) im.upload(lambda x: x + 1, outputs=n_upload, inputs=n_upload) im.change(lambda x: x + 1, outputs=n_change, inputs=n_change) im.input(lambda x: x + 1, outputs=n_input, inputs=n_input) im.change(predict, outputs=im_preview, inputs=im, show_progress="hidden") demo.launch() ``` ## On Listener Decorator ```python import gradio as gr with gr.Blocks() as demo: name = gr.Textbox(label="Name") output = gr.Textbox(label="Output Box") greet_btn = gr.Button("Greet") @gr.on(triggers=[name.submit, greet_btn.click], inputs=name, outputs=output) def greet(name): return "Hello " + name + "!" demo.launch() ``` ## Render Merge ```python import gradio as gr import time with gr.Blocks() as demo: text_count = gr.Slider(1, 5, value=1, step=1, label="Textbox Count") @gr.render(inputs=text_count) def render_count(count): boxes = [] for i in range(count): box = gr.Textbox(label=f"Box {i}") boxes.append(box) def merge(*args): time.sleep(0.2) # simulate a delay return " ".join(args) merge_btn.click(merge, boxes, output) def clear(): time.sleep(0.2) # simulate a delay return [" "] * count clear_btn.click(clear, None, boxes) def countup(): time.sleep(0.2) # simulate a delay return list(range(count)) count_btn.click(countup, None, boxes, queue=False) with gr.Row(): merge_btn = gr.Button("Merge") clear_btn = gr.Button("Clear") count_btn = gr.Button("Count") output = gr.Textbox() demo.launch() ``` ## Reverse Audio 2 ```python import gradio as gr import numpy as np def reverse_audio(audio): sr, data = audio return (sr, np.flipud(data)) demo = gr.Interface(fn=reverse_audio, inputs="microphone", outputs="audio", api_name="predict") demo.launch() ``` ## Sepia Filter ```python import numpy as np import gradio as gr def sepia(input_img): sepia_filter = np.array([ [0.393, 0.769, 0.189], [0.349, 0.686, 0.168], [0.272, 0.534, 0.131] ]) sepia_img = input_img.dot(sepia_filter.T) sepia_img /= sepia_img.max() return sepia_img demo = gr.Interface(sepia, gr.Image(), "image", api_name="predict") demo.launch() ``` ## Sort Records ```python import gradio as gr def sort_records(records): return records.sort("Quantity") demo = gr.Interface( sort_records, gr.Dataframe( headers=["Item", "Quantity"], datatype=["str", "number"], row_count=3, column_count=2, column_limits=(2, 2), type="polars" ), "dataframe", description="Sort by Quantity" ) demo.launch() ``` ## Streaming Simple ```python import gradio as gr with gr.Blocks() as demo: with gr.Row(): with gr.Column(): input_img = gr.Image(label="Input", sources="webcam") with gr.Column(): output_img = gr.Image(label="Output") input_img.stream(lambda s: s, input_img, output_img, time_limit=15, stream_every=0.1, concurrency_limit=30) if __name__ == "__main__": demo.launch() ``` ## Tabbed Interface Lite ```python import gradio as gr hello_world = gr.Interface(lambda name: "Hello " + name, "text", "text", api_name="predict") bye_world = gr.Interface(lambda name: "Bye " + name, "text", "text", api_name="predict") chat = gr.ChatInterface(lambda *args: "Hello " + args[0], api_name="chat") demo = gr.TabbedInterface([hello_world, bye_world, chat], ["Hello World", "Bye World", "Chat"]) demo.launch() ``` ## Tax Calculator ```python import gradio as gr def tax_calculator(income, marital_status, assets): tax_brackets = [(10, 0), (25, 8), (60, 12), (120, 20), (250, 30)] total_deductible = sum(cost for cost, deductible in zip(assets["Cost"], assets["Deductible"]) if deductible) taxable_income = income - total_deductible total_tax = 0 for bracket, rate in tax_brackets: if taxable_income > bracket: total_tax += (taxable_income - bracket) * rate / 100 if marital_status == "Married": total_tax *= 0.75 elif marital_status == "Divorced": total_tax *= 0.8 return round(total_tax) demo = gr.Interface( tax_calculator, [ "number", gr.Radio(["Single", "Married", "Divorced"]), gr.Dataframe( headers=["Item", "Cost", "Deductible"], datatype=["str", "number", "bool"], label="Assets Purchased this Year", ), ], gr.Number(label="Tax due"), examples=[ [10000, "Married", [["Suit", 5000, True], ["Laptop (for work)", 800, False], ["Car", 1800, True]]], [80000, "Single", [["Suit", 800, True], ["Watch", 1800, True], ["Food", 800, True]]], ], live=True, api_name="predict" ) demo.launch() ``` ## Timer Simple ```python import gradio as gr import random import time with gr.Blocks() as demo: timer = gr.Timer(1) timestamp = gr.Number(label="Time") timer.tick(lambda: round(time.time()), outputs=timestamp, api_name="timestamp") number = gr.Number(lambda: random.randint(1, 10), every=timer, label="Random Number") with gr.Row(): gr.Button("Start").click(lambda: gr.Timer(active=True), None, timer) gr.Button("Stop").click(lambda: gr.Timer(active=False), None, timer) gr.Button("Go Fast").click(lambda: 0.2, None, timer) if __name__ == "__main__": demo.launch() ``` ## Variable Outputs ```python import gradio as gr max_textboxes = 10 def variable_outputs(k): k = int(k) return [gr.Textbox(visible=True)]*k + [gr.Textbox(visible=False)]*(max_textboxes-k) with gr.Blocks() as demo: s = gr.Slider(1, max_textboxes, value=max_textboxes, step=1, label="How many textboxes to show:") textboxes = [] for i in range(max_textboxes): t = gr.Textbox(f"Textbox {i}") textboxes.append(t) s.change(variable_outputs, s, textboxes) if __name__ == "__main__": demo.launch() ``` ## Video Identity ```python import gradio as gr from gradio.media import get_video def video_identity(video): return video # get_video() returns file paths to sample media included with Gradio demo = gr.Interface(video_identity, gr.Video(), "playable_video", examples=[ get_video("world.mp4") ], cache_examples=True, api_name="predict",) demo.launch() ``` -
SKILL.md 25 KB
--- name: hugging-face-gradio description: Build Gradio web UIs and demos in Python. Use when creating or editing Gradio apps, components, event listeners, layouts, or chatbots. risk: critical source: https://github.com/huggingface/skills/tree/main/skills/huggingface-gradio source_repo: huggingface/skills source_type: official date_added: 2026-07-01 license: Apache-2.0 license_source: https://github.com/huggingface/skills/blob/main/LICENSE --- # Gradio ## When to Use Use this skill when you need build Gradio web UIs and demos in Python. Use when creating or editing Gradio apps, components, event listeners, layouts, or chatbots. Gradio is a Python library for building interactive web UIs and ML demos. This skill covers the core API, patterns, and examples. ## Guides Detailed guides on specific topics (read these when relevant): - [Quickstart](https://www.gradio.app/guides/quickstart) - [The Interface Class](https://www.gradio.app/guides/the-interface-class) - [Blocks and Event Listeners](https://www.gradio.app/guides/blocks-and-event-listeners) - [Controlling Layout](https://www.gradio.app/guides/controlling-layout) - [More Blocks Features](https://www.gradio.app/guides/more-blocks-features) - [Custom CSS and JS](https://www.gradio.app/guides/custom-CSS-and-JS) - [Streaming Outputs](https://www.gradio.app/guides/streaming-outputs) - [Streaming Inputs](https://www.gradio.app/guides/streaming-inputs) - [Sharing Your App](https://www.gradio.app/guides/sharing-your-app) - [Custom HTML Components](https://www.gradio.app/guides/custom-HTML-components) - [Getting Started with the Python Client](https://www.gradio.app/guides/getting-started-with-the-python-client) - [Getting Started with the JS Client](https://www.gradio.app/guides/getting-started-with-the-js-client) ## Core Patterns **Interface** (high-level): wraps a function with input/output components. ```python import gradio as gr def greet(name): return f"Hello {name}!" gr.Interface(fn=greet, inputs="text", outputs="text").launch() ``` **Blocks** (low-level): flexible layout with explicit event wiring. ```python import gradio as gr with gr.Blocks() as demo: name = gr.Textbox(label="Name") output = gr.Textbox(label="Greeting") btn = gr.Button("Greet") btn.click(fn=lambda n: f"Hello {n}!", inputs=name, outputs=output) demo.launch() ``` **ChatInterface**: high-level wrapper for chatbot UIs. ```python import gradio as gr def respond(message, history): return f"You said: {message}" gr.ChatInterface(fn=respond).launch() ``` ## Key Component Signatures ### `Textbox(value: str | I18nData | Callable | None = None, type: Literal['text', 'password', 'email'] = "text", lines: int = 1, max_lines: int | None = None, placeholder: str | I18nData | None = None, label: str | I18nData | None = None, info: str | I18nData | None = None, every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, show_label: bool | None = None, container: bool = True, scale: int | None = None, min_width: int = 160, interactive: bool | None = None, visible: bool | Literal['hidden'] = True, elem_id: str | None = None, autofocus: bool = False, autoscroll: bool = True, elem_classes: list[str] | str | None = None, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", text_align: Literal['left', 'right'] | None = None, rtl: bool = False, buttons: list[Literal['copy'] | Button] | None = None, max_length: int | None = None, submit_btn: str | bool | None = False, stop_btn: str | bool | None = False, html_attributes: InputHTMLAttributes | None = None)` Creates a textarea for user to enter string input or display string output.. ### `Number(value: float | Callable | None = None, label: str | I18nData | None = None, placeholder: str | I18nData | None = None, info: str | I18nData | None = None, every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, show_label: bool | None = None, container: bool = True, scale: int | None = None, min_width: int = 160, interactive: bool | None = None, visible: bool | Literal['hidden'] = True, elem_id: str | None = None, elem_classes: list[str] | str | None = None, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", buttons: list[Button] | None = None, precision: int | None = None, minimum: float | None = None, maximum: float | None = None, step: float = 1)` Creates a numeric field for user to enter numbers as input or display numeric output.. ### `Slider(minimum: float = 0, maximum: float = 100, value: float | Callable | None = None, step: float | None = None, precision: int | None = None, label: str | I18nData | None = None, info: str | I18nData | None = None, every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, show_label: bool | None = None, container: bool = True, scale: int | None = None, min_width: int = 160, interactive: bool | None = None, visible: bool | Literal['hidden'] = True, elem_id: str | None = None, elem_classes: list[str] | str | None = None, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", randomize: bool = False, buttons: list[Literal['reset']] | None = None)` Creates a slider that ranges from {minimum} to {maximum} with a step size of {step}.. ### `Checkbox(value: bool | Callable = False, label: str | I18nData | None = None, info: str | I18nData | None = None, every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, show_label: bool | None = None, container: bool = True, scale: int | None = None, min_width: int = 160, interactive: bool | None = None, visible: bool | Literal['hidden'] = True, elem_id: str | None = None, elem_classes: list[str] | str | None = None, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", buttons: list[Button] | None = None)` Creates a checkbox that can be set to `True` or `False`. ### `Dropdown(choices: Sequence[str | int | float | tuple[str, str | int | float]] | None = None, value: str | int | float | Sequence[str | int | float] | Callable | DefaultValue | None = DefaultValue(), type: Literal['value', 'index'] = "value", multiselect: bool | None = None, allow_custom_value: bool = False, max_choices: int | None = None, filterable: bool = True, label: str | I18nData | None = None, info: str | I18nData | None = None, every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, show_label: bool | None = None, container: bool = True, scale: int | None = None, min_width: int = 160, interactive: bool | None = None, visible: bool | Literal['hidden'] = True, elem_id: str | None = None, elem_classes: list[str] | str | None = None, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", buttons: list[Button] | None = None)` Creates a dropdown of choices from which a single entry or multiple entries can be selected (as an input component) or displayed (as an output component).. ### `Radio(choices: Sequence[str | int | float | tuple[str, str | int | float]] | None = None, value: str | int | float | Callable | None = None, type: Literal['value', 'index'] = "value", label: str | I18nData | None = None, info: str | I18nData | None = None, every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, show_label: bool | None = None, container: bool = True, scale: int | None = None, min_width: int = 160, interactive: bool | None = None, visible: bool | Literal['hidden'] = True, elem_id: str | None = None, elem_classes: list[str] | str | None = None, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", rtl: bool = False, buttons: list[Button] | None = None)` Creates a set of (string or numeric type) radio buttons of which only one can be selected.. ### `Image(value: str | PIL.Image.Image | np.ndarray | Callable | None = None, format: str = "webp", height: int | str | None = None, width: int | str | None = None, image_mode: Literal['1', 'L', 'P', 'RGB', 'RGBA', 'CMYK', 'YCbCr', 'LAB', 'HSV', 'I', 'F'] | None = "RGB", sources: list[Literal['upload', 'webcam', 'clipboard']] | Literal['upload', 'webcam', 'clipboard'] | None = None, type: Literal['numpy', 'pil', 'filepath'] = "numpy", label: str | I18nData | None = None, every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, show_label: bool | None = None, buttons: list[Literal['download', 'share', 'fullscreen'] | Button] | None = None, container: bool = True, scale: int | None = None, min_width: int = 160, interactive: bool | None = None, visible: bool | Literal['hidden'] = True, streaming: bool = False, elem_id: str | None = None, elem_classes: list[str] | str | None = None, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", webcam_options: WebcamOptions | None = None, placeholder: str | None = None, watermark: WatermarkOptions | None = None)` Creates an image component that can be used to upload images (as an input) or display images (as an output).. ### `Audio(value: str | Path | tuple[int, np.ndarray] | Callable | None = None, sources: list[Literal['upload', 'microphone']] | Literal['upload', 'microphone'] | None = None, type: Literal['numpy', 'filepath'] = "numpy", label: str | I18nData | None = None, every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, show_label: bool | None = None, container: bool = True, scale: int | None = None, min_width: int = 160, interactive: bool | None = None, visible: bool | Literal['hidden'] = True, streaming: bool = False, elem_id: str | None = None, elem_classes: list[str] | str | None = None, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", format: Literal['wav', 'mp3'] | None = None, autoplay: bool = False, editable: bool = True, buttons: list[Literal['download', 'share'] | Button] | None = None, waveform_options: WaveformOptions | dict | None = None, loop: bool = False, recording: bool = False, subtitles: str | Path | list[dict[str, Any]] | None = None, playback_position: float = 0)` Creates an audio component that can be used to upload/record audio (as an input) or display audio (as an output).. ### `Video(value: str | Path | Callable | None = None, format: str | None = None, sources: list[Literal['upload', 'webcam']] | Literal['upload', 'webcam'] | None = None, height: int | str | None = None, width: int | str | None = None, label: str | I18nData | None = None, every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, show_label: bool | None = None, container: bool = True, scale: int | None = None, min_width: int = 160, interactive: bool | None = None, visible: bool | Literal['hidden'] = True, elem_id: str | None = None, elem_classes: list[str] | str | None = None, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", webcam_options: WebcamOptions | None = None, include_audio: bool | None = None, autoplay: bool = False, buttons: list[Literal['download', 'share'] | Button] | None = None, loop: bool = False, streaming: bool = False, watermark: WatermarkOptions | None = None, subtitles: str | Path | list[dict[str, Any]] | None = None, playback_position: float = 0)` Creates a video component that can be used to upload/record videos (as an input) or display videos (as an output). ### `File(value: str | list[str] | Callable | None = None, file_count: Literal['single', 'multiple', 'directory'] = "single", file_types: list[str] | None = None, type: Literal['filepath', 'binary'] = "filepath", label: str | I18nData | None = None, every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, show_label: bool | None = None, container: bool = True, scale: int | None = None, min_width: int = 160, height: int | str | float | None = None, interactive: bool | None = None, visible: bool | Literal['hidden'] = True, elem_id: str | None = None, elem_classes: list[str] | str | None = None, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", allow_reordering: bool = False, buttons: list[Button] | None = None)` Creates a file component that allows uploading one or more generic files (when used as an input) or displaying generic files or URLs for download (as output). ### `Chatbot(value: list[MessageDict | Message] | Callable | None = None, label: str | I18nData | None = None, every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, show_label: bool | None = None, container: bool = True, scale: int | None = None, min_width: int = 160, visible: bool | Literal['hidden'] = True, elem_id: str | None = None, elem_classes: list[str] | str | None = None, autoscroll: bool = True, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", height: int | str | None = 400, resizable: bool = False, max_height: int | str | None = None, min_height: int | str | None = None, editable: Literal['user', 'all'] | None = None, latex_delimiters: list[dict[str, str | bool]] | None = None, rtl: bool = False, buttons: list[Literal['share', 'copy', 'copy_all'] | Button] | None = None, watermark: str | None = None, avatar_images: tuple[str | Path | None, str | Path | None] | None = None, sanitize_html: bool = True, render_markdown: bool = True, feedback_options: list[str] | tuple[str, ...] | None = ('Like', 'Dislike'), feedback_value: Sequence[str | None] | None = None, line_breaks: bool = True, layout: Literal['panel', 'bubble'] | None = None, placeholder: str | None = None, examples: list[ExampleMessage] | None = None, allow_file_downloads: <class 'inspect._empty'> = True, group_consecutive_messages: bool = True, allow_tags: list[str] | bool = True, reasoning_tags: list[tuple[str, str]] | None = None, like_user_message: bool = False)` Creates a chatbot that displays user-submitted messages and responses. ### `Button(value: str | I18nData | Callable = "Run", every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, variant: Literal['primary', 'secondary', 'stop', 'huggingface'] = "secondary", size: Literal['sm', 'md', 'lg'] = "lg", icon: str | Path | None = None, link: str | None = None, link_target: Literal['_self', '_blank', '_parent', '_top'] = "_self", visible: bool | Literal['hidden'] = True, interactive: bool = True, elem_id: str | None = None, elem_classes: list[str] | str | None = None, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", scale: int | None = None, min_width: int | None = None)` Creates a button that can be assigned arbitrary .click() events. ### `Markdown(value: str | I18nData | Callable | None = None, label: str | I18nData | None = None, every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, show_label: bool | None = None, rtl: bool = False, latex_delimiters: list[dict[str, str | bool]] | None = None, visible: bool | Literal['hidden'] = True, elem_id: str | None = None, elem_classes: list[str] | str | None = None, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", sanitize_html: bool = True, line_breaks: bool = False, header_links: bool = False, height: int | str | None = None, max_height: int | str | None = None, min_height: int | str | None = None, buttons: list[Literal['copy']] | None = None, container: bool = False, padding: bool = False)` Used to render arbitrary Markdown output. ### `HTML(value: Any | Callable | None = None, label: str | I18nData | None = None, html_template: str = "${value}", css_template: str = "", js_on_load: str | None = "element.addEventListener('click', function() { trigger('click') });", apply_default_css: bool = True, every: Timer | float | None = None, inputs: Component | Sequence[Component] | set[Component] | None = None, show_label: bool = False, visible: bool | Literal['hidden'] = True, elem_id: str | None = None, elem_classes: list[str] | str | None = None, render: bool = True, key: int | str | tuple[int | str, ...] | None = None, preserved_by_key: list[str] | str | None = "value", min_height: int | None = None, max_height: int | None = None, container: bool = False, padding: bool = False, autoscroll: bool = False, buttons: list[Button] | None = None, server_functions: list[Callable] | None = None, props: Any)` Creates a component with arbitrary HTML. ## Custom HTML Components If a task requires significant customization of an existing component or a component that doesn't exist in Gradio, you can create one with `gr.HTML`. It supports `html_template` (with `${}` JS expressions and `{{}}` Handlebars syntax), `css_template` for scoped styles, and `js_on_load` for interactivity — where `props.value` updates the component value and `trigger('event_name')` fires Gradio events. For reuse, subclass `gr.HTML` and define `api_info()` for API/MCP support. See the [full guide](https://www.gradio.app/guides/custom-HTML-components). Here's an example that shows how to create and use these kinds of components: ```python import gradio as gr class StarRating(gr.HTML): def __init__(self, label, value=0, **kwargs): html_template = """ <h2>${label} rating:</h2> ${Array.from({length: 5}, (_, i) => `<img class='${i < value ? '' : 'faded'}' src='https://upload.wikimedia.org/wikipedia/commons/d/df/Award-star-gold-3d.svg'>`).join('')} """ css_template = """ img { height: 50px; display: inline-block; cursor: pointer; } .faded { filter: grayscale(100%); opacity: 0.3; } """ js_on_load = """ const imgs = element.querySelectorAll('img'); imgs.forEach((img, index) => { img.addEventListener('click', () => { props.value = index + 1; }); }); """ super().__init__(value=value, label=label, html_template=html_template, css_template=css_template, js_on_load=js_on_load, **kwargs) def api_info(self): return {"type": "integer", "minimum": 0, "maximum": 5} with gr.Blocks() as demo: gr.Markdown("# Restaurant Review") food_rating = StarRating(label="Food", value=3) service_rating = StarRating(label="Service", value=3) ambience_rating = StarRating(label="Ambience", value=3) average_btn = gr.Button("Calculate Average Rating") rating_output = StarRating(label="Average", value=3) def calculate_average(food, service, ambience): return round((food + service + ambience) / 3) average_btn.click( fn=calculate_average, inputs=[food_rating, service_rating, ambience_rating], outputs=rating_output ) demo.launch() ``` ## Event Listeners All event listeners share the same signature: ```python component.event_name( fn: Callable | None | Literal["decorator"] = "decorator", inputs: Component | Sequence[Component] | set[Component] | None = None, outputs: Component | Sequence[Component] | set[Component] | None = None, api_name: str | None = None, api_description: str | None | Literal[False] = None, scroll_to_output: bool = False, show_progress: Literal["full", "minimal", "hidden"] = "full", show_progress_on: Component | Sequence[Component] | None = None, queue: bool = True, batch: bool = False, max_batch_size: int = 4, preprocess: bool = True, postprocess: bool = True, cancels: dict[str, Any] | list[dict[str, Any]] | None = None, trigger_mode: Literal["once", "multiple", "always_last"] | None = None, js: str | Literal[True] | None = None, concurrency_limit: int | None | Literal["default"] = "default", concurrency_id: str | None = None, api_visibility: Literal["public", "private", "undocumented"] = "public", time_limit: int | None = None, stream_every: float = 0.5, key: int | str | tuple[int | str, ...] | None = None, validator: Callable | None = None, ) -> Dependency ``` Supported events per component: - **AnnotatedImage**: select - **Audio**: stream, change, clear, play, pause, stop, pause, start_recording, pause_recording, stop_recording, upload, input - **BarPlot**: select, double_click - **BrowserState**: change - **Button**: click - **Chatbot**: change, select, like, retry, undo, example_select, option_select, clear, copy, edit - **Checkbox**: change, input, select - **CheckboxGroup**: change, input, select - **ClearButton**: click - **Code**: change, input, focus, blur - **ColorPicker**: change, input, submit, focus, blur - **Dataframe**: change, input, select, edit - **Dataset**: click, select - **DateTime**: change, submit - **DeepLinkButton**: click - **Dialogue**: change, input, submit - **DownloadButton**: click - **Dropdown**: change, input, select, focus, blur, key_up - **DuplicateButton**: click - **File**: change, select, clear, upload, delete, download - **FileExplorer**: change, input, select - **Gallery**: select, upload, change, delete, preview_close, preview_open - **HTML**: change, input, click, double_click, submit, stop, edit, clear, play, pause, end, start_recording, pause_recording, stop_recording, focus, blur, upload, release, select, stream, like, example_select, option_select, load, key_up, apply, delete, tick, undo, retry, expand, collapse, download, copy - **HighlightedText**: change, select - **Image**: clear, change, stream, select, upload, input - **ImageEditor**: clear, change, input, select, upload, apply - **ImageSlider**: clear, change, stream, select, upload, input - **JSON**: change - **Label**: change, select - **LinePlot**: select, double_click - **LoginButton**: click - **Markdown**: change, copy - **Model3D**: change, upload, edit, clear - **MultimodalTextbox**: change, input, select, submit, focus, blur, stop - **Navbar**: change - **Number**: change, input, submit, focus, blur - **ParamViewer**: change, upload - **Plot**: change - **Radio**: select, change, input - **ScatterPlot**: select, double_click - **SimpleImage**: clear, change, upload - **Slider**: change, input, release - **State**: change - **Textbox**: change, input, select, submit, focus, blur, stop, copy - **Timer**: tick - **UploadButton**: click, upload - **Video**: change, clear, start_recording, stop_recording, stop, play, pause, end, upload, input ## Prediction CLI The `gradio` CLI includes `info` and `predict` commands for interacting with Gradio apps programmatically. These are especially useful for coding agents that need to use Spaces in their workflows. ### `gradio info` — Discover endpoints and parameters ```bash gradio info <space_id_or_url> ``` Returns a JSON payload describing all endpoints, their parameters (with types and defaults), and return values. ```bash gradio info gradio/calculator # { # "/predict": { # "parameters": [ # {"name": "num1", "required": true, "default": null, "type": {"type": "number"}}, # {"name": "operation", "required": true, "default": null, "type": {"enum": ["add", "subtract", "multiply", "divide"], "type": "string"}}, # {"name": "num2", "required": true, "default": null, "type": {"type": "number"}} # ], # "returns": [{"name": "output", "type": {"type": "number"}}], # "description": "" # } # } ``` File-type parameters show `"type": "filepath"` with instructions to include `"meta": {"_type": "gradio.FileData"}` — this signals the file will be uploaded to the remote server. ### `gradio predict` — Send predictions ```bash gradio predict <space_id_or_url> <endpoint> <json_payload> ``` Returns a JSON object with named output keys. ```bash # Simple numeric prediction gradio predict gradio/calculator /predict '{"num1": 5, "operation": "multiply", "num2": 3}' # {"output": 15} # Image generation gradio predict black-forest-labs/FLUX.2-dev /infer '{"prompt": "A majestic dragon"}' # {"Result": "/tmp/gradio/.../image.webp", "Seed": 1117868604} # File upload (must include meta key) gradio predict gradio/image_mod /predict '{"image": {"path": "/path/to/image.png", "meta": {"_type": "gradio.FileData"}}}' # {"output": "/tmp/gradio/.../output.png"} ``` Both commands accept `--token` for accessing private Spaces. ## Additional Reference - [End-to-End Examples](examples.md) — complete working apps ## Limitations - Use this skill only when the task clearly matches its upstream product or API scope. - Verify commands, API behavior, pricing, quotas, credentials, and deployment effects against current official documentation before making changes. - Do not treat generated examples as a substitute for environment-specific tests, security review, or user approval for destructive or costly actions.
Comments (0)
Sign in to join the conversation.
Reviews (0)
No reviews yet.
No comments yet.