diff --git a/apps/theme/app/contrast-charts/page.module.css b/apps/theme/app/contrast-charts/page.module.css new file mode 100644 index 0000000000..059bbeb235 --- /dev/null +++ b/apps/theme/app/contrast-charts/page.module.css @@ -0,0 +1,4 @@ +.subHeading { + margin-bottom: 12px !important; + margin-top: 32px !important; +} diff --git a/apps/theme/app/contrast-charts/page.tsx b/apps/theme/app/contrast-charts/page.tsx new file mode 100644 index 0000000000..b00c31c3ce --- /dev/null +++ b/apps/theme/app/contrast-charts/page.tsx @@ -0,0 +1,27 @@ +'use client'; +import { Heading } from '@digdir/designsystemet-react'; +import { Container } from '@repo/components'; +import { ContrastChart } from '../../components/ContrastChart/ContrastChart'; +import classes from './page.module.css'; + +export default function ContrastCharts() { + return ( +
+
+ +
+ Kontrastoversikt + + Light mode + + + + Dark mode + + +
+
+
+
+ ); +} diff --git a/apps/theme/components/ContrastChart/ContrastChart.module.css b/apps/theme/components/ContrastChart/ContrastChart.module.css new file mode 100644 index 0000000000..9de6862c30 --- /dev/null +++ b/apps/theme/components/ContrastChart/ContrastChart.module.css @@ -0,0 +1,103 @@ +.color { + height: 36px; + display: block; + flex: 1 1; + box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1); + border-radius: 2px; +} + +.colors { + display: flex; + gap: 12px; +} + +.table { + background-color: #e2e2e2; + margin-bottom: 100px; +} + +.cell { + padding: 14px; + display: flex; + flex-direction: column; + justify-content: space-between; + height: 100%; +} + +.tag { + background-color: #d23e3e; + color: white; + border-radius: 400px; + font-size: 13px; + font-weight: 500; + display: flex; + align-items: center; + justify-content: center; + padding: 3px 9px; +} + +.AA { + background-color: green; + margin-left: 4px; +} + +.AAA { + background-color: #407be9; +} + +.AA18 { + background-color: #fbb025; + color: black; +} + +.meta { + display: flex; + align-items: center; + justify-content: space-between; +} + +.contrast { + font-size: 16px; + font-weight: 500; + width: 48px; + text-align: center; +} + +.table, +.td, +.th { + border: 4px solid var(--ds-color-neutral-background-default); + border-collapse: collapse; + background-color: var(--ds-color-neutral-surface-default); +} + +.th { + height: 90px; + width: 140px; + padding: 16px; +} + +.td { + height: 90px; + width: 140px; + vertical-align: top; +} + +.header { + font-size: 16px; + width: 30px; + text-align: left; + display: flex; + flex-direction: column; + gap: 2px; + font-weight: 500; +} + +.headerHex { + color: var(--ds-color-neutral-text-subtle); + font-weight: 400; +} + +.contrastChart { + background-color: transparent; +} diff --git a/apps/theme/components/ContrastChart/ContrastChart.tsx b/apps/theme/components/ContrastChart/ContrastChart.tsx new file mode 100644 index 0000000000..bf62f573ff --- /dev/null +++ b/apps/theme/components/ContrastChart/ContrastChart.tsx @@ -0,0 +1,107 @@ +import { + type ColorInfo, + generateThemeForColor, + getColorNameFromNumber, + getContrastFromHex, +} from '@/packages/cli/dist/src'; + +import cl from 'clsx/lite'; +import classes from './ContrastChart.module.css'; + +type ContrastChartProps = { + type?: 'light' | 'dark'; +}; + +export const ContrastChart = ({ type = 'light' }: ContrastChartProps) => { + const theme = generateThemeForColor('#0062BA'); + const includedColorIndexes = [1, 2, 3, 4, 5, 6, 7, 8, 12, 13]; + const reducedLight = theme.light.filter((color) => + includedColorIndexes.includes(color.number), + ); + const reducedDark = theme.dark.filter((color) => + includedColorIndexes.includes(color.number), + ); + + const Tag = ({ + color1, + color2, + }: { color1: ColorInfo; color2: ColorInfo }) => { + const contrast = getContrastFromHex(color1.hex, color2.hex); + let type = 'AAA'; + + if (contrast < 3) { + type = 'FAIL'; + } else if (contrast < 4.5) { + type = 'AA18'; + } else if (contrast < 7) { + type = 'AA'; + } + + return
{type}
; + }; + + const TdCell = ({ + color1, + color2, + }: { color1: ColorInfo; color2: ColorInfo }) => { + return ( +
+
+
+
+
+
+ +
+ {Math.floor(getContrastFromHex(color1.hex, color2.hex) * 10) / 10} + :1 +
+
+
+ ); + }; + + const ThCell = ({ color }: { color: ColorInfo }) => { + return ( + +
+ {getColorNameFromNumber(color.number)} +
{color.hex}
+
+ + ); + }; + + const reducedColors = type === 'light' ? reducedLight : reducedDark; + const themeColors = type === 'light' ? theme.light : theme.dark; + + return ( +
+ + + + + {includedColorIndexes.map((number, index) => ( + + + {reducedColors.map((color, index) => ( + + ))} + + ))} +
+ {reducedColors.map((color, index) => ( + + ))} +
+ +
+
+ ); +}; diff --git a/packages/cli/src/colors/theme.ts b/packages/cli/src/colors/theme.ts index 9a55e87e8e..4576fee6be 100644 --- a/packages/cli/src/colors/theme.ts +++ b/packages/cli/src/colors/theme.ts @@ -68,18 +68,18 @@ const generateThemeColor = (color: CssColor, colorScheme: ColorMode, contrastMod leoBackgroundColor.colorKeys[0], ); - const textSubLightLightness = contrastMode === 'aa' ? 42 : 30; + const textSubLightLightness = contrastMode === 'aa' ? 41 : 30; const textDefLightLightness = contrastMode === 'aa' ? 18 : 12; - const textSubDarkLightness = contrastMode === 'aa' ? 67 : 80; + const textSubDarkLightness = contrastMode === 'aa' ? 66 : 80; const textDefDarkLightness = contrastMode === 'aa' ? 90 : 94; let lightnessScale: number[] = []; if (colorScheme === 'light') { - lightnessScale = [100, 96, 90, 84, 78, 76, 54, 33, textSubLightLightness, textDefLightLightness]; + lightnessScale = [100, 96, 90, 84, 78, 76, 53, 41, textSubLightLightness, textDefLightLightness]; } else if (colorScheme === 'dark') { - lightnessScale = [10, 14, 20, 26, 32, 35, 47, 77, textSubDarkLightness, textDefDarkLightness]; + lightnessScale = [10, 14, 20, 26, 32, 35, 52, 66, textSubDarkLightness, textDefDarkLightness]; } else { lightnessScale = [1, 6, 14, 20, 26, 58, 70, 82, 80, 95]; }