Skip to content

Commit

Permalink
feat: ColorField and ColorWheel
Browse files Browse the repository at this point in the history
  • Loading branch information
HBS999 committed Oct 31, 2024
1 parent 7631960 commit 99bd0e2
Show file tree
Hide file tree
Showing 24 changed files with 3,231 additions and 0 deletions.
84 changes: 84 additions & 0 deletions apps/docs/src/examples/color-field.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
.color-field {
display: flex;
flex-direction: column;
gap: 4px;
}

.color-field__label {
color: hsl(240 6% 10%);
font-size: 14px;
font-weight: 500;
user-select: none;
}

.color-field__input {
display: inline-flex;
width: 200px;
border-radius: 6px;
padding: 6px 12px;
font-size: 16px;
outline: none;
background-color: white;
border: 1px solid hsl(240 6% 90%);
color: hsl(240 4% 16%);
transition:
border-color 250ms,
color 250ms;
}

.color-field__input:hover {
border-color: hsl(240 5% 65%);
}

.color-field__input:focus-visible {
outline: 2px solid hsl(200 98% 39%);
outline-offset: 2px;
}

.color-field__input[data-invalid] {
border-color: hsl(0 72% 51%);
color: hsl(0 72% 51%);
}

.color-field__input::placeholder {
color: hsl(240 4% 46%);
}

.color-field__description {
color: hsl(240 5% 26%);
font-size: 12px;
user-select: none;
}

.color-field__error-message {
color: hsl(0 72% 51%);
font-size: 12px;
user-select: none;
}

[data-kb-theme="dark"] .color-field__input {
background-color: hsl(240 4% 16%);
border: 1px solid hsl(240 5% 34%);
color: hsl(0 100% 100% / 0.9);
}

[data-kb-theme="dark"] .color-field__input:hover {
border-color: hsl(240 4% 46%);
}

[data-kb-theme="dark"] .color-field__input[data-invalid] {
border-color: hsl(0 72% 51%);
color: hsl(0 72% 51%);
}

[data-kb-theme="dark"] .color-field__input::placeholder {
color: hsl(0 100% 100% / 0.5);
}

[data-kb-theme="dark"] .color-field__label {
color: hsl(240 5% 84%);
}

[data-kb-theme="dark"] .color-field__description {
color: hsl(240 5% 65%);
}
97 changes: 97 additions & 0 deletions apps/docs/src/examples/color-field.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import { createSignal } from "solid-js";
import { ColorField } from "../../../../packages/core/src/colors/color-field";

import style from "./color-field.module.css";

export function BasicExample() {
return (
<ColorField class={style["color-field"]}>
<ColorField.Label class={style["color-field__label"]}>Favorite color</ColorField.Label>
<ColorField.Input class={style["color-field__input"]} />
</ColorField>
);
}

export function DefaultValueExample() {
return (
<ColorField class={style["color-field"]} defaultValue="#7f007f">
<ColorField.Label class={style["color-field__label"]}>Favorite color</ColorField.Label>
<ColorField.Input class={style["color-field__input"]} />
</ColorField>
);
}

export function ControlledExample() {
const [value, setValue] = createSignal("#7f007f");

return (
<>
<ColorField class={style["color-field"]} value={value()} onChange={setValue}>
<ColorField.Label class={style["color-field__label"]}>Favorite color</ColorField.Label>
<ColorField.Input class={style["color-field__input"]} />
</ColorField>
<p class="not-prose text-sm mt-4">Your favorite color is: {value()}</p>
</>
);
}

export function DescriptionExample() {
return (
<ColorField class={style["color-field"]}>
<ColorField.Label class={style["color-field__label"]}>Favorite color</ColorField.Label>
<ColorField.Input class={style["color-field__input"]} />
<ColorField.Description class={style["color-field__description"]}>
Choose the color you like the most.
</ColorField.Description>
</ColorField>
);
}

export function ErrorMessageExample() {
const [value, setValue] = createSignal("#7f007f");

return (
<ColorField
class={style["color-field"]}
value={value()}
onChange={setValue}
validationState={value() !== "#000000" ? "invalid" : "valid"}
>
<ColorField.Label class={style["color-field__label"]}>Favorite color</ColorField.Label>
<ColorField.Input class={style["color-field__input"]} />
<ColorField.ErrorMessage class={style["color-field__error-message"]}>
Hmm, I prefer black.
</ColorField.ErrorMessage>
</ColorField>
);
}

export function HTMLFormExample() {
let formRef: HTMLFormElement | undefined;

const onSubmit = (e: SubmitEvent) => {
e.preventDefault();
e.stopPropagation();

const formData = new FormData(formRef);

alert(JSON.stringify(Object.fromEntries(formData), null, 2));
};

return (
<form ref={formRef} onSubmit={onSubmit} class="flex flex-col items-center space-y-6">
<ColorField class={style["color-field"]} name="favorite-color">
<ColorField.Label class={style["color-field__label"]}>Favorite color</ColorField.Label>
<ColorField.Input class={style["color-field__input"]} />
</ColorField>
<div class="flex space-x-2">
<button type="reset" class="kb-button">
Reset
</button>
<button type="submit" class="kb-button-primary">
Submit
</button>
</div>
</form>
);
}
33 changes: 33 additions & 0 deletions apps/docs/src/examples/color-wheel.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
.ColorWheelRoot {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
user-select: none;
touch-action: none;
}

