构建自动色板功能的基本页面结构。

This commit is contained in:
徐涛 2025-01-16 12:27:04 +08:00
parent 7a8bbaa826
commit b126858d8e
3 changed files with 160 additions and 0 deletions

View File

@ -10,6 +10,7 @@ import { LightenDarken } from './pages/LightenDarken';
import { MainLayout } from './pages/MainLayout'; import { MainLayout } from './pages/MainLayout';
import { Mixer } from './pages/Mixer'; import { Mixer } from './pages/Mixer';
import { NewScheme } from './pages/NewScheme'; import { NewScheme } from './pages/NewScheme';
import { AutomaticPalette } from './pages/Palette';
import { SchemeDetail } from './pages/SchemeDetail'; import { SchemeDetail } from './pages/SchemeDetail';
import { SchemeNotFound } from './pages/SchemeNotFound'; import { SchemeNotFound } from './pages/SchemeNotFound';
import { Schemes } from './pages/Schemes'; import { Schemes } from './pages/Schemes';
@ -39,6 +40,7 @@ const routes = createBrowserRouter([
{ path: 'tints-shades', element: <TintsShades /> }, { path: 'tints-shades', element: <TintsShades /> },
{ path: 'lighten-darken', element: <LightenDarken /> }, { path: 'lighten-darken', element: <LightenDarken /> },
{ path: 'mixer', element: <Mixer /> }, { path: 'mixer', element: <Mixer /> },
{ path: 'palette', element: <AutomaticPalette /> },
{ path: 'wacg', element: <WACGCheck /> }, { path: 'wacg', element: <WACGCheck /> },
{ path: 'compare', element: <ColorCompare /> }, { path: 'compare', element: <ColorCompare /> },
{ {

View File

@ -0,0 +1,47 @@
@layer pages {
.palette_workspace {
flex-direction: column;
}
.palette_section {
width: 100%;
flex: 1;
display: flex;
flex-direction: row;
align-items: stretch;
gap: var(--spacing-m);
}
.function_side {
display: flex;
flex-direction: column;
gap: var(--spacing-m);
font-size: var(--font-size-s);
.mode_navigation {
display: flex;
flex-direction: column;
align-items: stretch;
gap: var(--spacing-s);
}
h5 {
padding-block: var(--spacing-m);
font-size: var(--font-size-m);
}
}
.palette_content {
flex: 1;
padding: 0 var(--spacing-m);
display: flex;
flex-direction: column;
gap: var(--spacing-s);
h5 {
padding-block: var(--spacing-m);
font-size: var(--font-size-m);
}
.color_value_mode {
display: flex;
flex-direction: row;
align-items: center;
gap: var(--spacing-s);
font-size: var(--font-size-s);
}
}
}

111
src/pages/Palette.tsx Normal file
View File

@ -0,0 +1,111 @@
import cx from 'clsx';
import { useAtom } from 'jotai';
import { useEffect, useMemo, useState } from 'react';
import { ColorPicker } from '../components/ColorPicker';
import { HSegmentedControl } from '../components/HSegmentedControl';
import { Labeled } from '../components/Labeled';
import { LabeledPicker } from '../components/LabeledPicker';
import { ScrollArea } from '../components/ScrollArea';
import { Switch } from '../components/Switch';
import { currentPickedColor } from '../stores/colors';
import styles from './Palette.module.css';
export function AutomaticPalette() {
const [selectedColor, setSelectedColor] = useAtom(currentPickedColor);
const [useReferenceColor, setUseReferenceColor] = useState(false);
const [swatchAmount, setSwatchAmount] = useState(5);
const maxBias = useMemo(
() => (swatchAmount > 3 ? Math.floor(swatchAmount / 2) - 1 : 0),
[swatchAmount],
);
const [referenceBias, setReferenceBias] = useState(0);
const [minLightness, setMinLightness] = useState(10);
const [maxLightness, setMaxLightness] = useState(90);
const [mode, setMode] = useState<'hex' | 'rgb' | 'hsl' | 'lab' | 'oklch'>('hex');
useEffect(() => {
if (useReferenceColor) {
setReferenceBias(0);
}
}, [swatchAmount, useReferenceColor]);
return (
<div className={cx('workspace', styles.palette_workspace)}>
<header>
<h3>Automatic Palette</h3>
<p>
Automatically generate a color palette suitable for UI color matching according to the
given color algorithm.
</p>
</header>
<ScrollArea enableY>
<section className={styles.palette_section}>
<aside className={styles.function_side}>
<div>
<h5>Reference Color</h5>
<ColorPicker color={selectedColor} onSelect={(color) => setSelectedColor(color)} />
</div>
<div>
<h5>Palette Setting</h5>
<Labeled label="Use Reference Color" inline>
<Switch checked={useReferenceColor} onChange={setUseReferenceColor} />
</Labeled>
<LabeledPicker
title="Swatch Amount"
min={3}
max={15}
step={1}
value={swatchAmount}
onChange={(value) => setSwatchAmount(value)}
/>
<LabeledPicker
title="Reference Bias"
min={0}
max={maxBias}
step={1}
value={referenceBias}
onChange={setReferenceBias}
disabled={!useReferenceColor || maxBias < 2}
/>
<LabeledPicker
title="Min Lightness"
min={0}
max={100}
step={1}
value={minLightness}
onChange={setMinLightness}
unit="%"
/>
<LabeledPicker
title="Max Lightness"
min={0}
max={100}
step={1}
value={maxLightness}
onChange={setMaxLightness}
unit="%"
/>
</div>
</aside>
<div className={styles.palette_content}>
<h5>Generated Palette</h5>
<div className={styles.color_value_mode}>
<label>Copy color value in</label>
<HSegmentedControl
options={[
{ label: 'HEX', value: 'hex' },
{ label: 'RGB', value: 'rgb' },
{ label: 'HSL', value: 'hsl' },
{ label: 'LAB', value: 'lab' },
{ label: 'OKLCH', value: 'oklch' },
]}
valu={mode}
onChange={setMode}
/>
</div>
</div>
</section>
</ScrollArea>
</div>
);
}