mirror of
https://github.com/gradio-app/gradio.git
synced 2025-04-06 12:30:29 +08:00
Lite playground design changes (#7811)
* prevent new line on cmd+enter shortcut * add copy button * add download button * better font sizing and align editor buttons * button colors and header positioning * add layout attribute * height issue * border fix * overflow * add changeset * tests * tweaks to index * fix formatting in index.html * fix event listener * better alignment on header * fix padding on code editor buttonsm * add dark mode * formatting * fix heights issues * add to guide * shared worker and small fix * Update guides/08_gradio-clients-and-lite/gradio-lite.md about SharedWorker mode (#7923) * layout edit in guide --------- Co-authored-by: gradio-pr-bot <gradio-pr-bot@users.noreply.github.com> Co-authored-by: Abubakar Abid <abubakar@huggingface.co> Co-authored-by: Yuichiro Tachibana (Tsuchiya) <t.yic.yt@gmail.com>
This commit is contained in:
parent
a4782f7a09
commit
b43055b297
7
.changeset/gentle-onions-wait.md
Normal file
7
.changeset/gentle-onions-wait.md
Normal file
@ -0,0 +1,7 @@
|
||||
---
|
||||
"@gradio/app": minor
|
||||
"@gradio/lite": minor
|
||||
"gradio": minor
|
||||
---
|
||||
|
||||
feat:Lite playground design changes
|
@ -2,7 +2,7 @@
|
||||
|
||||
Tags: SERVERLESS, BROWSER, PYODIDE
|
||||
|
||||
Gradio is a popular Python library for creating interactive machine learning apps. Traditionally, Gradio applications have relied on server-side infrastructure to run, which can be a hurdle for developers who need to host their applications.
|
||||
Gradio is a popular Python library for creating interactive machine learning apps. Traditionally, Gradio applications have relied on server-side infrastructure to run, which can be a hurdle for developers who need to host their applications.
|
||||
|
||||
Enter Gradio-lite (`@gradio/lite`): a library that leverages [Pyodide](https://pyodide.org/en/stable/) to bring Gradio directly to your browser. In this blog post, we'll explore what `@gradio/lite` is, go over example code, and discuss the benefits it offers for running Gradio applications.
|
||||
|
||||
@ -15,7 +15,7 @@ Enter Gradio-lite (`@gradio/lite`): a library that leverages [Pyodide](https://p
|
||||
Let's build a "Hello World" Gradio app in `@gradio/lite`
|
||||
|
||||
|
||||
### 1. Import JS and CSS
|
||||
### 1. Import JS and CSS
|
||||
|
||||
Start by creating a new HTML file, if you don't have one already. Importing the JavaScript and CSS corresponding to the `@gradio/lite` package by using the following code:
|
||||
|
||||
@ -33,7 +33,7 @@ Note that you should generally use the latest version of `@gradio/lite` that is
|
||||
|
||||
### 2. Create the `<gradio-lite>` tags
|
||||
|
||||
Somewhere in the body of your HTML page (wherever you'd like the Gradio app to be rendered), create opening and closing `<gradio-lite>` tags.
|
||||
Somewhere in the body of your HTML page (wherever you'd like the Gradio app to be rendered), create opening and closing `<gradio-lite>` tags.
|
||||
|
||||
```html
|
||||
<html>
|
||||
@ -58,7 +58,7 @@ Note: you can add the `theme` attribute to the `<gradio-lite>` tag to force the
|
||||
|
||||
### 3. Write your Gradio app inside of the tags
|
||||
|
||||
Now, write your Gradio app as you would normally, in Python! Keep in mind that since this is Python, whitespace and indentations matter.
|
||||
Now, write your Gradio app as you would normally, in Python! Keep in mind that since this is Python, whitespace and indentations matter.
|
||||
|
||||
```html
|
||||
<html>
|
||||
@ -72,7 +72,7 @@ Now, write your Gradio app as you would normally, in Python! Keep in mind that s
|
||||
|
||||
def greet(name):
|
||||
return "Hello, " + name + "!"
|
||||
|
||||
|
||||
gr.Interface(greet, "textbox", "textbox").launch()
|
||||
</gradio-lite>
|
||||
</body>
|
||||
@ -110,7 +110,7 @@ def add(a, b):
|
||||
return a + b
|
||||
</gradio-file>
|
||||
|
||||
</gradio-lite>
|
||||
</gradio-lite>
|
||||
|
||||
```
|
||||
|
||||
@ -142,12 +142,53 @@ demo = gr.Interface(classify, "textbox", "json")
|
||||
demo.launch()
|
||||
</gradio-file>
|
||||
|
||||
</gradio-lite>
|
||||
</gradio-lite>
|
||||
|
||||
```
|
||||
|
||||
**Try it out**: You can see this example running in [this Hugging Face Static Space](https://huggingface.co/spaces/abidlabs/gradio-lite-classify), which lets you host static (serverless) web applications for free. Visit the page and you'll be able to run a machine learning model without internet access!
|
||||
|
||||
### SharedWorker mode
|
||||
|
||||
By default, Gradio-Lite executes Python code in a [Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) with [Pyodide](https://pyodide.org/) runtime, and each Gradio-Lite app has its own worker.
|
||||
It has some benefits such as environment isolation.
|
||||
|
||||
However, when there are many Gradio-Lite apps in the same page, it may cause performance issues such as high memory usage because each app has its own worker and Pyodide runtime.
|
||||
In such cases, you can use the **SharedWorker mode** to share a single Pyodide runtime in a [SharedWorker](https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker) among multiple Gradio-Lite apps. To enable the SharedWorker mode, set the `shared-worker` attribute to the `<gradio-lite>` tag.
|
||||
|
||||
```html
|
||||
<!-- These two Gradio-Lite apps share a single worker -->
|
||||
|
||||
<gradio-lite shared-worker>
|
||||
import gradio as gr
|
||||
# ...
|
||||
</gradio-lite>
|
||||
|
||||
<gradio-lite shared-worker>
|
||||
import gradio as gr
|
||||
# ...
|
||||
</gradio-lite>
|
||||
```
|
||||
|
||||
When using the SharedWorker mode, you should be aware of the following points:
|
||||
* The apps share the same Python environment, which means that they can access the same modules and objects. If, for example, one app makes changes to some modules, the changes will be visible to other apps.
|
||||
* The file system is shared among the apps, while each app's files are mounted in each home directory, so each app can access the files of other apps.
|
||||
|
||||
### Code and Demo Playground
|
||||
|
||||
If you'd like to see the code side-by-side with the demo just pass in the `playground` attribute to the gradio-lite element. This will create an interactive playground that allows you to change the code and update the demo! If you're using playground, you can also set layout to either 'vertical' or 'horizontal' which will determine if the code editor and preview are side-by-side or on top of each other (by default it's reposnsive with the width of the page).
|
||||
|
||||
```html
|
||||
<gradio-lite playground layout="horizontal">
|
||||
import gradio as gr
|
||||
|
||||
gr.Interface(fn=lambda x: x,
|
||||
inputs=gr.Textbox(),
|
||||
outputs=gr.Textbox()
|
||||
).launch()
|
||||
</gradio-lite>
|
||||
```
|
||||
|
||||
## Benefits of Using `@gradio/lite`
|
||||
|
||||
### 1. Serverless Deployment
|
||||
@ -161,7 +202,7 @@ Since all processing occurs within the user's browser, `@gradio/lite` enhances p
|
||||
|
||||
### Limitations
|
||||
|
||||
* Currently, the biggest limitation in using `@gradio/lite` is that your Gradio apps will generally take more time (usually 5-15 seconds) to load initially in the browser. This is because the browser needs to load the Pyodide runtime before it can render Python code.
|
||||
* Currently, the biggest limitation in using `@gradio/lite` is that your Gradio apps will generally take more time (usually 5-15 seconds) to load initially in the browser. This is because the browser needs to load the Pyodide runtime before it can render Python code.
|
||||
|
||||
* Not every Python package is supported by Pyodide. While `gradio` and many other popular packages (including `numpy`, `scikit-learn`, and `transformers-js`) can be installed in Pyodide, if your app has many dependencies, its worth checking whether whether the dependencies are included in Pyodide, or can be [installed with `micropip`](https://micropip.pyodide.org/en/v0.2.2/project/api.html#micropip.install).
|
||||
|
||||
@ -181,7 +222,7 @@ You can immediately try out `@gradio/lite` by copying and pasting this code in a
|
||||
|
||||
def greet(name):
|
||||
return "Hello, " + name + "!"
|
||||
|
||||
|
||||
gr.Interface(greet, "textbox", "textbox").launch()
|
||||
</gradio-lite>
|
||||
</body>
|
||||
@ -189,8 +230,6 @@ You can immediately try out `@gradio/lite` by copying and pasting this code in a
|
||||
```
|
||||
|
||||
|
||||
We've also created a playground on the Gradio website that allows you to interactively edit code and see the results immediately!
|
||||
We've also created a playground on the Gradio website that allows you to interactively edit code and see the results immediately!
|
||||
|
||||
Playground: https://www.gradio.app/playground
|
||||
|
||||
|
||||
|
@ -1,2 +1,2 @@
|
||||
<!-- Lightning https://iconscout.com/icons/lightning by IconLauk https://iconscout.com/contributors/icon-lauk on IconScout https://iconscout.com" -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 32 32" viewBox="0 0 32 32" id="lightning"><path fill="#999b9e" d="M26.9,10.5C26.7,10.2,26.4,10,26,10h-9V2c0-0.4-0.3-0.8-0.7-1c-0.4-0.1-0.9,0-1.1,0.4l-10,14c-0.2,0.3-0.3,0.7-0.1,1 C5.3,16.8,5.6,17,6,17h8.8L13,29.9c-0.1,0.5,0.2,0.9,0.6,1.1c0.1,0,0.2,0.1,0.3,0.1c0.3,0,0.7-0.2,0.8-0.5l12-19 C27,11.2,27,10.8,26.9,10.5z"/></svg>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" enable-background="new 0 0 32 32" viewBox="0 0 32 32" id="lightning"><path fill="#ff7c00" d="M26.9,10.5C26.7,10.2,26.4,10,26,10h-9V2c0-0.4-0.3-0.8-0.7-1c-0.4-0.1-0.9,0-1.1,0.4l-10,14c-0.2,0.3-0.3,0.7-0.1,1 C5.3,16.8,5.6,17,6,17h8.8L13,29.9c-0.1,0.5,0.2,0.9,0.6,1.1c0.1,0,0.2,0.1,0.3,0.1c0.3,0,0.7-0.2,0.8-0.5l12-19 C27,11.2,27,10.8,26.9,10.5z"/></svg>
|
Before Width: | Height: | Size: 545 B After Width: | Height: | Size: 545 B |
@ -4,11 +4,10 @@
|
||||
import { mount_css as default_mount_css } from "../css";
|
||||
import type { api_factory } from "@gradio/client";
|
||||
import type { WorkerProxy } from "@gradio/wasm";
|
||||
import { SvelteComponent, createEventDispatcher } from "svelte";
|
||||
import { SvelteComponent, createEventDispatcher, onMount } from "svelte";
|
||||
import Code from "@gradio/code";
|
||||
import ErrorDisplay from "./ErrorDisplay.svelte";
|
||||
import lightning from "../images/lightning.svg";
|
||||
import play from "../images/play.svg";
|
||||
import type { LoadingStatus } from "js/statustracker";
|
||||
|
||||
export let autoscroll: boolean;
|
||||
@ -34,6 +33,7 @@
|
||||
|
||||
export let code: string | undefined;
|
||||
export let error_display: SvelteComponent | null;
|
||||
export let layout: string | null = null;
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
@ -60,65 +60,94 @@
|
||||
});
|
||||
|
||||
function shortcut_run(e: KeyboardEvent): void {
|
||||
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) {
|
||||
e.preventDefault();
|
||||
if (e.key == "Enter" && (e.metaKey || e.ctrlKey)) {
|
||||
dispatch("code", { code });
|
||||
e.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
function handle_theme_mode(target: HTMLDivElement): "light" | "dark" {
|
||||
const force_light = window.__gradio_mode__ === "website";
|
||||
|
||||
let new_theme_mode: ThemeMode;
|
||||
if (force_light) {
|
||||
new_theme_mode = "light";
|
||||
} else {
|
||||
const url = new URL(window.location.toString());
|
||||
const url_color_mode: ThemeMode | null = url.searchParams.get(
|
||||
"__theme"
|
||||
) as ThemeMode | null;
|
||||
new_theme_mode = theme_mode || url_color_mode || "system";
|
||||
}
|
||||
|
||||
if (new_theme_mode === "dark" || new_theme_mode === "light") {
|
||||
apply_theme(target, new_theme_mode);
|
||||
} else {
|
||||
new_theme_mode = sync_system_theme(target);
|
||||
}
|
||||
return new_theme_mode;
|
||||
}
|
||||
|
||||
function sync_system_theme(target: HTMLDivElement): "light" | "dark" {
|
||||
const theme = update_scheme();
|
||||
window
|
||||
?.matchMedia("(prefers-color-scheme: dark)")
|
||||
?.addEventListener("change", update_scheme);
|
||||
|
||||
function update_scheme(): "light" | "dark" {
|
||||
let _theme: "light" | "dark" = window?.matchMedia?.(
|
||||
"(prefers-color-scheme: dark)"
|
||||
).matches
|
||||
? "dark"
|
||||
: "light";
|
||||
|
||||
apply_theme(target, _theme);
|
||||
return _theme;
|
||||
}
|
||||
return theme;
|
||||
}
|
||||
|
||||
function apply_theme(target: HTMLDivElement, theme: "dark" | "light"): void {
|
||||
const dark_class_element = is_embed ? target.parentElement! : document.body;
|
||||
const bg_element = is_embed ? target : target.parentElement!;
|
||||
if (theme === "dark") {
|
||||
dark_class_element.classList.add("dark");
|
||||
} else {
|
||||
dark_class_element.classList.remove("dark");
|
||||
}
|
||||
}
|
||||
|
||||
let active_theme_mode: ThemeMode;
|
||||
let parent_container: HTMLDivElement;
|
||||
|
||||
onMount(() => {
|
||||
var code_editors = document.getElementsByClassName("code-editor");
|
||||
for (var i = 0; i < code_editors.length; i++) {
|
||||
code_editors[i].addEventListener(
|
||||
"keydown",
|
||||
shortcut_run as EventListener,
|
||||
true
|
||||
);
|
||||
}
|
||||
active_theme_mode = handle_theme_mode(parent_container);
|
||||
});
|
||||
|
||||
$: loading_text;
|
||||
$: loaded;
|
||||
$: code;
|
||||
</script>
|
||||
|
||||
<svelte:window on:keydown={shortcut_run} />
|
||||
|
||||
<div class="parent-container">
|
||||
<div class="child-container">
|
||||
<div class:code-editor-border={loaded} class="code-editor">
|
||||
<div class="loading-panel">
|
||||
<div class="code-header">app.py</div>
|
||||
{#if !loaded}
|
||||
<div style="display: flex;"></div>
|
||||
<div class="loading-section">
|
||||
<div class="loading-dot"></div>
|
||||
{loading_text}
|
||||
</div>
|
||||
{:else}
|
||||
<div style="display: flex;"></div>
|
||||
<div class="loading-section">
|
||||
<img src={lightning} alt="lightning icon" class="lightning-logo" />
|
||||
Interactive
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<div style="flex-grow: 1;">
|
||||
{#if loaded}
|
||||
<Code
|
||||
bind:value={code}
|
||||
label=""
|
||||
language="python"
|
||||
target={dummy_elem}
|
||||
gradio={dummy_gradio}
|
||||
lines={10}
|
||||
interactive={true}
|
||||
loading_status={dummy_loading_status}
|
||||
/>
|
||||
{:else}
|
||||
<Code
|
||||
bind:value={code}
|
||||
label=""
|
||||
language="python"
|
||||
target={dummy_elem}
|
||||
gradio={dummy_gradio}
|
||||
lines={10}
|
||||
interactive={false}
|
||||
loading_status={dummy_loading_status}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{#if loaded}
|
||||
<div class="preview">
|
||||
<div class="parent-container" bind:this={parent_container}>
|
||||
<div class="wrapper">
|
||||
<div class="loading-panel">
|
||||
<div class="code-header">app.py</div>
|
||||
{#if !loaded}
|
||||
<div style="display: flex;"></div>
|
||||
<div class="loading-section">
|
||||
<div class="loading-dot"></div>
|
||||
{loading_text}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="buttons">
|
||||
<div class="run">
|
||||
<button
|
||||
@ -128,61 +157,131 @@
|
||||
}}
|
||||
>
|
||||
Run
|
||||
<img src={play} alt="play icon" class="play-logo" />
|
||||
<div class="shortcut">⌘+↵</div>
|
||||
</button>
|
||||
<div class="shortcut">⌘+↵</div>
|
||||
</div>
|
||||
|
||||
<div style="display: flex; float: right;"></div>
|
||||
</div>
|
||||
<div>
|
||||
{#if !error_display}
|
||||
<Index
|
||||
{autoscroll}
|
||||
{version}
|
||||
{initial_height}
|
||||
{app_mode}
|
||||
{is_embed}
|
||||
{theme_mode}
|
||||
{control_page_title}
|
||||
{container}
|
||||
{info}
|
||||
{eager}
|
||||
{mount_css}
|
||||
{client}
|
||||
{upload_files}
|
||||
bind:worker_proxy
|
||||
{fetch_implementation}
|
||||
{EventSource_factory}
|
||||
{space}
|
||||
{host}
|
||||
{src}
|
||||
<div style="flex-grow: 1"></div>
|
||||
<div class="loading-section">
|
||||
<img src={lightning} alt="lightning icon" class="lightning-logo" />
|
||||
Interactive
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<div
|
||||
class:horizontal={layout === "horizontal"}
|
||||
class:vertical={layout === "vertical"}
|
||||
class="child-container"
|
||||
>
|
||||
<div class:code-editor-border={loaded} class="code-editor">
|
||||
<div style="flex-grow: 1;">
|
||||
{#if loaded}
|
||||
<Code
|
||||
bind:value={code}
|
||||
label=""
|
||||
language="python"
|
||||
target={dummy_elem}
|
||||
gradio={dummy_gradio}
|
||||
lines={10}
|
||||
interactive={true}
|
||||
loading_status={dummy_loading_status}
|
||||
/>
|
||||
{:else}
|
||||
<ErrorDisplay
|
||||
is_embed={error_display.is_embed}
|
||||
error={error_display.error}
|
||||
<Code
|
||||
bind:value={code}
|
||||
label=""
|
||||
language="python"
|
||||
target={dummy_elem}
|
||||
gradio={dummy_gradio}
|
||||
lines={10}
|
||||
interactive={false}
|
||||
loading_status={dummy_loading_status}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{#if loaded}
|
||||
<div class="preview">
|
||||
<div class="flex-grow: 1;">
|
||||
{#if !error_display}
|
||||
<Index
|
||||
{autoscroll}
|
||||
{version}
|
||||
{initial_height}
|
||||
{app_mode}
|
||||
{is_embed}
|
||||
{theme_mode}
|
||||
{control_page_title}
|
||||
{container}
|
||||
{info}
|
||||
{eager}
|
||||
{mount_css}
|
||||
{client}
|
||||
{upload_files}
|
||||
bind:worker_proxy
|
||||
{fetch_implementation}
|
||||
{EventSource_factory}
|
||||
{space}
|
||||
{host}
|
||||
{src}
|
||||
/>
|
||||
{:else}
|
||||
<ErrorDisplay
|
||||
is_embed={error_display.is_embed}
|
||||
error={error_display.error}
|
||||
/>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<style>
|
||||
.wrapper {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow-y: scroll;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.parent-container {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
border: 1px solid rgb(229 231 235);
|
||||
border-radius: 0.375rem;
|
||||
}
|
||||
:global(.dark .parent-container) {
|
||||
border-color: #374151 !important;
|
||||
color-scheme: dark !important;
|
||||
}
|
||||
|
||||
.child-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: 1px solid rgb(229 231 235);
|
||||
border-radius: 0.375rem;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.horizontal {
|
||||
flex-direction: row !important;
|
||||
}
|
||||
|
||||
.vertical {
|
||||
flex-direction: column !important;
|
||||
}
|
||||
|
||||
.vertical .code-editor-border {
|
||||
border-right: none !important;
|
||||
}
|
||||
|
||||
.horizontal .code-editor-border {
|
||||
border-right: 1px solid rgb(229 231 235);
|
||||
border-bottom: none;
|
||||
}
|
||||
:global(.dark .horizontal .code-editor-border) {
|
||||
border-right: 1px solid #374151 !important;
|
||||
}
|
||||
|
||||
@media (min-width: 768px) {
|
||||
@ -192,13 +291,20 @@
|
||||
.code-editor-border {
|
||||
border-right: 1px solid rgb(229 231 235);
|
||||
}
|
||||
:global(.dark .code-editor-border) {
|
||||
border-right: 1px solid #374151 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.code-editor {
|
||||
flex-grow: 1;
|
||||
flex: 1 1 0%;
|
||||
flex: 1 1 50%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-bottom: 1px solid;
|
||||
border-color: rgb(229 231 235);
|
||||
}
|
||||
:global(.dark .code-editor) {
|
||||
border-color: #374151 !important;
|
||||
}
|
||||
|
||||
.loading-panel {
|
||||
@ -211,11 +317,21 @@
|
||||
border-bottom: 1px solid rgb(229 231 235);
|
||||
}
|
||||
|
||||
:global(.dark .loading-panel) {
|
||||
background: #1f2937 !important;
|
||||
border-color: #374151 !important;
|
||||
}
|
||||
|
||||
.code-header {
|
||||
padding-top: 0.25rem;
|
||||
flex-grow: 1;
|
||||
align-self: center;
|
||||
font-family: monospace;
|
||||
margin-top: 4px;
|
||||
font-size: 14px;
|
||||
font-weight: lighter;
|
||||
margin-right: 4px;
|
||||
color: #535d6d;
|
||||
}
|
||||
:global(.dark .code-header) {
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.loading-section {
|
||||
@ -225,7 +341,13 @@
|
||||
margin-right: 0.5rem;
|
||||
color: #999b9e;
|
||||
font-family: sans-serif;
|
||||
font-size: 15px;
|
||||
align-self: center;
|
||||
}
|
||||
:global(.dark .loading-section) {
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
.lightning-logo {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
@ -233,7 +355,7 @@
|
||||
}
|
||||
|
||||
.preview {
|
||||
flex: 1 1 0%;
|
||||
flex: 1 1 50%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
@ -243,38 +365,46 @@
|
||||
justify-content: space-between;
|
||||
align-items: middle;
|
||||
height: 2rem;
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.5rem;
|
||||
border-bottom: 1px solid rgb(229 231 235);
|
||||
}
|
||||
|
||||
.run {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: #999b9e;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.button {
|
||||
display: flex;
|
||||
height: 80%;
|
||||
align-items: center;
|
||||
font-weight: 500;
|
||||
padding-left: 0.5rem;
|
||||
padding-right: 0.25rem;
|
||||
font-weight: 600;
|
||||
padding-left: 0.8rem;
|
||||
padding-right: 0.8rem;
|
||||
border-radius: 0.375rem;
|
||||
float: right;
|
||||
margin: 0.25rem;
|
||||
color: rgb(107 114 128);
|
||||
background: #eff1f3;
|
||||
border: none;
|
||||
font-size: 100%;
|
||||
border: 1px solid #e5e7eb;
|
||||
background: linear-gradient(to bottom right, #f3f4f6, #e5e7eb);
|
||||
color: #374151;
|
||||
cursor: pointer;
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.play-logo {
|
||||
width: 0.75rem;
|
||||
height: 0.75rem;
|
||||
margin: 0.125rem;
|
||||
:global(.dark .button) {
|
||||
border-color: #374151 !important;
|
||||
background: linear-gradient(to bottom right, #4b5563, #374151) !important;
|
||||
color: white !important;
|
||||
}
|
||||
.shortcut {
|
||||
align-self: center;
|
||||
margin-top: 2px;
|
||||
font-size: 10px;
|
||||
font-weight: lighter;
|
||||
padding-left: 0.15rem;
|
||||
color: #374151;
|
||||
}
|
||||
:global(.dark .shortcut) {
|
||||
color: white !important;
|
||||
}
|
||||
|
||||
:global(div.code-editor div.block) {
|
||||
@ -285,6 +415,9 @@
|
||||
:global(div.code-editor div.block .cm-gutters) {
|
||||
background-color: white;
|
||||
}
|
||||
:global(.dark div.code-editor div.block .cm-gutters) {
|
||||
background: #1f2937 !important;
|
||||
}
|
||||
|
||||
:global(div.code-editor div.block .cm-content) {
|
||||
width: 0;
|
||||
@ -320,10 +453,34 @@
|
||||
height: 100%;
|
||||
}
|
||||
:global(.code-editor .container) {
|
||||
display: none;
|
||||
padding: 2px;
|
||||
padding-right: 0;
|
||||
height: 100%;
|
||||
}
|
||||
:global(.code-editor button) {
|
||||
display: none;
|
||||
|
||||
:global(.code-editor .container a) {
|
||||
display: block;
|
||||
width: 65%;
|
||||
color: #9095a0;
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
:global(.code-editor .block button) {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
color: #9095a0;
|
||||
height: 100%;
|
||||
padding: 5px;
|
||||
padding-left: 0;
|
||||
}
|
||||
|
||||
:global(.code-editor .block .check) {
|
||||
width: 65%;
|
||||
color: #ff7c00;
|
||||
margin: auto;
|
||||
}
|
||||
:global(.gradio-container) {
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
.loading-dot {
|
||||
|
@ -63,6 +63,7 @@ export function bootstrap_custom_element(
|
||||
files: gradioLiteAppOptions.files,
|
||||
entrypoint: gradioLiteAppOptions.entrypoint,
|
||||
playground: this.hasAttribute("playground"),
|
||||
layout: this.getAttribute("layout"),
|
||||
...gradioComponentOptions
|
||||
});
|
||||
});
|
||||
|
@ -78,7 +78,8 @@ def hi(name):
|
||||
autoScroll: false,
|
||||
controlPageTitle: false,
|
||||
appMode: true,
|
||||
playground: false
|
||||
playground: false,
|
||||
layout: null
|
||||
});
|
||||
});
|
||||
onDestroy(() => {
|
||||
|
@ -67,6 +67,7 @@ export interface Options {
|
||||
controlPageTitle: boolean;
|
||||
appMode: boolean;
|
||||
playground: boolean | undefined;
|
||||
layout: string | null;
|
||||
}
|
||||
export function create(options: Options): GradioAppController {
|
||||
// TODO: Runtime type validation for options.
|
||||
@ -213,7 +214,9 @@ export function create(options: Options): GradioAppController {
|
||||
upload_files,
|
||||
mount_css: overridden_mount_css,
|
||||
fetch_implementation: overridden_fetch,
|
||||
EventSource_factory
|
||||
EventSource_factory,
|
||||
// For playground
|
||||
layout: options.layout
|
||||
};
|
||||
|
||||
if (options.playground) {
|
||||
|
@ -73,9 +73,16 @@ helloWorld();
|
||||
<a href="https://example.com/moreinfo">our information page</a>.
|
||||
</p>
|
||||
|
||||
<gradio-lite playground>
|
||||
import gradio as gr gr.Interface(fn=lambda x: x, inputs=gr.Textbox(),
|
||||
outputs=gr.Textbox()).launch()
|
||||
<gradio-lite
|
||||
playground
|
||||
layout="horizontal"
|
||||
style="height: 300px; padding: 20px"
|
||||
shared-worker
|
||||
>
|
||||
import gradio as gr
|
||||
<!-- -->
|
||||
gr.Interface(fn=lambda x: x,
|
||||
inputs=gr.Textbox(),outputs=gr.Textbox()).launch()
|
||||
</gradio-lite>
|
||||
|
||||
<h3>Subsection: Vestibulum</h3>
|
||||
@ -115,8 +122,23 @@ helloWorld();
|
||||
<a href="https://example.com/moreinfo">our information page</a>.
|
||||
</p>
|
||||
|
||||
<gradio-lite playground>
|
||||
import gradio as gr gr.ChatInterface(lambda x,y:x).launch()
|
||||
<gradio-lite playground layout="vertical" shared-worker>
|
||||
import gradio as gr
|
||||
<!-- -->
|
||||
gr.ChatInterface(lambda x,y:x).launch()
|
||||
</gradio-lite>
|
||||
|
||||
<h3>Subsection: Vestibulum</h3>
|
||||
|
||||
<p>
|
||||
Vestibulum id ligula porta felis euismod semper. Sed posuere consectetur
|
||||
est at lobortis.
|
||||
</p>
|
||||
|
||||
<gradio-lite playground style="height: 300px" shared-worker>
|
||||
import gradio as gr
|
||||
<!-- -->
|
||||
gr.ChatInterface(lambda x,y:x).launch()
|
||||
</gradio-lite>
|
||||
</body>
|
||||
</html>
|
||||
|
Loading…
x
Reference in New Issue
Block a user