feat(ComboControl): Add tooltips and enhance intraction effects

This commit is contained in:
Ilia Mashkov
2026-01-24 15:37:06 +03:00
parent 3dce409034
commit 873b697e8c

View File

@@ -16,6 +16,11 @@ import {
Trigger as PopoverTrigger,
} from '$shared/shadcn/ui/popover';
import { Slider } from '$shared/shadcn/ui/slider';
import {
Content as TooltipContent,
Root as TooltipRoot,
Trigger as TooltipTrigger,
} from '$shared/shadcn/ui/tooltip';
import MinusIcon from '@lucide/svelte/icons/minus';
import PlusIcon from '@lucide/svelte/icons/plus';
import type { ChangeEventHandler } from 'svelte/elements';
@@ -71,61 +76,105 @@ const handleSliderChange = (newValue: number) => {
};
</script>
<ButtonGroupRoot class="bg-transparent border-none shadow-none">
<Button
variant="ghost"
class="hover:bg-white/50 bg-white/20 border-none"
size="icon"
aria-label={decreaseLabel}
onclick={control.decrease}
disabled={control.isAtMin}
>
<MinusIcon class="size-4" />
</Button>
<PopoverRoot>
<PopoverTrigger>
{#snippet child({ props })}
<Button
{...props}
variant="ghost"
class="hover:bg-white/50 bg-white/20 border-none"
size="icon"
aria-label={controlLabel}
>
{control.value}
</Button>
{/snippet}
</PopoverTrigger>
<PopoverContent class="w-auto p-4">
<div class="flex flex-col items-center gap-3">
<Slider
min={control.min}
max={control.max}
step={control.step}
value={sliderValue}
onValueChange={handleSliderChange}
type="single"
orientation="vertical"
class="h-48"
<TooltipRoot>
<ButtonGroupRoot class="bg-transparent border-none shadow-none">
<TooltipTrigger class="flex items-center">
<Button
variant="ghost"
class="
group relative border-none size-9
bg-white/20 hover:bg-white/60
transition-all duration-200 ease-out
will-change-transform
hover:-translate-y-0.5
active:translate-y-0 active:scale-95 active:shadow-none
cursor-pointer
disabled:opacity-50 disabled:pointer-events-none
"
size="icon"
onclick={control.decrease}
disabled={control.isAtMin}
aria-label={decreaseLabel}
>
<MinusIcon
class="
size-4 transition-all duration-200
stroke-slate-600/50
group-hover:stroke-indigo-500 group-hover:scale-110 group-hover:stroke-3
group-active:scale-90 group-active:-rotate-6
group-disabled:stroke-transparent
"
/>
<Input
value={control.value}
onchange={handleInputChange}
min={control.min}
max={control.max}
class="w-16 text-center"
</Button>
<PopoverRoot>
<PopoverTrigger>
{#snippet child({ props })}
<Button
{...props}
variant="ghost"
class="hover:bg-white/50 hover:font-bold bg-white/20 border-none duration-150 will-change-transform active:scale-95 cursor-pointer"
size="icon"
aria-label={controlLabel}
>
{control.value}
</Button>
{/snippet}
</PopoverTrigger>
<PopoverContent class="w-auto p-4">
<div class="flex flex-col items-center gap-3">
<Slider
min={control.min}
max={control.max}
step={control.step}
value={sliderValue}
onValueChange={handleSliderChange}
type="single"
orientation="vertical"
class="h-48"
/>
<Input
value={control.value}
onchange={handleInputChange}
min={control.min}
max={control.max}
class="w-16 text-center"
/>
</div>
</PopoverContent>
</PopoverRoot>
<Button
variant="ghost"
class="
group relative border-none size-9
bg-white/20 hover:bg-white/60
transition-all duration-200 ease-out
will-change-transform
hover:-translate-y-0.5
active:translate-y-0 active:scale-95 active:shadow-none
disabled:opacity-50 disabled:pointer-events-none
cursor-pointer
"
size="icon"
aria-label={increaseLabel}
onclick={control.increase}
disabled={control.isAtMax}
>
<PlusIcon
class="
size-4 transition-all duration-200
stroke-slate-600/50
group-hover:stroke-indigo-500 group-hover:scale-110 group-hover:stroke-3
group-active:scale-90 group-active:rotate-6
group-disabled:stroke-transparent
"
/>
</div>
</PopoverContent>
</PopoverRoot>
<Button
variant="ghost"
class="hover:bg-white/50 bg-white/20 border-none"
size="icon"
aria-label={increaseLabel}
onclick={control.increase}
disabled={control.isAtMax}
>
<PlusIcon class="size-4" />
</Button>
</ButtonGroupRoot>
</Button>
</TooltipTrigger>
</ButtonGroupRoot>
{#if controlLabel}
<TooltipContent>
{controlLabel}
</TooltipContent>
{/if}
</TooltipRoot>