Skip to content

Inputs

ColorField

Color input with a swatch, a native picker, hex, rgb() and oklch() text entry, and a live WCAG contrast readout.

<script>
  import { ColorField } from "@codeatlasdev/ui";
  let brand = $state("#2b5fd9");
</script>

<ColorField label="Brand color" bind:value={brand} against="#ffffff" role="fill" minRatio={3} />

The swatch shows the color, the chip at the end opens the native picker, and the text field accepts #rgb, #rrggbb, a bare rrggbb, rgb(), oklch() and color-mix(). value keeps the notation the person typed, so an oklch() stays oklch(); format only decides what the picker writes. An invalid entry shows an error and never reaches value.

With against the field shows the WCAG contrast ratio and says in words whether it passes (Passes AA, Below 4.5:1), so the verdict never rests on color alone. Use role="text" (default) to measure the color as text on against, or role="fill" to measure against as the label on the color. Translucent colors are composited over the background before measuring, and the verdict follows the real ratio, not the rounded one shown.

The color helpers behind it are public: parseColorInput, contrast, wcagLevel, toHex, toOklch, formatOklch, and extractPalette with pickBrand for deriving a brand from the pixels of a logo.

#990

Brand color

Contrast of white on the color, as a UI part (3:1).

Type #hex, rgb() or oklch(), or pick.

5.6:1 Passes AA

value: #2b5fd9

Reference #990 · Pick in the gallery

Code
svelte
<script lang="ts">
  import { ColorField } from '@codeatlasdev/ui';

  let brand = $state('#2b5fd9');
</script>

<div class="col">
  <ColorField label="Brand color" bind:value={brand} against="#ffffff" role="fill" minRatio={3} description="Type #hex, rgb() or oklch(), or pick." />
  <p class="out">value: {brand}</p>
</div>

<style>
  .col {
    display: flex;
    flex-direction: column;
    gap: var(--ca-space-3);
    max-inline-size: 22rem;
  }

  .out {
    margin: 0;
    font-size: var(--ca-font-size-caption);
    color: var(--ca-text-secondary);
  }
</style>
#991

Text color

Text on a white page, oklch output from the picker, 4.5:1.

4.8:1 Passes AA

The quick brown fox jumps over the lazy dog.

Reference #991 · Pick in the gallery

Code
svelte
<script lang="ts">
  import { ColorField } from '@codeatlasdev/ui';

  let text = $state('#6b7280');
  const page = '#ffffff';
</script>

<div class="col">
  <ColorField label="Body text" bind:value={text} against={page} minRatio={4.5} format="oklch" />
  <div class="sample" style="--sample-ink:{text}">
    <p class="sample__p">The quick brown fox jumps over the lazy dog.</p>
  </div>
</div>

<style>
  .col {
    display: flex;
    flex-direction: column;
    gap: var(--ca-space-3);
    max-inline-size: 22rem;
  }

  .sample {
    padding: var(--ca-space-3);
    background: #ffffff;
    border-radius: var(--ca-radius-md);
  }

  .sample__p {
    margin: 0;
    color: var(--sample-ink);
  }
</style>

Props

PropTypeDefaultDescription
labelstring–Visible label and accessible name of the text field.
valuestring'#000000'Bindable committed color, as typed.
format'hex' | 'oklch''hex'What the native picker writes back.
againststring–Background to measure contrast against (any CSS color). Omit to hide the readout.
role'text' | 'fill''text'`text`: value on `against`. `fill`: `against` on value.
minRationumber4.5Ratio that counts as passing. 3 for UI parts.
descriptionstring–Hint under the field.
disabledbooleanfalseDisables the field and the picker.
classstring–Extra classes on the root.
onchange(value: string) => void–Called when a valid color is committed (Enter, blur or the picker).