Skip to content

feat(color_picker): editable hex field with a per-picker reuse palette - #59

Merged
kirillDevPro merged 4 commits into
masterfrom
feat/badges-color-picker
Sep 1, 2026
Merged

feat(color_picker): editable hex field with a per-picker reuse palette#59
kirillDevPro merged 4 commits into
masterfrom
feat/badges-color-picker

Conversation

@kirillDevPro

Copy link
Copy Markdown
Collaborator

What & why

MoonColorPicker rendered its hex value as a MoonText label — readable, not typeable — so a colour outside the supplied swatch list was unreachable. A consumer with more items than swatches (MoonTerminal's detect badges: 23 types) had no way to give each one a distinct colour.

This adds:

  • an editable hex field in the popover, accepting #RRGGBB and bare RRGGBB, case-insensitive, rejecting an invalid value without destroying what the field held;
  • a per-picker reuse list of colours entered that way, offered back at the front of the palette, with custom_colors(..) / set_custom_colors(..) / custom() and a new MoonColorPickerEvent::CustomAdded(Hsla) so a parent can fan one picker's new colour out to its siblings;
  • rgb8_of, replacing a truncating conversion with a rounding one.

The swatch grid is capped at GRID_MAX_HEIGHT_UI with overflow_y_scroll() so a large supplied palette does not grow the popover without bound.

default_value's signature is unchanged — a hex_dirty flag carries the state instead, which avoided a mechanical change across every existing call site and a "signature changed" entry in the component API baseline.

How to verify

  • 8 unit tests in moon/color_picker/tests.rs cover hex parsing, the reuse list, MRU ordering and the hex-rounding round-trip.
  • moon-ui-gallery's demo seeds .custom_colors(..) — run the gallery and type a hex into the picker.

Notes

  • 27deda9 fixes a real bug caught during review: custom_colors/set_custom_colors reversed the MRU order, so remembered colours came back oldest-first.
  • docs/component-api-baseline.json is refreshed — pure additions plus one signature-text reformat.
  • The color_picker manifest class is Mirror and tracks only the separate root Longbridge-fork file, so editing moon/color_picker.rs needs no class change.
  • Downstream: MoonTerminal's badge-palette change depends on this landing first.

MoonColorPicker's hex readout was a plain read-only label. Add a hex MoonInput to the
popover (accepts #RRGGBB/RRGGBB, case-insensitive; a value that fails to parse is
rejected without touching the held colour), and let a committed value join a
most-recent-first custom-colour list shown ahead of the caller's fixed palette for
quick reuse. Fixes hex_label's truncating byte conversion (now rounds, matching every
other Hsla->u8 path in this codebase) so the label and the new field agree exactly.
Caps the swatch grid's height with a scroll region, since a caller-supplied 65-swatch
palette plus a full custom list would otherwise grow the popover past the window.

default_value keeps its exact signature (a hex_dirty flag drained at render time
instead), so no MoonTerminal or gallery call site needs touching for that alone.
Round-trip and rejection cases for parse_hex_rgb, and push_custom's front-insert,
no-op-on-recommit, dedupe-by-move, and MAX_CUSTOM_COLORS cap. Each mutated and
reddened for its named reason before landing (breakage-prover dispatch).
… order

Both fed an already most-recent-first list straight into push_custom, which inserts
each colour at the front -- so a two-Codex-angle review (Job 1, flow + contracts)
independently caught the same reversal: seeding/replacing with [newest, older]
produced [older, newest], and over the 20-entry cap it kept the OLDEST 20 instead
of the newest. New push_all_custom processes the source in reverse so push_custom's
per-call front-insertion restores the intended order.
…d-trip

seeded_custom_colours_preserve_most_recent_first_order pins push_all_custom's
reverse-iteration fix (Job 1 caught the reversal independently, twice).
hsl_middle_gray_rounds_to_the_picker_hex_byte uses an HSL-derived (non-byte-sourced)
50% gray to demonstrate the rounding-vs-truncation difference a byte-sourced value
cannot expose (breakage-prover dispatch, round 2).
@kirillDevPro
kirillDevPro merged commit a262ff8 into master Sep 1, 2026
2 checks passed
@kirillDevPro
kirillDevPro deleted the feat/badges-color-picker branch September 1, 2026 17:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant