Skip to content

feat: Added color picker component - #1973

Open
rkaraivanov wants to merge 63 commits into
masterfrom
rkaraivanov/color-picker
Open

feat: Added color picker component#1973
rkaraivanov wants to merge 63 commits into
masterfrom
rkaraivanov/color-picker

Conversation

@rkaraivanov

Copy link
Copy Markdown
Member

No description provided.

rkaraivanov and others added 20 commits November 14, 2025 10:10
Introduce an explicit "missing color" sentinel and surface it through the
color picker.

ColorModel:
- Add `ColorModel.empty()` factory and an `isEmpty` getter representing a
  missing/undefined color. `default()` keeps returning black.
- Clear the empty state when any channel (r/g/b/h/s/l/v/alpha) is modified.
- `asString()` returns an empty string while empty; `clone()` preserves the
  empty state and `equals()` accounts for it.
- `parse()` returns the empty sentinel for null/undefined/empty/whitespace
  input.

Component:
- Initialize the internal color as empty so an unset picker has an empty value.
- Render the trigger anchor with a checkered background while the value is
  empty, via an `empty` shadow part token.
- Validate the color value input on commit using the new `isValidColor`
  helper; empty or invalid input reverts the field to the current color.

Styles:
- Add a checkered pattern on `[part~='empty']::part(base)`, mirroring the
  alpha slider track.

Add `isValidColor()` and update model, common and component unit tests to
cover the empty sentinel, validation and revert behavior.
Comment thread src/components/color-picker/common.ts Dismissed
Comment thread src/components/color-picker/common.ts Dismissed
Some code reorganization and refactoring was done to support the new input mode.
The color picker component now has an input mode that allows users to enter color values directly.
The component will handle changes from the input field and update the color value accordingly.
Copilot AI review requested due to automatic review settings July 21, 2026 12:02

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new igc-color-picker web component to the Ignite UI Web Components library, including its internal color model/converters, styles, Storybook story, and unit tests.

Changes:

  • Introduces the IgcColorPickerComponent (and supporting igc-picker-canvas) with theming and interactions (hue/SV selection, alpha, swatches, copy, eyedropper).
  • Adds a color parsing/model layer (ColorModel, converters, validation helpers) plus unit tests.
  • Wires the component into the public exports and the “define all components” registration list, and adds a Storybook story.

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
tsconfig.json Extends lit plugin global attributes (adds inert).
stories/color-picker.stories.ts Adds Storybook coverage for the new color picker.
src/index.ts Exports IgcColorPickerComponent from the package entry.
src/components/common/definitions/defineAllComponents.ts Registers IgcColorPickerComponent in the “define all” list.
src/components/color-picker/themes/picker-canvas.base.scss Styles for the SV picker canvas and marker.
src/components/color-picker/themes/color-picker.base.scss Styles for the overall color picker UI (sliders, buttons, swatches).
src/components/color-picker/picker-canvas.ts New SV picker surface with pointer + keyboard interactions and events.
src/components/color-picker/model.ts ColorModel implementation and context helper for parsing.
src/components/color-picker/model.spec.ts Unit tests for ColorModel.
src/components/color-picker/converters.ts RGB/HSL/HSV conversion utilities.
src/components/color-picker/common.ts Color parsing + validation helpers.
src/components/color-picker/common.spec.ts Unit tests for parsing/validation helpers.
src/components/color-picker/color-picker.ts Main igc-color-picker component implementation.
src/components/color-picker/color-picker.spec.ts Component-level tests incl. a11y and form association.

Comment thread src/components/color-picker/converters.ts Outdated
Comment thread src/components/color-picker/converters.ts
Comment thread src/components/color-picker/color-picker.ts Outdated
Comment thread src/components/color-picker/color-picker.ts Outdated
Comment thread stories/color-picker.stories.ts Outdated
Comment thread src/components/color-picker/color-picker.ts
Comment thread src/components/color-picker/color-picker.ts
Copilot AI review requested due to automatic review settings July 29, 2026 06:40

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 35 out of 36 changed files in this pull request and generated no new comments.

Suppressed comments (5)

src/components/color-picker/color-picker.ts:697

  • The internal <igc-select> in the picker popup is a form-associated control and currently has name="format". This can cause the nested select to submit an extra format field when the color picker is placed in a form. Other composite components avoid giving internal controls a name (see src/components/select/select.ts:783-799). Remove the name attribute here.
      <igc-select
        id="format-select"
        part="format-select"
        placeholder="Color format"
        name="format"
        outlined

