🐛 Fix colorpicker inputs (#9793)

This commit is contained in:
Eva Marco 2026-05-25 10:45:49 +02:00 committed by GitHub
parent 841ad69d26
commit f3f697b4a2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 204 additions and 182 deletions

View File

@ -236,7 +236,7 @@ test("Bug 10089 - Cannot change alpha", async ({ page }) => {
const swatch = workspacePage.page.getByRole("button", { name: "#B1B2B5" });
await swatch.click();
const alpha = workspacePage.page.getByLabel("A", { exact: true });
const alpha = workspacePage.page.getByRole("spinbutton", { name: "Alpha" });
await expect(alpha).toHaveValue("100");
const alphaSlider = workspacePage.page.getByTestId("slider-opacity");

View File

@ -43,10 +43,9 @@
}
.text-icon {
color: var(--color-foreground-secondary);
@include t.use-typography("body-small");
color: var(--color-foreground-secondary);
inline-size: fit-content;
min-inline-size: px2rem(46);
padding-inline-start: var(--sp-xs);

View File

@ -22,6 +22,7 @@
[:id :string]
[:icon {:optional true}
[:maybe [:and :string [:fn #(contains? icon-list %)]]]]
[:text-icon {:optional true} [:maybe :string]]
[:has-hint {:optional true} :boolean]
[:hint-type {:optional true} [:maybe [:enum "hint" "error" "warning"]]]
[:type {:optional true} :string]
@ -33,7 +34,7 @@
(mf/defc input-field*
{::mf/forward-ref true
::mf/schema schema:input-field}
[{:keys [id icon class type
[{:keys [id icon text-icon class type
has-hint hint-type
max-length variant
slot-start slot-end
@ -86,6 +87,9 @@
:class (stl/css :icon)
:size "s"
:on-click on-icon-click}])
(when (some? text-icon)
[:span {:class (stl/css :text-icon)}
text-icon])
(if aria-label
[:> tooltip* {:content aria-label
:trigger-ref (or ref input-ref)

View File

@ -125,3 +125,12 @@
.tooltip-wrapper {
inline-size: 100%;
}
.text-icon {
@include use-typography("body-small");
color: var(--color-foreground-secondary);
inline-size: fit-content;
min-inline-size: px2rem(46);
padding-inline-start: var(--sp-xs);
}

View File

@ -10,6 +10,8 @@
[app.common.data :as d]
[app.common.math :as mth]
[app.common.types.color :as cc]
[app.main.ui.ds.controls.input :refer [input*]]
[app.main.ui.ds.foundations.assets.icon :as i]
[app.util.dom :as dom]
[app.util.keyboard :as kbd]
[rumext.v2 :as mf]))
@ -194,123 +196,139 @@
(cond
(= type :rgb)
[:*
[:div {:class (stl/css :input-wrapper)}
[:label {:for "red-value" :class (stl/css :input-label)} "R"]
[:input {:id "red-value"
:ref (:r refs)
:type "number"
:min 0
:max 255
:default-value red
:on-change (on-change-property :r 255)
:on-key-down (on-key-down-property :r 255)}]]
[:div {:class (stl/css :input-wrapper)}
[:label {:for "green-value" :class (stl/css :input-label)} "G"]
[:input {:id "green-value"
:ref (:g refs)
:type "number"
:min 0
:max 255
:default-value green
:on-change (on-change-property :g 255)
:on-key-down (on-key-down-property :g 255)}]]
[:div {:class (stl/css :input-wrapper)}
[:label {:for "blue-value" :class (stl/css :input-label)} "B"]
[:input {:id "blue-value"
:ref (:b refs)
:type "number"
:min 0
:max 255
:default-value blue
:on-change (on-change-property :b 255)
:on-key-down (on-key-down-property :b 255)}]]]
[:> input* {:id "red-value"
:ref (:r refs)
:type "number"
:min 0
:icon i/character-r
:property "Red"
:aria-label "Red"
:max 255
:default-value red
:on-change (on-change-property :r 255)
:on-key-down (on-key-down-property :r 255)}]
[:> input* {:id "green-value"
:ref (:g refs)
:type "number"
:min 0
:icon i/character-g
:property "Green"
:aria-label "Green"
:max 255
:default-value green
:on-change (on-change-property :g 255)
:on-key-down (on-key-down-property :g 255)}]
[:> input* {:id "blue-value"
:ref (:b refs)
:type "number"
:min 0
:icon i/character-b
:property "Blue"
:aria-label "Blue"
:max 255
:default-value blue
:on-change (on-change-property :b 255)
:on-key-down (on-key-down-property :b 255)}]]
(= hsb-mode :hsl)
[:*
[:div {:class (stl/css :input-wrapper)}
[:label {:for "hue-value" :class (stl/css :input-label)} "H"]
[:input {:id "hue-value"
:ref (:h refs)
:type "number"
:min 0
:max 360
:default-value hue
:on-change (on-change-property :h 360)
:on-key-down (on-key-down-property :h 360)}]]
[:div {:class (stl/css :input-wrapper)}
[:label {:for "hsl-saturation-value" :class (stl/css :input-label)} "S"]
[:input {:id "hsl-saturation-value"
:ref (:hsl-s refs)
:type "number"
:min 0
:max 100
:step 1
:default-value (mth/precision (* hsl-s 100) 2)
:on-change (on-change-property :hsl-s 100)
:on-key-down (on-key-down-property :hsl-s 100)}]]
[:div {:class (stl/css :input-wrapper)}
[:label {:for "lightness-value" :class (stl/css :input-label)} "L"]
[:input {:id "lightness-value"
:ref (:hsl-l refs)
:type "number"
:min 0
:max 100
:step 1
:default-value (mth/precision (* hsl-l 100) 2)
:on-change (on-change-property :hsl-l 100)
:on-key-down (on-key-down-property :hsl-l 100)}]]]
[:> input* {:id "hue-value"
:ref (:h refs)
:type "number"
:min 0
:icon i/character-h
:property "Hue"
:aria-label "Hue"
:max 360
:default-value hue
:on-change (on-change-property :h 360)
:on-key-down (on-key-down-property :h 360)}]
[:> input* {:id "saturation-value"
:ref (:s refs)
:type "number"
:min 0
:icon i/character-s
:property "Saturation"
:aria-label "Saturation"
:max 100
:step 1
:default-value saturation
:on-change (on-change-property :s 100)
:on-key-down (on-key-down-property :s 100)}]
[:> input* {:id "lightness-value"
:ref (:hsl-l refs)
:type "number"
:min 0
:icon i/character-l
:property "Lightness"
:aria-label "Lightness"
:max 100
:step 1
:default-value (mth/precision (* hsl-l 100) 2)
:on-change (on-change-property :hsl-l 100)
:on-key-down (on-key-down-property :hsl-l 100)}]]
:else
[:*
[:div {:class (stl/css :input-wrapper)}
[:label {:for "hue-value" :class (stl/css :input-label)} "H"]
[:input {:id "hue-value"
:ref (:h refs)
:type "number"
:min 0
:max 360
:default-value hue
:on-change (on-change-property :h 360)
:on-key-down (on-key-down-property :h 360)}]]
[:div {:class (stl/css :input-wrapper)}
[:label {:for "saturation-value" :class (stl/css :input-label)} "S"]
[:input {:id "saturation-value"
:ref (:s refs)
:type "number"
:min 0
:max 100
:step 1
:default-value saturation
:on-change (on-change-property :s 100)
:on-key-down (on-key-down-property :s 100)}]]
[:div {:class (stl/css :input-wrapper)}
[:label {:for "brightness-value" :class (stl/css :input-label)} "B(V)"]
[:input {:id "brightness-value"
:ref (:v refs)
:type "number"
:min 0
:max 100
:default-value value
:on-change (on-change-property :v 100)
:on-key-down (on-key-down-property :v 100)}]]])]
[:> input* {:id "hue-value"
:ref (:h refs)
:type "number"
:min 0
:icon i/character-h
:property "Hue"
:aria-label "Hue"
:max 360
:default-value hue
:on-change (on-change-property :h 360)
:on-key-down (on-key-down-property :h 360)}]
[:> input* {:id "saturation-value"
:ref (:s refs)
:type "number"
:min 0
:icon i/character-s
:property "Saturation"
:max 100
:step 1
:aria-label "Saturation"
:default-value saturation
:on-change (on-change-property :s 100)
:on-key-down (on-key-down-property :s 100)}]
[:> input* {:id "brightness-value"
:ref (:v refs)
:type "number"
:min 0
:text-icon "B(V)"
:property "Brightness"
:aria-label "Brightness (Value)"
:max 100
:step 1
:default-value value
:on-change (on-change-property :v 100)
:on-key-down (on-key-down-property :v 100)}]])]
[:div {:class (stl/css :hex-alpha-wrapper)}
[:div {:class (stl/css-case :input-wrapper true
:hex true)}
[:label {:for "hex-value" :class (stl/css :input-label)} "HEX"]
[:input {:id "hex-value"
:ref (:hex refs)
:default-value hex
:on-change on-change-hex
:on-blur on-blur-hex}]]
[:> input* {:id "hex-value"
:class (stl/css :hex-input)
:ref (:hex refs)
:type "text"
:text-icon "HEX"
:property "Hex"
:aria-label "Hexadecimal color value"
:max 7
:default-value hex
:on-change on-change-hex
:on-blur on-blur-hex}]
(when (not disable-opacity)
[:div {:class (stl/css-case :input-wrapper true)}
[:label {:for "alpha-value" :class (stl/css :input-label)} "A"]
[:input {:id "alpha-value"
:ref (:alpha refs)
:type "number"
:min 0
:step 1
:max 100
:default-value (if (= alpha :multiple) "" alpha)
:on-change (on-change-property :alpha 100)
:on-key-down (on-key-down-property :alpha 100)}]])]]))
[:> input* {:id "alpha-value"
:ref (:alpha refs)
:type "number"
:class (stl/css :alpha-input)
:min 0
:icon i/character-a
:property "Alpha"
:max 100
:step 1
:aria-label "Alpha"
:default-value (if (= alpha :multiple) "" (mth/precision (* alpha 100) 2))
:on-change (on-change-property :alpha 100)
:on-key-down (on-key-down-property :alpha 100)}])]]))

