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/Header.svelte b/src/lib/components/Header.svelte index 360fff76..2c1578b8 100644 --- a/src/lib/components/Header.svelte +++ b/src/lib/components/Header.svelte @@ -1,18 +1,31 @@
-

+

OddContrast

- +
+ + +
diff --git a/src/lib/components/SpaceSelect.svelte b/src/lib/components/SpaceSelect.svelte index 41fd50fd..ba21c9a4 100644 --- a/src/lib/components/SpaceSelect.svelte +++ b/src/lib/components/SpaceSelect.svelte @@ -23,7 +23,7 @@ }); -
+
- - 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); }, );