Files
myeasycms-v2/apps/dev-tool/app/components/components/story-select.tsx
Giancarlo Buomprisco ad427365c9 Storybook (#328)
* feat(docs): add interactive examples and API references for Button, Card, and LoadingFallback components
- Updated dependencies
- Set `retries` to a fixed value of 3 for consistent test retries across environments.
- Increased `timeout` from 60 seconds to 120 seconds to allow more time for tests to complete.
- Reduced `expect` timeout from 10 seconds to 5 seconds for quicker feedback on assertions.
2025-08-22 07:35:44 +08:00

166 lines
4.7 KiB
TypeScript

'use client';
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
} from '@kit/ui/select';
import { cn } from '@kit/ui/utils';
import type { SelectOption } from '../lib/story-utils';
interface StorySelectProps<T = string> {
value: T;
onValueChange: (value: T) => void;
options: SelectOption<T>[];
placeholder?: string;
className?: string;
}
export function StorySelect<T extends string = string>({
value,
onValueChange,
options,
placeholder,
className,
}: StorySelectProps<T>) {
const selectedOption = options.find((opt) => opt.value === value);
return (
<Select value={value} onValueChange={onValueChange}>
<SelectTrigger className={cn('min-h-[3.5rem] py-2', className)}>
<div className="flex w-full items-center">
{selectedOption ? (
<div
className={cn(
'flex w-full',
selectedOption.icon ? 'gap-3' : 'gap-0',
)}
>
{selectedOption.icon && (
<selectedOption.icon
className={cn(
'mt-0.5 h-4 w-4 flex-shrink-0',
selectedOption.color && `text-${selectedOption.color}`,
)}
/>
)}
<div className="flex min-w-0 flex-col gap-0.5">
<span className="text-sm leading-none font-medium">
{selectedOption.label}
</span>
<span className="text-muted-foreground text-xs leading-tight">
{selectedOption.description}
</span>
</div>
</div>
) : (
<span className="text-muted-foreground">{placeholder}</span>
)}
</div>
</SelectTrigger>
<SelectContent>
{options.map((option) => {
const Icon = option.icon;
return (
<SelectItem
key={option.value}
value={option.value}
className="min-h-[3.5rem] items-start py-2"
>
<div
className={cn(
'flex w-full',
Icon ? 'items-start gap-3' : 'items-center gap-0',
)}
>
{Icon && (
<Icon
className={cn(
'mt-0.5 h-4 w-4 flex-shrink-0',
option.color && `text-${option.color}`,
)}
/>
)}
<div className="flex min-w-0 flex-col gap-0.5">
<span className="text-sm leading-none font-medium">
{option.label}
</span>
<span className="text-muted-foreground text-xs leading-tight">
{option.description}
</span>
</div>
</div>
</SelectItem>
);
})}
</SelectContent>
</Select>
);
}
interface SimpleStorySelectProps<T = string> {
value: T;
onValueChange: (value: T) => void;
options: Array<{
value: T;
label: string;
description: string;
}>;
placeholder?: string;
className?: string;
}
export function SimpleStorySelect<T extends string = string>({
value,
onValueChange,
options,
placeholder,
className,
}: SimpleStorySelectProps<T>) {
const selectedOption = options.find((opt) => opt.value === value);
return (
<Select value={value} onValueChange={onValueChange}>
<SelectTrigger className={cn('min-h-[3rem] py-2', className)}>
<div className="flex w-full items-center">
{selectedOption ? (
<div className="flex flex-col items-start gap-0.5">
<span className="text-sm leading-none font-medium">
{selectedOption.label}
</span>
<span className="text-muted-foreground text-xs leading-tight">
{selectedOption.description}
</span>
</div>
) : (
<span className="text-muted-foreground">{placeholder}</span>
)}
</div>
</SelectTrigger>
<SelectContent>
{options.map((option) => (
<SelectItem
key={option.value}
value={option.value}
className="min-h-[3rem] items-start py-2"
>
<div className="flex flex-col items-start gap-0.5">
<span className="text-sm leading-none font-medium">
{option.label}
</span>
<span className="text-muted-foreground text-xs leading-tight">
{option.description}
</span>
</div>
</SelectItem>
))}
</SelectContent>
</Select>
);
}