diff --git a/src/content/market/plugin-toolbar.ts b/src/content/market/plugin-toolbar.ts index 41ade2f..b6fed94 100644 --- a/src/content/market/plugin-toolbar.ts +++ b/src/content/market/plugin-toolbar.ts @@ -730,42 +730,53 @@ function findNativeActionButton( function applyToolbarRootStyles(root: HTMLElement): void { root.style.display = "inline-flex"; root.style.alignItems = "center"; - root.style.columnGap = "8px"; - root.style.flexWrap = "wrap"; + root.style.columnGap = "10px"; + root.style.flex = "1 1 auto"; + root.style.minWidth = "0"; + root.style.flexWrap = "nowrap"; } function applyToolbarPanelStyles(panel: HTMLElement): void { panel.style.display = "flex"; panel.style.flexDirection = "column"; - panel.style.gap = "8px"; + panel.style.alignItems = "stretch"; + panel.style.gap = "6px"; + panel.style.flex = "1 1 auto"; panel.style.minWidth = "0"; - panel.style.padding = "4px 0"; + panel.style.padding = "2px 0"; + panel.style.overflowX = "visible"; + panel.style.overflowY = "hidden"; } function applyToolbarRowStyles(row: HTMLElement): void { row.style.display = "flex"; row.style.alignItems = "center"; - row.style.gap = "10px"; + row.style.justifyContent = "flex-start"; + row.style.gap = "6px"; row.style.minHeight = "32px"; row.style.minWidth = "0"; - row.style.flexWrap = "wrap"; + row.style.width = "100%"; + row.style.flexWrap = "nowrap"; } function applyToolbarGroupStyles(group: HTMLElement): void { group.style.display = "flex"; group.style.alignItems = "center"; - group.style.gap = "8px"; + group.style.gap = "6px"; group.style.minWidth = "0"; - group.style.flexWrap = "wrap"; + group.style.flex = "0 0 auto"; + group.style.flexWrap = "nowrap"; } function createToolbarGroupTitle(document: Document, label: string): HTMLElement { const title = document.createElement("span"); + title.dataset.pluginToolbarTitle = label; title.textContent = label; title.style.color = "#64748b"; title.style.fontSize = "12px"; title.style.fontWeight = "700"; title.style.lineHeight = "32px"; + title.style.flex = "0 0 auto"; title.style.whiteSpace = "nowrap"; return title; } @@ -781,7 +792,8 @@ function applyToolbarActionStyles(actions: HTMLElement): void { actions.style.display = "flex"; actions.style.alignItems = "center"; actions.style.gap = "8px"; - actions.style.paddingLeft = "12px"; + actions.style.flex = "0 0 auto"; + actions.style.paddingLeft = "10px"; actions.style.borderLeft = "1px solid #e5e7eb"; } @@ -839,10 +851,11 @@ function applyNativeControlStyles( element.style.height = "32px"; element.style.border = "1px solid #d0d7de"; element.style.borderRadius = "6px"; - element.style.padding = "0 10px"; + element.style.padding = "0 8px"; element.style.background = "#fff"; element.style.color = "#1f2329"; element.style.boxSizing = "border-box"; + element.style.flex = "0 0 auto"; }); controls.exportRangeSelect.style.minWidth = "104px"; @@ -854,7 +867,7 @@ function applyNativeControlStyles( controls.spreadFilterFlowTypeSelect, controls.spreadFilterRangeSelect ].forEach((select) => { - select.style.minWidth = "92px"; + select.style.minWidth = "84px"; }); Object.values(controls).forEach((element) => { @@ -863,7 +876,7 @@ function applyNativeControlStyles( element.dataset.pluginSpreadThreshold ) { element.style.width = - element.dataset.pluginSpreadThreshold === "playMedian" ? "112px" : "86px"; + element.dataset.pluginSpreadThreshold === "playMedian" ? "104px" : "78px"; } }); } diff --git a/tests/market-content-entry.test.ts b/tests/market-content-entry.test.ts index db5ed0d..ce1f072 100644 --- a/tests/market-content-entry.test.ts +++ b/tests/market-content-entry.test.ts @@ -384,6 +384,63 @@ describe("market-content-entry", () => { expect(audienceProfileByIdExportButton?.style.color).toBe("rgb(255, 255, 255)"); }); + test("keeps plugin filters in two compact aligned rows", async () => { + document.body.innerHTML = buildMarketFixture(); + + const { createMarketController } = await import("../src/content/market/index"); + const controller = trackController(createMarketController({ + document, + loadAuthorMetrics: async () => ({ + success: false, + reason: "request-failed" + }), + window + })); + + await controller.ready; + + const toolbar = document.querySelector( + '[data-plugin-toolbar="root"]' + ) as HTMLElement | null; + const panel = document.querySelector( + '[data-plugin-toolbar-panel="root"]' + ) as HTMLElement | null; + const rows = document.querySelectorAll("[data-plugin-toolbar-row]"); + const primaryRow = document.querySelector( + '[data-plugin-toolbar-row="primary"]' + ) as HTMLElement | null; + const thresholdRow = document.querySelector( + '[data-plugin-toolbar-row="thresholds"]' + ) as HTMLElement | null; + const dataGroup = document.querySelector( + '[data-plugin-toolbar-group="data"]' + ) as HTMLElement | null; + const videoGroup = document.querySelector( + '[data-plugin-toolbar-group="video"]' + ) as HTMLElement | null; + const thresholdGroup = document.querySelector( + '[data-plugin-toolbar-group="thresholds"]' + ) as HTMLElement | null; + const titles = Array.from(document.querySelectorAll("[data-plugin-toolbar-title]")) + .map((element) => element.textContent); + + expect(toolbar?.style.flexWrap).toBe("nowrap"); + expect(panel?.style.flexDirection).toBe("column"); + expect(panel?.style.alignItems).toBe("stretch"); + expect(panel?.style.padding).toBe("2px 0px"); + expect(panel?.style.overflowX).toBe("visible"); + expect(rows).toHaveLength(2); + expect(primaryRow?.style.flexWrap).toBe("nowrap"); + expect(thresholdRow?.style.flexWrap).toBe("nowrap"); + expect(dataGroup?.parentElement).toBe(primaryRow); + expect(videoGroup?.parentElement).toBe(primaryRow); + expect(thresholdGroup?.parentElement).toBe(thresholdRow); + expect(thresholdGroup?.style.flexWrap).toBe("nowrap"); + expect(primaryRow?.style.justifyContent).toBe("flex-start"); + expect(thresholdRow?.style.justifyContent).toBe("flex-start"); + expect(titles).toEqual(["达人数据", "视频口径", "传播指标"]); + }); + test("remounts the plugin action bar when the native market action row appears later", async () => { document.body.innerHTML = buildMarketTableOnlyFixture(); const observer = createMutationObserverFactory();