diff --git a/src/page-components/scheme/Q2Scheme.tsx b/src/page-components/scheme/Q2Scheme.tsx index f15ac69..fb027d7 100644 --- a/src/page-components/scheme/Q2Scheme.tsx +++ b/src/page-components/scheme/Q2Scheme.tsx @@ -6,6 +6,7 @@ import { Q2SchemeStorage } from '../../q-2-scheme'; import { isNilOrEmpty } from '../../utls'; import { SchemeExport } from './Export'; import { Q2SchemeBuilder } from './q-2-scheme/Builder'; +import Q2SchemePreview from './q-2-scheme/Preview'; const tabOptions = [ { title: 'Overview', id: 'overview' }, @@ -33,6 +34,7 @@ export function Q2Scheme({ scheme }: Q2SchemeProps) { export: isNilOrEmpty(scheme.schemeStorage?.cssVariables), }} /> + {isEqual(activeTab, 'overview') && } {isEqual(activeTab, 'builder') && ( setActiveTab('overview')} /> )} diff --git a/src/page-components/scheme/q-2-scheme/Preview.module.css b/src/page-components/scheme/q-2-scheme/Preview.module.css new file mode 100644 index 0000000..81f9785 --- /dev/null +++ b/src/page-components/scheme/q-2-scheme/Preview.module.css @@ -0,0 +1,58 @@ +@layer pages { + .preview_layout { + padding: var(--spacing-s) var(--spacing-m); + width: 100%; + display: flex; + flex-direction: column; + align-items: stretch; + gap: var(--spacing-m); + } + .preview_block { + width: inherit; + padding: var(--spacing-xl) var(--spacing-m); + display: flex; + flex-direction: column; + justify-content: flex-start; + align-items: stretch; + gap: var(--spacing-xs); + h2 { + font-size: var(--font-size-xl); + font-weight: bold; + line-height: 1.7em; + } + } + .preview_unit { + width: inherit; + display: grid; + grid-template-columns: repeat(5, 1fr); + gap: var(--spacing-xs); + } + .preview_indi_block { + width: inherit; + display: grid; + grid-template-columns: repeat(4, 1fr); + gap: var(--spacing-xs); + } + .preview_swatch { + width: inherit; + display: grid; + grid-template-columns: repeat(16, 1fr); + gap: var(--spacing-xs); + .preview_swatch_cell { + height: 1em; + } + } + .preview_cell { + padding: var(--spacing-xs) var(--spacing-s); + display: flex; + flex-direction: column; + align-items: flex-start; + gap: var(--spacing-xxs); + font-size: var(--font-size-s); + line-height: 1.5em; + .wacg { + font-size: var(--font-size-xxs); + line-height: 1em; + } + } +} diff --git a/src/page-components/scheme/q-2-scheme/Preview.tsx b/src/page-components/scheme/q-2-scheme/Preview.tsx new file mode 100644 index 0000000..c9141a8 --- /dev/null +++ b/src/page-components/scheme/q-2-scheme/Preview.tsx @@ -0,0 +1,169 @@ +import { capitalize, keys } from 'lodash-es'; +import { FC, ReactNode, useMemo } from 'react'; +import { useColorFunction } from '../../../ColorFunctionContext'; +import { ScrollArea } from '../../../components/ScrollArea'; +import { SchemeContent } from '../../../models'; +import { Q2Baseline, Q2ColorSet, Q2ColorUnit, Q2SchemeStorage } from '../../../q-2-scheme'; +import styles from './Preview.module.css'; + +interface PreviewCellProps { + bg: string; + fg: string; + children: ReactNode; +} + +const PreviewCell: FC = ({ bg, fg, children }) => { + const { colorFn } = useColorFunction(); + const wacgRatio = useMemo(() => { + try { + if (!colorFn) return null; + return colorFn.wacg_relative_contrast(fg, bg); + } catch (e) { + console.error('[Error on calc WACG Ratio]', e); + } + return null; + }, [bg, fg]); + + return ( + + {children} + {wacgRatio && WACG {wacgRatio?.toFixed(2)}} + + ); +}; + +interface PreviewLineProps { + name: string; + unit: Q2ColorSet; +} + +const PreviewLine: FC = ({ name, unit }) => { + return ( + + + {name} + + + {name} Hover + + + {name} Active + + + {name} Focus + + + {name} Disabled + + + ); +}; + +interface PreviewSwatchLineProps { + swatch: Record; +} + +const PreviewSwatchLine: FC = ({ swatch }) => { + const cells = useMemo(() => { + const collection: ReactNode[] = []; + for (const key of keys(swatch)) { + const color = swatch[key]; + collection.push( + , + ); + } + return collection; + }, [swatch]); + + return {cells}; +}; + +interface PreviewSetProps { + name: string; + colorUnit: Q2ColorUnit; +} + +const PreviewSet: FC = ({ name, colorUnit }) => { + return ( + <> + + + + > + ); +}; + +interface PreviewBlockProps { + baseline: Q2Baseline; + title: string; +} + +const PreviewBlock: FC = ({ baseline, title }) => { + const customSets = useMemo(() => { + const colors = keys(baseline.custom); + const elements: ReactNode[] = []; + + for (const key of colors) { + const color = baseline.custom[key]; + elements.push(); + } + + return elements; + }, [baseline.custom]); + + return ( + + {title} + + + + + + + + + + + + + + + Shadow + + + Overlay + + + Outline + + + Outline Variant + + + {customSets} + + ); +}; + +interface PreviewProps { + scheme: SchemeContent; +} + +const Q2SchemePreview: FC = ({ scheme }) => { + return ( + + + + {scheme.schemeStorage.scheme?.light && ( + + )} + {scheme.schemeStorage.scheme?.dark && ( + + )} + + + + ); +}; + +export default Q2SchemePreview; diff --git a/src/q-2-scheme.ts b/src/q-2-scheme.ts index 98f2379..b204d4f 100644 --- a/src/q-2-scheme.ts +++ b/src/q-2-scheme.ts @@ -13,7 +13,7 @@ export type Q2ColorSet = { export type Q2ColorUnit = { root: Q2ColorSet; surface: Q2ColorSet; - swatch: Map; + swatch: Record; }; export type Q2Baseline = { @@ -33,7 +33,7 @@ export type Q2Baseline = { overlay: string; outline: string; outlineVariant: string; - custom: Map; + custom: Record; }; export type Q2Scheme = {