From 38dd9ce33b1c0d49a53b6059ed64f0d175115150 Mon Sep 17 00:00:00 2001 From: Sarcastic-Soul Date: Tue, 22 Sep 2026 02:21:03 +0530 Subject: [PATCH] web: collapse right-side block buttons into one dropdown Three inline buttons for adding a code, metrics or diagram block crowd the row once more block types exist. Give BottomAction a dropdown path for two or more buttons, keeping the single-button inline path (used by LeftSideBlock) unchanged. Fixes oxynote#160 --- .../BottomAction.nuxt.test.ts | 38 ++++++++++++----- .../split-documentation/BottomAction.vue | 42 ++++++++++++++----- 2 files changed, 60 insertions(+), 20 deletions(-) diff --git a/web/app/components/editor/blocks/split-documentation/BottomAction.nuxt.test.ts b/web/app/components/editor/blocks/split-documentation/BottomAction.nuxt.test.ts index bda535e4..0a1de2d8 100644 --- a/web/app/components/editor/blocks/split-documentation/BottomAction.nuxt.test.ts +++ b/web/app/components/editor/blocks/split-documentation/BottomAction.nuxt.test.ts @@ -1,8 +1,10 @@ import type { VueWrapper } from "@vue/test-utils" -import { describe, it } from "vitest" +import { beforeEach, describe, it } from "vitest" import BottomAction from "./BottomAction.vue" import { + clearTeleportedOverlays, findButtonByText, + menuItem, mountUnderTooltipProvider, renderedIconNames, t, @@ -18,6 +20,11 @@ const CODE_KEY = "editor.split-documentation.right-side-bottom-action-buttons.add-code" const METRICS_KEY = "editor.split-documentation.right-side-bottom-action-buttons.add-metrics" +const TRIGGER_KEY = "editor.split-documentation.bottom-action-trigger-label" + +function openDropdown(wrapper: VueWrapper) { + return wrapper.get("[data-slot='dropdown-menu-trigger']").trigger("click") +} function mountAction(buttons: Record[]) { return mountUnderTooltipProvider(BottomAction, { props: { buttons } }) @@ -32,7 +39,9 @@ function clicks(wrapper: VueWrapper): unknown[] { return (action.emitted("button-click") ?? []).map((args) => args[0]) } -describe("", () => { +describe("", { concurrent: false }, () => { + beforeEach(clearTeleportedOverlays) + it("labels a button with its text", async ({ expect }) => { const wrapper = await mountAction([{ id: "params", text: t(PARAMS_KEY) }]) @@ -61,19 +70,26 @@ describe("", () => { expect(clicks(wrapper)).toEqual(["params"]) }) - it("renders one button per entry", async ({ expect }) => { + it("shows a single trigger for two or more entries", async ({ expect }) => { const wrapper = await mountAction([ { id: "code", text: t(CODE_KEY), icon: "lucide:code" }, { id: "metrics", text: t(METRICS_KEY) }, ]) - expect(wrapper.findAll("button")).toHaveLength(2) - expect(wrapper.text()).toContain(t(CODE_KEY)) - expect(wrapper.text()).toContain(t(METRICS_KEY)) - expect(renderedIconNames(wrapper)).toEqual([ - "lucide:code", - "lucide:circle-plus", + expect(wrapper.findAll("button")).toHaveLength(1) + expect(wrapper.text()).toContain(t(TRIGGER_KEY)) + }) + + it("lists every entry once the trigger is opened", async ({ expect }) => { + const wrapper = await mountAction([ + { id: "code", text: t(CODE_KEY), icon: "lucide:code" }, + { id: "metrics", text: t(METRICS_KEY) }, ]) + + await openDropdown(wrapper) + + expect(menuItem(t(CODE_KEY))).not.toBeNull() + expect(menuItem(t(METRICS_KEY))).not.toBeNull() }) it("reports a click on a later button with its own id", async ({ @@ -84,7 +100,9 @@ describe("", () => { { id: "metrics", text: t(METRICS_KEY) }, ]) - await findButtonByText(wrapper, t(METRICS_KEY)).trigger("click") + await openDropdown(wrapper) + menuItem(t(METRICS_KEY)).click() + await nextTick() expect(clicks(wrapper)).toEqual(["metrics"]) }) diff --git a/web/app/components/editor/blocks/split-documentation/BottomAction.vue b/web/app/components/editor/blocks/split-documentation/BottomAction.vue index f7b77cc9..9fe3241c 100644 --- a/web/app/components/editor/blocks/split-documentation/BottomAction.vue +++ b/web/app/components/editor/blocks/split-documentation/BottomAction.vue @@ -14,6 +14,8 @@ const emit = defineEmits<{ (e: "button-click", id: T): void }>() +const { t } = useI18n({ useScope: "global" }) + function handleClick(id: T) { emit("button-click", id) } @@ -36,22 +38,42 @@ function handleClick(id: T) { } " > - + {{ button.text }} + + +