sforkowany z mirror/soapbox
ThemeEditor: add hue sliders
rodzic
faf513c049
commit
2505f622e2
|
@ -1,7 +1,9 @@
|
||||||
import React from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
|
|
||||||
import { HStack } from 'soapbox/components/ui';
|
import { HStack, Stack, Slider } from 'soapbox/components/ui';
|
||||||
|
import { usePrevious } from 'soapbox/hooks';
|
||||||
import { compareId } from 'soapbox/utils/comparators';
|
import { compareId } from 'soapbox/utils/comparators';
|
||||||
|
import { hueShift } from 'soapbox/utils/theme';
|
||||||
|
|
||||||
import Color from './color';
|
import Color from './color';
|
||||||
|
|
||||||
|
@ -18,6 +20,9 @@ interface IPalette {
|
||||||
const Palette: React.FC<IPalette> = ({ palette, onChange }) => {
|
const Palette: React.FC<IPalette> = ({ palette, onChange }) => {
|
||||||
const tints = Object.keys(palette).sort(compareId);
|
const tints = Object.keys(palette).sort(compareId);
|
||||||
|
|
||||||
|
const [hue, setHue] = useState(0);
|
||||||
|
const lastHue = usePrevious(hue);
|
||||||
|
|
||||||
const handleChange = (tint: string) => {
|
const handleChange = (tint: string) => {
|
||||||
return (color: string) => {
|
return (color: string) => {
|
||||||
onChange({
|
onChange({
|
||||||
|
@ -27,12 +32,27 @@ const Palette: React.FC<IPalette> = ({ palette, onChange }) => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const delta = hue - (lastHue || 0);
|
||||||
|
|
||||||
|
const adjusted = Object.entries(palette).reduce<ColorGroup>((result, [tint, hex]) => {
|
||||||
|
result[tint] = hueShift(hex, delta * 360);
|
||||||
|
return result;
|
||||||
|
}, {});
|
||||||
|
|
||||||
|
onChange(adjusted);
|
||||||
|
}, [hue]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<HStack className='w-full h-8 rounded-md overflow-hidden'>
|
<Stack className='w-full'>
|
||||||
{tints.map(tint => (
|
<HStack className='h-8 rounded-md overflow-hidden'>
|
||||||
<Color color={palette[tint]} onChange={handleChange(tint)} />
|
{tints.map(tint => (
|
||||||
))}
|
<Color color={palette[tint]} onChange={handleChange(tint)} />
|
||||||
</HStack>
|
))}
|
||||||
|
</HStack>
|
||||||
|
|
||||||
|
<Slider value={hue} onChange={setHue} />
|
||||||
|
</Stack>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -116,3 +116,18 @@ export const colorsToCss = (colors: TailwindColorPalette): string => {
|
||||||
export const generateThemeCss = (soapboxConfig: SoapboxConfig): string => {
|
export const generateThemeCss = (soapboxConfig: SoapboxConfig): string => {
|
||||||
return colorsToCss(soapboxConfig.colors.toJS() as TailwindColorPalette);
|
return colorsToCss(soapboxConfig.colors.toJS() as TailwindColorPalette);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const hexToHsl = (hex: string): Hsl | null => {
|
||||||
|
const rgb = hexToRgb(hex);
|
||||||
|
return rgb ? rgbToHsl(rgb) : null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const hueShift = (hex: string, delta: number): string => {
|
||||||
|
const { h, s, l } = hexToHsl(hex)!;
|
||||||
|
|
||||||
|
return hslToHex({
|
||||||
|
h: (h + delta) % 360,
|
||||||
|
s,
|
||||||
|
l,
|
||||||
|
});
|
||||||
|
};
|
Ładowanie…
Reference in New Issue