Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add a gr.ClearButton #4456

Merged
merged 33 commits into from Jun 14, 2023
Merged
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
592a24b
clear button
abidlabs Jun 8, 2023
a9721d5
Merge branch 'main' into clear-button
abidlabs Jun 8, 2023
8bdfec1
Merge branch 'main' into clear-button
abidlabs Jun 12, 2023
ae8e033
restore
abidlabs Jun 12, 2023
e35e773
Merge branch 'main' into clear-button
abidlabs Jun 12, 2023
d906202
button in interface
abidlabs Jun 12, 2023
0d12406
Merge branch 'clear-button' of github.com:gradio-app/gradio into clea…
abidlabs Jun 12, 2023
43ccc7b
changelog
abidlabs Jun 12, 2023
f231010
fixes
abidlabs Jun 12, 2023
0a90bcb
Merge branch 'main' into clear-button
abidlabs Jun 12, 2023
ccb143b
simplify
abidlabs Jun 12, 2023
fca1144
changes
abidlabs Jun 12, 2023
91ac52b
components
abidlabs Jun 12, 2023
5d400ab
changed dropdown behavior
abidlabs Jun 12, 2023
def0127
fix label
abidlabs Jun 12, 2023
3230c2c
add tests
abidlabs Jun 12, 2023
965c473
update demos
abidlabs Jun 13, 2023
9c48eea
changelog
abidlabs Jun 13, 2023
4166595
changelog
abidlabs Jun 13, 2023
4d687d6
restore
abidlabs Jun 13, 2023
ed37e9a
Merge branch 'main' into clear-button
abidlabs Jun 13, 2023
1379eef
formatting
abidlabs Jun 13, 2023
7d080d7
revert dropdown
abidlabs Jun 13, 2023
5fd0901
frontend changes
abidlabs Jun 13, 2023
adb8f6d
other fixes
abidlabs Jun 13, 2023
8b9619e
changelog
abidlabs Jun 13, 2023
c615b45
update guide
abidlabs Jun 13, 2023
0e79056
future
abidlabs Jun 13, 2023
48fd114
fix tests
abidlabs Jun 13, 2023
2abf85a
fix tests
abidlabs Jun 13, 2023
f2b026d
fix tests
abidlabs Jun 13, 2023
4e5e488
changelog
abidlabs Jun 13, 2023
4d5d383
update guide
abidlabs Jun 13, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
22 changes: 0 additions & 22 deletions .vscode/settings.json

This file was deleted.

23 changes: 21 additions & 2 deletions CHANGELOG.md
Expand Up @@ -2,10 +2,26 @@

## New Features:

