Skip to content

Commit 0a4df04

Browse files
committed
add palette component
1 parent 67f2bb1 commit 0a4df04

File tree

2 files changed

+112
-0
lines changed

2 files changed

+112
-0
lines changed

src/components/Palette.svelte

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<script lang="ts">
2+
export let colors = 8;
3+
export let saturation = 100;
4+
export let lightness = 50;
5+
6+
function x(n: number) {
7+
return Math.sin((2 * Math.PI) / colors) * n;
8+
}
9+
10+
function y(n: number) {
11+
return n - Math.cos((2 * Math.PI) / colors) * n;
12+
}
13+
// Sharp angle (doesnt work for 2)
14+
// `M50 0 l${x(50)} ${y(50)}L${50+x(25)} ${25+y(25)}L50 25z`
15+
$: path =
16+
colors > 1
17+
? `M50 0 a50 50 0 01 ${x(50)} ${y(50)}L${50 + x(25)} ${25 + y(25)}A25 25 0 00 50 25`
18+
: "M50 0a50 50 0 01 0 100a50 50 0 01 0-100m0 25a25 25 0 01 0 50a25 25 0 01 0-50";
19+
20+
let current_color = "";
21+
async function copyColor(
22+
event: MouseEvent & { currentTarget: SVGPathElement }
23+
) {
24+
const rgb = getComputedStyle(event.currentTarget).fill;
25+
const hex =
26+
"#" +
27+
rgb
28+
.slice(4, -1)
29+
.split(", ")
30+
.map((d) => parseInt(d).toString(16).padStart(2, "0"))
31+
.join("")
32+
.toUpperCase();
33+
await navigator.clipboard.writeText(hex);
34+
current_color = hex;
35+
setTimeout(() => (current_color = ""), 1000);
36+
}
37+
</script>
38+
39+
<div class="container">
40+
<svg viewBox="0 0 100 100">
41+
{#key colors}
42+
{#each Array(colors) as _, i}
43+
{@const rotation = (360 / colors) * i}
44+
<!-- svelte-ignore a11y-click-events-have-key-events -->
45+
<!-- svelte-ignore a11y-no-static-element-interactions -->
46+
<path
47+
d={path}
48+
style:rotate="{rotation}deg"
49+
style:fill="hsl({rotation}
50+
{saturation}
51+
{lightness})"
52+
on:click={copyColor}
53+
/>
54+
{/each}
55+
{/key}
56+
</svg>
57+
{#if current_color !== ""}
58+
<div class="copied" style:--color={current_color}>
59+
{current_color} copied
60+
</div>
61+
{/if}
62+
</div>
63+
64+
<style lang="scss">
65+
.container {
66+
position: relative;
67+
}
68+
.copied {
69+
position: absolute;
70+
inset: 0;
71+
margin: auto;
72+
width: fit-content;
73+
height: fit-content;
74+
background-color: var(--color);
75+
color: black;
76+
padding: 1rem 2rem;
77+
border-radius: 100rem;
78+
}
79+
path {
80+
transform-origin: center;
81+
fill-rule: evenodd;
82+
transition: scale ease 0.15s;
83+
&:hover {
84+
scale: 0.95;
85+
cursor: pointer;
86+
}
87+
}
88+
</style>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<script lang="ts">
2+
import type { Hst } from "@histoire/plugin-svelte";
3+
import Palette from "../../components/Palette.svelte";
4+
5+
export let Hst: Hst;
6+
7+
let colors = 8;
8+
let saturation = 50;
9+
let lightness = 70;
10+
</script>
11+
12+
<!-- svelte-ignore reactive-component -->
13+
<Hst.Story
14+
title="Components/Palette"
15+
icon="ic:outline-palette"
16+
>
17+
<Palette {colors} {saturation} {lightness}/>
18+
19+
<svelte:fragment slot="controls">
20+
<Hst.Slider bind:value={colors} title="Colors" min={1} max={360} />
21+
<Hst.Slider bind:value={saturation} title="Saturation" min={0} max={100} />
22+
<Hst.Slider bind:value={lightness} title="Lightness" min={0} max={100} />
23+
</svelte:fragment>
24+
</Hst.Story>

0 commit comments

Comments
 (0)