diff --git a/src/App.tsx b/src/App.tsx
index 83384b1..e0d4022 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -5,6 +5,7 @@ import { Harmonies } from './pages/Harmonies';
import { Home } from './pages/Home';
import { LightenDarken } from './pages/LightenDarken';
import { MainLayout } from './pages/MainLayout';
+import { Mixer } from './pages/Mixer';
import { NewScheme } from './pages/NewScheme';
import { SchemeDetail } from './pages/SchemeDetail';
import { SchemeNotFound } from './pages/SchemeNotFound';
@@ -33,6 +34,7 @@ const routes = createBrowserRouter([
{ path: 'tones', element: },
{ path: 'tints-shades', element: },
{ path: 'lighten-darken', element: },
+ { path: 'mixer', element: },
],
},
]);
diff --git a/src/pages/Mixer.module.css b/src/pages/Mixer.module.css
new file mode 100644
index 0000000..4c1f217
--- /dev/null
+++ b/src/pages/Mixer.module.css
@@ -0,0 +1,34 @@
+@layer pages {
+ .mixer_workspace {
+ flex-direction: column;
+ }
+ .mixer_content {
+ width: 100%;
+ display: flex;
+ flex-direction: row;
+ justify-content: space-around;
+ align-items: flex-start;
+ gap: var(--spacing-m);
+ .mixer_column {
+ display: flex;
+ flex-direction: column;
+ gap: var(--spacing-s);
+ font-size: var(--font-size-s);
+ .color_value_mode {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ gap: var(--spacing-s);
+ font-size: var(--font-size-s);
+ }
+ .colors_booth {
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ align-items: stretch;
+ gap: var(--spacing-xs);
+ min-height: 12em;
+ }
+ }
+ }
+}
diff --git a/src/pages/Mixer.tsx b/src/pages/Mixer.tsx
new file mode 100644
index 0000000..bb8f65d
--- /dev/null
+++ b/src/pages/Mixer.tsx
@@ -0,0 +1,79 @@
+import cx from 'clsx';
+import { useMemo, useState } from 'react';
+import { useColorFunction } from '../ColorFunctionContext';
+import { ColorPicker } from '../components/ColorPicker';
+import { FlexColorStand } from '../components/FlexColorStand';
+import { HSegmentedControl } from '../components/HSegmentedControl';
+import { LabeledPicker } from '../components/LabeledPicker';
+import { ScrollArea } from '../components/ScrollArea';
+import styles from './Mixer.module.css';
+
+export function Mixer() {
+ const { colorFn } = useColorFunction();
+ const [basicColor, setBasicColor] = useState('000000');
+ const [mixColor, setMixColor] = useState('000000');
+ const [mixRatio, setMixRatio] = useState(0);
+ const [mode, setMode] = useState<'hex' | 'rgb' | 'hsl' | 'lab' | 'oklch'>('hex');
+ const mixedColor = useMemo(() => {
+ try {
+ if (!colorFn) {
+ return '000000';
+ }
+ const mixed = colorFn.mix(basicColor, mixColor, mixRatio / 100);
+ return mixed;
+ } catch (e) {
+ console.error('[Mix Color]', e);
+ }
+ return '000000';
+ }, [basicColor, mixColor, mixRatio]);
+
+ return (
+
+
+
+
+
+
Basic Color
+
+
+
+
Mix Color
+
+
+
+
+
Mix Result
+
+
+
+
+
+
+
+
+
+
+
+ );
+}