* Start scanner-mobile-checkout convoy for the cart-then-commit phone flow. Co-authored-by: Cursor <cursoragent@cursor.com> * Ship a cart-then-commit mobile scanner so phone sessions stay on the camera. Scan matches enqueue locally instead of auto-writing ownership, checkout happens in a sheet, and audit fixes cover stale commit detection, returnUrl open redirects, nested Escape, and ember detection chrome. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
69 lines
2.9 KiB
Markdown
69 lines
2.9 KiB
Markdown
---
|
|
convoy: scanner-mobile-checkout
|
|
brief_number: 1
|
|
depends_on: []
|
|
recommended_model: composer-2.5-fast
|
|
model_tier: fast
|
|
files:
|
|
- components/Layout.js
|
|
- test/components/Layout.test.js
|
|
cross_brief_commitments:
|
|
- brief: 4
|
|
description: |
|
|
Brief 4 passes `chrome="immersive"` on `<Layout>` from `pages/scanner.js`
|
|
for authenticated scanner sessions. This brief only adds the prop and
|
|
mobile-only hiding behavior; Brief 4 owns when it is set.
|
|
---
|
|
|
|
# Brief 1: Layout immersive chrome
|
|
|
|
## Goal (1 sentence)
|
|
|
|
Add a narrow `chrome="immersive"` prop to `Layout` that hides global app chrome on viewports `< md` without restyling the desktop sidebar.
|
|
|
|
## Files in scope (do not edit anything else)
|
|
|
|
- `components/Layout.js`
|
|
- `test/components/Layout.test.js`
|
|
|
|
## Conventions to follow
|
|
|
|
- Extend the existing `Layout` signature: `export default function Layout({ children, user = null, showSearch = false })` → add `chrome = 'default'`.
|
|
- Immersive is **mobile-only** (`md:hidden` / `max-md:` patterns). At `md+`, immersive behaves like `default` (sidebar + TopSearchBar unchanged per D3 desktop note).
|
|
- Hide when `chrome === 'immersive'` on `< md`:
|
|
- `<MobileNavigation />` (line ~674)
|
|
- `<TopSearchBar />` (line ~986)
|
|
- Desktop `<aside>` sidebar is already `hidden md:flex` — no change needed at `md+`; on mobile the drawer + bottom nav are the chrome to suppress.
|
|
- Main column: remove `pb-16` bottom padding when immersive (no bottom nav). Use `max-md:pb-0` on the main wrapper (`flex-1 flex flex-col pb-16 md:pb-0`).
|
|
- Outer shell: optional `max-md:p-0` when immersive so camera can be true full-bleed.
|
|
- Do **not** change sidebar styles, nav items, or command palette behavior.
|
|
- Use CSS tokens only — no new hex in JSX.
|
|
|
|
## Implementation shape (verified against `Layout.js`)
|
|
|
|
```js
|
|
export default function Layout({
|
|
children,
|
|
user = null,
|
|
showSearch = false,
|
|
chrome = 'default',
|
|
}) {
|
|
const isImmersive = chrome === 'immersive';
|
|
// ...
|
|
// MobileNavigation: {!isImmersive && <MobileNavigation ... />}
|
|
// TopSearchBar: {user && !isImmersive && <TopSearchBar ... />}
|
|
// Main wrapper className: include isImmersive && 'max-md:pb-0'
|
|
}
|
|
```
|
|
|
|
## Acceptance criteria
|
|
|
|
- [ ] `chrome="immersive"` hides `MobileNavigation` and `TopSearchBar` below `md` breakpoint
|
|
- [ ] `chrome="immersive"` at `md+` renders identical chrome to `chrome="default"` (sidebar + TopSearchBar visible)
|
|
- [ ] `chrome="default"` (or omitted) is unchanged from current behavior
|
|
- [ ] `test/components/Layout.test.js` adds regression tests: immersive hides mobile nav landmark; default still renders Sign-in CTA when `user={null}` (existing 5 assertions preserved)
|
|
- [ ] No scope expansion (do not edit files outside `files:` above)
|
|
|
|
## Rationale (≤3 sentences)
|
|
|
|
Immersive chrome is isolated to `Layout.js` so visual-diff-sensitive sidebar code stays untouched. Mobile-only gating matches design-direction desktop exception. Brief 4 wires the prop from `/scanner` without further Layout changes.
|