Skip to content

Animate ColorPicker open/close & KeyPicker text swap (+ ColorPicker resize/DPI fixes) - #9

Open
corradedied wants to merge 3 commits into
ui-input-polishfrom
sidebar-dropdown-fuzzy-search
Open

Animate ColorPicker open/close & KeyPicker text swap (+ ColorPicker resize/DPI fixes)#9
corradedied wants to merge 3 commits into
ui-input-polishfrom
sidebar-dropdown-fuzzy-search

Conversation

@corradedied

@corradedied corradedied commented Aug 26, 2026

Copy link
Copy Markdown
Owner

Summary

Gives ColorPicker an open/close animation consistent with Dropdown/KeyPicker,
adds a text wipe to KeyPicker's key-name label, and fixes three long-standing
ColorPicker resize/DPI bugs that were discovered along the way.

Changes

1. Animation flag scaffolding

Added ColorPicker, Input, Button to both Animations tables
(Library defaults and Templates.Window.Animations), plus matching
*TransitionInfo constants next to the existing ones. All default to
false. Nothing reads these yet outside of step 2, and existing lookups
(Library.Animations[AnimationType], SetAnimations) are already
untyped/generic, so this is pure plumbing — no other call sites needed
changes.

2. ColorPicker open animation

ColorMenu's AddContextMenu call now passes "ColorPicker" as the
AnimationType arg, so it reuses the exact Animated() / OpenCloseTween
logic Dropdown and KeyPicker already share. One call-site change; gated
behind Animations.ColorPicker (off by default).

3. KeyPicker text wipe

Added a wipe-out/wipe-in transition for the "..." ⇄ key-name swap,
gated behind the existing Animations.KeyPicker flag:

  • KeyPicker:Display (non-slide-overflow branch): when the flag is on
    and the display text actually changed, it tweens TextTransparency
    to 1, swaps Text/Size at the midpoint, then tweens back to
    whatever transparency it was at before the swap — captured live
    rather than hardcoded, since hover already animates
    TextTransparency (0.4 idle / 0 hovered) independently and we don't
    want the wipe to fight or snap against that.
  • A WipeTween upvalue (alongside the existing
    SlideForwardTween/SlideBackTween pattern) tracks the in-flight
    tween so rapid text changes (e.g. cycling modifiers while held)
    cancel the previous wipe instead of stacking.
  • When the flag is off, or the text is unchanged, behavior is byte-for-byte
    the same synchronous set as before.
  • Collapsed the listen-for-input "..." handling
    (if IsForButton and SlideOverflow then ... else ... end) into a
    single KeyPicker:Display("...") call, since Display already
    branches on IsForButton/SlideOverflow internally. Both paths now
    funnel through Display, so the "..." swap and the modifier-hold
    update both get the wipe for free.

Reviewer note: this rides the same Animations.KeyPicker boolean as
the step-2 menu open/close animation, but it's a separate mechanism
(TextTransparency tween on the label vs. Menu.Size tween on the
dropdown). Toggling the flag turns both on/off together even though
nothing else connects them — worth deciding whether that's fine
long-term or should eventually split into its own flag.

Misc fixes (found/fixed while in this code)

  • Resize handle sizing: was AnchorPoint(1,0) / Size 1,1 (full
    footer height) — too big and top-anchored. Now AnchorPoint(1,1),
    positioned at (1, -CornerRadius/4, 0.95, 0), sized 0.8 scale —
    closer to the true bottom-right corner without overlapping the footer
    divider or bleeding into the rounded background corner.
    FooterBackground also gained ClipsDescendants = true so the handle
    can't visually spill past the footer edge.
  • Resize "leak"/lag: ColorMenu.Menu is an AutomaticSize.Y
    ScrollingFrame driven by a UIListLayout. Dragging the resize
    handle updated the color map's size every frame but left the
    container's height to recompute automatically — which isn't
    synchronous with the child-size change, so it lags a frame. Since
    it's a ScrollingFrame, it clips anything outside that stale bound:
    content growing past the old boundary got cut off, and the footer
    (last in layout order) got pushed outside the visible area until
    extra dragging forced a recompute. Fixed by measuring the real
    overhead once per drag, switching AutomaticSize off, and setting
    both width and height on Menu.Size explicitly every frame —
    restored to AutomaticSize.Y when the drag ends.
  • Blank space at >100% DPI on open: Menu.AbsoluteSize.Y is already
    DPI-scaled (there's a UIScale under Menu), but it was being
    written back into Size, which gets scaled by that same UIScale
    again on render — double-applying DPIScale. At 100% that's a no-op,
    which is exactly why it only showed up above 100%: the open tween
    overshot taller than the real content and left a gap until
    AutomaticSize re-clamped it. Fixed by dividing by Library.DPIScale
    before using it as a Size offset. This lives in the shared
    AddContextMenu function, so it was silently affecting any animated
    auto-sizing menu, not just ColorPicker.
  • Also fixed a matching unit mismatch in the resize viewport clamp
    (ClampToViewport compared logical map sizes against real screen
    pixels without dividing by DPI scale), which under-restricted how far
    the picker could be dragged above 100% DPI.

Why

The animation flags/tween were requested to bring ColorPicker and
KeyPicker's text swap in line with the existing Dropdown/KeyPicker
open-close polish. The resize/DPI fixes were found incidentally while
working in the same block of code and are small enough to ship in the
same PR rather than opening three more for one file region.

Testing

  • Manual: toggle Animations.ColorPicker / Animations.KeyPicker on
    and off, confirm both animated and instant paths look right.
  • Manual: drag the ColorPicker resize handle at 100% and >100% DPI,
    confirm no clipping/lag and no blank gap on open.
  • Confirm KeyPicker text wipe cancels cleanly on rapid modifier cycling
    (no stacked/racing tweens).

Added FuzzyScore/NormalizeSearch/MatchesSearch, a VSCode-style fuzzy
matcher (exact substring still scores best, falls back to in-order
non-consecutive char matching), and swapped it in for the old
Text:lower():find(Search, 1, true) checks in CheckDepbox and
ApplySearchToTab.

Tabs, Groupboxes, and Tabbox sub-tabs now carry Name/Description;
if a container's own name matches Search, its children are pulled
in automatically instead of needing to match individually.

Dropdown search now scores entries with the same fuzzy matcher and
sorts by score (ties keep original order) instead of leaving
filtered results unordered.

Exact substring matching meant anything short of typing a setting's
name correctly returned zero results, making the search bar mostly
useless for anything but exact recall. This gets it closer to how
search works in most modern UIs.
- Condense fuzzy-sort comment to one line, drop "VSCode-style" wording
- Inline GroupboxMatches assignment as suggested
- Trim Fuzzy Search header to a single comment line

No logic changes.
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