import gradio as gr from fastapi import FastAPI, Request from fastapi.responses import RedirectResponse import uvicorn BUILTIN_THEMES = ["default", "base", "soft", "monochrome", "glass", "origin", "citrus", "ocean", "spark"] def load_theme(theme_id: str): """Load theme by ID. Supports built-in and Hub themes.""" if not theme_id or theme_id == "default": return gr.themes.Default() # Community theme from Hub (e.g., "gradio/seafoam") if "/" in theme_id: try: return gr.Theme.from_hub(theme_id) except Exception as e: print(f"Failed to load '{theme_id}' from Hub: {e}") return gr.themes.Default() # Built-in theme builtin = { "base": gr.themes.Base, "soft": gr.themes.Soft, "monochrome": gr.themes.Monochrome, "glass": gr.themes.Glass, "origin": gr.themes.Origin, "citrus": gr.themes.Citrus, "ocean": gr.themes.Ocean, } theme_cls = builtin.get(theme_id.lower()) return theme_cls() if theme_cls else gr.themes.Default() def process(text, number, checkbox, radio, dropdown): return f"""**Results:** - Text: {text} - Number: {number} - Checkbox: {checkbox} - Radio: {radio} - Dropdown: {dropdown}""" def make_demo(theme_id: str): """Create a demo app with the specified theme.""" theme = load_theme(theme_id) display_name = theme_id if "/" in theme_id else theme_id.capitalize() with gr.Blocks(theme=theme, title=f"Theme: {display_name}") as demo: gr.Markdown(f"# {display_name} Theme") gr.Markdown("Preview of Gradio components with this theme.") with gr.Row(): with gr.Column(): text_input = gr.Textbox( label="Text Input", placeholder="Type something here...", info="A standard text input field" ) number_input = gr.Slider( minimum=0, maximum=100, value=50, label="Slider", info="Drag to select a value" ) checkbox = gr.Checkbox( value=True, label="Enable feature", info="Toggle this option" ) with gr.Row(): submit_btn = gr.Button("Submit", variant="primary") clear_btn = gr.Button("Clear", variant="secondary") stop_btn = gr.Button("Stop", variant="stop") with gr.Column(): output = gr.Markdown(label="Output") radio = gr.Radio( choices=["Option A", "Option B", "Option C"], value="Option A", label="Radio Selection" ) dropdown = gr.Dropdown( choices=["Choice 1", "Choice 2", "Choice 3"], value="Choice 1", label="Dropdown Menu" ) with gr.Row(): with gr.Column(): gr.Markdown("### Additional Components") with gr.Tabs(): with gr.Tab("Tab 1"): gr.Textbox(label="Tab 1 Content", value="Content in first tab") with gr.Tab("Tab 2"): gr.Textbox(label="Tab 2 Content", value="Content in second tab") with gr.Column(): with gr.Accordion("Advanced Settings", open=False): gr.Slider(0, 10, 5, label="Advanced Option 1") gr.Slider(0, 10, 3, label="Advanced Option 2") gr.Checkbox(label="Advanced Toggle") with gr.Row(): gr.Number(label="Number Input", value=42) gr.ColorPicker(label="Color", value="#ff7700") submit_btn.click( fn=process, inputs=[text_input, number_input, checkbox, radio, dropdown], outputs=output ) clear_btn.click( fn=lambda: ("", 50, True, "Option A", "Choice 1", ""), outputs=[text_input, number_input, checkbox, radio, dropdown, output] ) return demo # Pre-build demos for all built-in themes DEMOS = {tid: make_demo(tid) for tid in BUILTIN_THEMES} # Hub theme cache HUB_DEMOS = {} app = FastAPI() @app.get("/") async def root(request: Request): """Redirect to appropriate theme path based on query param.""" theme = request.query_params.get("theme", "default").lower() # Handle hub themes if "/" in theme: # URL encode the slash for the path safe_theme = theme.replace("/", "--") if safe_theme not in HUB_DEMOS: try: HUB_DEMOS[safe_theme] = make_demo(theme) gr.mount_gradio_app(app, HUB_DEMOS[safe_theme], path=f"/{safe_theme}") except Exception as e: print(f"Error creating demo for {theme}: {e}") return RedirectResponse("/default/") return RedirectResponse(f"/{safe_theme}/") # Handle built-in themes if theme not in DEMOS: theme = "default" return RedirectResponse(f"/{theme}/") # Mount all built-in theme demos for theme_id, demo in DEMOS.items(): app = gr.mount_gradio_app(app, demo, path=f"/{theme_id}") if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=7860)