From aa4f33704babbfe5b6801bf51823dea16c24db14 Mon Sep 17 00:00:00 2001 From: PavelMakarchuk Date: Fri, 16 Oct 2026 15:36:56 -0400 Subject: [PATCH 1/3] Build: the run bar reaches the scroll area's edge and keeps one row, with the no-name note inside it Co-Authored-By: Claude Opus 5.5 --- .../flagship/reform/DraftHeader.tsx | 110 ++++++++---------- 1 file changed, 50 insertions(+), 60 deletions(-) diff --git a/app/src/components/flagship/reform/DraftHeader.tsx b/app/src/components/flagship/reform/DraftHeader.tsx index ee22ffef2..502f6fc11 100644 --- a/app/src/components/flagship/reform/DraftHeader.tsx +++ b/app/src/components/flagship/reform/DraftHeader.tsx @@ -393,6 +393,9 @@ export function DraftRunBar({ draft }: { draft: DraftReform }) { return (
+ {/* An unnamed reform runs as "Untitled reform": said in the bar's own row, with a quick way to name it. */} + {adjusted.length > 0 && + (!draft.label.trim() || naming) && + (naming ? ( + setDraftLabel(event.target.value)} + onBlur={() => setNaming(false)} + onKeyDown={(event) => { + if (event.key === 'Enter' || event.key === 'Escape') { + setNaming(false); + } + }} + placeholder="Name your reform" + aria-label="Reform name" + style={{ + width: 220, + maxWidth: '100%', + height: 36, + padding: `0 ${spacing.sm}`, + border: `1px solid ${colors.border.light}`, + borderRadius: 6, + background: colors.background.primary, + fontSize: typography.fontSize.sm, + fontFamily: typography.fontFamily.primary, + color: colors.text.primary, + }} + /> + ) : ( + + No name yet. The report will be called “{UNTITLED_REFORM}”. + + + ))} @@ -485,65 +534,6 @@ export function DraftRunBar({ draft }: { draft: DraftReform }) { - {/* An unnamed reform runs as "Untitled reform": said once, with a quick way to name it. */} - {adjusted.length > 0 && (!draft.label.trim() || naming) && ( -
- {naming ? ( - setDraftLabel(event.target.value)} - onBlur={() => setNaming(false)} - onKeyDown={(event) => { - if (event.key === 'Enter' || event.key === 'Escape') { - setNaming(false); - } - }} - placeholder="Name your reform" - aria-label="Reform name" - style={{ - width: 240, - maxWidth: '100%', - height: 28, - padding: `0 ${spacing.sm}`, - border: `1px solid ${colors.border.light}`, - borderRadius: 6, - background: colors.background.primary, - fontSize: typography.fontSize.sm, - fontFamily: typography.fontFamily.primary, - color: colors.text.primary, - }} - /> - ) : ( - <> - No name yet. The report will be called “{UNTITLED_REFORM}”. - - - )} -
- )} {/* Unchanged parameters still leave the run quietly; only "nothing changed" is said. */} {!empty && adjusted.length === 0 && (

Date: Fri, 16 Oct 2026 15:38:46 -0400 Subject: [PATCH 2/3] Build: the run bar sticks to the scroll area's bottom, past the page padding Co-Authored-By: Claude Opus 5.5 --- app/src/components/flagship/reform/DraftHeader.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/app/src/components/flagship/reform/DraftHeader.tsx b/app/src/components/flagship/reform/DraftHeader.tsx index 502f6fc11..2c43cf154 100644 --- a/app/src/components/flagship/reform/DraftHeader.tsx +++ b/app/src/components/flagship/reform/DraftHeader.tsx @@ -393,12 +393,11 @@ export function DraftRunBar({ draft }: { draft: DraftReform }) { return (

Date: Fri, 16 Oct 2026 16:19:41 -0400 Subject: [PATCH 3/3] Test the run bar's sticky offset class, not bottom: 0 Co-Authored-By: Claude Opus 5.5 --- .../unit/components/flagship/reform/DraftHeader.test.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/app/src/tests/unit/components/flagship/reform/DraftHeader.test.tsx b/app/src/tests/unit/components/flagship/reform/DraftHeader.test.tsx index 90eb7d8a9..8880c51ff 100644 --- a/app/src/tests/unit/components/flagship/reform/DraftHeader.test.tsx +++ b/app/src/tests/unit/components/flagship/reform/DraftHeader.test.tsx @@ -110,8 +110,10 @@ describe('DraftHeader', () => { text === 'Discard' || text === 'Save' || /^Save and run 2026 report$/.test(text ?? '') ); expect(verbs).toEqual(['Discard', 'Save', 'Save and run 2026 report']); - // It stays in view at the bottom of the window while the reform is long. - expect(bar).toHaveStyle({ position: 'sticky', bottom: '0px' }); + // It stays in view at the bottom of the window while the reform is long, + // stuck over the page's bottom padding so nothing shows under it. + expect(bar).toHaveStyle({ position: 'sticky' }); + expect(bar).toHaveClass('tw:-bottom-lg', 'tw:sm:-bottom-2xl'); }); test('given nothing changed yet then the run waits for a change', () => {