[READ-ONLY] Mirror of https://github.com/flo-bit/ui-kit. 🦊 fox ui, svelte 5 and tailwind 4 flo-bit.dev/ui-kit/
svelte tailwindcss ui-components
0

Configure Feed

Select the types of activity you want to include in your feed.

start gradient color picker

Florian (Mar 21, 2025, 3:14 AM +0100) e2dcc8e0 29b2ed49

+114 -3
+1 -1
src/docs/site-components/Cards.svelte
··· 44 44 </script> 45 45 46 46 <h2 class="text-base-800 dark:text-base-200 mb-4 text-xl font-semibold">Base components</h2> 47 - <div class="grid w-full grid-cols-1 gap-6 sm:grid-cols-2 md:grid-cols-3 md:gap-8 lg:grid-cols-4"> 47 + <div class="grid w-full grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3 lg:gap-8 xl:grid-cols-4"> 48 48 {#each baseComponents as card} 49 49 <div 50 50 class="group relative flex flex-col items-start gap-3 transition-opacity duration-150 hover:opacity-90 md:gap-4"
+101
src/lib/components/extra/color-gradient-picker/ColorGradientPicker.svelte
··· 1 + <script lang="ts"> 2 + import { cn } from '$lib'; 3 + import * as Popover from '$lib/components/base/popover'; 4 + import { 5 + ColorPicker, 6 + type OKhsv, 7 + type OKlab, 8 + type RGB 9 + } from '$lib/components/extra/color-picker/base'; 10 + import { type OKlch } from '../color-picker/base/color'; 11 + 12 + let { 13 + class: className, 14 + onchange 15 + }: { 16 + rgb?: RGB; 17 + oklab?: OKlab; 18 + okhsv?: OKhsv; 19 + class?: string; 20 + onchange?: (color: { hex: string; rgb: RGB; oklab: OKlab; okhsv: OKhsv; oklch: OKlch }) => void; 21 + } = $props(); 22 + 23 + type Color = { rgb: RGB; position: number }; 24 + 25 + let colors: Color[] = $state([ 26 + { rgb: { r: 0, g: 0, b: 0 }, position: 0 }, 27 + { rgb: { r: 1, g: 0, b: 0 }, position: 0.25 }, 28 + { rgb: { r: 0, g: 1, b: 0 }, position: 0.5 }, 29 + { rgb: { r: 0, g: 0, b: 1 }, position: 0.75 }, 30 + { rgb: { r: 1, g: 1, b: 0 }, position: 1 } 31 + ]); 32 + 33 + $effect(() => { 34 + colors.sort((a, b) => a.position - b.position); 35 + }); 36 + 37 + const gradientString = $derived( 38 + `linear-gradient(to right, ${colors 39 + .map(({ rgb, position }) => `rgb(${rgb.r * 255}, ${rgb.g * 255}, ${rgb.b * 255}) ${position * 100}%`) 40 + .join(', ')})` 41 + ); 42 + 43 + $inspect(gradientString); 44 + 45 + let activeColor: Color | undefined = $state(undefined); 46 + let activePosition: number | undefined = $state(undefined); 47 + let mouseDownPosition: number | undefined = $state(undefined); 48 + 49 + let gradientRef = $state<HTMLDivElement | undefined>(undefined); 50 + </script> 51 + 52 + <div 53 + class="relative h-8 w-full rounded-2xl border border-base-300 dark:border-base-700 touch-none" 54 + style={'background: ' + gradientString} 55 + bind:this={gradientRef} 56 + 57 + onpointermove={(evt) => { 58 + if (activeColor && activePosition !== undefined && mouseDownPosition !== undefined) { 59 + const delta = evt.clientX - mouseDownPosition; 60 + 61 + // get the gradient bounding box 62 + const gradientBoundingBox = gradientRef?.getBoundingClientRect(); 63 + let movement = delta / (gradientBoundingBox?.width ?? 1); 64 + 65 + const newPosition = activePosition + movement; 66 + activeColor.position = newPosition; 67 + } 68 + }} 69 + > 70 + {#each colors as color, i} 71 + <Popover.Root> 72 + <Popover.Trigger 73 + class={cn( 74 + 'absolute top-4 left-0', 75 + 'focus-visible:outline-base-900 dark:focus-visible:outline-base-100 cursor-pointer rounded-full focus-visible:outline-2 focus-visible:outline-offset-2' 76 + )} 77 + style={`left: calc(${color.position * 100}% - 16px)`} 78 + onpointerdown={(evt) => { 79 + activeColor = color; 80 + mouseDownPosition = evt.clientX; 81 + activePosition = color.position; 82 + }} 83 + onpointerup={() => { 84 + activeColor = undefined; 85 + activePosition = undefined; 86 + mouseDownPosition = undefined; 87 + }} 88 + > 89 + <div 90 + class="border-base-300 dark:border-base-950 focus-visible:outline-accent-500 z-10 size-8 rounded-full border-2" 91 + style={`background-color: rgb(${color.rgb.r * 255}, ${color.rgb.g * 255}, ${color.rgb.b * 255});`} 92 + ></div> 93 + 94 + <div class="absolute inset-0 size-8 rounded-full border border-base-700 dark:border-base-300"></div> 95 + </Popover.Trigger> 96 + <Popover.Content side="bottom" sideOffset={10}> 97 + <ColorPicker bind:rgb={colors[i].rgb} class={className} /> 98 + </Popover.Content> 99 + </Popover.Root> 100 + {/each} 101 + </div>
+6 -2
src/lib/components/extra/color-picker/popover/PopoverColorPicker.svelte
··· 13 13 rgb = $bindable(), 14 14 oklab = $bindable(), 15 15 okhsv = $bindable(), 16 + sideOffset = 10, 17 + side = 'bottom', 16 18 class: className, 17 19 onchange 18 20 }: { ··· 20 22 oklab?: OKlab; 21 23 okhsv?: OKhsv; 22 24 class?: string; 25 + sideOffset?: number; 26 + side?: 'top' | 'right' | 'bottom' | 'left'; 23 27 onchange?: (color: { hex: string; rgb: RGB; oklab: OKlab; okhsv: OKhsv; oklch: OKlch }) => void; 24 28 } = $props(); 25 29 ··· 57 61 style={`background-color: rgb(${internalColor.r * 255}, ${internalColor.g * 255}, ${internalColor.b * 255});`} 58 62 ></div> 59 63 </Popover.Trigger> 60 - <Popover.Content side="bottom" sideOffset={10}> 61 - <ColorPicker bind:rgb class={className} /> 64 + <Popover.Content side={side} sideOffset={sideOffset}> 65 + <ColorPicker bind:rgb bind:oklab bind:okhsv class={className} onchange={onchange} /> 62 66 </Popover.Content> 63 67 </Popover.Root>
+6
src/routes/components/extras/color-gradient-picker/+page.svelte
··· 1 + <script> 2 + import ColorGradientPicker from "$lib/components/extra/color-gradient-picker/ColorGradientPicker.svelte"; 3 + 4 + </script> 5 + 6 + <ColorGradientPicker />