diff --git a/.changeset/odd-bees-pay.md b/.changeset/odd-bees-pay.md
new file mode 100644
index 0000000000000..44673cebb20e1
--- /dev/null
+++ b/.changeset/odd-bees-pay.md
@@ -0,0 +1,8 @@
+---
+"@gradio/atoms": minor
+"@gradio/core": minor
+"@gradio/dataframe": minor
+"gradio": minor
+---
+
+feat:Allow sorting by multiple columns in dataframe
diff --git a/js/atoms/src/IconButton.svelte b/js/atoms/src/IconButton.svelte
index 7769eec5056e3..53a1581dfba0d 100644
--- a/js/atoms/src/IconButton.svelte
+++ b/js/atoms/src/IconButton.svelte
@@ -4,7 +4,7 @@
export let label = "";
export let show_label = false;
export let pending = false;
- export let size: "small" | "large" | "medium" = "small";
+ export let size: "x-small" | "small" | "large" | "medium" = "small";
export let padded = true;
export let highlight = false;
export let disabled = false;
@@ -30,6 +30,7 @@
>
{#if show_label}{label}{/if}
setTimeout(resolve, 500));
}}
/>
+
+ {
+ const canvas = within(canvasElement);
+ const user = userEvent.setup();
+
+ const header_1 = canvas.getAllByText("A")[1];
+ await userEvent.click(header_1);
+
+ const cell_menu_button = canvas.getAllByLabelText("Open cell menu")[0];
+ await userEvent.click(cell_menu_button);
+
+ const sort_ascending_button = canvas.getByRole("button", {
+ name: "Sort ascending"
+ });
+ await userEvent.click(sort_ascending_button);
+
+ const header_2 = canvas.getAllByText("B")[1];
+ await userEvent.click(header_2);
+
+ const cell_menu_button_2 = canvas.getAllByLabelText("Open cell menu")[1];
+ await userEvent.click(cell_menu_button_2);
+
+ const sort_descending_button = canvas.getByRole("button", {
+ name: "Sort descending"
+ });
+ await userEvent.click(sort_descending_button);
+
+ const header_3 = canvas.getAllByText("C")[1];
+ await userEvent.click(header_3);
+
+ const cell_menu_button_3 = canvas.getAllByLabelText("Open cell menu")[2];
+ await userEvent.click(cell_menu_button_3);
+
+ const sort_ascending_button_3 = canvas.getByRole("button", {
+ name: "Sort ascending"
+ });
+ await userEvent.click(sort_ascending_button_3);
+
+ await userEvent.click(header_3);
+ await userEvent.click(cell_menu_button_3);
+ await userEvent.click(canvas.getByText("Clear sort"));
+ }}
+/>
diff --git a/js/dataframe/shared/CellMenu.svelte b/js/dataframe/shared/CellMenu.svelte
index 0a7b3b0707c2e..e1fc3ab869810 100644
--- a/js/dataframe/shared/CellMenu.svelte
+++ b/js/dataframe/shared/CellMenu.svelte
@@ -2,6 +2,7 @@
import { onMount } from "svelte";
import CellMenuIcons from "./CellMenuIcons.svelte";
import type { I18nFormatter } from "js/utils/src";
+ import type { SortDirection } from "./context/table_context";
export let x: number;
export let y: number;
@@ -16,6 +17,10 @@
export let on_delete_col: () => void;
export let can_delete_rows: boolean;
export let can_delete_cols: boolean;
+ export let on_sort: (direction: SortDirection) => void = () => {};
+ export let on_clear_sort: () => void = () => {};
+ export let sort_direction: SortDirection | null = null;
+ export let sort_priority: number | null = null;
export let i18n: I18nFormatter;
let menu_element: HTMLDivElement;
@@ -52,6 +57,33 @@