- A `gr.ClearButton` which allows users to easily clear the values of components by [@abidlabs](https://github.com/abidlabs) in [PR 4456](https://github.com/gradio-app/gradio/pull/4456)

Example usage:

```py
import gradio as gr

with gr.Blocks() as demo:
chatbot = gr.Chatbot([("Hello", "How are you?")])
with gr.Row():
textbox = gr.Textbox(scale=3, interactive=True)
gr.ClearButton([textbox, chatbot], scale=1)

demo.launch()
```

- Min and max value for gr.Number by [@artegoser](https://github.com/artegoser) and [@dawoodkhan82](https://github.com/dawoodkhan82) in [PR 3991](https://github.com/gradio-app/gradio/pull/3991)
- Add `start_recording` and `stop_recording` events to `Video` and `Audio` components by [@pngwn](https://github.com/pngwn) in [PR 4422](https://github.com/gradio-app/gradio/pull/4422)
- Add `autoplay` kwarg to `Video` and `Audio` components by [@pngwn](https://github.com/pngwn) in [PR 4453](https://github.com/gradio-app/gradio/pull/4453)
- Add `detailed_view` parameter to `Gallery` to control whether a detailed view is displayed on click by
- Add `allow_preview` parameter to `Gallery` to control whether a detailed preview is displayed on click by
[@freddyaboulton](https://github.com/freddyaboulton) in [PR 4470](https://github.com/gradio-app/gradio/pull/4470)

## Bug Fixes:
Expand All @@ -16,16 +32,19 @@
- Frontend code no longer crashes when there is a relative URL in an `<a>` element, by [@akx](https://github.com/akx) in [PR 4449](https://github.com/gradio-app/gradio/pull/4449).
- Fix bug where setting `format='mp4'` on a video component would cause the function to error out if the uploaded video was not playable by [@freddyaboulton](https://github.com/freddyaboulton) in [PR 4467](https://github.com/gradio-app/gradio/pull/4467)
- Fix `_js` parameter to work even without backend function, by [@aliabid94](https://github.com/aliabid94) in [PR 4486](https://github.com/gradio-app/gradio/pull/4486).
- Fixes issue with Clear button not working for `Label` component by [@abidlabs](https://github.com/abidlabs) in [PR 4456](https://github.com/gradio-app/gradio/pull/4456)


## Other Changes:

- Clean up unnecessary `new Promise()`s by [@akx](https://github.com/akx) in [PR 4442](https://github.com/gradio-app/gradio/pull/4442).
- Minor UI cleanup for Examples and Dataframe components [@aliabid94](https://github.com/aliabid94) in [PR 4455](https://github.com/gradio-app/gradio/pull/4455).
- Add Catalan translation [@jordimas](https://github.com/jordimas) in [PR 4483](https://github.com/gradio-app/gradio/pull/4483).
- The API endpoint that loads examples upon click has been given an explicit name ("/load_examples") by [@abidlabs](https://github.com/abidlabs) in [PR 4456](https://github.com/gradio-app/gradio/pull/4456).

## Breaking Changes:

No changes to highlight.
- The behavior of the `Clear` button has been changed for `Slider`, `CheckboxGroup`, `Radio`, `Dropdown` components by [@abidlabs](https://github.com/abidlabs) in [PR 4456](https://github.com/gradio-app/gradio/pull/4456). The Clear button now sets the value of these components to be empty as opposed to the original default set by the developer. This is to make them in line with the rest of the Gradio components.

# 3.34.0

Expand Down
2 changes: 1 addition & 1 deletion demo/blocks_plug/run.ipynb
@@ -1 +1 @@
{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: blocks_plug"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "def change_tab():\n", " return gr.Tabs.update(selected=2)\n", "\n", "\n", "identity_demo, input_demo, output_demo = gr.Blocks(), gr.Blocks(), gr.Blocks()\n", "\n", "with identity_demo:\n", " gr.Interface(lambda x: x, \"text\", \"text\")\n", "\n", "with input_demo:\n", " t = gr.Textbox(label=\"Enter your text here\")\n", " with gr.Row():\n", " btn = gr.Button(\"Submit\")\n", " clr = gr.Button(\"Clear\")\n", " clr.click(lambda x: \"\", t, t)\n", "\n", "with output_demo:\n", " gr.Textbox(\"This is a static output\")\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(\"Three demos in one!\")\n", " with gr.Tabs(selected=1) as tabs:\n", " with gr.TabItem(\"Text Identity\", id=0) as tab0:\n", " tab0.select(lambda: gr.Tabs.update(selected=0), None, tabs)\n", " identity_demo.render()\n", " with gr.TabItem(\"Text Input\", id=1) as tab1:\n", " tab1.select(lambda: gr.Tabs.update(selected=1), None, tabs)\n", " input_demo.render()\n", " with gr.TabItem(\"Text Static\", id=2) as tab2:\n", " tab2.select(lambda: gr.Tabs.update(selected=2), None, tabs)\n", " output_demo.render()\n", " btn = gr.Button(\"Change tab\")\n", " btn.click(inputs=None, outputs=tabs, fn=change_tab)\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_plug"]}, {"cell_type": "code", "execution_count": null, "id": 272996653310673477252411125948039410165, "metadata": {}, "outputs": [], "source": ["!pip install -q gradio "]}, {"cell_type": "code", "execution_count": null, "id": 288918539441861185822528903084949547379, "metadata": {}, "outputs": [], "source": ["import gradio as gr\n", "\n", "\n", "def change_tab():\n", " return gr.Tabs.update(selected=2)\n", "\n", "\n", "identity_demo, input_demo, output_demo = gr.Blocks(), gr.Blocks(), gr.Blocks()\n", "\n", "with identity_demo:\n", " gr.Interface(lambda x: x, \"text\", \"text\")\n", "\n", "with input_demo:\n", " t = gr.Textbox(label=\"Enter your text here\")\n", " with gr.Row():\n", " btn = gr.Button(\"Submit\")\n", " clr = gr.ClearButton(t)\n", "\n", "with output_demo:\n", " gr.Textbox(\"This is a static output\")\n", "\n", "with gr.Blocks() as demo:\n", " gr.Markdown(\"Three demos in one!\")\n", " with gr.Tabs(selected=1) as tabs:\n", " with gr.TabItem(\"Text Identity\", id=0) as tab0:\n", " tab0.select(lambda: gr.Tabs.update(selected=0), None, tabs)\n", " identity_demo.render()\n", " with gr.TabItem(\"Text Input\", id=1) as tab1:\n", " tab1.select(lambda: gr.Tabs.update(selected=1), None, tabs)\n", " input_demo.render()\n", " with gr.TabItem(\"Text Static\", id=2) as tab2:\n", " tab2.select(lambda: gr.Tabs.update(selected=2), None, tabs)\n", " output_demo.render()\n", " btn = gr.Button(\"Change tab\")\n", " btn.click(inputs=None, outputs=tabs, fn=change_tab)\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
3 changes: 1 addition & 2 deletions demo/blocks_plug/run.py
Expand Up @@ -14,8 +14,7 @@ def change_tab():
t = gr.Textbox(label="Enter your text here")
with gr.Row():
btn = gr.Button("Submit")
clr = gr.Button("Clear")
clr.click(lambda x: "", t, t)
clr = gr.ClearButton(t)

with output_demo:
gr.Textbox("This is a static output")
Expand Down
2 changes: 1 addition & 1 deletion demo/chatbot_simple/run.ipynb
@@ -1 +1 @@
{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: chatbot_simple"]}, {"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", "import time\n", "\n", "with gr.Blocks() as demo:\n", " chatbot = gr.Chatbot()\n", " msg = gr.Textbox()\n", " clear = gr.Button(\"Clear\")\n", "\n", " def respond(message, chat_history):\n", " bot_message = random.choice([\"How are you?\", \"I love you\", \"I'm very hungry\"])\n", " chat_history.append((message, bot_message))\n", " time.sleep(2)\n", " return \"\", chat_history\n", "\n", " msg.submit(respond, [msg, chatbot], [msg, chatbot])\n", " clear.click(lambda: None, None, chatbot, queue=False)\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: chatbot_simple"]}, {"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", "import time\n", "\n", "with gr.Blocks() as demo:\n", " chatbot = gr.Chatbot()\n", " msg = gr.Textbox()\n", " clear = gr.ClearButton([msg, chatbot])\n", "\n", " def respond(message, chat_history):\n", " bot_message = random.choice([\"How are you?\", \"I love you\", \"I'm very hungry\"])\n", " chat_history.append((message, bot_message))\n", " time.sleep(2)\n", " return \"\", chat_history\n", "\n", " msg.submit(respond, [msg, chatbot], [msg, chatbot])\n", "\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
3 changes: 1 addition & 2 deletions demo/chatbot_simple/run.py
Expand Up @@ -5,7 +5,7 @@
with gr.Blocks() as demo:
chatbot = gr.Chatbot()
msg = gr.Textbox()
clear = gr.Button("Clear")
clear = gr.ClearButton([msg, chatbot])

def respond(message, chat_history):
bot_message = random.choice(["How are you?", "I love you", "I'm very hungry"])
Expand All @@ -14,7 +14,6 @@ def respond(message, chat_history):
return "", chat_history

msg.submit(respond, [msg, chatbot], [msg, chatbot])
clear.click(lambda: None, None, chatbot, queue=False)

if __name__ == "__main__":
demo.launch()
2 changes: 1 addition & 1 deletion demo/chatbot_streaming/run.ipynb
@@ -1 +1 @@
{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: chatbot_streaming"]}, {"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", "import time\n", "\n", "with gr.Blocks() as demo:\n", " chatbot = gr.Chatbot()\n", " msg = gr.Textbox()\n", " clear = gr.Button(\"Clear\")\n", "\n", " def user(user_message, history):\n", " return gr.update(value=\"\", interactive=False), history + [[user_message, None]]\n", "\n", " def bot(history):\n", " bot_message = random.choice([\"How are you?\", \"I love you\", \"I'm very hungry\"])\n", " history[-1][1] = \"\"\n", " for character in bot_message:\n", " history[-1][1] += character\n", " time.sleep(0.05)\n", " yield history\n", "\n", " response = msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False).then(\n", " bot, chatbot, chatbot\n", " )\n", " response.then(lambda: gr.update(interactive=True), None, [msg], queue=False)\n", " clear.click(lambda: None, None, chatbot, queue=False)\n", "\n", "demo.queue()\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
{"cells": [{"cell_type": "markdown", "id": 302934307671667531413257853548643485645, "metadata": {}, "source": ["# Gradio Demo: chatbot_streaming"]}, {"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", "import time\n", "\n", "with gr.Blocks() as demo:\n", " chatbot = gr.Chatbot()\n", " msg = gr.Textbox()\n", " clear = gr.ClearButton([msg, chatbot])\n", "\n", " def user(user_message, history):\n", " return gr.update(value=\"\", interactive=False), history + [[user_message, None]]\n", "\n", " def bot(history):\n", " bot_message = random.choice([\"How are you?\", \"I love you\", \"I'm very hungry\"])\n", " history[-1][1] = \"\"\n", " for character in bot_message:\n", " history[-1][1] += character\n", " time.sleep(0.05)\n", " yield history\n", "\n", " response = msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False).then(\n", " bot, chatbot, chatbot\n", " )\n", " response.then(lambda: gr.update(interactive=True), None, [msg], queue=False)\n", "\n", "demo.queue()\n", "if __name__ == \"__main__\":\n", " demo.launch()\n"]}], "metadata": {}, "nbformat": 4, "nbformat_minor": 5}
3 changes: 1 addition & 2 deletions demo/chatbot_streaming/run.py
Expand Up @@ -5,7 +5,7 @@
with gr.Blocks() as demo:
chatbot = gr.Chatbot()
msg = gr.Textbox()
clear = gr.Button("Clear")
clear = gr.ClearButton([msg, chatbot])

def user(user_message, history):
return gr.update(value="", interactive=False), history + [[user_message, None]]
Expand All @@ -22,7 +22,6 @@ def bot(history):
bot, chatbot, chatbot
)
response.then(lambda: gr.update(interactive=True), None, [msg], queue=False)
clear.click(lambda: None, None, chatbot, queue=False)

demo.queue()
if __name__ == "__main__":
Expand Down
1 change: 1 addition & 0 deletions gradio/__init__.py
Expand Up @@ -7,6 +7,7 @@
import gradio.templates
import gradio.themes as themes
from gradio.blocks import Blocks
from gradio.buttons import ClearButton
from gradio.components import (
HTML,
JSON,
Expand Down
70 changes: 70 additions & 0 deletions gradio/buttons.py
@@ -0,0 +1,70 @@
""" Predefined buttons with bound events that can be included in a gr.Blocks for convenience. """

from __future__ import annotations

import json

from gradio_client.documentation import document, set_documentation_group
from typing_extensions import Literal

from gradio.components import Button, Component

set_documentation_group("component")
abidlabs marked this conversation as resolved.
Show resolved Hide resolved


@document("add")
abidlabs marked this conversation as resolved.
Show resolved Hide resolved
class ClearButton(Button):
"""
Button that clears the value of a component or a list of components when clicked. It is instantiated with the list of components to clear.
Preprocessing: passes the button value as a {str} into the function
Postprocessing: expects a {str} to be returned from a function, which is set as the label of the button
"""

is_template = True

def __init__(
self,
components: None | list[Component] | Component = None,
*,
value: str = "Clear",
variant: Literal["primary", "secondary", "stop"] = "secondary",
size: Literal["sm", "lg"] | None = None,
visible: bool = True,
interactive: bool = True,
elem_id: str | None = None,
elem_classes: list[str] | str | None = None,
scale: int | None = None,
min_width: int | None = None,
**kwargs,
):
super().__init__(
value,
variant=variant,
size=size,
visible=visible,
interactive=interactive,
elem_id=elem_id,
elem_classes=elem_classes,
scale=scale,
min_width=min_width,
**kwargs,
)
self.add(components)

def add(self, components: None | Component | list[Component]) -> ClearButton:
"""
Adds a component or list of components to the list of components that will be cleared when the button is clicked.
"""
if not components:
# This needs to be here because when the ClearButton is created in an gr.Interface, we don't
# want to create dependencies for it before we have created the dependencies for the submit function.
# We generally assume that the submit function dependency is the first thing created in an gr.Interface.
return self

if isinstance(components, Component):
components = [components]
clear_values = json.dumps(
abidlabs marked this conversation as resolved.
Show resolved Hide resolved
[component.postprocess(None) for component in components]
)
self.click(None, [], components, _js=f"() => {clear_values}")
return self