Skip to content

Commit

Permalink
Add ColorSwitcher component
Browse files Browse the repository at this point in the history
  • Loading branch information
hcodes committed Aug 25, 2024
1 parent d420b55 commit 1a0290d
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 0 deletions.
9 changes: 9 additions & 0 deletions src/components/ColorSwitcher/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
.color-switcher {
margin-top: 1em;
}

.color-switcher__list {
margin: .5em 0 0 0;
padding: 0;
display: flex;
}
48 changes: 48 additions & 0 deletions src/components/ColorSwitcher/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { h } from 'preact';

import { block } from '../../utils/css/bem';
import { useCallback, useState } from 'preact/hooks';
import { ColorSwitcherItem } from '../ColorSwitcherItem';

import './index.css';

interface ColorSwitcherProps {
label?: string;
title?: string;
selected?: string;
items: {
title?: string;
value: string;
color: string;
}[];
}

const b = block('color-switcher');

export function ColorSwitcher(props: ColorSwitcherProps) {
const [ value, setValue ] = useState<string>(props.selected || props.items[0].value);

const handleClick = useCallback((data: string) => {
setValue(data);
}, [setValue]);

return (
<div class={b()}>
{props.label ?(<div class={b('label')} title={props.title}>{props.label}</div>) : null }
<ul class={b('list')}>
{props.items.map(item => {
return (
<ColorSwitcherItem
onClick={handleClick}
key={item.value}
color={item.color}
title={item.title}
value={item.value}
selected={item.value === value }
/>
);
})}
</ul>
</div>
);
}
49 changes: 49 additions & 0 deletions src/components/ColorSwitcherItem/index.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
.color-switcher-item {
display: block;
width: 40px;
height: 40px;
margin: 0 10px 0 0;
padding: 0;
border: 2px solid transparent;
border-radius: 100% 100%;
cursor: pointer;
list-style-type: none;
box-sizing: border-box;
transition: border-color .2s ease;
}

.color-switcher-item_selected {
border-color: gold;
}

.color-switcher-item__color {
position: relative;
border-radius: 100% 100%;
width: 100%;
height: 100%;
}

.color-switcher-item__color:before {
position: absolute;
left: 0;
top: 0;
right: 0;
bottom: 0;
content: '';
border: 1px solid rgba(0, 0, 0, .5);
border-radius: 100% 100%;
box-sizing: border-box;
}

.color-switcher-item__color:after {
position: absolute;
left: 1px;
top: 1px;
right: 1px;
bottom: 1px;
content: '';
border: 1px solid rgba(255, 255, 255, .5);
border-radius: 100% 100%;
box-sizing: border-box;
}

29 changes: 29 additions & 0 deletions src/components/ColorSwitcherItem/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { h } from 'preact';
import { useCallback } from 'preact/hooks';

import { block } from '../../utils/css/bem';

import './index.css';

const b = block('color-switcher-item');

interface ColorSwitcherItemProps {
color: string;
title?: string;
value: string;
selected: boolean;

onClick: (value: string) => void;
}

export function ColorSwitcherItem(props: ColorSwitcherItemProps) {
const handleClick = useCallback(() => {
props.onClick(props.value);
}, []);

return (<li
class={b({ selected: props.selected })}
>
<div onClick={handleClick} title={props.title} class={b('color')} style={`background-color: ${props.color}`}></div>
</li>);
}

0 comments on commit 1a0290d

Please sign in to comment.