diff --git a/.changeset/chat-tag-filter-padding.md b/.changeset/chat-tag-filter-padding.md new file mode 100644 index 0000000000..f5f388fbad --- /dev/null +++ b/.changeset/chat-tag-filter-padding.md @@ -0,0 +1,7 @@ +--- +"@runfusion/fusion": patch +--- + +summary: Give the chat sidebar tag filter proper inner padding so "All tags" is not cramped. +category: fix +dev: Updates `.chat-tag-filter select` padding in ChatView.css to `var(--space-sm) var(--space-md)`; pinned by a stylesheet-source regression test. diff --git a/packages/dashboard/app/components/ChatView.css b/packages/dashboard/app/components/ChatView.css index 7c60c18012..a2ed978016 100644 --- a/packages/dashboard/app/components/ChatView.css +++ b/packages/dashboard/app/components/ChatView.css @@ -2486,9 +2486,15 @@ Thinking-section text uses the defined muted text token across all themes. The m border-color: color-mix(in srgb, var(--color-warning) 55%, transparent); } -/* FNXC:ChatTags 2026-08-05-10:55: shared ChatView hosts expose Direct-only tag filters and compact chips without introducing a second sidebar layout. */ +/* +FNXC:ChatTags 2026-08-05-10:55: +Shared ChatView hosts expose Direct-only tag filters and compact chips without introducing a second sidebar layout. + +FNXC:ChatTags 2026-08-23-15:51: +The tag filter select must use the sibling sidebar search input's comfortable token-based inner padding so "All tags" is not flush against its border across desktop, narrow, and mobile hosts. +*/ .chat-tag-filter { display: flex; align-items: center; gap: var(--space-xs); color: var(--text-muted); } -.chat-tag-filter select { flex: 1; min-width: 0; border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--bg); color: var(--text); padding: var(--space-xs); } +.chat-tag-filter select { flex: 1; min-width: 0; border: 1px solid var(--border); border-radius: var(--radius-md); background: var(--bg); color: var(--text); padding: var(--space-sm) var(--space-md); } .chat-session-tags { display: flex; flex-wrap: wrap; gap: var(--space-xs); overflow: hidden; } .chat-session-tag { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; padding: 0 var(--space-xs); border-radius: var(--radius-sm); background: var(--surface-2); color: var(--text-muted); font-size: var(--font-size-xs); } /* FNXC:ChatTags 2026-08-05-12:15: direct-conversation tag controls keep assignment, rename, and deletion in the existing context menu so shared Chat hosts do not grow another sidebar action row. */ diff --git a/packages/dashboard/app/components/__tests__/ChatView.tag-filter-padding.test.ts b/packages/dashboard/app/components/__tests__/ChatView.tag-filter-padding.test.ts new file mode 100644 index 0000000000..4b4e4c94cc --- /dev/null +++ b/packages/dashboard/app/components/__tests__/ChatView.tag-filter-padding.test.ts @@ -0,0 +1,60 @@ +import { readFileSync } from "node:fs"; +import { resolve } from "node:path"; +import { describe, expect, it } from "vitest"; + +/* +FNXC:ChatTags 2026-08-23-15:51: +The shared Direct-scope tag filter must preserve the sidebar search input's comfortable token-based padding in every ChatView host. jsdom does not compute cascaded external stylesheet padding, so this stylesheet-source assertion is the enforceable regression seam for the cramped "All tags" control. +*/ +const chatViewCss = readFileSync(resolve(__dirname, "../ChatView.css"), "utf8"); + +function uncomment(css: string): string { + return css.replace(/\/\*[\s\S]*?\*\//g, ""); +} + +function collectTagFilterBlocks(css: string): Array<{ selector: string; block: string }> { + const blocks: Array<{ selector: string; block: string }> = []; + const rulePattern = /([^{}]+)\{([^{}]*)\}/g; + + for (const match of uncomment(css).matchAll(rulePattern)) { + const selector = match[1].trim(); + if (selector.split(",").some((part) => part.trim().includes(".chat-tag-filter select"))) { + blocks.push({ selector, block: match[2] }); + } + } + + return blocks; +} + +function paddingDeclaration(block: string): string | undefined { + return block.match(/(?:^|;)\s*padding\s*:\s*([^;]+)/)?.[1]?.trim(); +} + +describe("ChatView tag filter padding", () => { + it("keeps the All tags select aligned with the sidebar search input across stylesheet rules", () => { + const blocks = collectTagFilterBlocks(chatViewCss); + expect(blocks.length).toBeGreaterThanOrEqual(1); + + const base = blocks.find(({ selector }) => selector === ".chat-tag-filter select"); + expect(base, "base .chat-tag-filter select rule must exist").toBeDefined(); + + const basePadding = paddingDeclaration(base!.block); + expect(basePadding).toContain("var(--space-sm)"); + expect(basePadding).toContain("var(--space-md)"); + + for (const { selector, block } of blocks) { + const padding = paddingDeclaration(block); + if (!padding) continue; + + expect(padding, `tag filter rule "${selector}" must not restore cramped padding`).not.toMatch( + /^var\(--space-xs\)$/, + ); + expect(padding, `tag filter rule "${selector}" must use design tokens, not raw dimensions or colors`).not.toMatch( + /(?:\d(?:\.\d+)?(?:px|rem)|#[0-9a-f]{3,8})/i, + ); + expect(padding, `tag filter rule "${selector}" must use only --space-* tokens`).toMatch( + /^var\(--space-[a-z0-9-]+\)(?:\s+var\(--space-[a-z0-9-]+\)){0,3}$/, + ); + } + }); +});