Backend / staging cleanup, performance substrate, and create-flow polish #60
@@ -156,7 +156,7 @@ const Button = memo<ButtonProps>(
|
|||||||
// Note: State prop is informational for Figma alignment - actual state is handled by CSS pseudo-classes
|
// Note: State prop is informational for Figma alignment - actual state is handled by CSS pseudo-classes
|
||||||
// For now, we maintain existing behavior and state prop is for documentation/alignment purposes
|
// For now, we maintain existing behavior and state prop is for documentation/alignment purposes
|
||||||
|
|
||||||
const baseStyles = `inline-flex items-center justify-start box-border whitespace-nowrap shrink-0 ${sizeStyles[size]} rounded-[var(--radius-measures-radius-full)] ${fontStyles[size]} transition-all duration-500 ease-in-out cursor-pointer ${variantStyles[variant]} ${outlineStyles}`;
|
const baseStyles = `inline-flex items-center justify-start box-border whitespace-nowrap shrink-0 touch-manipulation [-webkit-tap-highlight-color:transparent] ${sizeStyles[size]} rounded-[var(--radius-measures-radius-full)] ${fontStyles[size]} transition-[transform,color,background-color,border-color,box-shadow,outline-color] duration-150 ease-out cursor-pointer ${variantStyles[variant]} ${outlineStyles}`;
|
||||||
const combinedStyles = `${baseStyles} ${className}`;
|
const combinedStyles = `${baseStyles} ${className}`;
|
||||||
|
|
||||||
const sharedA11y = {
|
const sharedA11y = {
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const Footer = memo(() => {
|
|||||||
const tChrome = useTranslation("controlsChrome");
|
const tChrome = useTranslation("controlsChrome");
|
||||||
|
|
||||||
const linkFocusClass =
|
const linkFocusClass =
|
||||||
"hover:opacity-80 active:opacity-60 focus:opacity-80 focus:outline-none focus:ring-2 focus:ring-[var(--color-content-default-primary)] focus:ring-offset-2 focus:ring-offset-[var(--color-surface-default-primary)] transition-opacity";
|
"touch-manipulation [-webkit-tap-highlight-color:transparent] hover:opacity-80 active:opacity-60 focus:opacity-80 focus:outline-none focus:ring-2 focus:ring-[var(--color-content-default-primary)] focus:ring-offset-2 focus:ring-offset-[var(--color-surface-default-primary)] transition-opacity duration-150 ease-out";
|
||||||
|
|
||||||
const bodyTextClass =
|
const bodyTextClass =
|
||||||
"text-[var(--color-content-default-primary)] font-inter text-base font-medium leading-5 tracking-[0%] lg:text-2xl lg:font-normal lg:leading-7";
|
"text-[var(--color-content-default-primary)] font-inter text-base font-medium leading-5 tracking-[0%] lg:text-2xl lg:font-normal lg:leading-7";
|
||||||
|
|||||||
@@ -53,6 +53,16 @@ describe("Button (behavioral tests)", () => {
|
|||||||
expect(handleClick).toHaveBeenCalledTimes(1);
|
expect(handleClick).toHaveBeenCalledTimes(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("uses fast transitions and touch-friendly press feedback", () => {
|
||||||
|
render(<Button buttonType="filled">Press me</Button>);
|
||||||
|
|
||||||
|
const button = screen.getByRole("button", { name: "Press me" });
|
||||||
|
expect(button.className).toContain("touch-manipulation");
|
||||||
|
expect(button.className).toContain("duration-150");
|
||||||
|
expect(button.className).not.toContain("duration-500");
|
||||||
|
expect(button.className).toContain("active:scale-[0.98]");
|
||||||
|
});
|
||||||
|
|
||||||
it("renders as a link when href is provided", () => {
|
it("renders as a link when href is provided", () => {
|
||||||
render(
|
render(
|
||||||
<Button href="/learn" buttonType="filled" palette="default">
|
<Button href="/learn" buttonType="filled" palette="default">
|
||||||
|
|||||||
Reference in New Issue
Block a user