From 60ba00dd8f84e1595847b9c0f92bb1f3c0a11bb4 Mon Sep 17 00:00:00 2001 From: Johannes Kirschbauer Date: Tue, 5 Aug 2025 13:35:01 +0200 Subject: [PATCH] Select: add simple select dropdown for single select --- .../src/components/Select/Select.module.css | 88 +++++++++++++ .../src/components/Select/Select.stories.tsx | 71 +++++++++++ .../ui/src/components/Select/Select.tsx | 118 ++++++++++++++++++ 3 files changed, 277 insertions(+) create mode 100644 pkgs/clan-app/ui/src/components/Select/Select.module.css create mode 100644 pkgs/clan-app/ui/src/components/Select/Select.stories.tsx create mode 100644 pkgs/clan-app/ui/src/components/Select/Select.tsx diff --git a/pkgs/clan-app/ui/src/components/Select/Select.module.css b/pkgs/clan-app/ui/src/components/Select/Select.module.css new file mode 100644 index 000000000..bff926029 --- /dev/null +++ b/pkgs/clan-app/ui/src/components/Select/Select.module.css @@ -0,0 +1,88 @@ +.trigger { + @apply bg-def-1 flex flex-grow justify-between items-center gap-2 h-7 px-2 py-1; + @apply rounded-[4px]; + + &[data-expanded] { + @apply outline-def-2 outline-1 outline; + z-index: 40; + } + + &[data-highlighted] { + @apply outline outline-1 outline-inv-2 + } + + &:hover { + @apply bg-def-2; + + & .icon { + @apply bg-def-1 text-fg-def-1; + } + } + + &:active { + @apply bg-def-4; + + & .icon { + @apply bg-inv-4 text-fg-inv-1; + } + } + + &:focus-visible { + @apply outline-def-2 outline-1 outline; + } +} + +.icon { + @apply bg-def-2 rounded-sm; + @apply flex items-center justify-center h-[14px] w-[14px] p-[2px]; + &[data-disabled] { + @apply cursor-not-allowed; + } +} + +.options_content { + @apply bg-def-1 px-1 py-3 rounded-[4px] -mt-8 pt-10 -mx-1; + @apply outline-def-2 outline-1 outline; + + transform-origin: var(--kb-popper-content-transform-origin); + &[data-expanded] { + animation: overlayShow 250ms ease-out; + } + + /* Option elements (typically
  • ) */ + & [role="option"] { + @apply px-1 py-2 rounded-sm flex items-center gap-1 flex-shrink-0 ; + + &[data-highlighted], + &:focus-visible { + @apply outline outline-1 outline-inv-2 + } + + &:hover { + @apply bg-def-2; + } + + &:active { + @apply bg-def-4; + } + + } + + & [role="listbox"] { + &:focus-visible { + @apply outline-none; + } + } +} + + +@keyframes overlayShow { + from { + opacity: 0; + transform: scaleY(0.94); + } + to { + opacity: 1; + transform: scaleY(1); + } +} diff --git a/pkgs/clan-app/ui/src/components/Select/Select.stories.tsx b/pkgs/clan-app/ui/src/components/Select/Select.stories.tsx new file mode 100644 index 000000000..3890d998b --- /dev/null +++ b/pkgs/clan-app/ui/src/components/Select/Select.stories.tsx @@ -0,0 +1,71 @@ +import { TagProps } from "@/src/components/Tag/Tag"; +import { Meta, StoryContext, StoryObj } from "@kachurun/storybook-solid"; + +import { Select, SelectProps } from "./Select"; +import { Fieldset } from "../Form/Fieldset"; + +// const meta: Meta = { +// title: "Components/Select", +// component: Select, +// }; +const meta = { + title: "Components/Form/Select", + component: Select, + decorators: [ + (Story: StoryObj, context: StoryContext) => { + return ( +
    +
    + +
    +
    + ); + }, + ], +} satisfies Meta; + +export default meta; + +type Story = StoryObj; + +export const Default: Story = { + args: { + required: true, + label: { + label: "Select your pet", + description: "Choose your favorite pet from the list", + }, + options: [ + { value: "dog", label: "Doggy" }, + { value: "cat", label: "Catty" }, + { value: "fish", label: "Fishy" }, + { value: "bird", label: "Birdy" }, + { value: "hamster", label: "Hammy" }, + { value: "snake", label: "Snakey" }, + { value: "turtle", label: "Turtly" }, + ], + placeholder: "Select your pet", + }, +}; + +// +// {(field, input) => ( +//