mirror of
https://github.com/we-promise/sure.git
synced 2026-05-30 07:49:01 +00:00
fix(goals): theme-aware avatar text contrast; compact picker popup
Avatar letter/icon now uses `--avatar-color` CSS variable + the new `.goal-avatar` class. Light mode darkens the text to 55% color + 45% black so pale palette entries (cyan-300, green-300) stay readable on the 10%-mix tint over white (~4.5:1). Dark mode reverts to the full brand color via [data-theme="dark"] .goal-avatar override so the text doesn't disappear against the near-black tinted surface. Verified live: #805dee renders as a darker oklab in light mode and full rgb(128,93,238) in dark mode. Picker popup compacted: - 80 (320px) wide, max-h-[60vh] overflow-y-auto so it never spills off-screen. - Anchored below the avatar + horizontally centered to it (top-full left-1/2 -translate-x-1/2) so it doesn't drift off to the right edge of the form on narrow modals. - Icon grid max-h-40 (160px, ~5 rows) with the in-house `scrollbar` utility for a thin gray thumb that works in both themes. - Section headers (Color / Icon) styled `uppercase tracking-wide` for visual hierarchy. Verified popup at 320x310px in edit modal, no vertical overflow.
This commit is contained in:
@@ -188,6 +188,20 @@
|
||||
scrollbar-width:none
|
||||
}
|
||||
|
||||
/* Tinted-bg + colored-content avatar used by Goals::AvatarComponent and
|
||||
the goals color/icon picker. Theme-aware text color: light mode darkens
|
||||
the letter/icon so pale palette entries (cyan-300, green-300, etc.) keep
|
||||
~4.5:1 contrast against the 10%-mix tint over white. Dark mode reverts
|
||||
to the full color so the letter doesn't disappear against the near-black
|
||||
surface. */
|
||||
.goal-avatar {
|
||||
background-color: color-mix(in oklab, var(--avatar-color) 10%, transparent);
|
||||
color: color-mix(in oklab, var(--avatar-color) 55%, black);
|
||||
}
|
||||
[data-theme="dark"] .goal-avatar {
|
||||
color: var(--avatar-color);
|
||||
}
|
||||
|
||||
.invite_code [data-clipboard-target="iconDefault"],
|
||||
.invite_code [data-clipboard-target="iconSuccess"] {
|
||||
transition: opacity 0.2s;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<span class="inline-flex items-center justify-center font-semibold <%= box_classes %> <%= text_classes %> <%= radius_classes %>"
|
||||
style="background-color: color-mix(in oklab, <%= color %> 10%, transparent); color: <%= color %>;"
|
||||
<span class="goal-avatar inline-flex items-center justify-center font-semibold <%= box_classes %> <%= text_classes %> <%= radius_classes %>"
|
||||
style="--avatar-color: <%= color %>;"
|
||||
aria-hidden="true"
|
||||
data-testid="goal-avatar">
|
||||
<% if icon.present? %>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<%# locals: (form:, colors:, icons:) %>
|
||||
<div data-controller="color-icon-picker" data-color-icon-picker-preset-colors-value="<%= colors %>">
|
||||
<div class="w-fit relative">
|
||||
<span class="inline-flex items-center justify-center w-11 h-11 rounded-xl font-semibold text-base"
|
||||
style="background-color: color-mix(in oklab, <%= form.object.color %> 10%, transparent); color: <%= form.object.color %>;"
|
||||
<span class="goal-avatar inline-flex items-center justify-center w-11 h-11 rounded-xl font-semibold text-base"
|
||||
style="--avatar-color: <%= form.object.color %>;"
|
||||
data-color-icon-picker-target="avatar">
|
||||
<% if form.object.icon.present? %>
|
||||
<%= icon(form.object.icon, color: "current", size: "md") %>
|
||||
@@ -16,11 +16,12 @@
|
||||
<%= icon("pen", size: "xs") %>
|
||||
</summary>
|
||||
|
||||
<div class="absolute left-0 sm:left-auto sm:right-0 mt-2 z-50 bg-container p-4 border border-alpha-black-25 rounded-2xl shadow-xs h-fit w-87 max-w-[calc(100vw-2rem)]" data-color-icon-picker-target="popup">
|
||||
<div class="flex gap-2 flex-col mb-4" data-color-icon-picker-target="selection">
|
||||
<div class="absolute top-full left-1/2 -translate-x-1/2 mt-2 z-50 bg-container p-3 border border-alpha-black-25 rounded-2xl shadow-xs w-80 max-w-[calc(100vw-2rem)] max-h-[60vh] overflow-y-auto"
|
||||
data-color-icon-picker-target="popup">
|
||||
<div class="flex gap-2 flex-col mb-3" data-color-icon-picker-target="selection">
|
||||
<div data-color-icon-picker-target="pickerSection"></div>
|
||||
<h4 class="text-secondary text-sm">Color</h4>
|
||||
<div class="flex flex-wrap md:flex-nowrap gap-2 items-center" data-color-icon-picker-target="colorsSection">
|
||||
<h4 class="text-secondary text-xs uppercase tracking-wide">Color</h4>
|
||||
<div class="flex flex-wrap gap-2 items-center" data-color-icon-picker-target="colorsSection">
|
||||
<% colors.each do |c| %>
|
||||
<label class="relative">
|
||||
<%= form.radio_button :color, c, class: "sr-only peer", data: { action: "change->color-icon-picker#handleColorChange" } %>
|
||||
@@ -45,9 +46,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap gap-2 justify-center flex-col">
|
||||
<h4 class="text-secondary text-sm">Icon</h4>
|
||||
<div class="flex flex-wrap gap-0.5 max-h-52 overflow-auto">
|
||||
<div class="flex flex-col gap-2">
|
||||
<h4 class="text-secondary text-xs uppercase tracking-wide">Icon</h4>
|
||||
<div class="flex flex-wrap gap-0.5 max-h-40 overflow-y-auto scrollbar">
|
||||
<% icons.each do |icon_name| %>
|
||||
<label class="relative">
|
||||
<%= form.radio_button :icon, icon_name, class: "sr-only peer", data: { action: "change->color-icon-picker#handleIconChange change->color-icon-picker#handleIconColorChange", color_icon_picker_target: "icon" } %>
|
||||
|
||||
Reference in New Issue
Block a user