From 269fe03a80e677c8b003aec644c51fdb71bb5c22 Mon Sep 17 00:00:00 2001 From: Simon Date: Fri, 6 Nov 2026 14:04:34 +0100 Subject: [PATCH] Live picks: one shared card with animated banner header for desktop and phone popup Co-Authored-By: Claude Sonnet 5.5 --- src/e2e/tests/orders.ui.spec.ts | 2 +- .../src/components/views/LivePicks.tsx | 38 ++++++++----------- src/frontend/src/styles.css | 4 +- 3 files changed, 19 insertions(+), 25 deletions(-) diff --git a/src/e2e/tests/orders.ui.spec.ts b/src/e2e/tests/orders.ui.spec.ts index c222e07..33ed162 100644 --- a/src/e2e/tests/orders.ui.spec.ts +++ b/src/e2e/tests/orders.ui.spec.ts @@ -85,7 +85,7 @@ test("live picks on phones: bolt button with count opens a popup and minimizes a await expect(page.getByText("1 person has ordered")).toBeVisible(); await page.reload(); await expect(page.getByText("1 person has ordered")).toBeVisible(); // expanded state is remembered - await page.getByRole("button", { name: "Minimize live picks" }).click(); + await page.getByRole("button", { name: /1 ordered/ }).click(); await expect(page.getByText("1 person has ordered")).toBeHidden(); await expect(fab).toBeVisible(); await page.close(); diff --git a/src/frontend/src/components/views/LivePicks.tsx b/src/frontend/src/components/views/LivePicks.tsx index e87f2d9..6ae9efb 100644 --- a/src/frontend/src/components/views/LivePicks.tsx +++ b/src/frontend/src/components/views/LivePicks.tsx @@ -1,6 +1,6 @@ import React, { useState } from "react"; -import { CloseOutlined, DownOutlined, LockOutlined, ThunderboltFilled } from "@ant-design/icons"; -import { Button, Card, Flex, Progress, Typography } from "antd"; +import { DownOutlined, LockOutlined, ThunderboltFilled } from "@ant-design/icons"; +import { Card, Flex, Progress, Typography } from "antd"; import type { OrderStats } from "../../lib/services/ordersService"; import { getStoredValue, setStoredValue } from "../../lib/storage"; @@ -55,22 +55,17 @@ function summary(stats: OrderStats, closed: boolean) { const icon = (closed: boolean) => (closed ? : ); -/** Desktop: expandable banner above the order card; the bars unfold below it. */ -export function LivePicksBanner({ stats, closed }: { stats: OrderStats; closed: boolean }) { - const [open, setOpen] = useStoredFlag(EXPANDED_KEY); +/** One card for both layouts: the animated banner is its header, the bars unfold below it. */ +function LivePicksCard({ stats, closed, open, onToggle }: { stats: OrderStats; closed: boolean; open: boolean; onToggle: () => void }) { return ( -
- {open && ( - + )} @@ -78,21 +73,18 @@ export function LivePicksBanner({ stats, closed }: { stats: OrderStats; closed: ); } -/** Phones: a bolt button with the order count; tap for the popup, tap again (or the X) to minimize. */ +/** Desktop: inline above the order card. */ +export function LivePicksBanner({ stats, closed }: { stats: OrderStats; closed: boolean }) { + const [open, setOpen] = useStoredFlag(EXPANDED_KEY); + return setOpen(!open)} />; +} + +/** Phones: a bolt button with the order count; tap for the card as a popup, tap its header to minimize. */ export function LivePicksFab({ stats, closed }: { stats: OrderStats; closed: boolean }) { const [open, setOpen] = useStoredFlag(EXPANDED_KEY); return (
- {open && ( - } onClick={() => setOpen(false)} />} - > - - - )} + {open && setOpen(false)} />} {!open && (