Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Group formats #137

Merged
merged 20 commits into from
Dec 19, 2023
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions src/lib/components/colors/FormatGroup.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<script lang="ts">
import { inGamut } from 'colorjs.io/fn';
import type { PlainColorObject } from 'colorjs.io/types/src/color';

import Output from '$lib/components/colors/Output.svelte';
import type { ColorFormatId } from '$lib/constants';
import { ColorSpace } from '$lib/stores';
import { getSpaceFromFormatId } from '$lib/utils';

import ExternalLink from '../util/ExternalLink.svelte';

export let type: 'bg' | 'fg';
export let color: PlainColorObject;
export let name: string;
export let formats: ColorFormatId[];

$: gamutSpace = ColorSpace.get(
getSpaceFromFormatId(formats[0] as ColorFormatId),
jgerigmeyer marked this conversation as resolved.
Show resolved Hide resolved
);
$: isInGamut = inGamut(color, gamutSpace);
</script>

<div data-content="format-group">
<h5>{name}</h5>
{#if !isInGamut}
<span data-color-info="warning"
>Selected color is <ExternalLink
href="https://www.w3.org/TR/css-color-4/#out-of-gamut"
>outside the {gamutSpace.name} gamut.</ExternalLink
></span
>
{/if}
{#each formats as format (format)}
<Output {type} {color} {format} />
{/each}
</div>

<style lang="scss">
[data-color-info='warning'] {
grid-area: message;
}
</style>
25 changes: 20 additions & 5 deletions src/lib/components/colors/Formats.svelte
Original file line number Diff line number Diff line change
@@ -1,22 +1,37 @@
<script lang="ts">
import type { PlainColorObject } from 'colorjs.io/types/src/color';

import Output from '$lib/components/colors/Output.svelte';
import FormatGroup from '$lib/components/colors/FormatGroup.svelte';
import type { ColorFormatId } from '$lib/constants';
import { FORMATS } from '$lib/constants';
import { FORMAT_GROUPS } from '$lib/constants';

export let type: 'bg' | 'fg';
export let color: PlainColorObject;
export let format: ColorFormatId;

function otherFormatGroups(
selectedFormat: ColorFormatId,
): typeof FORMAT_GROUPS {
const otherFormats: typeof FORMAT_GROUPS = {};
Object.keys(FORMAT_GROUPS).forEach((key) => {
const groupFormats = FORMAT_GROUPS[key]!.filter(
(s) => s !== selectedFormat,
);
if (groupFormats.length) {
otherFormats[key] = groupFormats;
}
});
return otherFormats;
}

$: displayType = type === 'bg' ? 'Background' : 'Foreground';
$: otherFormats = FORMATS.filter((s) => s !== format);
$: otherFormats = otherFormatGroups(format);
</script>

<div data-content="formats" data-column="tool">
<h4 class="small-only label">{displayType} Color</h4>
{#each otherFormats as format (format)}
<Output {type} {color} {format} />
{#each Object.entries(otherFormats) as [name, formats]}
<FormatGroup {type} {color} {name} {formats} />
{/each}
</div>

Expand Down
14 changes: 2 additions & 12 deletions src/lib/components/colors/Output.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<script lang="ts">
import { inGamut, serialize, to } from 'colorjs.io/fn';
import { serialize, to } from 'colorjs.io/fn';
import type { PlainColorObject } from 'colorjs.io/types/src/color';

import SupportWarning from '$lib/components/colors/SupportWarning.svelte';
Expand All @@ -13,23 +13,17 @@

$: targetSpace = getSpaceFromFormatId(format);
$: targetColor = to(color, targetSpace);
$: isInGamut = inGamut(targetColor);
$: targetColorValue = serialize(targetColor, {
format,
inGamut: false,
});
</script>

<ul data-group="output {type}">
<li>
<li data-testid={`format-${format}`}>
<CopyButton text={targetColorValue} />
<span data-color-info="value">{targetColorValue}</span>
<SupportWarning {format} />
{#if !isInGamut}
<span data-color-info="warning"
>This color is outside the {targetColor.space.name} gamut.</span
>
{/if}
</li>
</ul>

Expand All @@ -45,8 +39,4 @@
[data-color-info='value'] {
grid-area: color;
}

[data-color-info='warning'] {
grid-area: message;
}
</style>
6 changes: 6 additions & 0 deletions src/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ export const FORMATS: ColorFormatId[] = [
'srgb',
];

export const FORMAT_GROUPS: { [key: string]: ColorFormatId[] } = {
'sRGB Formats': ['hex', 'hsl', 'srgb'],
'Unbounded Spaces': ['lab', 'lch', 'oklab', 'oklch'],
'Display p3 Space': ['p3'],
};

export const RATIOS = {
AA: {
Normal: 4.5,
Expand Down
6 changes: 6 additions & 0 deletions test/js/fixtures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,9 @@ export const HSL_BLACK: PlainColorObject = {
};

export const HSL_WHITE_SERIALIZED = serialize(HSL_WHITE, { inGamut: false });

export const OUT_OF_BOUNDED_GAMUTS: PlainColorObject = {
space: ColorSpace.get('oklch'),
coords: [1, 1, 1],
alpha: 1,
};
40 changes: 40 additions & 0 deletions test/js/lib/components/colors/FormatGroup.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { render } from '@testing-library/svelte';

import FormatGroup from '$lib/components/colors/FormatGroup.svelte';
import { FORMAT_GROUPS } from '$src/lib/constants';
import { HSL_WHITE, OUT_OF_BOUNDED_GAMUTS } from '$test/fixtures';

describe('FormatGroup', () => {
it('renders selected group', () => {
const GROUP_NAME = 'sRGB Formats';
const { getByTestId, getByText } = render(FormatGroup, {
type: 'bg',
color: HSL_WHITE,
name: GROUP_NAME,
formats: FORMAT_GROUPS[GROUP_NAME]!,
});

expect(getByText(GROUP_NAME)).toBeVisible();
FORMAT_GROUPS[GROUP_NAME]?.forEach((format) => {
expect(getByTestId(`format-${format}`)).toBeVisible();
});
});

it('renders warning if out of gamut', () => {
const GROUP_NAME = 'sRGB Formats';
const { getByTestId, getByText } = render(FormatGroup, {
type: 'bg',
color: OUT_OF_BOUNDED_GAMUTS,
name: GROUP_NAME,
formats: FORMAT_GROUPS[GROUP_NAME]!,
});

expect(getByText(GROUP_NAME)).toBeVisible();
FORMAT_GROUPS[GROUP_NAME]?.forEach((format) => {
expect(getByTestId(`format-${format}`)).toBeVisible();
});
expect(
getByText('Selected color is outside the sRGB gamut.'),
).toBeVisible();
});
});
17 changes: 0 additions & 17 deletions test/js/lib/components/colors/Output.spec.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import { render } from '@testing-library/svelte';
import { serialize, to } from 'colorjs.io/fn';
import type { PlainColorObject } from 'colorjs.io/types/src/color';

import Output from '$lib/components/colors/Output.svelte';
import { ColorSpace } from '$lib/stores';
import { HSL_WHITE, HSL_WHITE_SERIALIZED } from '$test/fixtures';

describe('Output', () => {
Expand All @@ -28,19 +26,4 @@ describe('Output', () => {
getByText(serialize(to(HSL_WHITE, 'oklch'), { inGamut: false })),
).toBeVisible();
});

it('renders warning if out of gamut', () => {
const color: PlainColorObject = {
space: ColorSpace.get('oklch'),
coords: [0.01, 0.02, 0],
alpha: 1,
};
const { getByText } = render(Output, {
type: 'fg',
color,
format: 'hsl',
});

expect(getByText('outside the HSL gamut', { exact: false })).toBeVisible();
});
});
Loading