feat(tui): restyle the ADR split and import overlays (#144) - #150
Merged
Conversation
Slice 5 of the map #136 cut: the ADR split review flow and the forge import flow move onto internal/tui/theme and internal/tui/widget, and the two overlay-adjacent leftovers the earlier slices recorded are taken with them - the section 4 step 1 backdrop dim and the pointer package's raw reverse-video escape. Both overlays are widget.Overlay panels: the rounded borders are deleted, rows carry a semantic kind that picks the token, pointer targets are structural, and the busy states adopt the bubbles spinner and progress bar. adrsplit/view.go and issueimport/view.go leave the seam allowlist, which is down to one entry.
|
This was referenced Aug 19, 2026
aksOps
added a commit
that referenced
this pull request
Aug 20, 2026
* feat(tui): spin the card editor's drafting and saving states Spec section 5.2 assigns the bubbles spinner to every busy state that was static text; the card editor's drafting and saving footers were the last two left behind (PR #150 deviation 8). The pattern is PR #150's: the editor holds a spinner.Model, SetStyles adopts the theme's spinner, the tick is batched at the operation start so an idle editor costs no timers, and the tick loop stops as soon as neither drafting nor saving is in flight. Refs #145. * docs: add v1.1.0 release notes The redesign release: the Strata design language, the full-frame board and proportional overlays, visible semantic-colored buttons, the adopted charm components, and the text-field key fixes. No database migration. Refs #145.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Slice 5 of the map #136 cut (spec section 9.3): the ADR split review flow and
the forge import flow move onto
internal/tui/themeandinternal/tui/widget.The binding spec is
docs/design/tui-design-spec.mdondesign/tui-spec.This slice also takes the two overlay-adjacent leftovers the merged slices
recorded and handed forward: the section 4 step 1 backdrop dim (PR #147
deviation 1, PR #149 deviation 6) and
pointer.go's raw reverse-video escape(PR #149 deviation 8).
Closes #144.
What the spec dictated
Section 4 - elevation. Both
NewStyle().Border(RoundedBorder())frames(spec section 9.1 names them) are gone. Each overlay is a
widget.Overlaypanel: a solid
Brandheader band carrying the title, anOverlaySurfbody,OverlayBandsection breaks (SOURCE,STORIES,ISSUES), anOverlayBandfooter band carrying the hints with the ADR split's scroll indicator
right-aligned, and the two
Shadowbands cast one cell down and right throughwidget.OverlayLayers. Geometry and the per-overlay width caps come fromtheme.Metrics.Overlay(ADRSplit100,IssueImport88); the two deadliterals are gone.
Section 4 step 1 - the dim, finally wired.
Model.backdrop()returns themodel the board renders through: with any overlay open it is the same model
carrying
styles.Dimmed, sorenderBoardre-renders the whole board throughthe second built palette. It is not a post-pass over a rendered string, which
is what the spec forbids, and it is one call at the compose site because #148
made the board renderer take styles.
Section 9.1 - the pressed token.
pointer.State.Rendertakes a*theme.Stylesand delegates to the newStyles.PressedRun. The theme ownsthe attribute and the re-arming a composed run needs; the pointer package only
decides which control wears it. The run still closes by clearing the attribute
alone rather than resetting the style, because callers substitute it into the
middle of a styled line (
help.go,settings_view.go).Sections 6.2 and 9.2 - the seam.
adrsplit/view.goandissueimport/view.goleave the seam allowlist; the list is down to oneentry (
help.go) and its size cap with it. Both overlays take a*theme.StylesthroughSetStyles, threaded frominternal/tui/model.goonconstruction and on
tea.BackgroundColorMsg, and neither constructs a style.Section 5.1 - kb widgets. Actions are
widget.Button, the include andproposal marks are
widget.Check, the ADR split's scroll position iswidget.ScrollHint, and every body row goes throughwidget.OverlayRoworwidget.Section.Section 5.2 - charm, where the spec assigns it. huh's inline
Selectrenders the Source, Max stories, Priority, Effort and Destination choices;
huh's
Noterenders the two AI disclaimer blocks inadrsplit. The bubblesspinnerreplaces the static...on every busy state in both overlays(reading the file, splitting, creating card i of N, fetching and drafting), and
the bubbles
progressbar rendersissueimport'swriting i/N. The huhadapters moved from
internal/tuitointernal/tui/formviewbecause threepackages now render them;
formview.HuhInlineSelectis the new one.Section 6.4 - goldens.
TestADRSplitInputGoldenis regenerated and nowpins
theme.StructureProfileexplicitly. Three goldens are new:TestADRSplitReviewColorGolden, and the pair spec section 6.4 asks for on theissue-import overlay, which had none -
TestIssueImportGolden(structure) andTestIssueImportColorGolden(truecolor over a board background, with the writeprogress bar in frame).
Interaction is frozen
Every keymap, flow, session-scoping rule and mouse target of v1.0.1 survives.
Three mechanical changes were needed to keep them surviving a themed render:
by line arithmetic over the body (
adrsplit.controlRows) or by matching therendered line text (
issueimport). Rows now carry their target, and thebuttons that share a row carry their column offset. Same control ids, same
rects, same messages - and an ADR or a forge draft title can no longer
impersonate a control, which is what the two impersonation tests assert.
arithmetic skipped created stories entirely; the row model blanks their
targets instead, so neither the tab cycle nor a click can reopen a story that
is already written.
[>Discard<]and[>Cancel<]are gone; the labels stay[ Discard ]and[ Cancel ]andwear reverse video. Two assertions moved from the substituted text to the
attribute in the composed frame.
Deviations, and why
issueimport'smaxstays a plain field. Spec section 5.2 assignsSelectto "Max stories"; that is the ADR split's field and it is a choice.The import's
maxaccepts digit keys 0-9 as direct entry, which an inlineSelect cannot express, so it keeps its value rendering.
layout gives each choice one row and one pointer target; a stacked Select is
a title plus one row per option. The inline form is the only one that fits.
As in feat(tui): restyle the editor, settings, and dialogs (#143) #149 the field is built from kb's state, rendered and dropped - huh
owns focus and its own keymap, and exposes no hit regions.
widget.Checkreplaces[x] includeand[ ]. Section 5.1 assigns thechecklist row to the widget, and these two rows are checklist rows. A
created or already-written item takes the third mark (
CheckDropped), whichis what "out of the batch" looks like. Three test needles moved with it.
overlays; the panel has a footer band for exactly that, and it costs each
overlay one row less. While a status shows it replaces the hint ladder,
which is the pattern feat(tui): restyle the card detail overlay (#142) #147 and feat(tui): restyle the editor, settings, and dialogs (#143) #149 already ship.
is the card detail pane's. This overlay windows its own proposals
(
reviewWindow, frozen atmin(h-10, 12)rows) and has never scrolled apanel, so pinning the panel to the frame would have double-limited it. The
ADR split, which does scroll, takes the fixed
min(max(h-2,7), h)geometryand gains one body row from losing the border.
issueimport's ref field goes throughformview.Input. It renderedtextinput.Model.View()straight into a row whose own truncation mapscontrol runes to spaces, so its escapes showed up as visible
[37mtext.Incidental, pre-existing, and fixed here because this is the row's restyle.
walk the batch and skip the tick. The alternative - ticking for as long as
the overlay is open - costs a timer on an idle overlay.
cardeditor'sdrafting/savingstates keep their static text. Specsection 5.2 names them for the spinner too, but they are Restyle the editor, settings, and dialogs #143's surface and
it has shipped. Left for the map to place.
Dependency
charm.land/bubbles/v2/progresspullsgithub.com/charmbracelet/harmonica v0.2.0(MIT, charmbracelet) as an indirect requirement for its springanimation. The bar itself is rendered with
ViewAs, so nothing animates.Verification
go build ./...go vet ./...sh scripts/check-go-coverage.shinternal/tuicoverageinternal/tui/adrsplitcoverageinternal/tui/issueimportcoverageinternal/tui/formviewcoverageinternal/tui/theme,widget,pointercoveragego test -race ./internal/tui/...sh scripts/check-go-format.sh