Skip to content
Draft
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
e9f0112
feat: Added color picker component
rkaraivanov Nov 14, 2025
0545c92
fix: Stylelint auto-fix for SCSS files in color-picker component
rkaraivanov Nov 14, 2025
d0019f8
Merge remote-tracking branch 'origin/master' into rkaraivanov/color-p…
rkaraivanov Nov 28, 2025
14fc703
Merge branch 'master' into rkaraivanov/color-picker
kdinev Feb 10, 2026
c67ec5b
Merge branch 'master' into rkaraivanov/color-picker
kdinev May 12, 2026
6b94da8
Merge remote-tracking branch 'origin/master' into rkaraivanov/color-p…
rkaraivanov May 26, 2026
003ea7f
refactor: Cleaned up color syncing logic in color-picker component
rkaraivanov May 26, 2026
3454a37
Merge branch 'rkaraivanov/color-picker' of https://github.com/IgniteU…
rkaraivanov May 26, 2026
8f11e47
Merge remote-tracking branch 'origin/master' into rkaraivanov/color-p…
rkaraivanov May 26, 2026
6dbefd3
feat: Use EyeDropper API for color picking where supported
rkaraivanov May 26, 2026
c384860
Merge remote-tracking branch 'origin/master' into rkaraivanov/color-p…
rkaraivanov May 28, 2026
decc7e2
refactor: Use modern color formats and update color picker component
rkaraivanov May 28, 2026
feeeb37
Merge remote-tracking branch 'origin/master' into rkaraivanov/color-p…
rkaraivanov Jun 2, 2026
a19a9da
feat: Added predefined swatches to color picker
rkaraivanov Jun 2, 2026
08a81e2
Merge remote-tracking branch 'origin/master' into rkaraivanov/color-p…
rkaraivanov Jun 22, 2026
09db9b1
refactor: Align color picker width with design specifications
rkaraivanov Jun 22, 2026
5c1760e
Merge remote-tracking branch 'origin/master' into rkaraivanov/color-p…
rkaraivanov Jun 23, 2026
227b4e1
feat(color-picker): support empty/undefined color values
rkaraivanov Jun 23, 2026
b5735fd
test: color-picker empty value handling
rkaraivanov Jun 23, 2026
1ce4b89
chore: fix styleint error
rkaraivanov Jun 23, 2026
8202b68
Merge remote-tracking branch 'origin/master' into rkaraivanov/color-p…
rkaraivanov Jun 25, 2026
cb4b008
feat: added input mode for the color picker component
rkaraivanov Jun 25, 2026
0a6cdf8
Merge remote-tracking branch 'origin/master' into rkaraivanov/color-p…
rkaraivanov Jul 21, 2026
8aa2b80
Merge remote-tracking branch 'origin/master' into rkaraivanov/color-p…
rkaraivanov Jul 29, 2026
0193fea
fix: Addressed PR review comments
rkaraivanov Jul 29, 2026
7eb3424
fix: More bug fixes and improvements to the color picker component
rkaraivanov Jul 29, 2026
00f0751
feat: Added additional keybinding for opening and closing the picker
rkaraivanov Jul 29, 2026
bcd073a
feat: Finalize color-picker component
rkaraivanov Jul 30, 2026
108b35b
fix: ARIA improvements for color picker component
rkaraivanov Jul 30, 2026
68722e0
feat: Disabled state and external label association
rkaraivanov Jul 31, 2026
faf04d1
Merge branch 'master' into rkaraivanov/color-picker
rkaraivanov Aug 7, 2026
25f7483
Merge branch 'master' into rkaraivanov/color-picker
desig9stein Aug 7, 2026
0246200
Merge branch 'master' into rkaraivanov/color-picker
simeonoff Aug 11, 2026
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
189 changes: 189 additions & 0 deletions src/components/color-picker/color-picker.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
import { elementUpdated, expect, fixture, html } from '@open-wc/testing';

import { defineComponents } from '../common/definitions/defineComponents.js';
import { createFormAssociatedTestBed } from '../common/utils.spec.js';
import type IgcInputComponent from '../input/input.js';
import IgcColorPickerComponent from './color-picker.js';

async function createDefaultColorPicker() {
return await fixture<IgcColorPickerComponent>(
html`<igc-color-picker label="Choose a color"></igc-color-picker>`
);
}

