From 6c3157819f6b421449597540ab4cc125d99f5f71 Mon Sep 17 00:00:00 2001 From: stavros-tomas Date: Thu, 21 May 2026 14:28:41 +0100 Subject: [PATCH 01/45] chore: add debug-storybook to the list of git ignored files --- .gitignore | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 85dd12e..e42d625 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,8 @@ -node_modules +.mypy_cache +.vscode build dist +node_modules storybook.log storybook-static -.mypy_cache -.vscode +debug-storybook.log From 14188f3d34bce2c93323225f58ff29e91b828da6 Mon Sep 17 00:00:00 2001 From: stavros-tomas Date: Thu, 21 May 2026 14:41:01 +0100 Subject: [PATCH 02/45] chore: pick stories from inside the src folder --- .storybook/main.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.storybook/main.ts b/.storybook/main.ts index 8f81623..3a6f575 100644 --- a/.storybook/main.ts +++ b/.storybook/main.ts @@ -1,5 +1,8 @@ const config = { - stories: ["../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)"], + stories: [ + "../stories/**/*.stories.@(js|jsx|mjs|ts|tsx)", + "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)" + ], addons: [ "@storybook/addon-links", @@ -20,10 +23,9 @@ const config = { typescript: { reactDocgen: "react-docgen-typescript" }, - previewBody: (body: any) => ` + previewBody: (body: any) => ` ${body} - ${ - `` From 5181f148b2851c5e6584ccf2f29ae94df770bc42 Mon Sep 17 00:00:00 2001 From: stavros-tomas Date: Thu, 21 May 2026 15:53:07 +0100 Subject: [PATCH 03/45] chore: reorder stuff --- src/shadcn/ui/accordion.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shadcn/ui/accordion.tsx b/src/shadcn/ui/accordion.tsx index 0eff067..5b8d849 100644 --- a/src/shadcn/ui/accordion.tsx +++ b/src/shadcn/ui/accordion.tsx @@ -1,8 +1,8 @@ "use client" -import * as React from "react" import * as AccordionPrimitive from "@radix-ui/react-accordion" import { ChevronDownIcon } from "@radix-ui/react-icons" +import * as React from "react" import { cn } from "../../utils/cn" @@ -54,4 +54,4 @@ const AccordionContent = React.forwardRef< )) AccordionContent.displayName = AccordionPrimitive.Content.displayName -export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } +export { Accordion, AccordionContent, AccordionItem, AccordionTrigger } From 1050fc6a43bd1462c4cb1498df6a8ed5f3ba734d Mon Sep 17 00:00:00 2001 From: stavros-tomas Date: Thu, 21 May 2026 16:13:49 +0100 Subject: [PATCH 04/45] chore: remove whitespace --- src/utils/darkMode.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/utils/darkMode.ts b/src/utils/darkMode.ts index 5942ab6..ac77f56 100644 --- a/src/utils/darkMode.ts +++ b/src/utils/darkMode.ts @@ -52,8 +52,7 @@ const subscribeToTheme = (callback: (state: {isDark: boolean, mode: Mode}) => vo }; export { - getTheme, + getTheme, setTheme, - subscribeToTheme, + subscribeToTheme }; - From 0a775cadb85264c7545c56624bdc410d60bb2fe5 Mon Sep 17 00:00:00 2001 From: stavros-tomas Date: Thu, 21 May 2026 17:27:00 +0100 Subject: [PATCH 05/45] chore: imports --- src/custom/multi-select/index.ts | 2 ++ src/index.ts | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 src/custom/multi-select/index.ts diff --git a/src/custom/multi-select/index.ts b/src/custom/multi-select/index.ts new file mode 100644 index 0000000..dbc4f76 --- /dev/null +++ b/src/custom/multi-select/index.ts @@ -0,0 +1,2 @@ +export { MultiSelect } from "./multi-select" +export type { MultiSelectOption, MultiSelectProps } from "./types" diff --git a/src/index.ts b/src/index.ts index 256d953..4ac0e3e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,3 +1,4 @@ +export * from "./custom/multi-select"; export * from "./custom/icons"; export * from "./custom/slide-in"; export * from "./custom/theme-selector"; @@ -38,4 +39,3 @@ export * from "./shadcn/ui/toggle-group"; export * from "./shadcn/ui/tooltip"; export * from "./tailwindTheme"; export * from "./utils"; - From 23c040bd711df4f6d56bcbe69f397564b08fa7d7 Mon Sep 17 00:00:00 2001 From: stavros-tomas Date: Thu, 21 May 2026 18:53:08 +0100 Subject: [PATCH 06/45] feat: multiselect label --- .../multi-select/multi-select-label.tsx | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 src/custom/multi-select/multi-select-label.tsx diff --git a/src/custom/multi-select/multi-select-label.tsx b/src/custom/multi-select/multi-select-label.tsx new file mode 100644 index 0000000..d652cf4 --- /dev/null +++ b/src/custom/multi-select/multi-select-label.tsx @@ -0,0 +1,31 @@ +"use client" + +import { Info } from "lucide-react" +import { Tooltip, TooltipContent, TooltipTrigger } from "../../shadcn/ui/tooltip" +import { cn } from "../../utils/cn" +import type { MultiSelectLabelProps } from "./types" + +export const MultiSelectLabel = ({ + htmlFor, + label, + tooltip, + position = "top", + icon: Icon, +}: MultiSelectLabelProps) => { + return ( +
+ {Icon && } + + {tooltip && ( + + + + + {tooltip} + + )} +
+ ) +} From a2ede79e26f38f7f14831cb52675d682b720d6e5 Mon Sep 17 00:00:00 2001 From: stavros-tomas Date: Thu, 21 May 2026 19:27:03 +0100 Subject: [PATCH 07/45] feat: multiselect trigger --- .../multi-select/multi-select-trigger.tsx | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/custom/multi-select/multi-select-trigger.tsx diff --git a/src/custom/multi-select/multi-select-trigger.tsx b/src/custom/multi-select/multi-select-trigger.tsx new file mode 100644 index 0000000..03ed881 --- /dev/null +++ b/src/custom/multi-select/multi-select-trigger.tsx @@ -0,0 +1,70 @@ +import { ChevronDown, ChevronUp, Loader2 } from "lucide-react" +import { forwardRef } from "react" +import { Badge } from "../../shadcn/ui/badge" +import { cn } from "../../utils/cn" + +import type { MultiSelectTriggerProps } from "./types" + +export const MultiSelectTrigger = forwardRef( + ({ + open, + value, + placeholder, + isLoading, + hasError, + showChips, + className, + ...props + }, ref) => ( + + ), +) +MultiSelectTrigger.displayName = "MultiSelectTrigger" From b7b71fec4b1714ed26326f942fd420e2d6ca90a5 Mon Sep 17 00:00:00 2001 From: stavros-tomas Date: Thu, 21 May 2026 19:27:47 +0100 Subject: [PATCH 08/45] feat: multiselect trigger formatting --- src/custom/multi-select/multi-select-trigger.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/custom/multi-select/multi-select-trigger.tsx b/src/custom/multi-select/multi-select-trigger.tsx index 03ed881..85407d9 100644 --- a/src/custom/multi-select/multi-select-trigger.tsx +++ b/src/custom/multi-select/multi-select-trigger.tsx @@ -55,6 +55,7 @@ export const MultiSelectTrigger = forwardRef )} +
{isLoading ? ( @@ -67,4 +68,5 @@ export const MultiSelectTrigger = forwardRef ), ) + MultiSelectTrigger.displayName = "MultiSelectTrigger" From 04082bf84ce1e29fa5fe8f87a60c2359a7da88f7 Mon Sep 17 00:00:00 2001 From: stavros-tomas Date: Fri, 22 May 2026 00:06:43 +0100 Subject: [PATCH 09/45] feat: multiselect list item --- src/custom/multi-select/index.ts | 2 +- .../multi-select/multi-select-list-item.tsx | 51 +++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 src/custom/multi-select/multi-select-list-item.tsx diff --git a/src/custom/multi-select/index.ts b/src/custom/multi-select/index.ts index dbc4f76..b3f5744 100644 --- a/src/custom/multi-select/index.ts +++ b/src/custom/multi-select/index.ts @@ -1,2 +1,2 @@ export { MultiSelect } from "./multi-select" -export type { MultiSelectOption, MultiSelectProps } from "./types" +export type { MultiSelectItem, MultiSelectProps } from "./types" diff --git a/src/custom/multi-select/multi-select-list-item.tsx b/src/custom/multi-select/multi-select-list-item.tsx new file mode 100644 index 0000000..c8aa006 --- /dev/null +++ b/src/custom/multi-select/multi-select-list-item.tsx @@ -0,0 +1,51 @@ +import { CheckIcon } from "@radix-ui/react-icons" + +import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../../shadcn/ui/tooltip" +import { cn } from "../../utils/cn" + +import type { MultiSelectListItemProps } from "./types" + +export const MultiSelectListItem = ({ + item, + isSelected, + isDisabled, + disabledTooltip, + renderOption, +}: MultiSelectListItemProps) => { + const itemContent = ( +
+
+ +
+ +
+ {renderOption ? ( + renderOption(item) + ) : ( + <> + {item.icon && } + {item.label} + + )} +
+
+ ) + + if (isDisabled) { + return ( + + + {itemContent} + {disabledTooltip} + + + ) + } + + return itemContent +} From 27f3190d13a5da3a02f37e965fe774ab0fbd4205 Mon Sep 17 00:00:00 2001 From: stavros-tomas Date: Fri, 22 May 2026 00:26:21 +0100 Subject: [PATCH 10/45] feat: multiselect list --- src/custom/multi-select/multi-select-list.tsx | 127 ++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 src/custom/multi-select/multi-select-list.tsx diff --git a/src/custom/multi-select/multi-select-list.tsx b/src/custom/multi-select/multi-select-list.tsx new file mode 100644 index 0000000..9b2f695 --- /dev/null +++ b/src/custom/multi-select/multi-select-list.tsx @@ -0,0 +1,127 @@ +import { Command as CommandPrimitive } from "cmdk" +import { Loader2, Search } from "lucide-react" +import { useCallback, useMemo } from "react" +import { Command, CommandEmpty, CommandGroup, CommandItem, CommandList, CommandSeparator } from "../../shadcn/ui/command" +import { cn } from "../../utils/cn" + +import { MultiSelectListItem } from "./multi-select-list-item" +import type { MultiSelectListProps } from "./types" + +export const MultiSelectList = ({ + inputValue, + isLoading, + items, + value, + searchPlaceholder, + emptySearchMessage, + isSearchVisible = true, + disabledTooltip, + clearAllText = "Clear All", + renderOption, + onInputChange, + onSelect, + onClearAll, +}: MultiSelectListProps) => { + const hasSearched = inputValue.length > 0 + + const selectedValues = useMemo( + () => new Set(value.map((v) => v.value)), + [value], + ) + + const handleItemSelect = useCallback( + (optionValue: string) => { + const option = items.find((o) => o.value === optionValue) + if (option) { + onSelect(option) + } + }, + [items, onSelect], + ) + + const screenReaderAnnouncement = isLoading ? "Loading options": "Search results" + + const isEmptyMessageVisible = !isLoading && hasSearched && items.length === 0 + + const SearchSection = () => { + if (!isSearchVisible) return null + + return ( +
+ + + + + {isLoading && } +
+ ) + } + + const ItemsSection = () => { + if (items.length === 0) return null + + return ( + + {items.map((option) => { + const isSelected = selectedValues.has(option.value) + const isDisabled = option.disabled === true + + return ( + + + + ) + })} + + ) + } + + const ClearAllSection = () => { + if (value.length === 0) return null + + return ( + <> + + + + {clearAllText} + + + + ) + } + + return ( + +
{screenReaderAnnouncement}
+ + + + { isEmptyMessageVisible && {emptySearchMessage} } + + + +
+ ) +} From fc25b384cb47d6a8390171efc9dd2a9f74e65c55 Mon Sep 17 00:00:00 2001 From: stavros-tomas Date: Fri, 22 May 2026 00:38:34 +0100 Subject: [PATCH 11/45] fix: multiselect list and label fixes --- .../multi-select/multi-select-label.tsx | 2 +- src/custom/multi-select/multi-select-list.tsx | 146 +++++++++--------- 2 files changed, 73 insertions(+), 75 deletions(-) diff --git a/src/custom/multi-select/multi-select-label.tsx b/src/custom/multi-select/multi-select-label.tsx index d652cf4..01f57c7 100644 --- a/src/custom/multi-select/multi-select-label.tsx +++ b/src/custom/multi-select/multi-select-label.tsx @@ -15,7 +15,7 @@ export const MultiSelectLabel = ({ return (
{Icon && } -