diff --git a/src/main/frontend/components/icon.cljs b/src/main/frontend/components/icon.cljs index 16c74467d9..c68eebe746 100644 --- a/src/main/frontend/components/icon.cljs +++ b/src/main/frontend/components/icon.cljs @@ -1571,12 +1571,16 @@ :data {:value avatar-value :backgroundColor backgroundColor :color color}}) - on-chosen (:on-chosen opts)] + on-chosen (:on-chosen opts) + highlighted-id (:highlighted-id opts)] [:div.custom-tab-content ;; Text option (when text-item [:button.custom-tab-item - {:on-click #(reset! *view :text-picker)} + {:data-item-id "custom-text" + :tabIndex "-1" + :class (when (= "custom-text" highlighted-id) "is-highlighted") + :on-click #(reset! *view :text-picker)} [:div.custom-tab-item-preview (icon text-item {:size 24})] [:span.custom-tab-item-label "Text"]]) @@ -1584,14 +1588,20 @@ ;; Avatar option (when avatar-item [:button.custom-tab-item - {:on-click #(on-chosen % avatar-item)} + {:data-item-id "custom-avatar" + :tabIndex "-1" + :class (when (= "custom-avatar" highlighted-id) "is-highlighted") + :on-click #(on-chosen % avatar-item)} [:div.custom-tab-item-preview (icon avatar-item {:size 24})] [:span.custom-tab-item-label "Avatar"]]) ;; Image option — always show dashed placeholder with camera icon [:button.custom-tab-item - {:on-click #(reset! *view :asset-picker)} + {:data-item-id "custom-image" + :tabIndex "-1" + :class (when (= "custom-image" highlighted-id) "is-highlighted") + :on-click #(reset! *view :asset-picker)} [:div.custom-tab-item-preview [:span.image-tile-placeholder {:style {:width 28 diff --git a/src/main/frontend/components/icon.css b/src/main/frontend/components/icon.css index 4d597f6d53..891f19a119 100644 --- a/src/main/frontend/components/icon.css +++ b/src/main/frontend/components/icon.css @@ -430,15 +430,40 @@ @apply transition-all duration-150; border: 1px solid var(--rx-gray-06); background-color: var(--rx-gray-03); + /* Baseline transparent outline so outline-color can transition + transparent → accent without the browser's currentColor flashing + through during the discrete style/width jump. */ + outline: 2px solid transparent; + outline-offset: -2px; &:hover { border-color: var(--rx-accent-09); } } +/* Keyboard-nav highlight for custom tiles: neutralize the generic + button.is-highlighted rule (which paints the full column including + the label) and move the ring onto the 48x48 preview child instead. */ +.cp__emoji-icon-picker button.custom-tab-item.is-highlighted { + background-color: transparent !important; + outline: none; + border-radius: 0 !important; +} + +.cp__emoji-icon-picker button.custom-tab-item.is-highlighted .custom-tab-item-preview { + background-color: var(--lx-accent-04); + outline: 2px solid var(--lx-accent-09); + outline-offset: -2px; +} + +.cp__emoji-icon-picker button.custom-tab-item.is-highlighted .custom-tab-item-label { + color: var(--lx-accent-11); +} + .custom-tab-item-label { @apply text-xs; color: var(--rx-gray-11); + transition: color 150ms; } /* Shared drag overlay hint — used by both icon picker and asset picker */