FN-7287: collapse custom shadcn color controls
Collapse dashboard shadcn color overrides behind an accessible shared toggle by default. - Add an icon-only expand/collapse affordance with aria state for the shared shadcn color picker. - Move reset and color override inputs into the expanded controls panel with responsive styling. - Cover collapsed and expanded picker behavior across theme selector surfaces. - Add a patch changeset for the dashboard theme control fix. Files changed: .changeset/fn-7287-collapse-shadcn-colors.md | 7 ++ .../dashboard/app/components/ShadcnColorPicker.css | 26 +++++- .../dashboard/app/components/ShadcnColorPicker.tsx | 104 +++++++++++++-------- .../__tests__/ShadcnColorPicker.test.tsx | 48 +++++++++- .../components/__tests__/ThemeDropdown.test.tsx | 11 +++ .../components/__tests__/ThemeSelector.test.tsx | 11 +++ 6 files changed, 163 insertions(+), 44 deletions(-) Fusion-Task-Id: FN-7287 Fusion-Task-Lineage: 315ef23e-07e1-473c-8187-a40d0516960e Co-authored-by: Fusion (runfusion.ai) <noreply@runfusion.ai>
This commit is contained in:
7
.changeset/fn-7287-collapse-shadcn-colors.md
Normal file
7
.changeset/fn-7287-collapse-shadcn-colors.md
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
---
|
||||||
|
"@runfusion/fusion": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
summary: Collapse custom shadcn color controls by default in dashboard theme surfaces.
|
||||||
|
category: fix
|
||||||
|
dev: Adds an accessible shared show/collapse affordance for the custom shadcn color picker.
|
||||||
@@ -14,6 +14,10 @@
|
|||||||
gap: var(--space-md);
|
gap: var(--space-md);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.shadcn-color-picker-heading {
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.shadcn-color-picker-title {
|
.shadcn-color-picker-title {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
color: var(--text);
|
color: var(--text);
|
||||||
@@ -27,6 +31,21 @@
|
|||||||
font-size: var(--font-size-xs);
|
font-size: var(--font-size-xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.shadcn-color-picker-toggle {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadcn-color-picker-controls-panel {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--space-sm);
|
||||||
|
}
|
||||||
|
|
||||||
|
.shadcn-color-picker-actions {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
.shadcn-color-picker-grid {
|
.shadcn-color-picker-grid {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(calc(var(--space-2xl) * 7), 1fr));
|
grid-template-columns: repeat(auto-fit, minmax(calc(var(--space-2xl) * 7), 1fr));
|
||||||
@@ -85,11 +104,16 @@
|
|||||||
@media (max-width: 768px) {
|
@media (max-width: 768px) {
|
||||||
.shadcn-color-picker-header,
|
.shadcn-color-picker-header,
|
||||||
.shadcn-color-picker-row,
|
.shadcn-color-picker-row,
|
||||||
.shadcn-color-picker-controls {
|
.shadcn-color-picker-controls,
|
||||||
|
.shadcn-color-picker-actions {
|
||||||
align-items: stretch;
|
align-items: stretch;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.shadcn-color-picker-toggle {
|
||||||
|
align-self: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
.shadcn-color-picker-grid {
|
.shadcn-color-picker-grid {
|
||||||
grid-template-columns: 1fr;
|
grid-template-columns: 1fr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { useMemo } from "react";
|
import { useId, useMemo, useState } from "react";
|
||||||
|
import { ChevronDown, ChevronUp } from "lucide-react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import {
|
import {
|
||||||
SHADCN_CUSTOM_COLOR_TOKENS,
|
SHADCN_CUSTOM_COLOR_TOKENS,
|
||||||
@@ -28,6 +29,9 @@ function toColorInputValue(value: string): string {
|
|||||||
/*
|
/*
|
||||||
FNXC:Theme 2026-06-20-18:38:
|
FNXC:Theme 2026-06-20-18:38:
|
||||||
The shadcn custom picker is shared by Settings and Command Center; it only edits the sanitized token→hex override map while the parent surfaces decide visibility for shadcn-custom so no other theme receives inline overrides.
|
The shadcn custom picker is shared by Settings and Command Center; it only edits the sanitized token→hex override map while the parent surfaces decide visibility for shadcn-custom so no other theme receives inline overrides.
|
||||||
|
|
||||||
|
FNXC:Theme 2026-06-30-00:00:
|
||||||
|
Custom shadcn controls default collapsed to keep dashboard theme surfaces compact while leaving the override editor discoverable through an accessible icon affordance wherever this shared picker renders.
|
||||||
*/
|
*/
|
||||||
export function ShadcnColorPicker({
|
export function ShadcnColorPicker({
|
||||||
value = {},
|
value = {},
|
||||||
@@ -35,16 +39,23 @@ export function ShadcnColorPicker({
|
|||||||
resolvedThemeMode = "dark",
|
resolvedThemeMode = "dark",
|
||||||
}: ShadcnColorPickerProps) {
|
}: ShadcnColorPickerProps) {
|
||||||
const { t } = useTranslation("app");
|
const { t } = useTranslation("app");
|
||||||
|
const [expanded, setExpanded] = useState(false);
|
||||||
|
const controlsId = useId();
|
||||||
const sanitizedValue = useMemo(() => sanitizeShadcnCustomColors(value), [value]);
|
const sanitizedValue = useMemo(() => sanitizeShadcnCustomColors(value), [value]);
|
||||||
|
|
||||||
const updateToken = (cssVar: string, nextValue: string) => {
|
const updateToken = (cssVar: string, nextValue: string) => {
|
||||||
onChange(sanitizeShadcnCustomColors({ ...sanitizedValue, [cssVar]: nextValue }));
|
onChange(sanitizeShadcnCustomColors({ ...sanitizedValue, [cssVar]: nextValue }));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const toggleLabel = expanded
|
||||||
|
? t("theme.shadcnCustom.collapse", "Collapse custom colors")
|
||||||
|
: t("theme.shadcnCustom.show", "Show custom colors");
|
||||||
|
const ToggleIcon = expanded ? ChevronUp : ChevronDown;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section className="shadcn-color-picker card" data-testid="shadcn-color-picker" aria-labelledby="shadcn-color-picker-title">
|
<section className="shadcn-color-picker card" data-testid="shadcn-color-picker" aria-labelledby="shadcn-color-picker-title">
|
||||||
<div className="shadcn-color-picker-header">
|
<div className="shadcn-color-picker-header">
|
||||||
<div>
|
<div className="shadcn-color-picker-heading">
|
||||||
<h3 id="shadcn-color-picker-title" className="shadcn-color-picker-title">
|
<h3 id="shadcn-color-picker-title" className="shadcn-color-picker-title">
|
||||||
{t("theme.shadcnCustom.title", "Custom shadcn colors")}
|
{t("theme.shadcnCustom.title", "Custom shadcn colors")}
|
||||||
</h3>
|
</h3>
|
||||||
@@ -52,44 +63,61 @@ export function ShadcnColorPicker({
|
|||||||
{t("theme.shadcnCustom.description", "Override shadcn design tokens with hex colors. Blank tokens use the theme defaults.")}
|
{t("theme.shadcnCustom.description", "Override shadcn design tokens with hex colors. Blank tokens use the theme defaults.")}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" className="btn" onClick={() => onChange({})}>
|
<button
|
||||||
{t("theme.shadcnCustom.reset", "Reset custom colors")}
|
type="button"
|
||||||
|
className="btn btn-icon btn-sm shadcn-color-picker-toggle"
|
||||||
|
aria-expanded={expanded}
|
||||||
|
aria-controls={controlsId}
|
||||||
|
aria-label={toggleLabel}
|
||||||
|
title={toggleLabel}
|
||||||
|
onClick={() => setExpanded((current) => !current)}
|
||||||
|
>
|
||||||
|
<ToggleIcon size={16} aria-hidden="true" />
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="shadcn-color-picker-grid">
|
{expanded ? (
|
||||||
{SHADCN_CUSTOM_COLOR_TOKENS.map((token) => {
|
<div id={controlsId} className="shadcn-color-picker-controls-panel" data-testid="shadcn-color-picker-controls">
|
||||||
const fallback = getShadcnCustomDefaultValue(token, resolvedThemeMode);
|
<div className="shadcn-color-picker-actions">
|
||||||
const currentValue = sanitizedValue[token.cssVar] ?? fallback;
|
<button type="button" className="btn btn-sm" onClick={() => onChange({})}>
|
||||||
const inputId = `shadcn-color-${token.cssVar.replace(/^--/, "").replace(/[^a-z0-9]+/gi, "-")}`;
|
{t("theme.shadcnCustom.reset", "Reset custom colors")}
|
||||||
return (
|
</button>
|
||||||
<div className="shadcn-color-picker-row" key={token.cssVar} data-testid={`shadcn-color-${token.cssVar}`}>
|
</div>
|
||||||
<label className="shadcn-color-picker-label" htmlFor={inputId}>
|
<div className="shadcn-color-picker-grid">
|
||||||
<span>{t(`theme.shadcnCustom.token.${token.cssVar}`, token.label)}</span>
|
{SHADCN_CUSTOM_COLOR_TOKENS.map((token) => {
|
||||||
<code>{token.cssVar}</code>
|
const fallback = getShadcnCustomDefaultValue(token, resolvedThemeMode);
|
||||||
</label>
|
const currentValue = sanitizedValue[token.cssVar] ?? fallback;
|
||||||
<div className="shadcn-color-picker-controls">
|
const inputId = `shadcn-color-${token.cssVar.replace(/^--/, "").replace(/[^a-z0-9]+/gi, "-")}`;
|
||||||
<input
|
return (
|
||||||
aria-label={t("theme.shadcnCustom.colorInput", "Pick {{label}} color", { label: token.label })}
|
<div className="shadcn-color-picker-row" key={token.cssVar} data-testid={`shadcn-color-${token.cssVar}`}>
|
||||||
className="shadcn-color-picker-native"
|
<label className="shadcn-color-picker-label" htmlFor={inputId}>
|
||||||
type="color"
|
<span>{t(`theme.shadcnCustom.token.${token.cssVar}`, token.label)}</span>
|
||||||
value={toColorInputValue(currentValue)}
|
<code>{token.cssVar}</code>
|
||||||
onChange={(event) => updateToken(token.cssVar, event.currentTarget.value)}
|
</label>
|
||||||
/>
|
<div className="shadcn-color-picker-controls">
|
||||||
<input
|
<input
|
||||||
id={inputId}
|
aria-label={t("theme.shadcnCustom.colorInput", "Pick {{label}} color", { label: token.label })}
|
||||||
aria-label={t("theme.shadcnCustom.hexInput", "{{label}} hex color", { label: token.label })}
|
className="shadcn-color-picker-native"
|
||||||
className="input shadcn-color-picker-hex"
|
type="color"
|
||||||
type="text"
|
value={toColorInputValue(currentValue)}
|
||||||
inputMode="text"
|
onChange={(event) => updateToken(token.cssVar, event.currentTarget.value)}
|
||||||
spellCheck={false}
|
/>
|
||||||
value={currentValue}
|
<input
|
||||||
onChange={(event) => updateToken(token.cssVar, event.currentTarget.value)}
|
id={inputId}
|
||||||
/>
|
aria-label={t("theme.shadcnCustom.hexInput", "{{label}} hex color", { label: token.label })}
|
||||||
</div>
|
className="input shadcn-color-picker-hex"
|
||||||
</div>
|
type="text"
|
||||||
);
|
inputMode="text"
|
||||||
})}
|
spellCheck={false}
|
||||||
</div>
|
value={currentValue}
|
||||||
|
onChange={(event) => updateToken(token.cssVar, event.currentTarget.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,57 @@
|
|||||||
|
import { readFileSync } from "node:fs";
|
||||||
import { fireEvent, render, screen, within } from "@testing-library/react";
|
import { fireEvent, render, screen, within } from "@testing-library/react";
|
||||||
import { describe, expect, it, vi } from "vitest";
|
import { describe, expect, it, vi } from "vitest";
|
||||||
import { ShadcnColorPicker } from "../ShadcnColorPicker";
|
import { ShadcnColorPicker } from "../ShadcnColorPicker";
|
||||||
import { SHADCN_CUSTOM_COLOR_TOKENS } from "../shadcnCustomColors";
|
import { SHADCN_CUSTOM_COLOR_TOKENS } from "../shadcnCustomColors";
|
||||||
|
|
||||||
|
function expandCustomColors() {
|
||||||
|
const toggle = screen.getByRole("button", { name: "Show custom colors" });
|
||||||
|
expect(toggle).toHaveAttribute("aria-expanded", "false");
|
||||||
|
expect(toggle).toHaveAttribute("aria-controls");
|
||||||
|
fireEvent.click(toggle);
|
||||||
|
expect(screen.getByRole("button", { name: "Collapse custom colors" })).toHaveAttribute("aria-expanded", "true");
|
||||||
|
}
|
||||||
|
|
||||||
describe("ShadcnColorPicker", () => {
|
describe("ShadcnColorPicker", () => {
|
||||||
it("renders one color control row per customizable token", () => {
|
it("is collapsed by default and toggles all custom color controls without dangling shells", () => {
|
||||||
render(<ShadcnColorPicker value={{}} onChange={vi.fn()} resolvedThemeMode="dark" />);
|
render(<ShadcnColorPicker value={{}} onChange={vi.fn()} resolvedThemeMode="dark" />);
|
||||||
|
|
||||||
expect(screen.getByTestId("shadcn-color-picker")).toBeDefined();
|
expect(screen.getByTestId("shadcn-color-picker")).toBeDefined();
|
||||||
|
expect(screen.getByText("Custom shadcn colors")).toBeDefined();
|
||||||
|
expect(screen.getByText("Override shadcn design tokens with hex colors. Blank tokens use the theme defaults.")).toBeDefined();
|
||||||
|
expect(screen.queryByTestId("shadcn-color-picker-controls")).toBeNull();
|
||||||
|
expect(screen.queryByRole("button", { name: "Reset custom colors" })).toBeNull();
|
||||||
|
for (const token of SHADCN_CUSTOM_COLOR_TOKENS) {
|
||||||
|
expect(screen.queryByTestId(`shadcn-color-${token.cssVar}`)).toBeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
expandCustomColors();
|
||||||
|
expect(screen.getByTestId("shadcn-color-picker-controls")).toBeDefined();
|
||||||
|
expect(screen.getByRole("button", { name: "Reset custom colors" })).toBeDefined();
|
||||||
for (const token of SHADCN_CUSTOM_COLOR_TOKENS) {
|
for (const token of SHADCN_CUSTOM_COLOR_TOKENS) {
|
||||||
expect(screen.getByTestId(`shadcn-color-${token.cssVar}`)).toBeDefined();
|
expect(screen.getByTestId(`shadcn-color-${token.cssVar}`)).toBeDefined();
|
||||||
expect(screen.getByText(token.cssVar)).toBeDefined();
|
expect(screen.getByText(token.cssVar)).toBeDefined();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fireEvent.click(screen.getByRole("button", { name: "Collapse custom colors" }));
|
||||||
|
expect(screen.getByRole("button", { name: "Show custom colors" })).toHaveAttribute("aria-expanded", "false");
|
||||||
|
expect(screen.queryByTestId("shadcn-color-picker-controls")).toBeNull();
|
||||||
|
expect(screen.queryByRole("button", { name: "Reset custom colors" })).toBeNull();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("uses light defaults when no override exists", () => {
|
it("uses light defaults when no override exists after expansion", () => {
|
||||||
render(<ShadcnColorPicker value={{}} onChange={vi.fn()} resolvedThemeMode="light" />);
|
render(<ShadcnColorPicker value={{}} onChange={vi.fn()} resolvedThemeMode="light" />);
|
||||||
|
|
||||||
|
expandCustomColors();
|
||||||
const bgRow = screen.getByTestId("shadcn-color---bg");
|
const bgRow = screen.getByTestId("shadcn-color---bg");
|
||||||
expect(within(bgRow).getByRole("textbox")).toHaveValue("#ffffff");
|
expect(within(bgRow).getByRole("textbox")).toHaveValue("#ffffff");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("emits sanitized changes and rejects invalid hex input", () => {
|
it("emits sanitized changes and rejects invalid hex input after expansion", () => {
|
||||||
const onChange = vi.fn();
|
const onChange = vi.fn();
|
||||||
render(<ShadcnColorPicker value={{}} onChange={onChange} resolvedThemeMode="dark" />);
|
render(<ShadcnColorPicker value={{}} onChange={onChange} resolvedThemeMode="dark" />);
|
||||||
|
|
||||||
|
expandCustomColors();
|
||||||
const accentRow = screen.getByTestId("shadcn-color---accent");
|
const accentRow = screen.getByTestId("shadcn-color---accent");
|
||||||
fireEvent.change(within(accentRow).getByRole("textbox"), { target: { value: "red" } });
|
fireEvent.change(within(accentRow).getByRole("textbox"), { target: { value: "red" } });
|
||||||
expect(onChange).toHaveBeenLastCalledWith({});
|
expect(onChange).toHaveBeenLastCalledWith({});
|
||||||
@@ -33,18 +60,29 @@ describe("ShadcnColorPicker", () => {
|
|||||||
expect(onChange).toHaveBeenLastCalledWith({ "--accent": "#FF8800" });
|
expect(onChange).toHaveBeenLastCalledWith({ "--accent": "#FF8800" });
|
||||||
});
|
});
|
||||||
|
|
||||||
it("normalizes short hex values for the native color input", () => {
|
it("normalizes short hex values for the native color input after expansion", () => {
|
||||||
render(<ShadcnColorPicker value={{ "--accent": "#fff" }} onChange={vi.fn()} resolvedThemeMode="dark" />);
|
render(<ShadcnColorPicker value={{ "--accent": "#fff" }} onChange={vi.fn()} resolvedThemeMode="dark" />);
|
||||||
|
|
||||||
|
expandCustomColors();
|
||||||
const accentRow = screen.getByTestId("shadcn-color---accent");
|
const accentRow = screen.getByTestId("shadcn-color---accent");
|
||||||
expect(within(accentRow).getByLabelText("Pick Accent color")).toHaveValue("#ffffff");
|
expect(within(accentRow).getByLabelText("Pick Accent color")).toHaveValue("#ffffff");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("reset clears all custom color overrides", () => {
|
it("reset clears all custom color overrides after expansion", () => {
|
||||||
const onChange = vi.fn();
|
const onChange = vi.fn();
|
||||||
render(<ShadcnColorPicker value={{ "--accent": "#123456" }} onChange={onChange} resolvedThemeMode="dark" />);
|
render(<ShadcnColorPicker value={{ "--accent": "#123456" }} onChange={onChange} resolvedThemeMode="dark" />);
|
||||||
|
|
||||||
|
expect(screen.queryByRole("button", { name: "Reset custom colors" })).toBeNull();
|
||||||
|
expandCustomColors();
|
||||||
fireEvent.click(screen.getByRole("button", { name: "Reset custom colors" }));
|
fireEvent.click(screen.getByRole("button", { name: "Reset custom colors" }));
|
||||||
expect(onChange).toHaveBeenCalledWith({});
|
expect(onChange).toHaveBeenCalledWith({});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("keeps mobile collapsed and expanded layout rules tokenized", () => {
|
||||||
|
const css = readFileSync("app/components/ShadcnColorPicker.css", "utf8");
|
||||||
|
|
||||||
|
expect(css).toMatch(/@media \(max-width: 768px\) \{[\s\S]*?\.shadcn-color-picker-toggle \{[\s\S]*?align-self: flex-start;/);
|
||||||
|
expect(css).toMatch(/\.shadcn-color-picker-controls-panel \{[\s\S]*?gap: var\(--space-sm\);/);
|
||||||
|
expect(css).not.toMatch(/#[\da-f]{3,8}\b|rgb\(/i);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -77,6 +77,17 @@ describe("ThemeDropdown", () => {
|
|||||||
/>,
|
/>,
|
||||||
);
|
);
|
||||||
expect(screen.getByTestId("shadcn-color-picker")).toBeDefined();
|
expect(screen.getByTestId("shadcn-color-picker")).toBeDefined();
|
||||||
|
const showCustomColors = screen.getByRole("button", { name: "Show custom colors" });
|
||||||
|
expect(showCustomColors).toHaveAttribute("aria-expanded", "false");
|
||||||
|
expect(screen.queryByTestId("shadcn-color-picker-controls")).toBeNull();
|
||||||
|
expect(screen.queryByRole("button", { name: "Reset custom colors" })).toBeNull();
|
||||||
|
expect(screen.queryByTestId("shadcn-color---accent")).toBeNull();
|
||||||
|
|
||||||
|
fireEvent.click(showCustomColors);
|
||||||
|
expect(screen.getByRole("button", { name: "Collapse custom colors" })).toHaveAttribute("aria-expanded", "true");
|
||||||
|
expect(screen.getByTestId("shadcn-color-picker-controls")).toBeDefined();
|
||||||
|
const accentRow = screen.getByTestId("shadcn-color---accent");
|
||||||
|
expect(within(accentRow).getByRole("textbox")).toHaveValue("#123456");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("renders compact theme mode controls when mode props are supplied", () => {
|
it("renders compact theme mode controls when mode props are supplied", () => {
|
||||||
|
|||||||
@@ -644,6 +644,17 @@ describe("ThemeSelector", () => {
|
|||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
expect(screen.getByTestId("shadcn-color-picker")).toBeDefined();
|
expect(screen.getByTestId("shadcn-color-picker")).toBeDefined();
|
||||||
|
const showCustomColors = screen.getByRole("button", { name: "Show custom colors" });
|
||||||
|
expect(showCustomColors).toHaveAttribute("aria-expanded", "false");
|
||||||
|
expect(screen.queryByTestId("shadcn-color-picker-controls")).toBeNull();
|
||||||
|
expect(screen.queryByRole("button", { name: "Reset custom colors" })).toBeNull();
|
||||||
|
expect(screen.queryByTestId("shadcn-color---accent")).toBeNull();
|
||||||
|
|
||||||
|
fireEvent.click(showCustomColors);
|
||||||
|
expect(screen.getByRole("button", { name: "Collapse custom colors" })).toHaveAttribute("aria-expanded", "true");
|
||||||
|
expect(screen.getByTestId("shadcn-color-picker-controls")).toBeDefined();
|
||||||
|
const accentRow = screen.getByTestId("shadcn-color---accent");
|
||||||
|
expect(within(accentRow).getByRole("textbox")).toHaveValue("#123456");
|
||||||
expect(screen.getByLabelText("Shadcn Custom theme").getAttribute("aria-pressed")).toBe("true");
|
expect(screen.getByLabelText("Shadcn Custom theme").getAttribute("aria-pressed")).toBe("true");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user