.ColorWheelTrack {
position: relative;
height: 160px;
width: 160px;
}

.ColorWheelThumb {
display: block;
width: 16px;
height: 16px;
border-radius: 9999px;
border: 2px solid #fff;
box-shadow: 0 0 0 1px #0000006b;
}

.ColorWheelThumb:focus {
outline: none;
}

.ColorWheelLabel {
display: flex;
justify-content: space-between;
width: 100%;
}
120 changes: 120 additions & 0 deletions apps/docs/src/examples/color-wheel.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { createSignal } from "solid-js";
import { ColorWheel } from "../../../../packages/core/src/colors/color-wheel";
import { parseColor } from "../../../../packages/core/src/colors/utils";
import style from "./color-wheel.module.css";

export function BasicExample() {
return (
<ColorWheel class={style.ColorWheelRoot} thickness={24}>
<ColorWheel.Track class={style.ColorWheelTrack}>
<ColorWheel.Thumb class={style.ColorWheelThumb}>
<ColorWheel.Input />
</ColorWheel.Thumb>
</ColorWheel.Track>
</ColorWheel>
);
}

export function DefaultValueExample() {
return (
<ColorWheel
class={style.ColorWheelRoot}
defaultValue={parseColor("hsl(80, 100%, 50%)")}
thickness={24}
>
<ColorWheel.Track class={style.ColorWheelTrack}>
<ColorWheel.Thumb class={style.ColorWheelThumb}>
<ColorWheel.Input />
</ColorWheel.Thumb>
</ColorWheel.Track>
</ColorWheel>
);
}

export function ThicknessExample() {
return (
<ColorWheel class={style.ColorWheelRoot} thickness={56}>
<ColorWheel.Track class={style.ColorWheelTrack}>
<ColorWheel.Thumb class={style.ColorWheelThumb}>
<ColorWheel.Input />
</ColorWheel.Thumb>
</ColorWheel.Track>
</ColorWheel>
);
}

export function ControlledValueExample() {
const [value, setValue] = createSignal(parseColor("hsl(0, 100%, 50%)"));

return (
<>
<ColorWheel class={style.ColorWheelRoot} value={value()} onChange={setValue} thickness={24}>
<ColorWheel.Track class={style.ColorWheelTrack}>
<ColorWheel.Thumb class={style.ColorWheelThumb}>
<ColorWheel.Input />
</ColorWheel.Thumb>
</ColorWheel.Track>
</ColorWheel>
<p class="not-prose text-sm mt-4">Current color value: {value().toString("hsl")}</p>
</>
);
}

export function CustomValueLabelExample() {
return (
<ColorWheel
class={style.ColorWheelRoot}
thickness={24}
getValueLabel={color =>
color
.toFormat("hsl")
.withChannelValue("saturation", 100)
.withChannelValue("lightness", 50)
.withChannelValue("alpha", 1)
.toString()
}
>
<div class={style.ColorWheelLabel}>
<ColorWheel.ValueLabel />
</div>
<ColorWheel.Track class={style.ColorWheelTrack}>
<ColorWheel.Thumb class={style.ColorWheelThumb}>
<ColorWheel.Input />
</ColorWheel.Thumb>
</ColorWheel.Track>
</ColorWheel>
);
}

export function HTMLFormExample() {
let formRef: HTMLFormElement | undefined;

const onSubmit = (e: SubmitEvent) => {
e.preventDefault();
e.stopPropagation();

const formData = new FormData(formRef);

alert(JSON.stringify(Object.fromEntries(formData), null, 2));
};

return (
<form ref={formRef} onSubmit={onSubmit} class="flex flex-col items-center space-y-6">
<ColorWheel class={style.ColorWheelRoot} name="hue" thickness={24}>
<ColorWheel.Track class={style.ColorWheelTrack}>
<ColorWheel.Thumb class={style.ColorWheelThumb}>
<ColorWheel.Input />
</ColorWheel.Thumb>
</ColorWheel.Track>
</ColorWheel>
<div class="flex space-x-2">
<button type="reset" class="kb-button">
Reset
</button>
<button type="submit" class="kb-button-primary">
Submit
</button>
</div>
</form>
);
}
10 changes: 10 additions & 0 deletions apps/docs/src/routes/docs/core.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,16 @@ const CORE_NAV_SECTIONS: NavSection[] = [
title: "Collapsible",
href: "/docs/core/components/collapsible",
},
{
title: "Color Field",
href: "/docs/core/components/color-field",
status: "new",
},
{
title: "Color Wheel",
href: "/docs/core/components/color-wheel",
status: "new",
},
{
title: "Combobox",
href: "/docs/core/components/combobox",
Expand Down
Loading

0 comments on commit 99bd0e2

Please sign in to comment.