svelte-awesome-color-picker
highly customizable color picker component library
- 🎹 built-in keyboard navigation
- 📱 mobile support
- 🤸♂️ accessibility information
- 🤯 works without javascript (fallback to the browser default color picker)
- 🏇 it’s compatible with form libraries
- 🧩 fully customizable
- 🔨 full typescript support
- 🖤 dark theme support
The library uses 2 libraries:
- colord: lightest color conversion library on the market at the time and supports a11y contrasts
- svelte-awesome-slider: another library I crafted and is higlhy customizable.
This documentation is the documentation of svelte-awesome-color-picker v3. If you are looking to upgrate to v3, see the section upgrade from v2 to v3. If you are looking for the v2 documentation, see the v2 documentation.
Install
npm i -D svelte-awesome-color-picker
Links
The same documentation can be seen on Github, on the npm registry or on the documentation site. I would suggest to visite the documentation site since it has interactive examples!
Examples
Default layout
Source code
<script>
import ColorPicker from 'svelte-awesome-color-picker';
</script>
<ColorPicker
bind:hex
bind:rgb
bind:hsv
bind:color
position="responsive"
/>
Color props
let hex = "#f6f0dc" let rgb = { "r": 255, "g": 0, "b": 0, "a": 1 } let hsv = { "h": 0, "s": 100, "v": 100, "a": 1 } let color = "// instance of Colord"
Chrome variant
Source code
<script>
import ColorPicker, { ChromeVariant } from 'svelte-awesome-color-picker';
</script>
<ColorPicker bind:rgb bind:hsv bind:hex components={ChromeVariant} sliderDirection="horizontal" />
Accessibility notice variant
background
contrast : 1.14
AAbackground
contrast : 1.14
AAtitle
contrast : 1.14
AAbutton
contrast : 3.51
AASource code
<script>
import ColorPicker, { A11yVariant } from 'svelte-awesome-color-picker';
</script>
<ColorPicker
components={A11yVariant}
bind:hex
bind:rgb
bind:hsv
isAlpha
a11yColors={[
{ textHex: '#FFF', reverse: true, placeholder: 'background' },
{ textHex: '#FFF', bgHex: '#FF0000', reverse: true, placeholder: 'background' },
{ bgHex: '#FFF', placeholder: 'title', size: 'large' },
{ bgHex: '#7F7F7F', placeholder: 'button' }
]}
/>
Note: set both attributes resverse
and bgHex
when you are chosing a transparency background color over a non white background.
Nullable version
Source code
<script>
import ColorPicker from 'svelte-awesome-color-picker';
</script>
<ColorPicker
bind:hex
bind:rgb
bind:hsv
bind:color
nullable
/>
Always open version
Source code
<script>
import ColorPicker, { ChromeVariant } from 'svelte-awesome-color-picker';
</script>
<ColorPicker
bind:rgb
bind:hsv
bind:hex
components={ChromeVariant}
sliderDirection="horizontal"
isDialog={false}
/>
on:input
’
Bind event ’ In this example, the color is appended to the history at each event.
Source code
<ColorPicker
{rgb}
on:input={(event) => {
historyHex = [...historyHex, event.detail.hex];
}}
/>
history variable
let history = []
Override the css variables
Source code
<ColorPicker
bind:rgb
bind:hsv
bind:hex
--picker-height="100px"
--picker-width="100px"
--slider-width="25px"
--picker-indicator-size="25px"
--picker-z-index="10"
--input-size="100px"
--focus-color="green"
/>
Dark theme
Source code
<script>
import ColorPicker from 'svelte-awesome-color-picker';
</script>
<div class="dark">
<ColorPicker />
</div>
<style>
.dark {
--cp-bg-color: #333;
--cp-border-color: white;
--cp-text-color: white;
--cp-input-color: #555;
--cp-button-hover-color: #777;
}</style>
Translate the color picker
Note: the texts
props can be partially overridden. It’s mostly used to translate the component. Most texts are used for accessibility aria-labels.
Source code
<ColorPicker
bind:rgb
bind:hsv
bind:hex
label="Choisir une couleur"
texts={{
label: {
h: 'teinte',
s: 'saturation',
v: 'luminosité',
r: 'rouge',
g: 'vert',
b: 'bleu',
a: 'transparence',
hex: 'couleur hexadécimale',
withoutColor: 'sans couleur'
},
color: {
rgb: 'rgb',
hsv: 'hsv',
hex: 'hex'
},
changeTo: 'changer à '
}}
/>
Api
The library exports 4 different things:
- The color picker as a default export
ChromeVariant
: the Chrome variantA11yVariant
: the accessibility variant (to display a panel which shows the WCAG grades)HsvaColor
andRgbaColor
: the two types defining HSV and RGB colors
Color picker
props
name | type | default value | usage |
---|---|---|---|
components | Partial<Components> | {} | customize the ColorPicker component parts. Can be used to display a Chrome variant or an Accessibility Notice |
label | string | 'Choose a color' | input label, hidden when the ColorPicker is always shown (prop isDialog={false} ) |
name | string | undefined | undefined | input name, useful in a native form |
nullable | boolean | false | if set to true, the color picker becomes nullable (rgb, hsv and hex set to undefined) |
rgb | RgbaColor | undefined | nullable ? undefined : { r: 255, g: 0, b: 0, a: 1 } | rgb color |
hsv | HsvaColor | undefined | nullable ? undefined : { h: 0, s: 100, v: 100, a: 1 } | hsv color |
hex | string | undefined | nullable ? undefined : '#ff0000' | hex color |
color | Colord | undefined | undefined | Colord color |
isDark | boolean | false | indicator whether the selected color is light or dark |
isAlpha | boolean | true | if set to false, disables the alpha channel |
isDialog | boolean | true | if set to false, the input and the label will not be displayed and the ColorPicker will always be visible |
isOpen | boolean | !isDialog | indicator of the popup state |
position | 'fixed' | 'responsive' | 'responsive-x' | 'responsive-y' | 'fixed' | if set to “responsive”, the popup will adjust its x and y position depending on the available window space, “responsive-x” and “responsive-y” limit the behavior to either the x or y axis. The value ‘responsive’ will become the default in the next major release |
isTextInput | boolean | true | if set to false, hide the hex, rgb and hsv text inputs |
textInputModes | Array<'hex' | 'rgb' | 'hsv'> | ['hex', 'rgb', 'hsv'] | configure which hex, rgb and hsv inputs will be visible and in which order. If overridden, it is necessary to provide at least one value |
sliderDirection | 'horizontal' | 'vertical' | 'vertical' | If set to “horizontal”, the hue and alpha sliders will be displayed horizontally. It is necessary to set this props to “horizontal” for the ChromeVariant |
disableCloseClickOutside | boolean | false | If set to true, it will not be possible to close the color picker by clicking outside |
a11yColors | Array<A11yColor> | [{ bgHex: '#ffffff' }] | used with the A11yVariant. Define the accessibility examples in the color picker |
a11yLevel | 'AA' | 'AAA' | 'AA' | required WCAG contrast level |
texts | TextsPartial | undefined | undefined | all translation tokens used in the library; can be partially overridden; see full object type |
a11yTexts | A11yTextsPartial | undefined | undefined | all a11y translation tokens used in the library; override with translations if necessary; see full object type |
events
Event | Type | Usage |
---|---|---|
input | { color, hsv, rgb, hex } | Event fired on every color change (click & drag & mouse, touch) |
See the example Bind event ’on:input
’.
css variables
Props | Default Value | Usage |
---|---|---|
--picker-height | 200px | picker & sliders height |
--picker-width | 200px (260px for the Chrome variant) | picker width |
--slider-width | 30px | sliders width |
--picker-indicator-size | 10px | picker indicator size |
--picker-z-index | 2 | popup picker z-index |
--input-size | 25px | color circle size |
--focus-color | red | focus color |
--cp-bg-color | white | background color |
--cp-border-color | black | border color |
--cp-text-color | --cp-border-color | text color |
--cp-input-color | #eee | background color of the inputs |
--cp-button-hover-color | #ccc | background color of the hovered button |
See the example Override the css variables’.
components
The color picker can be customized with components. The details and props are detailed below. It is easier to copy the library components and tweak them to your needs.
A Chrome variant and an accessibility variant are available. To use the Chrome variant you need to set the props sliderDirection
to horizontal
. You can also partially overwrite the components:
<script>
import ColorPicker, { ChromeVariant } from 'svelte-awesome-color-picker';
import CustomInput from '$lib/path/to/my/awesome/variant/Input.svelte';
import CustomWrapper from '$lib/path/to/my/awesome/variant/Wrapper.svelte';
let rgb;
</script>
<!-- example with the default display and a custom Input component -->
<ColorPicker bind:rgb components={{ input: CustomInput }} />
<!-- example with the Chrome variant and a custom Wrapper component -->
<ColorPicker bind:rgb components={{ ...ChromeVariant, wrapper: CustomWrapper }} />
<!-- example with the ChromeVariant -->
<ColorPicker bind:rgb components={ChromeVariant} sliderDirection="horizontal" />
The components that can be overridden are:
The 3 components a11yNotice
, a11ySummary
and a11ySingleNotice
are no longer included by default but can still be defined or passed through the a11yVariant object. This change was made in version 3.0.0 to lighten the library for those who do not use it.
Some components are no longer customizable in version 3.0.0: pickerWrapper
, sliderWrapper
, alphaWrapper
, sliderIndicator
and alphaIndicator
. Instead you can either use the css variables or you can style them from the wrapper
component.
pickerIndicator
Component representing the picker indicator.
- The component should be positioned with
position: absolute;
. - It should also have the css property
pointer-events: none;
.
Props:
name | type | default value | usage |
---|---|---|---|
pos | { x: number | indicator position in % | |
isDark | boolean | indicator whether the selected color is light or dark |
textInput
Component representing the rgb / hex / hsv textual input below the picker
Props:
name | type | default value | usage |
---|---|---|---|
isAlpha | boolean | if set to false, disables the alpha channel | |
rgb | RgbaColor | rgb color | |
hsv | HsvaColor | hsv color | |
hex | string | hex color | |
textInputModes | Array<'hex' | 'rgb' | 'hsv'> | configure which hex, rgb and hsv inputs will be visible and in which order. If overridden, it is necessary to provide at least one value | |
texts | Texts | all translation tokens used in the library; can be partially overridden; see full object type |
Input
Component representing the button to open the color picker and a hidden input with the hex value selected by the user
Props:
name | type | default value | usage |
---|---|---|---|
labelElement | HTMLLabelElement | DOM element of the label wrapper | |
hex | string | undefined | hex color | |
label | string | input label | |
name | string | undefined | undefined | input name, useful in a native form |
isOpen | boolean | indicator of the popup state |
wrapper
Encapsulates the whole color picker
Props:
name | type | default value | usage |
---|---|---|---|
wrapper | HTMLElement | DOM element of the wrapper element | |
isOpen | boolean | indicator of the popup state | |
isDialog | boolean | if set to true, the wrapper should have a dialog role and be absolute. It should be relative otherwise |
nullabilityCheckbox
Displays the checkbox to toggle an undefined value
Props:
name | type | default value | usage |
---|---|---|---|
isUndefined | boolean | whether the color picker is undefined | |
texts | Texts | all translation tokens used in the library; can be partially overridden; see full object type |
a11yNotice
Component displaying accessible contrast issues with the color chosen.
Props:
name | type | default value | usage |
---|---|---|---|
components | Components | customize the ColorPicker component parts. Can be used to display a Chrome variant or an Accessibility Notice | |
hex | string | hex color | |
a11yColors | Array<A11yColor> | define the accessibility examples in the color picker | |
a11yLevel | 'AA' | 'AAA' | required WCAG contrast level | |
a11yTexts | A11yTextsPartial | undefined | undefined | all a11y translation tokens used in the library; override with translations if necessary; see full object type |
Type A11yColor:
type A11yColor = {
placeholder?: string;
size?: 'normal' | 'large';
} & (
| {
textHex: string;
bgHex: string;
reverse: true;
}
| {
bgHex: string;
reverse?: false;
}
);
Attribute | Type | Usage |
---|---|---|
placeholder | string | placeholder text, default to Lorem Ipsum |
size | normal, large | used to check the contrast guidelines |
reverse | boolean | set to true if the color picker is used to chose a background color |
textHex | string | when choosing the background color, defines the text color |
bgHex | string | when choosing the text color, defines the background color ; hen choosing th background color, defines the color behind (in case of transparency) |
read more about this component accessibility in the #a11y section.
a11ySingleNotice
component display the accessibility result of the color over a single item of the a11yColors
props.
Props:
name | type | default value | usage |
---|---|---|---|
placeholder | string | undefined | undefined | placeholder, falls back to Lorem Ipsum |
size | 'normal' | 'large' | undefined | undefined | size of the text |
a11yLevel | 'AA' | 'AAA' | required WCAG contrast level | |
textColor | string | placeholder text color | |
bgColor | string | placeholder background color | |
contrast | number | 1 | RGAA contrast between the text and its background. Between 1 and 21 |
contrastText | string | define the accessibility “contrast” text |
Accessibility
The component itself
The svelte-awesome-color-picker uses svelte-awesome-slider (also made by me) to display the sliders. This library follows the W3c slider component accessibility guidelines.
The color picker follows the W3c component dialog combobox accessibility guidelines.
Accessibility notice
The component can display an accessibility notice that updates the WCAG contrast grades by using the a11yVariant
component override.
The contrast between 2 colors is a value between 1 and 21. It is computed with the colord a11y plugin library based on WCAG 2.0 guidelines for contrast accessibility.
A contrast between 2 colors succeed if it follows the WCAG contrast guidelines:
Text size | AA | AAA |
---|---|---|
small text (18.5px) | contrast > 4.5 | contrast > 7 |
big text (24px) | contrast > 3 | contrast > 4.5 |
In the default A11ySingleNotice
component that renders the AA and AAA tags, the small text values are used (can be configured for each reference color with the color
props).
See and the accessibility notice variant example and the definition of the A11yColor type for more information.
How to
Fix overflow issues inside a container
If you use the ColorPicker component inside a container that is set with overflow: auto
or overflow: hidden
, the picker will be hidden outside of the wrapper.
To fix this, you can override the Wrapper
component and use the svelte-portal library to render the picker outside of your container. An example of how to do that is presented in this svelte-awesome-color-picker portal REPL.
Fix overflow issues in the window
Please set the position
props to responsive
as stated in the props section.
Use the color of the document
Override the css variable --cp-border-color
:
body {
--cp-border-color: currentColor;
}
If you have a dark theme, make sure to handles it correctly.
Migration
upgrade from v2 to v3
The major version 3 has been released to remove accessibility issues (see issue #43). The library now comes with the possibility to deselect a color and it is also possible to theme the picker for dark themes. The library has also been made simpler and lighter. This comes with some breaking changes:
sliderIndicator
,alphaIndicator
,pickerWrapper
,sliderWrapper
,alphaWrapper
anda11ySummary
were removed, you can use css variables in thewrapper
component for design customization and texts in thetexts
anda11yTexts
props instead for translating the library.- props
isA11y
has been removed. The accessibility display is now a variant:<ColorPicker components={A11yVariant} />
. This change has been made to reduce the library bundle size. - props
isInput
andisPopup
have been merged and renamed asisDialog
. - props
isRight
has been replaced bysliderDirection="horizontal"
. - props
isA11yOpen
andisA11yClosable
have been removed.