Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
8dda7b5
feat(search): add editable pins menu
BigSimmo Aug 5, 2026
a9b2aae
Merge remote-tracking branch 'origin/main' into codex/editable-search…
BigSimmo Aug 5, 2026
725bf67
Merge remote-tracking branch 'origin/main' into codex/editable-search…
cursoragent Aug 5, 2026
da3e1b7
Fix editable search pins menu regressions
cursoragent Aug 5, 2026
fbac540
Fix type scale token usage in pin menus
cursoragent Aug 5, 2026
79b8f5f
Use design tokens in search pins menu
cursoragent Aug 5, 2026
cba943e
Gate pins universal search by command availability
cursoragent Aug 5, 2026
a52d71c
Merge remote-tracking branch 'origin/main' into codex/editable-search…
cursoragent Aug 5, 2026
70fd5c0
Restore document drawer focus fallback
cursoragent Aug 5, 2026
e3998ab
Resolve pins menu review regressions
cursoragent Aug 5, 2026
456d7a1
Cover pins sheet focus retarget
cursoragent Aug 5, 2026
0ded37e
Stabilize pins sheet focus test
cursoragent Aug 5, 2026
9de5586
Keep pins sheet mounted for focus restore
cursoragent Aug 5, 2026
ab66f36
Satisfy pins focus lint guards
cursoragent Aug 5, 2026
fffc6de
Fix pins menu focus callback wiring
cursoragent Aug 5, 2026
a8e92cc
Fix pins menu typecheck regression
cursoragent Aug 5, 2026
30262ca
Refresh design sync sheet metadata
cursoragent Aug 5, 2026
95032bc
Resolve remaining pins review feedback
cursoragent Aug 5, 2026
1cd2254
Update search-pins-menu.tsx
BigSimmo Aug 5, 2026
df05249
fix(search): close remaining pins menu review defects
cursoragent Aug 5, 2026
33d2ef2
Merge remote pins branch updates
cursoragent Aug 5, 2026
193afe6
fix(search): clear merge conflict markers in pins sync
cursoragent Aug 5, 2026
1b1fd89
Use sheet autofocus for first search pin
cursoragent Aug 5, 2026
7f1ac06
docs(ledger): record pins menu review follow-up
cursoragent Aug 5, 2026
e3d57a2
Merge remote-tracking branch 'origin/codex/editable-search-pins' into…
cursoragent Aug 5, 2026
c59ec43
Merge remote-tracking branch 'origin/codex/editable-search-pins' into…
cursoragent Aug 5, 2026
3c3a57e
fix(search): avoid setState-in-effect for command displayability
cursoragent Aug 5, 2026
d3f9a57
Fix command dropdown displayability state
cursoragent Aug 5, 2026
a0e2801
fix(search): resolve displayability merge and clear eager override
cursoragent Aug 5, 2026
52112ef
docs(ledger): supersede pins review follow-up at tip
cursoragent Aug 5, 2026
6d8a6af
Merge remote-tracking branch 'origin/main' into codex/editable-search…
cursoragent Aug 5, 2026
c464e99
Fix search pins review follow-ups
cursoragent Aug 5, 2026
fd445e8
fix(search): address new pins review findings
cursoragent Aug 5, 2026
4c8fb09
fix(search): merge pins review follow-ups and stabilize tests
cursoragent Aug 5, 2026
c534fa2
Stabilize search pins fallback tests
cursoragent Aug 5, 2026
88c6472
Merge remote-tracking branch 'origin/codex/editable-search-pins' into…
cursoragent Aug 5, 2026
cf8cb41
Fix dynamic sheet return focus
cursoragent Aug 5, 2026
67f2c71
Merge origin/main into editable search pins
cursoragent Aug 5, 2026
3022fcc
docs(ledger): supersede pins review record with decisive gate lines
cursoragent Aug 5, 2026
867226a
Fix sheet return focus lint regression
cursoragent Aug 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .design-sync/config.json

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions docs/branch-review-ledger.md
Original file line number Diff line number Diff line change
Expand Up @@ -641,5 +641,9 @@ Records before 2026-07-28 were written by hand and had drifted: 146 lines carrie
| 2026-08-05 | codex/v2-design-system-completion | 8863cea53bf4df59e8795dcaab1fa420b5109516 | PR #1616 v2 design system CI+reviews | fixed typecheck + review defects; baselines remain not-committed by design | tsc; vitest ui-v2/accessible-table/ui-primitives/design-system-adoption |
| 2026-08-05 | codex/v2-design-system-completion | 8b49bfa2b66ed78577b08e1a50414db55898f2df | PR #1616 v2 design system CI+reviews | fixed typecheck + review defects; baselines remain not-committed by design | tsc; vitest ui-v2/accessible-table/ui-primitives/design-system-adoption |
| 2026-08-05 | codex/v2-design-system-completion | 1ea30c19c48b3791519659abf85b20c9e8c7faab | PR #1616 review feedback disposition | COMPLETED: fixed mode-home empty composer reserve + chip category v2 tokens; dispositioned remaining Devin analysis findings to outstanding-issues; unresolved threads 0 | vitest search-route-ownership 12/12; ckb-v2-token-contract+related green; CI in progress on tip |
| 2026-08-05 | codex/editable-search-pins | 18c3069c7ad19b7e92e3ec9e0b65b5d845afe9c1 | editable search pins menu production integration and mockups | no findings; ready for draft review | verify:pr-local; focused pin tests; typecheck; responsive browser QA; phone-chrome contracts and journey |
| 2026-08-05 | codex/editable-search-pins | 193afe637481c0ed2fa82dbe9bb1f1d1c8bcc4d8 | editable search pins menu review follow-up | fixed remaining review defects; unresolved threads cleared; auto-merge armed | vitest:search-pins 18/18; tsc clean on touched surfaces; review threads 0 unresolved |
| 2026-08-05 | codex/editable-search-pins | a0e2801fb291a672274c9a723108637d3cdb43f9 | editable search pins menu review follow-up | fixed remaining review defects; lint setState-in-effect; unresolved threads cleared; auto-merge armed | vitest:search-pins 18/18; eslint touched surfaces; review threads 0 unresolved |
Comment thread
coderabbitai[bot] marked this conversation as resolved.
| 2026-08-05 | cursor/phone-mode-sheet-yes-05c0 | b579d68491980388ff3e4ce8aba85530e87a9d84 | Run PR sweep | threads already resolved; synced main via update-branch; CI was green pre-sync | CI: PR required SUCCESS pre-sync |
| 2026-08-05 | cursor/phone-mode-sheet-yes-05c0 | 9152e239076ff823ad3bf812d282ffc87c3295b7 | Run PR sweep | threads already resolved; merged origin/main; CI was green pre-sync | CI: PR required SUCCESS pre-sync; merge-tree clean |
| 2026-08-05 | codex/editable-search-pins | 67f2c71e8376fbc44615f765a73cb6a37c4ddb40 | editable search pins menu review follow-up | merged main; review threads cleared; auto-merge armed | vitest search-pins+mode-action+command-surface: Test Files 4 passed (4); Tests 33 passed (33); eslint max-warnings 0 on touched surfaces |
2 changes: 2 additions & 0 deletions docs/site-map.md
Original file line number Diff line number Diff line change
Expand Up @@ -1017,9 +1017,11 @@ This file is generated by `npm run docs:update` (or `npm run sitemap:update` dir
- `/mockups/mode-dropdown` - Route discovered from app directory Source: `src/app/mockups/mode-dropdown/page.tsx`.
- `/mockups/phone-inpage-navigation` - Route discovered from app directory Source: `src/app/mockups/phone-inpage-navigation/page.tsx`.
- `/mockups/phone-mode-sheet-yes` - Route discovered from app directory Source: `src/app/mockups/phone-mode-sheet-yes/page.tsx`.
- `/mockups/pinned-plus-menu` - Route discovered from app directory Source: `src/app/mockups/pinned-plus-menu/page.tsx`.
- `/mockups/recent-searches-bottom` - Route discovered from app directory Source: `src/app/mockups/recent-searches-bottom/page.tsx`.
- `/mockups/search-band-directions` - Route discovered from app directory Source: `src/app/mockups/search-band-directions/page.tsx`.
- `/mockups/search-heading` - Route discovered from app directory Source: `src/app/mockups/search-heading/page.tsx`.
- `/mockups/search-lens-menu` - Route discovered from app directory Source: `src/app/mockups/search-lens-menu/page.tsx`.
- `/mockups/search-refine-adaptive` - Route discovered from app directory Source: `src/app/mockups/search-refine-adaptive/page.tsx`.
- `/mockups/settings-search-clinical` - Route discovered from app directory Source: `src/app/mockups/settings-search-clinical/page.tsx`.
- `/mockups/settings-search-general` - Route discovered from app directory Source: `src/app/mockups/settings-search-general/page.tsx`.
Expand Down
26 changes: 26 additions & 0 deletions docs/superpowers/plans/2026-08-05-editable-pin-menu-mockups.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Search + Editable Pins Menu — Implementation Record

## Goal

Perfect `/mockups/search-lens-menu` around editable app-destination pins while preserving the original visual direction.

## Completed

- [x] Preserve the light attached fold-out and paired desktop/phone frames.
- [x] Replace editable search lenses with editable app-destination pins.
- [x] Add `Your pins` and a separate `Search in` section.
- [x] Keep Documents, global, and alternate-area search choices explicit.
- [x] Retain overlapping phone icon constellations with accessible labels.
- [x] Add a functional local `New pin` flow with editable name and destinations.
- [x] Add a functional Ward essentials edit flow.
- [x] Adapt the command deck to distinguish pins from search commands.
- [x] Adapt the inline builder into an inline pin bar.
- [x] Add focused DOM interaction coverage.
- [x] Verify 18 width/direction combinations, dialog containment, keyboard closing and focus restoration, reduced motion, forced colors, and console output.

## Remaining production work

- [ ] Decide persistence, synchronization, permissions, and pin limits.
- [ ] Map mockup destinations to canonical production routes.
- [ ] Complete physical iPhone Safari and installed-PWA acceptance.
- [ ] Conduct clinical governance review before production search integration.
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# Search + Editable Pins Menu — Final Mockup Direction

## Preferred artifact

Route: `/mockups/search-lens-menu`

The preferred visual direction is the original light clinical search-menu study, refined around the corrected pin model. It preserves its attached fold-out, deliberate page scrim, compact overlapping icons, and paired desktop/phone treatments.

## Product model

A **pin** is a user-named collection of useful destinations from anywhere in the app. It is not a search scope, filter, or saved query.

Example pins:

- Ward essentials: Documents, Medications, Forms.
- My quick tools: Clinical tools, Services, Differentials.

Users can create a pin, edit its name, add or remove destinations, and recognise its contents through the first three overlapping destination icons.

Search remains explicit and separate:

- Search Documents — current mode.
- Search all clinical areas — global search.
- Choose another search area — explicit alternate scope.

Opening or selecting a pin never silently changes the composer’s search scope.

## Direction 1 — Attached pin fold-out

Recommended.

- Opens from the composer `+` button.
- Shows `Your pins` first.
- Shows `Search in` as a separate section below.
- Includes useful actions without confusing them with either pins or search scope.
- Desktop/tablet use an attached panel with a subdued scrim.
- Phone uses a contained bottom sheet above the visible composer.

## Direction 2 — Pins and search command deck

- Presents pins and search commands in one power-user workspace.
- The navigation rail clearly labels both object types.
- Selecting a pin previews its app destinations.
- Selecting a search command runs the current query in that area.

## Direction 3 — Inline pin bar

- Pin destinations become removable chips directly above the composer.
- The Documents search scope remains visible and stable beneath the pin.
- Editing uses a compact destination picker on desktop and phone.

## Accessibility and responsive rules

- Minimum 48 px primary touch targets.
- Icon constellations expose full destination labels to assistive technology.
- Escape closes panels and restores focus to the composer trigger.
- Panels own internal scrolling and remain within device frames.
- Reduced-motion and forced-colors modes remain usable.
- Validate 320, 390, 639, 768, 1440, and 1920 px.

## Boundaries

This remains a local design-scratch artifact. It does not persist pins, call APIs or providers, alter production navigation/search, change retrieval ranking, or deploy anything.
5 changes: 4 additions & 1 deletion src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -1327,7 +1327,10 @@ summary::-webkit-details-marker {
outline-offset: 2px;
}

.mode-action-body {
/* Cap scrolling only inside the anchored popover surface, which defines
--mode-action-body-max-height. Sheet/dialog hosts leave the variable unset;
applying max-height there would create a nested non-capping scroll region. */
.mode-action-surface .mode-action-body {
max-height: var(--mode-action-body-max-height);
overflow-y: auto;
overscroll-behavior: contain;
Expand Down
8 changes: 8 additions & 0 deletions src/app/mockups/mockups-layout-client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ export function MockupsLayoutClient({ children }: { children: ReactNode }) {
const isWarningConsolidationMockup = pathname === "/mockups/warning-consolidation";
const isWarningLineMockup = pathname === "/mockups/warning-line";
const isAnswerHomeProposalMockup = pathname === "/mockups/answer-home-proposal";
// These studies draw complete app shells and their own search composers, so
// shared chrome would make the interaction studies ambiguous.
const isSearchLensMenuMockup = pathname === "/mockups/search-lens-menu";
const isPinnedPlusMenuMockup = pathname === "/mockups/pinned-plus-menu";
// Draws its own phone frames with an in-frame Choose mode sheet; shared chrome
// would read as a second real header over the study.
const isPhoneModeSheetYesMockup = pathname === "/mockups/phone-mode-sheet-yes";
Expand Down Expand Up @@ -80,6 +84,8 @@ export function MockupsLayoutClient({ children }: { children: ReactNode }) {
!isWarningConsolidationMockup &&
!isWarningLineMockup &&
!isAnswerHomeProposalMockup &&
!isSearchLensMenuMockup &&
!isPinnedPlusMenuMockup &&
!isPhoneModeSheetYesMockup
}
chromeVisible={
Expand All @@ -92,6 +98,8 @@ export function MockupsLayoutClient({ children }: { children: ReactNode }) {
!isWarningConsolidationMockup &&
!isWarningLineMockup &&
!isAnswerHomeProposalMockup &&
!isSearchLensMenuMockup &&
!isPinnedPlusMenuMockup &&
!isPhoneModeSheetYesMockup
}
>
Expand Down
5 changes: 5 additions & 0 deletions src/app/mockups/pinned-plus-menu/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { PinnedPlusMenuMockupsPage } from "@/components/pinned-plus-menu-mockups";

export default function Page() {
return <PinnedPlusMenuMockupsPage />;
}
5 changes: 5 additions & 0 deletions src/app/mockups/search-lens-menu/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { SearchLensMenuMockupsPage } from "@/components/search-lens-menu-mockups";

export default function SearchLensMenuMockupRoute() {
return <SearchLensMenuMockupsPage />;
}
2 changes: 1 addition & 1 deletion src/components/ClinicalDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3234,7 +3234,7 @@ export function ClinicalDashboard({
const returnTarget = documentsDrawerReturnFocusRef.current;
window.requestAnimationFrame(() => {
const fallbackTarget = Array.from(
document.querySelectorAll<HTMLElement>('button[aria-haspopup="menu"][aria-label$=" options"]'),
document.querySelectorAll<HTMLElement>('button[aria-haspopup][aria-label$=" options"]'),
).find((element) => element.isConnected && element.getClientRects().length > 0);
const focusTarget = returnTarget?.isConnected ? returnTarget : fallbackTarget;
focusTarget?.focus({ preventScroll: true });
Expand Down
69 changes: 58 additions & 11 deletions src/components/clinical-dashboard/master-search-header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
Filter,
Globe2,
Loader2,
Layers3,
Menu,
MessageSquarePlus,
Plus,
Expand All @@ -36,8 +37,10 @@ import { DocumentTagCloud } from "@/components/DocumentTagCloud";
import { PrivacyInputNotice } from "@/components/privacy-input-notice";
import { restoreFocusUnlessMoved, useDismissableLayer } from "@/components/use-dismissable-layer";
import { useHideOnScroll } from "@/components/clinical-dashboard/use-hide-on-scroll";
import { useEventCallback } from "@/components/clinical-dashboard/use-event-callback";
import { PhoneFooterLayerPortal } from "@/components/clinical-dashboard/phone-footer-layer-portal";
import { AnswerFollowUpSuggestions } from "@/components/clinical-dashboard/answer-follow-up-suggestions";
import { SearchPinsMenu } from "@/components/clinical-dashboard/search-pins-menu";
import {
ModeActionPopup,
modeActionItemsFor,
Expand Down Expand Up @@ -76,6 +79,8 @@ import {
setModeHomeComposerReservePending,
} from "@/lib/mode-home-composer";
import { resolveScrollBehavior } from "@/lib/scroll-behavior";
import type { CommandSurfacePlacement } from "@/lib/search-command-surface";
import { useCommandDropdownDisplayableByPlacement } from "@/components/clinical-dashboard/use-command-dropdown-displayable";
import type { ClinicalDocument, ClinicalQueryMode } from "@/lib/types";
import { type SearchScopeFilters } from "@/lib/search-scope";
import { tagSearchText } from "@/lib/document-tags";
Expand Down Expand Up @@ -353,6 +358,7 @@ export function MasterSearchHeader({
const [commandDropdownOpen, setCommandDropdownOpen] = useState(false);
const [commandListboxId, setCommandListboxId] = useState<string>();
const [commandActiveItemId, setCommandActiveItemId] = useState<string | null>(null);
const commandDropdownDisplayableByPlacement = useCommandDropdownDisplayableByPlacement();
const [modeMenuOpen, setModeMenuOpen] = useState(false);
// Which menuitemradio should receive initial focus when the mode menu opens
// (keyboard ArrowOpen or the active mode on tap). Shared by the desktop
Expand Down Expand Up @@ -485,6 +491,7 @@ export function MasterSearchHeader({
const prefetchedModeHrefsRef = useRef(new Set<string>());
const scopePopoverRef = useRef<HTMLDivElement | null>(null);
const actionMenuTriggerRef = useRef<HTMLButtonElement | null>(null);
const actionMenuSheetReturnFocusRef = useRef<HTMLElement | null>(null);
const scopeFilterInputRef = useRef<HTMLInputElement | null>(null);
const touchStartY = useRef<number | null>(null);
const selectedDocumentIdSet = useMemo(() => new Set(selectedDocumentIds), [selectedDocumentIds]);
Expand Down Expand Up @@ -594,8 +601,6 @@ export function MasterSearchHeader({
? "factsheets"
: "answer";
const actionMenuItems = modeActionItemsFor(actionMenuSetId);
const actionMenuTitle = selectedAppMode.label;
const actionMenuSubtitle = searchMode === "answer" ? "Source-backed mode" : selectedAppMode.description;
const actionMenuButtonLabel = `Open ${selectedAppMode.label.toLowerCase()} options`;
const useMobileBackControl = mobileLeadingAction === "back";

Expand Down Expand Up @@ -1033,6 +1038,27 @@ export function MasterSearchHeader({
restoreFocusUnlessMoved(actionMenuTriggerRef.current);
});
}, []);
const handleFocusSearchInput = useEventCallback(() => {
queryInputRef?.current?.focus();
});
const retargetActionMenuSheetFocusToSearchInput = useEventCallback(() => {
const target = queryInputRef?.current ?? null;
actionMenuSheetReturnFocusRef.current = target;
if (!currentUsesScopeSheet()) {
window.requestAnimationFrame(() => {
restoreFocusUnlessMoved(target);
});
}
});
const handleActionMenuCurrentSearch = useEventCallback(() => {
retargetActionMenuSheetFocusToSearchInput();
setActionMenuOpen(false);
});
const handleActionMenuGlobalSearch = useEventCallback(() => {
retargetActionMenuSheetFocusToSearchInput();
setActionMenuOpen(false);
setCommandDropdownOpen(true);
});

const phoneLayoutGateRef = useRef<boolean | null>(null);
useEffect(() => {
Expand Down Expand Up @@ -1580,7 +1606,8 @@ export function MasterSearchHeader({
// Tablet/desktop composers keep the site-wide notice everywhere.
const showsComposerPrivacyNotice = usesPhoneSearchLayout ? isDesktopHomeComposer : true;

const commandSurfacePlacement = usesBottomComposerPlacement ? "bottom-dock" : "inline";
const commandSurfacePlacement: CommandSurfacePlacement = usesBottomComposerPlacement ? "bottom-dock" : "inline";
const commandDropdownDisplayable = commandDropdownDisplayableByPlacement[commandSurfacePlacement];
// Search sits outside the collapsing top-bar row. Sticky hosts pin an outer
// top-bar stack; result composers portal into page flow at sm+, so this
// relative fallback only covers the brief pre-portal default placement (a
Expand Down Expand Up @@ -1623,7 +1650,7 @@ export function MasterSearchHeader({
data-command-open={
// Phones never show the command dropdown, so the dock scrim must not
// grow for it — gate the open attribute to widths that can display it.
usesBottomComposerPlacement && !usesPhoneSearchLayout && commandDropdownOpen ? "true" : undefined
usesBottomComposerPlacement && commandDropdownDisplayable && commandDropdownOpen ? "true" : undefined
}
data-scroll-hidden={shouldHideBottomOnScroll && bottomComposerHidden ? "true" : undefined}
{...(shouldHideBottomOnScroll ? composerFocusProps : undefined)}
Expand Down Expand Up @@ -1719,7 +1746,7 @@ export function MasterSearchHeader({
onRunModeAction={runModeAction}
onListboxIdReady={setCommandListboxId}
onActiveItemIdChange={setCommandActiveItemId}
onFocusSearchInput={() => queryInputRef?.current?.focus()}
onFocusSearchInput={handleFocusSearchInput}
>
<div
data-menu-placement={actionMenuOpen ? actionMenuPlacement : undefined}
Expand All @@ -1732,29 +1759,49 @@ export function MasterSearchHeader({
>
<ModeActionPopup
open={actionMenuOpen}
title={actionMenuTitle}
titleIcon={SelectedAppModeIcon}
subtitle={actionMenuSubtitle}
title="Pins and search"
titleIcon={Layers3}
subtitle="Open a pin or choose where this search runs."
buttonLabel={actionMenuButtonLabel}
items={actionMenuItems}
modeOptions={actionMenuModeOptions}
selectedModeId={selectedAppMode.id}
onOpenChange={setActionMenuOpen}
onBeforeOpen={() => {
actionMenuSheetReturnFocusRef.current = null;
setUsesScopeSheet(currentUsesScopeSheet());
setCommandDropdownOpen(false);
setModeMenuOpen(false);
setScopeOpen(false);
setScopeSheetOpen(false);
}}
onAction={runModeAction}
onModeSelect={selectAppModeById}
onPlacementChange={setActionMenuPlacement}
triggerClassName="answer-footer-search-action"
triggerRef={actionMenuTriggerRef}
integrated={usesFooterChipLayout}
integratedChipRow={showFooterSearchChips}
useSheet={usesScopeSheet}
sheetReturnFocusRef={actionMenuSheetReturnFocusRef}
dismissIgnoreRefs={[modeMenuRef]}
customBody={
<SearchPinsMenu
key={actionMenuOpen ? "pins-menu-open" : "pins-menu-closed"}
currentModeId={selectedAppMode.id}
modeOptions={actionMenuModeOptions}
actions={actionMenuItems}
globalSearchAvailable={commandDropdownDisplayable}
onClose={() => setActionMenuOpen(false)}
onCurrentSearch={handleActionMenuCurrentSearch}
onGlobalSearch={handleActionMenuGlobalSearch}
onModeSelect={(modeId) => {
setActionMenuOpen(false);
selectAppModeById(modeId);
}}
onAction={(actionId) => {
setActionMenuOpen(false);
runModeAction(actionId);
}}
/>
}
/>

{/* The clear button is a flex sibling (not absolutely positioned): the
Expand Down
Loading
Loading