diff --git a/addons/controls/README.md b/addons/controls/README.md index 90efbbaeb3af..f69650dc6440 100644 --- a/addons/controls/README.md +++ b/addons/controls/README.md @@ -326,7 +326,7 @@ Here is the full list of available controls: | | select | select dropdown input | options | | | multi-select | multi-select dropdown input | options | | **string** | text | simple text input | - | -| | color | color picker input that assumes strings are color values | - | +| | color | color picker input that assumes strings are color values | presetColors | | | date | date picker input | - | Example customizing a control for an `enum` data type (defaults to `select` control type): @@ -357,6 +357,20 @@ export default { }; ``` +Example customizing a `color` data type: + +```js +export default { + title: 'Button', + component: Button, + argTypes: { + backgroundColor: { + control: { type: 'color', presetColors: ['#FFF', '#000', '#AAA'] }, + }, + }, +}; +``` + ### Parameters Controls supports the following configuration parameters, either [globally or on a per-story basis](https://storybook.js.org/docs/basics/writing-stories/#parameters): diff --git a/lib/components/src/controls/Color.stories.tsx b/lib/components/src/controls/Color.stories.tsx index 852f528b6106..85b2ba9f3420 100644 --- a/lib/components/src/controls/Color.stories.tsx +++ b/lib/components/src/controls/Color.stories.tsx @@ -1,6 +1,8 @@ import React, { useState } from 'react'; import { ColorControl } from './Color'; +const presetColors = ['#FE4A49', '#FED766', '#009FB7', '#E6E6EA', '#F4F4F8']; + export default { title: 'Controls/Color', component: ColorControl, @@ -10,3 +12,15 @@ export const Basic = () => { const [value, setValue] = useState('#ff0'); return setValue(newVal)} />; }; + +export const WithPresetColors = () => { + const [value, setValue] = useState('#ff0'); + return ( + setValue(newVal)} + presetColors={presetColors} + /> + ); +}; diff --git a/lib/components/src/controls/Color.tsx b/lib/components/src/controls/Color.tsx index 026ad907c413..6fa2a2d0c6ec 100644 --- a/lib/components/src/controls/Color.tsx +++ b/lib/components/src/controls/Color.tsx @@ -1,4 +1,4 @@ -import React, { FC, useState } from 'react'; +import React, { FC, useState, MouseEvent, KeyboardEvent } from 'react'; import { SketchPicker, ColorResult } from 'react-color'; import { styled } from '@storybook/theming'; @@ -30,7 +30,14 @@ const format = (color: ColorResult) => `rgba(${color.rgb.r},${color.rgb.g},${color.rgb.b},${color.rgb.a})`; export type ColorProps = ControlProps & ColorConfig; -export const ColorControl: FC = ({ name, value, onChange, onFocus, onBlur }) => { +export const ColorControl: FC = ({ + name, + value, + onChange, + onFocus, + onBlur, + presetColors, +}) => { const [showPicker, setShowPicker] = useState(false); return ( @@ -39,16 +46,28 @@ export const ColorControl: FC = ({ name, value, onChange, onFocus, o type="button" name={name} onClick={() => setShowPicker(!showPicker)} + onKeyDown={(e: KeyboardEvent) => { + if (e.key === 'Enter') { + setShowPicker(!showPicker); + } + }} size="flex" > {value ? value.toUpperCase() : 'Choose color'} {showPicker ? ( - + { + // @ts-ignore + if (e.target.tagName === 'INPUT') { + e.stopPropagation(); + } + }} + > onChange(name, format(color))} - {...{ onFocus, onBlur }} + {...{ onFocus, onBlur, presetColors }} /> ) : null} diff --git a/lib/components/src/controls/types.ts b/lib/components/src/controls/types.ts index 3ad2b8eb7bb2..34afbe0d68d8 100644 --- a/lib/components/src/controls/types.ts +++ b/lib/components/src/controls/types.ts @@ -20,7 +20,9 @@ export type BooleanValue = boolean; export interface BooleanConfig {} export type ColorValue = string; -export interface ColorConfig {} +export interface ColorConfig { + presetColors?: string[]; +} export type DateValue = Date | number; export interface DateConfig {}