diff --git a/src/App.tsx b/src/App.tsx
index e0d4022..c73fc51 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -12,6 +12,7 @@ import { SchemeNotFound } from './pages/SchemeNotFound';
import { Schemes } from './pages/Schemes';
import { TintsShades } from './pages/TintsShades';
import { Tones } from './pages/Tones';
+import { WACGCheck } from './pages/WACG';
import { Wheels } from './pages/Wheels';
const routes = createBrowserRouter([
@@ -35,6 +36,7 @@ const routes = createBrowserRouter([
{ path: 'tints-shades', element: },
{ path: 'lighten-darken', element: },
{ path: 'mixer', element: },
+ { path: 'wacg', element: },
],
},
]);
diff --git a/src/page-components/wacg/Ratio.module.css b/src/page-components/wacg/Ratio.module.css
new file mode 100644
index 0000000..ef4a55c
--- /dev/null
+++ b/src/page-components/wacg/Ratio.module.css
@@ -0,0 +1,13 @@
+@layer pages {
+ .ratio_layout {
+ width: 100%;
+ display: flex;
+ flex-direction: row;
+ justify-content: center;
+ padding: var(--spacing-s) var(--spacing-m);
+ .ratio {
+ font-size: calc(var(--font-size) * 5);
+ font-weight: bold;
+ }
+ }
+}
diff --git a/src/page-components/wacg/Ratio.tsx b/src/page-components/wacg/Ratio.tsx
new file mode 100644
index 0000000..79010b6
--- /dev/null
+++ b/src/page-components/wacg/Ratio.tsx
@@ -0,0 +1,13 @@
+import styles from './Ratio.module.css';
+
+type ContrastRatioProps = {
+ ratio: number;
+};
+
+export function ContrastRatio({ ratio }: ContrastRatioProps) {
+ return (
+
+
{ratio.toFixed(2)} : 1
+
+ );
+}
diff --git a/src/page-components/wacg/TextDemo.module.css b/src/page-components/wacg/TextDemo.module.css
new file mode 100644
index 0000000..ca57b12
--- /dev/null
+++ b/src/page-components/wacg/TextDemo.module.css
@@ -0,0 +1,46 @@
+@layer pages {
+ .demo_block {
+ border: 1px solid var(--color-border);
+ border-radius: var(--border-radius-xxs);
+ padding: var(--spacing-m) var(--spacing-s);
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ white-space: nowrap;
+ gap: var(--spacing-s);
+ .normal_text {
+ font-size: 14pt;
+ }
+ .large_text {
+ font-size: 18pt;
+ }
+ .bold_text {
+ font-size: 14pt;
+ font-weight: bold;
+ }
+ }
+ .wacg_rating {
+ width: 100%;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ gap: var(--spacing-s);
+ .rating_unit {
+ flex: 1;
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ gap: var(--spacing-m);
+ }
+ }
+ .sub_header {
+ display: flex;
+ flex-direction: row;
+ align-items: baseline;
+ gap: var(--spacing-m);
+ }
+ .description {
+ font-size: var(--font-size-xs);
+ color: var(--color-neutral-focus);
+ }
+}
diff --git a/src/page-components/wacg/TextDemo.tsx b/src/page-components/wacg/TextDemo.tsx
new file mode 100644
index 0000000..f4fc54c
--- /dev/null
+++ b/src/page-components/wacg/TextDemo.tsx
@@ -0,0 +1,61 @@
+import cx from 'clsx';
+import styles from './TextDemo.module.css';
+
+type TextDemoProps = {
+ fg: string;
+ bg: string;
+ ratio: number;
+};
+
+export function TextDemo({ fg, bg, ratio }: TextDemoProps) {
+ return (
+ <>
+
+ Normal Text
+ 14pt normal weight text.
+
+
+
The quick brown fox jumps over the lazy dog.
+
白日依山尽,黄河入海流。欲穷千里目,更上一层楼。
+
+
+
+ WACG AA:
+ 4.5 ? 'success' : 'danger')}>
+ {ratio > 4.5 ? 'pass' : 'failed'}
+
+
+
+ WACG AAA:
+ 7 ? 'success' : 'danger')}>
+ {ratio > 7 ? 'pass' : 'failed'}
+
+
+
+
+
+
The quick brown fox jumps over the lazy dog.
+
白日依山尽,黄河入海流。欲穷千里目,更上一层楼。
+
The quick brown fox jumps over the lazy dog.
+
白日依山尽,黄河入海流。欲穷千里目,更上一层楼。
+
+
+
+ WACG AA:
+ 3 ? 'success' : 'danger')}>
+ {ratio > 3 ? 'pass' : 'failed'}
+
+
+
+ WACG AAA:
+ 4.5 ? 'success' : 'danger')}>
+ {ratio > 4.5 ? 'pass' : 'failed'}
+
+
+
+ >
+ );
+}
diff --git a/src/pages/WACG.module.css b/src/pages/WACG.module.css
new file mode 100644
index 0000000..e9b5a20
--- /dev/null
+++ b/src/pages/WACG.module.css
@@ -0,0 +1,40 @@
+@layer pages {
+ .wacg_workspace {
+ flex-direction: column;
+ }
+ .explore_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);
+ }
+ }
+ .wacg_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);
+ }
+ }
+}
diff --git a/src/pages/WACG.tsx b/src/pages/WACG.tsx
new file mode 100644
index 0000000..5ab482e
--- /dev/null
+++ b/src/pages/WACG.tsx
@@ -0,0 +1,47 @@
+import cx from 'clsx';
+import { useMemo, useState } from 'react';
+import { useColorFunction } from '../ColorFunctionContext';
+import { ColorPicker } from '../components/ColorPicker';
+import { ScrollArea } from '../components/ScrollArea';
+import { ContrastRatio } from '../page-components/wacg/Ratio';
+import { TextDemo } from '../page-components/wacg/TextDemo';
+import styles from './WACG.module.css';
+
+export function WACGCheck() {
+ const { colorFn } = useColorFunction();
+ const [fgColor, setFgColor] = useState('ffffff');
+ const [bgColor, setBgColor] = useState('000000');
+ const contrastRatio = useMemo(() => {
+ try {
+ if (!colorFn) return 1;
+ const ratio = colorFn.wacg_relative_contrast(fgColor, bgColor);
+ return ratio;
+ } catch (e) {
+ console.error('[WACG Check]', e);
+ }
+ return 1;
+ }, [fgColor, bgColor]);
+
+ return (
+
+
+
+
+
+
+
WACG Contrast Ratio
+
+
+
+
+
+
+ );
+}