From 4522def714c2a13ba7f7f1c3b24e1624cbea1c4e Mon Sep 17 00:00:00 2001 From: Pierre Bertet Date: Tue, 30 Apr 2024 15:50:15 +0100 Subject: [PATCH] UI kit: Button visual updates (#136) --- ...imary.fixture.tsx => 1. Large.fixture.tsx} | 2 +- ...tive.fixture.tsx => 2. Medium.fixture.tsx} | 2 +- ...ative.fixture.tsx => 3. Small.fixture.tsx} | 2 +- ...ondary.fixture.tsx => 4. Mini.fixture.tsx} | 2 +- frontend/uikit-gallery/src/Button/shared.tsx | 42 ++++----- frontend/uikit/src/Button/Button.tsx | 85 +++++++++++++------ frontend/uikit/src/Theme/Theme.tsx | 25 +++++- 7 files changed, 108 insertions(+), 52 deletions(-) rename frontend/uikit-gallery/src/Button/{1. Primary.fixture.tsx => 1. Large.fixture.tsx} (65%) rename frontend/uikit-gallery/src/Button/{3. Positive.fixture.tsx => 2. Medium.fixture.tsx} (65%) rename frontend/uikit-gallery/src/Button/{4. Negative.fixture.tsx => 3. Small.fixture.tsx} (65%) rename frontend/uikit-gallery/src/Button/{2. Secondary.fixture.tsx => 4. Mini.fixture.tsx} (64%) diff --git a/frontend/uikit-gallery/src/Button/1. Primary.fixture.tsx b/frontend/uikit-gallery/src/Button/1. Large.fixture.tsx similarity index 65% rename from frontend/uikit-gallery/src/Button/1. Primary.fixture.tsx rename to frontend/uikit-gallery/src/Button/1. Large.fixture.tsx index 522636b7..b95a637f 100644 --- a/frontend/uikit-gallery/src/Button/1. Primary.fixture.tsx +++ b/frontend/uikit-gallery/src/Button/1. Large.fixture.tsx @@ -3,5 +3,5 @@ import { ButtonFixture } from "./shared"; export default function Fixture() { - return ; + return ; } diff --git a/frontend/uikit-gallery/src/Button/3. Positive.fixture.tsx b/frontend/uikit-gallery/src/Button/2. Medium.fixture.tsx similarity index 65% rename from frontend/uikit-gallery/src/Button/3. Positive.fixture.tsx rename to frontend/uikit-gallery/src/Button/2. Medium.fixture.tsx index 311f260f..929b948c 100644 --- a/frontend/uikit-gallery/src/Button/3. Positive.fixture.tsx +++ b/frontend/uikit-gallery/src/Button/2. Medium.fixture.tsx @@ -3,5 +3,5 @@ import { ButtonFixture } from "./shared"; export default function Fixture() { - return ; + return ; } diff --git a/frontend/uikit-gallery/src/Button/4. Negative.fixture.tsx b/frontend/uikit-gallery/src/Button/3. Small.fixture.tsx similarity index 65% rename from frontend/uikit-gallery/src/Button/4. Negative.fixture.tsx rename to frontend/uikit-gallery/src/Button/3. Small.fixture.tsx index d63fffa6..2d526461 100644 --- a/frontend/uikit-gallery/src/Button/4. Negative.fixture.tsx +++ b/frontend/uikit-gallery/src/Button/3. Small.fixture.tsx @@ -3,5 +3,5 @@ import { ButtonFixture } from "./shared"; export default function Fixture() { - return ; + return ; } diff --git a/frontend/uikit-gallery/src/Button/2. Secondary.fixture.tsx b/frontend/uikit-gallery/src/Button/4. Mini.fixture.tsx similarity index 64% rename from frontend/uikit-gallery/src/Button/2. Secondary.fixture.tsx rename to frontend/uikit-gallery/src/Button/4. Mini.fixture.tsx index 1634664e..97e75ebd 100644 --- a/frontend/uikit-gallery/src/Button/2. Secondary.fixture.tsx +++ b/frontend/uikit-gallery/src/Button/4. Mini.fixture.tsx @@ -3,5 +3,5 @@ import { ButtonFixture } from "./shared"; export default function Fixture() { - return ; + return ; } diff --git a/frontend/uikit-gallery/src/Button/shared.tsx b/frontend/uikit-gallery/src/Button/shared.tsx index 9ede4bf6..613ae382 100644 --- a/frontend/uikit-gallery/src/Button/shared.tsx +++ b/frontend/uikit-gallery/src/Button/shared.tsx @@ -1,38 +1,40 @@ "use client"; import { Button } from "@liquity2/uikit"; -import { useFixtureInput, useFixtureSelect } from "react-cosmos/client"; +import { useFixtureInput } from "react-cosmos/client"; + +const modes = ["primary", "secondary", "tertiary", "positive", "negative"] as const; export function ButtonFixture({ - defaultMode, + size, }: { - defaultMode: "primary" | "secondary" | "positive" | "negative"; + size: "mini" | "small" | "medium" | "large"; }) { - const [label] = useFixtureInput("label", "Button"); - const [mode] = useFixtureSelect("mode", { - options: ["primary", "secondary", "positive", "negative"], - defaultValue: defaultMode, - }); - const [size] = useFixtureSelect("size", { - options: ["medium", "large"], - defaultValue: "medium", - }); const [wide] = useFixtureInput("wide", false); + const [disabled] = useFixtureInput("disabled", false); return (
-
); } diff --git a/frontend/uikit/src/Button/Button.tsx b/frontend/uikit/src/Button/Button.tsx index 0b368a9c..6cb66dd9 100644 --- a/frontend/uikit/src/Button/Button.tsx +++ b/frontend/uikit/src/Button/Button.tsx @@ -1,6 +1,6 @@ import type { ComponentPropsWithoutRef } from "react"; -import { match } from "ts-pattern"; +import { match, P } from "ts-pattern"; import { css } from "../../styled-system/css"; import { useTheme } from "../Theme/Theme"; @@ -12,66 +12,95 @@ export function Button({ mode = "secondary", ...props }: ComponentPropsWithoutRef<"button"> & { - size?: "medium" | "large"; + size?: "mini" | "small" | "medium" | "large"; label: string; maxWidth?: number; wide?: boolean; - mode?: "primary" | "secondary" | "positive" | "negative"; + mode?: "primary" | "secondary" | "tertiary" | "positive" | "negative"; }) { const { color } = useTheme(); const geometry = match(size) + .with("mini", () => ({ + height: 26, + padding: "0 6px", + fontSize: 14, + borderRadius: 8, + })) + .with("small", () => ({ + height: 34, + padding: "0 8px", + fontSize: 14, + borderRadius: 8, + })) .with("medium", () => ({ height: 40, - padding: "0 16px", - fontSize: 14, + padding: "0 14px", + fontSize: 16, borderRadius: 20, })) .with("large", () => ({ height: 74, - padding: "0 32px", + padding: "0 30px", fontSize: 24, borderRadius: 120, })) .exhaustive(); const colors = match(mode) - .with("secondary", () => ({ - color: color("secondaryContent"), - background: color("secondary"), - })) .with("primary", () => ({ - color: color("accentContent"), - background: color("accent"), + "--color": color("accentContent"), + "--background": color("accent"), + "--backgroundHover": color("accentHint"), + "--backgroundPressed": color("accentActive"), })) - .with("positive", () => ({ - color: color("positiveContent"), - background: color("positive"), + .with(P.union("secondary", "tertiary"), (mode) => ({ + "--color": color("secondaryContent"), + "--background": mode === "secondary" ? color("secondary") : "transparent", + "--backgroundHover": color("secondaryHint"), + "--backgroundPressed": color("secondaryActive"), })) .with("negative", () => ({ - color: color("negativeContent"), - background: color("negative"), + "--color": color("negativeContent"), + "--background": color("negative"), + "--backgroundHover": color("negativeHint"), + "--backgroundPressed": color("negativeActive"), + })) + .with("positive", () => ({ + "--color": color("positiveContent"), + "--background": color("positive"), + "--backgroundHover": color("positiveHint"), + "--backgroundPressed": color("positiveActive"), })) .exhaustive(); return ( ); } diff --git a/frontend/uikit/src/Theme/Theme.tsx b/frontend/uikit/src/Theme/Theme.tsx index 3fa3865b..38b44d7e 100644 --- a/frontend/uikit/src/Theme/Theme.tsx +++ b/frontend/uikit/src/Theme/Theme.tsx @@ -90,11 +90,19 @@ export const colors = { // The light theme, which is the only theme for now. These // colors are meant to be used by components via useTheme(), // so that the theme can be changed at runtime. + +// Some notes about naming conventions: +// - "xContent" is the color used over a "x" background (text, icons or outlines). +// - "xHint" is the color used to hint that "x" is interactive (generally on hover). +// - "xActive" is the color used to indicate that "x" is being interacted with (generally on press). +// - "xSurface" is the color used for the surface of "x" (generally the background). export const lightTheme = { name: "light" as const, colors: { accent: "blue:500", + accentActive: "blue:600", accentContent: "white", + accentHint: "blue:400", background: "white", content: "gray:950", contentAlt: "gray:600", @@ -105,14 +113,23 @@ export const lightTheme = { fieldSurface: "gray:50", focused: "blue:500", interactive: "blue:950", - negative: "red:400", + negative: "red:500", + negativeActive: "red:600", negativeContent: "white", - positive: "green:400", + negativeHint: "red:400", + positive: "green:500", + positiveActive: "green:600", positiveContent: "white", - secondary: "blue:950", - secondaryContent: "white", + positiveHint: "green:400", + secondary: "blue:50", + secondaryActive: "blue:200", + secondaryContent: "blue:500", + secondaryHint: "blue:100", selected: "blue:500", warning: "yellow:400", + disabledBorder: "gray:200", + disabledContent: "gray:500", + disabledSurface: "gray:50", } satisfies Record, } as const;