src/components/color-picker/color-picker.ts:718

  • The popup color value <igc-input> is form-associated and currently has name="color-input", which can introduce an extra field in form submission when the color picker is used inside a form. Since the host component already handles form association and submission under its own name, the internal input should not have a name.
      <igc-input
        id="color-input"
        name="color-input"
        placeholder=${formatPlaceholders[this.format]}

src/components/color-picker/color-picker.ts:423

  • _handleColorInputChange() updates the component value but never emits igcInput, unlike the other interaction paths (canvas/slider/swatches/EyeDropper). This means typing/committing a color via the text field won’t notify consumers listening for igcInput. Emit igcInput after updating the color so all user-driven value changes behave consistently.
    this._color = cleared ? ColorModel.empty() : ColorModel.parse(value);
    this._updateColor();
    // The model was replaced directly rather than through `value`, so no
    // `value` change is recorded and the sync in `updated()` will not run.
    this._syncCanvasPosition();

src/components/color-picker/color-picker.ts:667

  • The internal alpha <igc-input> is form-associated and has a name attribute. When the color picker is used inside a form, this nested control can end up contributing an extra alpha field to form submission, which is inconsistent with other composite controls (e.g. combo/select render internal <igc-input> without name). Remove the name attribute from the internal input.

This issue also appears in the following locations of the same file:

  • line 692
  • line 715
        id="alpha"
        name="alpha"
        placeholder="Alpha value"

src/components/icon/internal-icons-lib.ts:40

  • The new internal colorize SVG hardcodes fill="#e3e3e3", unlike the other internal icons which rely on CSS/currentColor for theming. Hardcoding the fill can make the icon ignore theme/consumer styling. Drop the explicit fill attribute so it inherits like the rest of the icon set.

@desig9stein

desig9stein commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

All themes, Alpha value

If we add the percentage sign in the suffix container, in small size it "cuts" the value itself. Screenshot 2026-08-13 at 14 35 55

@sbayreva In the design, the % symbol is part of the input value. The design does not provide what happens if the % is in the suffix. If the % is a suffix, we have to either change the design or override the input per theme to make it look like the design, which in Bootstrap is nearly impossible without hacky overrides.

@rkaraivanov can we append the % to the input value, so we don't have to use the suffix?

@rkaraivanov

rkaraivanov commented Aug 14, 2026

Copy link
Copy Markdown
Member Author

@desig9stein @sbayreva
There is a new "re-imagining" of the alpha value input. IMO, I don't like it too much since it is not 100% accessible as the numeric input was but it covers the design.

@desig9stein

Copy link
Copy Markdown
Contributor

@sbayreva @sdimchevski, regarding the comments on overriding the colors for the icon button and input group—I strongly advise against altering the default color tokens for these components. Keeping the default color models ensures consistent theming and avoids maintenance friction across themes.

If you'd still like to proceed, please provide the complete color specs for both components in the context of the popover:

  • Icon Button: Idle, hover, active, and focus.
  • Input Group: Idle, filled, hover, active, and focus.

Keep in mind that hardcoding these overrides will prevent users from customizing these components via theming variables—unless they write specific CSS overrides within that exact scope.

@sbayreva, spacing and sizing should match the design now; you can test it.

@sdimchevski

Copy link
Copy Markdown

@desig9stein agreed with all of this. Let's use the defaults and not override the color tokens

@desig9stein

desig9stein commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

2. The border radius of the “Fill” should be 1px

@sbayreva To achieve this, we will need to use an SVG. Pure CSS cannot control an inner border arch independently; adjusting the outer radius to compensate would mismatch the parent container's radius, which isn't an ideal trade-off.
However using an SVG just to handle an inner border radius feels like unnecessary overhead for a minor visual detail. I'd prefer to stick with a native CSS approach—even if it means keeping a subtle visual compromise—rather than introducing SVG complexity. This is just in fluent theme since it's the only theme the inner element resolves to 1px radius. Can i keep it as it is?

@desig9stein

Copy link
Copy Markdown
Contributor

@rkaraivanov @sbayreva Just a heads-up, there's a new PR in the theming repo for the color changes. It includes a few variable name updates, so to avoid local errors, you'll need to use a package built directly from this PR until it gets merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants