diff --git a/src/lib/components/GamutSelect.svelte b/src/lib/components/GamutSelect.svelte
new file mode 100644
index 00000000..70f39133
--- /dev/null
+++ b/src/lib/components/GamutSelect.svelte
@@ -0,0 +1,15 @@
+
+
+
+
-
-
diff --git a/src/lib/components/colors/FormatGroup.svelte b/src/lib/components/colors/FormatGroup.svelte
index 7cbca4f2..9a0a481c 100644
--- a/src/lib/components/colors/FormatGroup.svelte
+++ b/src/lib/components/colors/FormatGroup.svelte
@@ -2,12 +2,11 @@
import { inGamut, type PlainColorObject } from 'colorjs.io/fn';
import Output from '$lib/components/colors/Output.svelte';
+ import ExternalLink from '$lib/components/util/ExternalLink.svelte';
import type { FormatGroup } from '$lib/constants';
import { ColorSpace } from '$lib/stores';
import { getSpaceFromFormatId } from '$lib/utils';
- import ExternalLink from '../util/ExternalLink.svelte';
-
interface Props {
type: 'bg' | 'fg';
color: PlainColorObject;
diff --git a/src/lib/components/colors/Header.svelte b/src/lib/components/colors/Header.svelte
index 6b3cf086..39037e67 100644
--- a/src/lib/components/colors/Header.svelte
+++ b/src/lib/components/colors/Header.svelte
@@ -1,10 +1,11 @@
diff --git a/src/sass/components/_color-settings.scss b/src/sass/components/_color-settings.scss
new file mode 100644
index 00000000..51d53a4b
--- /dev/null
+++ b/src/sass/components/_color-settings.scss
@@ -0,0 +1,23 @@
+@use '../config';
+
+[data-setting] {
+ align-items: center;
+ column-gap: var(--gutter);
+ display: grid;
+ grid-template:
+ 'format-label' auto
+ 'format-input' auto / 1fr;
+ justify-content: end;
+
+ @include config.above('sm-page-break') {
+ grid-template: 'format-label format-input' auto / 1fr auto;
+ }
+
+ label {
+ grid-area: format-label;
+ }
+
+ select {
+ grid-area: format-input;
+ }
+}
diff --git a/src/sass/components/_index.scss b/src/sass/components/_index.scss
index 33703f58..57f46e51 100644
--- a/src/sass/components/_index.scss
+++ b/src/sass/components/_index.scss
@@ -1,4 +1,5 @@
// Components Manifest
// ===================
+@forward 'color-settings';
@forward 'social-nav';
diff --git a/src/sass/initial/_layout.scss b/src/sass/initial/_layout.scss
index 35e3fa39..6c269086 100644
--- a/src/sass/initial/_layout.scss
+++ b/src/sass/initial/_layout.scss
@@ -40,10 +40,13 @@ body {
display: grid;
gap: var(--shim) var(--double-gutter);
grid-area: header;
- grid-template: 'logo colorspace' auto / auto 1fr;
+ grid-template: 'logo' auto 'settings' auto / 1fr;
@include config.above('sm-page-break') {
+ --justify-settings: safe end;
+
gap: var(--double-gutter);
+ grid-template: 'logo settings' auto / auto 1fr;
}
}
diff --git a/src/sass/patterns/_forms.scss b/src/sass/patterns/_forms.scss
index 65dacf9b..68e22752 100644
--- a/src/sass/patterns/_forms.scss
+++ b/src/sass/patterns/_forms.scss
@@ -61,6 +61,7 @@ select {
}
input[type='range'] {
+ border: var(--border-width) solid var(--border);
border-radius: var(--range-input);
box-shadow: 1px 1px var(--border-width-md) 0 var(--border-light);
height: var(--range-input);
diff --git a/test/lib/components/GamutSelect.spec.ts b/test/lib/components/GamutSelect.spec.ts
new file mode 100644
index 00000000..4486a755
--- /dev/null
+++ b/test/lib/components/GamutSelect.spec.ts
@@ -0,0 +1,22 @@
+import { fireEvent, render } from '@testing-library/svelte';
+import { get } from 'svelte/store';
+
+import Gamut from '$lib/components/GamutSelect.svelte';
+import { gamut, INITIAL_VALUES, reset } from '$lib/stores';
+
+describe('Space', () => {
+ afterEach(() => {
+ reset();
+ });
+
+ it('renders editable gamut select', async () => {
+ const { getByLabelText } = render(Gamut);
+
+ expect(get(gamut)).toBe(INITIAL_VALUES.gamut);
+
+ const select = getByLabelText('Show Gamut');
+ await fireEvent.change(select, { target: { value: 'rec2020' } });
+
+ expect(get(gamut)).toBe('rec2020');
+ });
+});
diff --git a/test/lib/utils.spec.ts b/test/lib/utils.spec.ts
index 98dcbae5..108e9247 100644
--- a/test/lib/utils.spec.ts
+++ b/test/lib/utils.spec.ts
@@ -3,7 +3,7 @@ import '$lib/stores';
import { type PlainColorObject, serialize, to } from 'colorjs.io/fn';
-import type { ColorFormatId } from '$lib/constants';
+import type { ColorFormatId, ColorGamutId } from '$lib/constants';
import {
getSpaceFromFormatId,
hashToStoreValues,
@@ -17,27 +17,31 @@ const cases = [
'color(display-p3 1 1 1)',
'color(display-p3 0.1 0.1 0.1)',
'p3',
+ '',
],
[
'valid hex',
- 'hex__*132b77__*4a0022',
+ 'hex__*132b77__*4a0022__srgb',
'rgb(7.451% 16.863% 46.667%)',
'rgb(29.02% 0% 13.333%)',
'hex',
+ 'srgb',
],
[
'oklab with percents',
- 'oklab__oklab(73.4~_0.177_0.107)__oklab(73.3~_0.102_0.0016)',
+ 'oklab__oklab(73.4~_0.177_0.107)__oklab(73.3~_0.102_0.0016)__p3',
'oklab(73.4% 0.177 0.107)',
'oklab(73.3% 0.102 0.0016)',
'oklab',
+ 'p3',
],
[
'oklab with negative values',
- 'oklab__oklab(73.4~_-0.215_-0.215)__oklab(73.3~_-0.298_-0.317)',
+ 'oklab__oklab(73.4~_-0.215_-0.215)__oklab(73.3~_-0.298_-0.317)__rec2020',
'oklab(73.4% -0.215 -0.215)',
'oklab(73.3% -0.298 -0.317)',
'oklab',
+ 'rec2020',
],
];
describe('Utils', () => {
@@ -61,26 +65,33 @@ describe('Utils', () => {
});
test.each(cases)(
'%s: %s returns values',
- (_, input, bgExpected, fgExpected, formatExpected) => {
- const { bg, fg, format } = hashToStoreValues(input) as {
+ (_, input, bgExpected, fgExpected, formatExpected, gamutExpected) => {
+ const { bg, fg, format, gamut } = hashToStoreValues(input) as {
bg: PlainColorObject;
fg: PlainColorObject;
format: ColorFormatId;
+ gamut: ColorGamutId;
};
expect(format).toBe(formatExpected);
expect(serialize(bg)).toBe(bgExpected);
expect(serialize(fg)).toBe(fgExpected);
+ expect(gamut ?? '').toBe(gamutExpected);
},
);
});
describe('storeValuesToHash', () => {
test.each(cases)(
'%s: returns %s',
- (_, output, bgInput, fgInput, format) => {
+ (_, output, bgInput, fgInput, format, gamut) => {
const space = getSpaceFromFormatId(format as ColorFormatId);
const bg = to(bgInput, space);
const fg = to(fgInput, space);
- const res = storeValuesToHash(bg, fg, format as ColorFormatId);
+ const res = storeValuesToHash(
+ bg,
+ fg,
+ format as ColorFormatId,
+ gamut as ColorGamutId,
+ );
expect(res).toBe(output);
},
);