Skip to content

Commit

Permalink
Expand and collapse dataframe cells (#10463)
Browse files Browse the repository at this point in the history
* - truncate long cell values
- add expand and collapse logic

* add changeset

* tweak

* add max_chars and single click expanding

* - fix test
- add story

* Update gradio/components/dataframe.py

Co-authored-by: Abubakar Abid <[email protected]>

---------

Co-authored-by: gradio-pr-bot <[email protected]>
Co-authored-by: Abubakar Abid <[email protected]>
  • Loading branch information
3 people authored Feb 3, 2025
1 parent ff5f976 commit ed7a091
Show file tree
Hide file tree
Showing 8 changed files with 109 additions and 14 deletions.
6 changes: 6 additions & 0 deletions .changeset/soft-insects-greet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@gradio/dataframe": minor
"gradio": minor
---

feat:Expand and collapse dataframe cells
3 changes: 3 additions & 0 deletions gradio/components/dataframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ def __init__(
show_fullscreen_button: bool = False,
show_copy_button: bool = False,
show_row_numbers: bool = False,
max_chars: int | None = None,
):
"""
Parameters:
Expand Down Expand Up @@ -129,6 +130,7 @@ def __init__(
show_fullscreen_button: If True, will show a button to view the values in the table in fullscreen mode.
show_copy_button: If True, will show a button to copy the table data to the clipboard.
show_row_numbers: If True, will display row numbers in a separate column.
max_chars: Maximum number of characters to display in each cell before truncating (single-clicking a cell value will still reveal the full content). If None, no truncation is applied.
"""
self.wrap = wrap
self.row_count = self.__process_counts(row_count)
Expand Down Expand Up @@ -165,6 +167,7 @@ def __init__(
self.show_fullscreen_button = show_fullscreen_button
self.show_copy_button = show_copy_button
self.show_row_numbers = show_row_numbers
self.max_chars = max_chars
super().__init__(
label=label,
every=every,
Expand Down
6 changes: 6 additions & 0 deletions gradio/templates.py
Original file line number Diff line number Diff line change
Expand Up @@ -606,6 +606,7 @@ def __init__(
column_widths: list[str | int] | None = None,
show_row_numbers: bool = False,
show_fullscreen_button: bool = False,
max_chars: int | None = None,
show_copy_button: bool = False,
):
super().__init__(
Expand Down Expand Up @@ -634,6 +635,7 @@ def __init__(
min_width=min_width,
show_row_numbers=show_row_numbers,
show_fullscreen_button=show_fullscreen_button,
max_chars=max_chars,
show_copy_button=show_copy_button,
)

Expand Down Expand Up @@ -679,6 +681,7 @@ def __init__(
column_widths: list[str | int] | None = None,
show_row_numbers: bool = False,
show_fullscreen_button: bool = True,
max_chars: int | None = None,
show_copy_button: bool = False,
):
super().__init__(
Expand Down Expand Up @@ -707,6 +710,7 @@ def __init__(
min_width=min_width,
show_row_numbers=show_row_numbers,
show_fullscreen_button=show_fullscreen_button,
max_chars=max_chars,
show_copy_button=show_copy_button,
)

Expand Down Expand Up @@ -752,6 +756,7 @@ def __init__(
column_widths: list[str | int] | None = None,
show_row_numbers: bool = False,
show_fullscreen_button: bool = True,
max_chars: int | None = None,
show_copy_button: bool = False,
):
super().__init__(
Expand Down Expand Up @@ -780,6 +785,7 @@ def __init__(
min_width=min_width,
show_row_numbers=show_row_numbers,
show_fullscreen_button=show_fullscreen_button,
max_chars=max_chars,
show_copy_button=show_copy_button,
)

Expand Down
28 changes: 28 additions & 0 deletions js/dataframe/Dataframe.stories.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,34 @@
}}
/>

<Story
name="Dataframe with truncated text"
args={{
values: [
[
"This is a very long text that should be truncated",
"Short text",
"Another very long text that needs truncation"
],
[
"Short",
"This text is also quite long and should be truncated as well",
"Medium length text here"
],
[
"Medium text",
"Brief",
"This is the longest text in the entire table and it should definitely be truncated"
]
],
headers: ["Column A", "Column B", "Column C"],
label: "Truncated Text Example",
max_chars: 20,
col_count: [3, "dynamic"],
row_count: [3, "dynamic"]
}}
/>

<Story
name="Dataframe with multiline headers"
args={{
Expand Down
2 changes: 2 additions & 0 deletions js/dataframe/Index.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
export let loading_status: LoadingStatus;
export let interactive: boolean;
export let show_fullscreen_button = false;
export let max_chars: number | undefined = undefined;
export let show_copy_button = false;
$: _headers = [...(value.headers || headers)];
Expand Down Expand Up @@ -106,6 +107,7 @@
stream_handler={(...args) => gradio.client.stream(...args)}
bind:value_is_output
{show_fullscreen_button}
{max_chars}
{show_copy_button}
/>
</Block>
59 changes: 52 additions & 7 deletions js/dataframe/shared/EditableCell.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,27 @@
export let line_breaks = true;
export let editable = true;
export let root: string;
export let max_chars: number | null = null;
const dispatch = createEventDispatcher();
let is_expanded = false;
export let el: HTMLInputElement | null;
$: _value = value;
function truncate_text(
text: string | number,
max_length: number | null = null
): string {
const str = String(text);
if (!max_length || str.length <= max_length) return str;
return str.slice(0, max_length) + "...";
}
$: display_text = is_expanded
? value
: truncate_text(display_value || value, max_chars);
function use_focus(node: HTMLInputElement): any {
if (clear_on_focus) {
_value = "";
Expand All @@ -52,11 +67,21 @@
function handle_keydown(event: KeyboardEvent): void {
if (event.key === "Enter") {
value = _value;
dispatch("blur");
if (edit) {
value = _value;
dispatch("blur");
} else if (!header) {
is_expanded = !is_expanded;
}
}
dispatch("keydown", event);
}
function handle_click(): void {
if (!edit && !header) {
is_expanded = !is_expanded;
}
}
</script>

{#if edit}
Expand All @@ -76,28 +101,31 @@
{/if}

<span
on:dblclick
tabindex="-1"
on:click={handle_click}
on:keydown={handle_keydown}
tabindex="0"
role="button"
class:edit
class:expanded={is_expanded}
class:multiline={header}
on:focus|preventDefault
style={styling}
class="table-cell-text"
data-editable={editable}
placeholder=" "
>
{#if datatype === "html"}
{@html value}
{@html display_text}
{:else if datatype === "markdown"}
<MarkdownCode
message={value.toLocaleString()}
message={display_text.toLocaleString()}
{latex_delimiters}
{line_breaks}
chatbot={false}
{root}
/>
{:else}
{editable ? value : display_value || value}
{editable ? display_text : display_value || display_text}
{/if}
</span>

Expand All @@ -118,13 +146,28 @@
span {
flex: 1 1 0%;
position: relative;
display: inline-block;
outline: none;
padding: var(--size-2);
-webkit-user-select: text;
-moz-user-select: text;
-ms-user-select: text;
user-select: text;
cursor: text;
width: 100%;
height: 100%;
}
input:where(:not(.header), [data-editable="true"]) {
width: calc(100% - var(--size-10));
}
span.expanded {
height: auto;
min-height: 100%;
white-space: pre-wrap;
word-break: break-word;
white-space: normal;
}
Expand All @@ -135,6 +178,8 @@
.header {
transform: translateX(0);
font-weight: var(--weight-bold);
white-space: normal;
word-break: break-word;
}
.edit {
Expand Down
17 changes: 10 additions & 7 deletions js/dataframe/shared/Table.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
export let show_fullscreen_button = false;
export let show_copy_button = false;
export let value_is_output = false;
export let max_chars: number | undefined = undefined;
let selected_cells: CellCoordinate[] = [];
$: selected_cells = [...selected_cells];
Expand Down Expand Up @@ -912,6 +913,7 @@
<div class="cell-wrap">
<div class="header-content">
<EditableCell
{max_chars}
bind:value={_headers[i].value}
bind:el={els[id].input}
{latex_delimiters}
Expand Down Expand Up @@ -1012,6 +1014,7 @@
}}
{clear_on_focus}
{root}
{max_chars}
/>
{#if editable && should_show_cell_menu([index, j], selected_cells, editable)}
<button
Expand Down Expand Up @@ -1216,11 +1219,11 @@
.cell-wrap {
display: flex;
align-items: center;
align-items: flex-start;
outline: none;
height: var(--size-full);
min-height: var(--size-9);
overflow: hidden;
position: relative;
height: auto;
}
.header-content {
Expand Down Expand Up @@ -1254,10 +1257,10 @@
padding: 0;
margin-right: var(--spacing-sm);
z-index: var(--layer-1);
}
.cell-menu-button:hover {
background-color: var(--color-bg-hover);
position: absolute;
right: var(--size-1);
top: 50%;
transform: translateY(-50%);
}
.cell-selected .cell-menu-button {
Expand Down
2 changes: 2 additions & 0 deletions test/components/test_dataframe.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ def test_component_functions(self):
"column_widths": [],
"show_fullscreen_button": False,
"show_copy_button": False,
"max_chars": None,
}
dataframe_input = gr.Dataframe()
output = dataframe_input.preprocess(DataframeData(**x_data))
Expand Down Expand Up @@ -103,6 +104,7 @@ def test_component_functions(self):
"line_breaks": True,
"column_widths": [],
"show_fullscreen_button": False,
"max_chars": None,
"show_copy_button": False,
}

Expand Down

0 comments on commit ed7a091

Please sign in to comment.