function getAnchor(picker: IgcColorPickerComponent): HTMLElement {
return picker.renderRoot.querySelector('[part~="anchor"]')!;
}

function isAnchorEmpty(picker: IgcColorPickerComponent): boolean {
return getAnchor(picker).part.contains('empty');
}

function getColorInput(picker: IgcColorPickerComponent): IgcInputComponent {
return picker.renderRoot.querySelector<IgcInputComponent>('#color-input')!;
}

function commitColorInput(input: IgcInputComponent, value: string): void {
input.value = value;
input.dispatchEvent(
new CustomEvent('igcChange', {
detail: value,
bubbles: true,
composed: true,
})
);
}

describe('Color picker', () => {
before(() => defineComponents(IgcColorPickerComponent));

let picker: IgcColorPickerComponent;

describe('Default', () => {
beforeEach(async () => {
picker = await createDefaultColorPicker();
});

it('is initialized', () => {
expect(picker).to.exist;
});

it('is accessible (close state)', async () => {
await expect(picker).shadowDom.to.be.accessible();
await expect(picker).lightDom.to.be.accessible();
});

it('is accessible (open state)', async () => {
picker.open = true;
await elementUpdated(picker);

await expect(picker).shadowDom.to.be.accessible();
await expect(picker).lightDom.to.be.accessible();
});
});

describe('API', () => {
beforeEach(async () => {
picker = await createDefaultColorPicker();
});

it('`toggle()`', async () => {
await picker.toggle();
expect(picker.open).to.be.true;

await picker.toggle();
expect(picker.open).to.be.false;
});
});

describe('Empty value', () => {
beforeEach(async () => {
picker = await createDefaultColorPicker();
});

it('has an empty value by default', () => {
expect(picker.value).to.equal('');
});

it('renders a checkered anchor when empty', async () => {
expect(isAnchorEmpty(picker)).to.be.true;

picker.value = '#ff0000';
await elementUpdated(picker);
expect(isAnchorEmpty(picker)).to.be.false;
});

it('reverts to an empty value for null/undefined/empty', async () => {
for (const value of ['', null, undefined]) {
picker.value = '#ff0000';
await elementUpdated(picker);

picker.value = value as unknown as string;
await elementUpdated(picker);

expect(picker.value).to.equal('');
expect(isAnchorEmpty(picker)).to.be.true;
}
});
});

describe('Color value input', () => {
beforeEach(async () => {
picker = await createDefaultColorPicker();
picker.value = '#ff0000';
picker.open = true;
await elementUpdated(picker);
});

it('commits a valid color', async () => {
commitColorInput(getColorInput(picker), '#00ff00');
await elementUpdated(picker);

expect(picker.value).to.equal('#00ff00');
});

it('reverts the input on an invalid color', async () => {
const input = getColorInput(picker);
commitColorInput(input, 'not-a-color');
await elementUpdated(picker);

expect(picker.value).to.equal('#ff0000');
expect(input.value).to.equal('#ff0000');
});

it('reverts the input on an empty color', async () => {
const input = getColorInput(picker);
commitColorInput(input, '');
await elementUpdated(picker);

expect(picker.value).to.equal('#ff0000');
expect(input.value).to.equal('#ff0000');
});
});

describe('Form associated', () => {
const spec = createFormAssociatedTestBed<IgcColorPickerComponent>(
html`<igc-color-picker name="color-picker"></igc-color-picker>`
);

beforeEach(async () => {
await spec.setup(IgcColorPickerComponent.tagName);
});

it('is form associated', () => {
expect(spec.element.form).to.equal(spec.form);
});

it('is not associated on submit if no value', async () => {
expect(spec.submit()?.get(spec.element.name)).to.be.null;
});

it('is associated on submit', () => {
spec.setProperties({ value: '#bada55' });
spec.assertSubmitHasValue('#bada55');
});

it('is correctly reset on form reset', () => {
spec.setProperties({ value: '#bada55' });

spec.reset();
expect(spec.element.value).to.equal('');
});

it('reflects disabled ancestor state', () => {
spec.setAncestorDisabledState(true);
expect(spec.element.disabled).to.be.true;

spec.setAncestorDisabledState(false);
expect(spec.element.disabled).to.be.false;
});

it('fulfils custom constraint', () => {
spec.element.setCustomValidity('invalid');
spec.assertSubmitFails();

spec.element.setCustomValidity('');
spec.assertSubmitPasses();
});
});
});
Loading