From dcb7e546cac6dbc30b53364a4cb39d40b9b146fe Mon Sep 17 00:00:00 2001 From: Brian McGee Date: Thu, 3 Jul 2025 16:57:27 +0100 Subject: [PATCH] feat(ui): flatten the Field pattern and introduce Orienter component --- pkgs/clan-app/ui/package-lock.json | 22 +++++++++ pkgs/clan-app/ui/package.json | 2 + .../components/v2/Button/Button.stories.tsx | 31 ++++++------ .../ui/src/components/v2/Divider/Divider.tsx | 7 ++- .../ui/src/components/v2/Form/Checkbox.css | 12 ++--- .../ui/src/components/v2/Form/Checkbox.tsx | 35 +++++++------- .../ui/src/components/v2/Form/Combobox.css | 16 +++---- .../ui/src/components/v2/Form/Combobox.tsx | 47 ++++++++++--------- .../ui/src/components/v2/Form/Field.css | 11 ----- .../ui/src/components/v2/Form/Field.tsx | 7 +-- .../ui/src/components/v2/Form/Orienter.css | 22 +++++++++ .../ui/src/components/v2/Form/Orienter.tsx | 20 ++++++++ .../ui/src/components/v2/Form/TextArea.tsx | 15 +++--- .../ui/src/components/v2/Form/TextInput.css | 6 --- .../ui/src/components/v2/Form/TextInput.tsx | 37 ++++++++------- pkgs/clan-app/ui/src/components/v2/shared.ts | 1 - 16 files changed, 169 insertions(+), 122 deletions(-) delete mode 100644 pkgs/clan-app/ui/src/components/v2/Form/Field.css create mode 100644 pkgs/clan-app/ui/src/components/v2/Form/Orienter.css create mode 100644 pkgs/clan-app/ui/src/components/v2/Form/Orienter.tsx delete mode 100644 pkgs/clan-app/ui/src/components/v2/shared.ts diff --git a/pkgs/clan-app/ui/package-lock.json b/pkgs/clan-app/ui/package-lock.json index 9835495b8..9343f78e3 100644 --- a/pkgs/clan-app/ui/package-lock.json +++ b/pkgs/clan-app/ui/package-lock.json @@ -43,9 +43,11 @@ "eslint": "^9.27.0", "eslint-plugin-tailwindcss": "^3.17.0", "eslint-plugin-unused-imports": "^4.1.4", + "extend": "^3.0.2", "http-server": "^14.1.1", "jsdom": "^26.1.0", "knip": "^5.61.2", + "markdown-to-jsx": "^7.7.10", "playwright": "~1.52.0", "postcss": "^8.4.38", "postcss-url": "^10.1.3", @@ -4529,6 +4531,13 @@ "node": ">=12.0.0" } }, + "node_modules/extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "dev": true, + "license": "MIT" + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -5684,6 +5693,19 @@ "node": ">=10" } }, + "node_modules/markdown-to-jsx": { + "version": "7.7.10", + "resolved": "https://registry.npmjs.org/markdown-to-jsx/-/markdown-to-jsx-7.7.10.tgz", + "integrity": "sha512-au62yyLyJukhC2P1TYi3uBi/RScGYai69uT72D8a048QH8rRj+yhND3C21GdZHE+6emtsf6Yqemcf//K+EIWDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "react": ">= 0.14.0" + } + }, "node_modules/math-intrinsics": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", diff --git a/pkgs/clan-app/ui/package.json b/pkgs/clan-app/ui/package.json index 65c77e3c0..6f0b3c45e 100644 --- a/pkgs/clan-app/ui/package.json +++ b/pkgs/clan-app/ui/package.json @@ -43,9 +43,11 @@ "eslint": "^9.27.0", "eslint-plugin-tailwindcss": "^3.17.0", "eslint-plugin-unused-imports": "^4.1.4", + "extend": "^3.0.2", "http-server": "^14.1.1", "jsdom": "^26.1.0", "knip": "^5.61.2", + "markdown-to-jsx": "^7.7.10", "playwright": "~1.52.0", "postcss": "^8.4.38", "postcss-url": "^10.1.3", diff --git a/pkgs/clan-app/ui/src/components/v2/Button/Button.stories.tsx b/pkgs/clan-app/ui/src/components/v2/Button/Button.stories.tsx index 0f02cfc3c..e86178276 100644 --- a/pkgs/clan-app/ui/src/components/v2/Button/Button.stories.tsx +++ b/pkgs/clan-app/ui/src/components/v2/Button/Button.stories.tsx @@ -144,7 +144,7 @@ export default meta; type Story = StoryObj; -const timeout = process.env.NODE_ENV === "test" ? 100 : 2000; +const timeout = process.env.NODE_ENV === "test" ? 500 : 2000; export const Primary: Story = { args: { @@ -158,12 +158,6 @@ export const Primary: Story = { } }), }, - parameters: { - test: { - // increase test timeout to allow for the loading action - mockTimers: true, - }, - }, play: async ({ canvas, step, userEvent, args }: StoryContext) => { const buttons = await canvas.findAllByRole("button"); @@ -195,16 +189,19 @@ export const Primary: Story = { await userEvent.click(button); // check the button has changed - await waitFor(async () => { - // the action handler should have been called - await expect(args.onAction).toHaveBeenCalled(); - // the button should have a loading class - await expect(button).toHaveClass("loading"); - // the loader should be visible - await expect(loader.clientWidth).toBeGreaterThan(0); - // the pointer should have changed to wait - await expect(getCursorStyle(button)).toEqual("wait"); - }); + await waitFor( + async () => { + // the action handler should have been called + await expect(args.onAction).toHaveBeenCalled(); + // the button should have a loading class + await expect(button).toHaveClass("loading"); + // the loader should be visible + await expect(loader.clientWidth).toBeGreaterThan(0); + // the pointer should have changed to wait + await expect(getCursorStyle(button)).toEqual("wait"); + }, + { timeout: timeout + 500 }, + ); // wait for the action handler to finish await waitFor( diff --git a/pkgs/clan-app/ui/src/components/v2/Divider/Divider.tsx b/pkgs/clan-app/ui/src/components/v2/Divider/Divider.tsx index d1cc9882b..08ef35734 100644 --- a/pkgs/clan-app/ui/src/components/v2/Divider/Divider.tsx +++ b/pkgs/clan-app/ui/src/components/v2/Divider/Divider.tsx @@ -1,15 +1,14 @@ import "./Divider.css"; import cx from "classnames"; -import { Orientation } from "@/src/components/v2/shared"; export interface DividerProps { inverted?: boolean; - orientation?: Orientation; + orientation?: "horizontal" | "vertical"; } export const Divider = (props: DividerProps) => { const inverted = props.inverted || false; - const orientation = props.orientation || "horizontal"; + const orientation = () => props.orientation || "horizontal"; - return
; + return
; }; diff --git a/pkgs/clan-app/ui/src/components/v2/Form/Checkbox.css b/pkgs/clan-app/ui/src/components/v2/Form/Checkbox.css index 924068121..40ef30eeb 100644 --- a/pkgs/clan-app/ui/src/components/v2/Form/Checkbox.css +++ b/pkgs/clan-app/ui/src/components/v2/Form/Checkbox.css @@ -1,10 +1,8 @@ -@import "./Field.css"; - div.form-field { &.checkbox { @apply items-start; - & > div.checkbox-control { + & div.checkbox-control { @apply w-5 h-5 rounded-sm bg-def-1 border border-inv-1 p-[0.0625rem]; &:hover { @@ -21,13 +19,9 @@ div.form-field { } } - &.horizontal.checkbox { - @apply items-center; - } - &.inverted { &.checkbox { - & > div.checkbox-control { + & div.checkbox-control { @apply bg-inv-1; &:hover, @@ -43,7 +37,7 @@ div.form-field { } &.s { - & > div.checkbox-control { + & div.checkbox-control { @apply w-4 h-4; } } diff --git a/pkgs/clan-app/ui/src/components/v2/Form/Checkbox.tsx b/pkgs/clan-app/ui/src/components/v2/Form/Checkbox.tsx index b7fa4ca8d..7a6b753d1 100644 --- a/pkgs/clan-app/ui/src/components/v2/Form/Checkbox.tsx +++ b/pkgs/clan-app/ui/src/components/v2/Form/Checkbox.tsx @@ -10,6 +10,7 @@ import { Label } from "./Label"; import { PolymorphicProps } from "@kobalte/core/polymorphic"; import "./Checkbox.css"; import { FieldProps } from "./Field"; +import { Orienter } from "./Orienter"; export type CheckboxProps = FieldProps & KCheckboxRootProps & { @@ -24,21 +25,23 @@ export const Checkbox = (props: CheckboxProps) => ( })} {...props} > -