From 8909e42a7c6272358ad413588d27a5124d151205 Mon Sep 17 00:00:00 2001 From: Dawood Khan Date: Tue, 12 Sep 2023 18:25:03 -0400 Subject: [PATCH] Adds `autoscroll` param to `gr.Textbox()` (#5488) * autoscroll param * add changeset * fix * test fix --------- Co-authored-by: gradio-pr-bot --- .changeset/curly-files-know.md | 6 ++++++ gradio/components/textbox.py | 6 ++++++ js/textbox/interactive/InteractiveTextbox.svelte | 2 ++ js/textbox/shared/Textbox.svelte | 9 +++++---- js/textbox/static/StaticTextbox.svelte | 2 ++ test/test_components.py | 1 + 6 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 .changeset/curly-files-know.md diff --git a/.changeset/curly-files-know.md b/.changeset/curly-files-know.md new file mode 100644 index 0000000000..88b78faef2 --- /dev/null +++ b/.changeset/curly-files-know.md @@ -0,0 +1,6 @@ +--- +"@gradio/textbox": minor +"gradio": minor +--- + +feat:Adds `autoscroll` param to `gr.Textbox()` diff --git a/gradio/components/textbox.py b/gradio/components/textbox.py index 36be39e946..dfd1ad85c4 100644 --- a/gradio/components/textbox.py +++ b/gradio/components/textbox.py @@ -67,6 +67,7 @@ class Textbox( visible: bool = True, elem_id: str | None = None, autofocus: bool = False, + autoscroll: bool = True, elem_classes: list[str] | str | None = None, type: Literal["text", "password", "email"] = "text", text_align: Literal["left", "right"] | None = None, @@ -96,6 +97,7 @@ class Textbox( text_align: How to align the text in the textbox, can be: "left", "right", or None (default). If None, the alignment is left if `rtl` is False, or right if `rtl` is True. Can only be changed if `type` is "text". rtl: If True and `type` is "text", sets the direction of the text to right-to-left (cursor appears on the left of the text). Default is False, which renders cursor on the right. show_copy_button: If True, includes a copy button to copy the text in the textbox. Only applies if show_label is True. + autoscroll: If True, will automatically scroll to the bottom of the textbox when the value changes. """ if type not in ["text", "password", "email"]: raise ValueError('`type` must be one of "text", "password", or "email".') @@ -109,6 +111,7 @@ class Textbox( self.show_copy_button = show_copy_button self.autofocus = autofocus self.select: EventListenerMethod + self.autoscroll = autoscroll """ Event listener for when the user selects text in the Textbox. Uses event data gradio.SelectData to carry `value` referring to selected substring, and `index` tuple referring to selected range endpoints. @@ -147,6 +150,7 @@ class Textbox( "container": self.container, "text_align": self.text_align, "rtl": self.rtl, + "autoscroll": self.autoscroll, **IOComponent.get_config(self), } @@ -169,6 +173,7 @@ class Textbox( rtl: bool | None = None, show_copy_button: bool | None = None, autofocus: bool | None = None, + autoscroll: bool | None = None, ): return { "lines": lines, @@ -188,6 +193,7 @@ class Textbox( "autofocus": autofocus, "text_align": text_align, "rtl": rtl, + "autoscroll": autoscroll, "__type__": "update", } diff --git a/js/textbox/interactive/InteractiveTextbox.svelte b/js/textbox/interactive/InteractiveTextbox.svelte index da858bf3bc..0e2add2d6c 100644 --- a/js/textbox/interactive/InteractiveTextbox.svelte +++ b/js/textbox/interactive/InteractiveTextbox.svelte @@ -49,6 +49,7 @@ export let rtl = false; export let text_align: "left" | "right" | undefined = undefined; export let autofocus = false; + export let autoscroll = true; gradio.dispatch("change", value)} on:input={() => gradio.dispatch("input")} on:submit={() => gradio.dispatch("submit")} diff --git a/js/textbox/shared/Textbox.svelte b/js/textbox/shared/Textbox.svelte index 6fde48d0a5..c00a162b80 100644 --- a/js/textbox/shared/Textbox.svelte +++ b/js/textbox/shared/Textbox.svelte @@ -26,11 +26,12 @@ export let rtl = false; export let autofocus = false; export let text_align: "left" | "right" | undefined = undefined; + export let autoscroll = true; let el: HTMLTextAreaElement | HTMLInputElement; let copied = false; let timer: NodeJS.Timeout; - let autoscroll: boolean; + let can_scroll: boolean; $: value, el && lines !== max_lines && resize({ target: el }); @@ -46,11 +47,11 @@ }>(); beforeUpdate(() => { - autoscroll = el && el.offsetHeight + el.scrollTop > el.scrollHeight - 100; + can_scroll = el && el.offsetHeight + el.scrollTop > el.scrollHeight - 100; }); const scroll = (): void => { - if (autoscroll) { + if (can_scroll && autoscroll) { el.scrollTo(0, el.scrollHeight); } }; @@ -62,7 +63,7 @@ } } afterUpdate(() => { - if (autoscroll) { + if (can_scroll && autoscroll) { scroll(); } value_is_output = false; diff --git a/js/textbox/static/StaticTextbox.svelte b/js/textbox/static/StaticTextbox.svelte index e744d2481b..bbd1262f9a 100644 --- a/js/textbox/static/StaticTextbox.svelte +++ b/js/textbox/static/StaticTextbox.svelte @@ -35,6 +35,7 @@ export let rtl = false; export let text_align: "left" | "right" | undefined = undefined; export let autofocus = false; + export let autoscroll = true; gradio.dispatch("change", value)} on:input={() => gradio.dispatch("input")} on:submit={() => gradio.dispatch("submit")} diff --git a/test/test_components.py b/test/test_components.py index 083f53a2d7..677d0cb04a 100644 --- a/test/test_components.py +++ b/test/test_components.py @@ -106,6 +106,7 @@ class TestTextbox: "rtl": False, "text_align": None, "autofocus": False, + 'autoscroll': True, } @pytest.mark.asyncio