feat(ui): select bileşenini geliştir
Scroll butonları, metin kısaltma ve genişlik ayarlamaları ekleyerek Select bileşenini daha kullanıcı dostu hale getirildi. TimerPage düzenlemesi yeni özelliklere uyum sağlamak için güncellendi.
This commit is contained in:
@@ -17,6 +17,21 @@ const ChevronDown = ({ className }: { className?: string }) => (
|
|||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const ChevronUp = ({ className }: { className?: string }) => (
|
||||||
|
<svg
|
||||||
|
viewBox="0 0 20 20"
|
||||||
|
fill="currentColor"
|
||||||
|
className={className}
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fillRule="evenodd"
|
||||||
|
d="M14.77 12.79a.75.75 0 0 1-1.06-.02L10 8.83l-3.71 3.94a.75.75 0 1 1-1.08-1.04l4.24-4.5a.75.75 0 0 1 1.08 0l4.24 4.5a.75.75 0 0 1-.02 1.06Z"
|
||||||
|
clipRule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
|
||||||
const Check = ({ className }: { className?: string }) => (
|
const Check = ({ className }: { className?: string }) => (
|
||||||
<svg
|
<svg
|
||||||
viewBox="0 0 20 20"
|
viewBox="0 0 20 20"
|
||||||
@@ -38,6 +53,8 @@ export const SelectGroup = SelectPrimitive.Group;
|
|||||||
|
|
||||||
export const SelectValue = SelectPrimitive.Value;
|
export const SelectValue = SelectPrimitive.Value;
|
||||||
|
|
||||||
|
export const SelectLabel = SelectPrimitive.Label;
|
||||||
|
|
||||||
export const SelectTrigger = React.forwardRef<
|
export const SelectTrigger = React.forwardRef<
|
||||||
React.ElementRef<typeof SelectPrimitive.Trigger>,
|
React.ElementRef<typeof SelectPrimitive.Trigger>,
|
||||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
|
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
|
||||||
@@ -45,12 +62,12 @@ export const SelectTrigger = React.forwardRef<
|
|||||||
<SelectPrimitive.Trigger
|
<SelectPrimitive.Trigger
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"flex h-10 items-center justify-between gap-2 rounded-md border border-slate-200 bg-white px-3 text-sm text-slate-700 shadow-sm transition focus:outline-none focus:ring-2 focus:ring-slate-300",
|
"flex h-10 w-full items-center justify-between gap-2 rounded-md border border-slate-200 bg-white px-3 text-sm text-slate-700 shadow-sm transition focus:outline-none focus:ring-2 focus:ring-slate-300 data-[placeholder]:text-slate-400",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
{children}
|
<span className="line-clamp-1">{children}</span>
|
||||||
<SelectPrimitive.Icon asChild>
|
<SelectPrimitive.Icon asChild>
|
||||||
<ChevronDown className="h-4 w-4 text-slate-400" />
|
<ChevronDown className="h-4 w-4 text-slate-400" />
|
||||||
</SelectPrimitive.Icon>
|
</SelectPrimitive.Icon>
|
||||||
@@ -58,28 +75,73 @@ export const SelectTrigger = React.forwardRef<
|
|||||||
));
|
));
|
||||||
SelectTrigger.displayName = "SelectTrigger";
|
SelectTrigger.displayName = "SelectTrigger";
|
||||||
|
|
||||||
|
export const SelectScrollUpButton = React.forwardRef<
|
||||||
|
React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<SelectPrimitive.ScrollUpButton
|
||||||
|
ref={ref}
|
||||||
|
className={clsx(
|
||||||
|
"flex cursor-default items-center justify-center py-1 text-slate-400",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<ChevronUp className="h-4 w-4" />
|
||||||
|
</SelectPrimitive.ScrollUpButton>
|
||||||
|
));
|
||||||
|
SelectScrollUpButton.displayName = "SelectScrollUpButton";
|
||||||
|
|
||||||
|
export const SelectScrollDownButton = React.forwardRef<
|
||||||
|
React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
|
||||||
|
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
|
||||||
|
>(({ className, ...props }, ref) => (
|
||||||
|
<SelectPrimitive.ScrollDownButton
|
||||||
|
ref={ref}
|
||||||
|
className={clsx(
|
||||||
|
"flex cursor-default items-center justify-center py-1 text-slate-400",
|
||||||
|
className
|
||||||
|
)}
|
||||||
|
{...props}
|
||||||
|
>
|
||||||
|
<ChevronDown className="h-4 w-4" />
|
||||||
|
</SelectPrimitive.ScrollDownButton>
|
||||||
|
));
|
||||||
|
SelectScrollDownButton.displayName = "SelectScrollDownButton";
|
||||||
|
|
||||||
export const SelectContent = React.forwardRef<
|
export const SelectContent = React.forwardRef<
|
||||||
React.ElementRef<typeof SelectPrimitive.Content>,
|
React.ElementRef<typeof SelectPrimitive.Content>,
|
||||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
|
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
|
||||||
>(({ className, children, position = "popper", ...props }, ref) => (
|
>(({ className, children, position = "popper", sideOffset = 4, ...props }, ref) => (
|
||||||
<SelectPrimitive.Portal>
|
<SelectPrimitive.Portal>
|
||||||
<SelectPrimitive.Content
|
<SelectPrimitive.Content
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border border-slate-200 bg-white text-slate-700 shadow-md",
|
"relative z-50 max-h-72 min-w-[8rem] overflow-hidden rounded-md border border-slate-200 bg-white text-slate-700 shadow-md",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
position={position}
|
position={position}
|
||||||
|
sideOffset={sideOffset}
|
||||||
{...props}
|
{...props}
|
||||||
>
|
>
|
||||||
<SelectPrimitive.Viewport className="p-1">
|
<SelectScrollUpButton />
|
||||||
|
<SelectPrimitive.Viewport
|
||||||
|
className={clsx(
|
||||||
|
"p-1",
|
||||||
|
position === "popper" &&
|
||||||
|
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
|
||||||
|
)}
|
||||||
|
>
|
||||||
{children}
|
{children}
|
||||||
</SelectPrimitive.Viewport>
|
</SelectPrimitive.Viewport>
|
||||||
|
<SelectScrollDownButton />
|
||||||
</SelectPrimitive.Content>
|
</SelectPrimitive.Content>
|
||||||
</SelectPrimitive.Portal>
|
</SelectPrimitive.Portal>
|
||||||
));
|
));
|
||||||
SelectContent.displayName = "SelectContent";
|
SelectContent.displayName = "SelectContent";
|
||||||
|
|
||||||
|
export const SelectSeparator = SelectPrimitive.Separator;
|
||||||
|
|
||||||
export const SelectItem = React.forwardRef<
|
export const SelectItem = React.forwardRef<
|
||||||
React.ElementRef<typeof SelectPrimitive.Item>,
|
React.ElementRef<typeof SelectPrimitive.Item>,
|
||||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
|
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
|
||||||
@@ -87,7 +149,7 @@ export const SelectItem = React.forwardRef<
|
|||||||
<SelectPrimitive.Item
|
<SelectPrimitive.Item
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={clsx(
|
className={clsx(
|
||||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-slate-100 data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-slate-100 data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -101,4 +163,3 @@ export const SelectItem = React.forwardRef<
|
|||||||
</SelectPrimitive.Item>
|
</SelectPrimitive.Item>
|
||||||
));
|
));
|
||||||
SelectItem.displayName = "SelectItem";
|
SelectItem.displayName = "SelectItem";
|
||||||
|
|
||||||
|
|||||||
@@ -337,44 +337,42 @@ export const TimerPage = () => {
|
|||||||
<div className="min-w-0 space-y-6">
|
<div className="min-w-0 space-y-6">
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
<div className="flex flex-wrap items-center justify-between gap-3">
|
<CardTitle className="flex items-center gap-2">
|
||||||
<CardTitle className="flex items-center gap-2">
|
<FontAwesomeIcon icon={faHourglassHalf} className="text-slate-400" />
|
||||||
<FontAwesomeIcon icon={faHourglassHalf} className="text-slate-400" />
|
Zamanlayıcı Torrentleri
|
||||||
Zamanlayıcı Torrentleri
|
</CardTitle>
|
||||||
</CardTitle>
|
<div className="flex items-center gap-2 text-xs font-semibold text-slate-500">
|
||||||
<div className="flex items-center gap-2 text-xs font-semibold text-slate-500">
|
<span>Sıralama</span>
|
||||||
<span>Sıralama</span>
|
<Select
|
||||||
<Select
|
value={sortKey}
|
||||||
value={sortKey}
|
onValueChange={(value) => {
|
||||||
onValueChange={(value) => {
|
if (value !== sortKey) {
|
||||||
if (value !== sortKey) {
|
setSortKey(value as typeof sortKey);
|
||||||
setSortKey(value as typeof sortKey);
|
setSortDirection("asc");
|
||||||
setSortDirection("asc");
|
}
|
||||||
}
|
}}
|
||||||
}}
|
>
|
||||||
>
|
<SelectTrigger className="h-9 w-[180px] text-xs">
|
||||||
<SelectTrigger className="h-9 min-w-[180px] text-xs">
|
<SelectValue />
|
||||||
<SelectValue />
|
</SelectTrigger>
|
||||||
</SelectTrigger>
|
<SelectContent align="end">
|
||||||
<SelectContent>
|
{sortOptions.map((option) => (
|
||||||
{sortOptions.map((option) => (
|
<SelectItem
|
||||||
<SelectItem
|
key={option.value}
|
||||||
key={option.value}
|
value={option.value}
|
||||||
value={option.value}
|
onClick={() => {
|
||||||
onClick={() => {
|
if (option.value === sortKey) {
|
||||||
if (option.value === sortKey) {
|
setSortDirection((current) =>
|
||||||
setSortDirection((current) =>
|
current === "asc" ? "desc" : "asc"
|
||||||
current === "asc" ? "desc" : "asc"
|
);
|
||||||
);
|
}
|
||||||
}
|
}}
|
||||||
}}
|
>
|
||||||
>
|
{option.label}
|
||||||
{option.label}
|
</SelectItem>
|
||||||
</SelectItem>
|
))}
|
||||||
))}
|
</SelectContent>
|
||||||
</SelectContent>
|
</Select>
|
||||||
</Select>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent className="space-y-4">
|
<CardContent className="space-y-4">
|
||||||
|
|||||||
Reference in New Issue
Block a user