View File

@ -5,74 +5,66 @@
// Copyright (c) KALEIDOS INC
@use "refactor/common-refactor.scss" as deprecated;
@use "ds/_borders.scss" as *;
@use "ds/spacing.scss" as *;
@use "ds/_sizes.scss" as *;
@use "ds/typography.scss" as t;
@use "ds/_utils.scss" as *;
.color-values {
@include deprecated.flex-column;
margin-top: deprecated.$s-8;
.model-switcher {
display: flex;
gap: deprecated.$s-4;
margin-bottom: deprecated.$s-8;
padding: deprecated.$s-2;
background-color: var(--color-background-tertiary);
border-radius: deprecated.$s-6;
align-self: flex-start;
.model-pill {
@include deprecated.body-small-typography;
padding: deprecated.$s-2 deprecated.$s-8;
border: none;
border-radius: deprecated.$s-4;
background: transparent;
color: var(--color-foreground-secondary);
cursor: pointer;
&:hover {
color: var(--color-foreground-primary);
}
&.model-pill-active {
background-color: var(--color-background-primary);
color: var(--color-accent-primary);
}
}
}
display: flex;
flex-direction: column;
gap: var(--sp-xs);
padding: 0 1px;
margin-block-start: var(--sp-s);
&.disable-opacity {
grid-template-columns: 3.5rem repeat(3, 1fr);
}
.colors-row {
@include deprecated.flex-row;
.input-wrapper {
@extend %input-element;
@include deprecated.body-small-typography;
width: deprecated.$s-84;
display: flex;
align-items: baseline;
}
}
.hex-alpha-wrapper {
@include deprecated.flex-row;
.input-wrapper {
@extend %input-element;
@include deprecated.body-small-typography;
width: deprecated.$s-84;
&.hex {
width: deprecated.$s-172;
display: flex;
align-items: baseline;
gap: deprecated.$s-8;
}
}
grid-template-columns: px2rem(56) repeat(3, 1fr);
}
}
.model-switcher {
display: flex;
align-self: flex-start;
gap: var(--sp-xs);
padding: var(--sp-xxs);
margin-block-end: var(--sp-s);
border-radius: $br-6;
background-color: var(--color-background-tertiary);
}
.model-pill {
@include t.use-typography("body-small");
padding: var(--sp-xxs) var(--sp-s);
border: none;
border-radius: $br-4;
color: var(--color-foreground-secondary);
background: transparent;
cursor: pointer;
&:hover {
color: var(--color-foreground-primary);
}
}
.model-pill-active {
background-color: var(--color-background-primary);
color: var(--color-accent-primary);
}
.colors-row {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: var(--sp-xs);
}
.hex-alpha-wrapper {
display: grid;
grid-template-columns: 1fr 1fr 1fr;
gap: var(--sp-xs);
}
.hex-input {
grid-column: span 2;
}