diff --git a/.specify/specs/021-sidebar-language-polish/plan.md b/.specify/specs/021-sidebar-language-polish/plan.md new file mode 100644 index 0000000..913d30f --- /dev/null +++ b/.specify/specs/021-sidebar-language-polish/plan.md @@ -0,0 +1,79 @@ +# Implementation Plan: Sidebar Icons and Language Menu Polish + +**Branch**: `codex/sidebar-language-fixes` | **Date**: 2026-06-15 | **Spec**: `.specify/specs/021-sidebar-language-polish/spec.md` +**Input**: Feature specification from `.specify/specs/021-sidebar-language-polish/spec.md` + +## Summary + +Unify duplicate authenticated navigation icons by reusing the Dashboard icon definitions across wardrobe screens, and restyle the global language menu with the same light elevated glass treatment used by the auth popup and cookie banner. + +## Technical Context + +**Language/Version**: TypeScript, React, Next.js App Router +**Primary Dependencies**: Next.js App Router, next-intl, Tailwind CSS v4 tokens, existing Dashboard navigation components +**Storage**: None changed +**Testing**: ESLint, TypeScript, Next build, feature-memory guard, diff whitespace check, browser smoke checks +**Target Platform**: Mobile-first web plus desktop authenticated dashboard surfaces +**Project Type**: Next.js web application +**Performance Goals**: Visual-only changes with no extra runtime fetches or provider calls +**Constraints**: Glassmorphism UI, achromatic interface, EN/RU only for MVP v1, shared UI reuse over local variants +**Scale/Scope**: Seven authenticated UI files plus global CSS styling for the language menu + +## Constitution Check + +- Glassmorphism UI: PASS; `.language-menu` now shares the elevated glass styling used by auth/cookie surfaces. +- Achromatic interface: PASS; no colored UI accents were introduced. +- Direct, Not Dictate: N/A; this is visual navigation and menu polish. +- Premium quality bar: PASS; duplicated icons now use the same artwork and 18px rendered size. +- Three upload methods: N/A; no upload behavior changed. +- Engineering reuse: PASS; local sidebar implementations import and reuse `DashboardIcon` and `DashboardIconName` for shared navigation entries. + +## Verification _(mandatory — required by SENAR)_ + +| Acceptance criterion | Evidence | +| --- | --- | +| US1-AC1 shared icons match Dashboard across authenticated screens | Browser verification on `http://localhost:3000/en/dashboard`, `/en/my-items`, `/en/capsule-result?tab=outfits`, `/en/capsule-result`, `/en/favorites`, `/en/for-sale`, `/en/for-repair`, and `/en/uncapsulated` compared SVG `outerHTML` for Dashboard, My Items, Outfits, Capsules, Shopping List, For Sale, and Settings against the Dashboard reference; all matched. | +| US1-AC2 Favourites keeps For Sale, Dashboard, Shopping List, and Settings dimensions stable | Browser DOM measurements showed affected shared icons rendered at 18x18 with stable sidebar alignment and no console errors. | +| US1-AC3 capsule-result active states stay stable | Source evidence: `CapsuleResultShell.tsx` keeps Outfits active only when `activeTab === "outfits"` and keeps Capsules active for capsule item/gap tabs while reusing Dashboard icons. | +| US2-AC1 language menu matches auth/cookie glass styling | Browser computed styles after opening the language dropdown showed `backgroundColor: rgba(255, 255, 255, 0.38)`, `backdropFilter: blur(64px) saturate(1.18)`, elevated shadow, and light border. | +| US2-AC2 only EN/RU options remain visible | Browser language-menu smoke check opened the existing `LanguageSwitcher` and confirmed EN/RU behavior remained unchanged; no ES-AR route, enum, or switcher control was added. | +| FR-001 through FR-006 shared navigation icon reuse | Source evidence: affected wardrobe shells import `DashboardIcon` / `DashboardIconName` from `@/components/dashboard/DashboardNavigation` and use Dashboard icon names for shared labels instead of local SVG variants. | +| FR-007 capsule-result active-state behavior | Source evidence and browser route checks covered `/en/capsule-result?tab=outfits` and `/en/capsule-result`, ensuring the icon reuse did not alter tab-specific active logic. | +| FR-008 through FR-010 visual-only language polish | Source evidence: `app/src/app/globals.css` applies the shared auth/cookie elevated glass surface to `.language-menu`; no product route, provider, or persistence code changed. | +| SC-003 local pipeline | `npm run lint` passed; `npm run typecheck` passed; `npm run build` passed; `npm run ci:check` passed; `git diff --check` passed. | +| SC-004 GitHub pipeline | PR #42 was opened, branch pushed, baseline checks ran, Codex review was triggered with `@codex review`, and guard is rerun after adding this feature memory. | + +Negative scenario evidence: + +- Local sidebar variants: source check confirms shared navigation labels now use `DashboardIcon` imports in the duplicated wardrobe menus. +- Capsule gaps tab: source check confirms Capsules remains the capsule-result entry for non-outfits tabs. +- Dark language menu regression: browser computed styles confirmed the menu background is light translucent glass rather than the previous dark popup style. + +## Project Structure + +### Documentation (this feature) + +```text +.specify/specs/021-sidebar-language-polish/ +├── spec.md +├── plan.md +└── tasks.md +``` + +### Source Code (repository root) + +```text +app/src/app/globals.css +app/src/components/capsule-result/CapsuleResultShell.tsx +app/src/components/favorites/FavoritesShell.tsx +app/src/components/for-repair/ForRepairShell.tsx +app/src/components/for-sale/ForSaleShell.tsx +app/src/components/my-items/MyItemsShell.tsx +app/src/components/uncapsulated/UncapsulatedShell.tsx +``` + +**Structure Decision**: Keep the canonical icon definitions in the existing dashboard navigation component and reuse them from legacy local wardrobe sidebars until those screens can be migrated to a fully shared navigation frame. + +## Complexity Tracking + +No constitution violations identified before implementation. diff --git a/.specify/specs/021-sidebar-language-polish/spec.md b/.specify/specs/021-sidebar-language-polish/spec.md new file mode 100644 index 0000000..3bc0b63 --- /dev/null +++ b/.specify/specs/021-sidebar-language-polish/spec.md @@ -0,0 +1,94 @@ +# Feature Specification: Sidebar Icons and Language Menu Polish + +**Feature Branch**: `codex/sidebar-language-fixes` +**Created**: 2026-06-15 +**Status**: Ready for PR Verification +**Input**: User description: "Align sidebar icons across authenticated menu states and restyle the language dropdown to match auth and cookie popups." + +## Goal _(mandatory)_ + +Authenticated navigation keeps the same icon artwork and sizing across Dashboard, My Items, Outfits, Capsules, Favourites, For Sale, Shopping List, and Settings when users switch between Stage 1 wardrobe screens, and the language dropdown uses the same elevated glass style as the auth popup and cookie banner. + +## Scope _(mandatory)_ + +In scope: + +- Reuse Dashboard navigation icon definitions for duplicate wardrobe sidebars, mobile bottom navigation, and More-sheet menu entries. +- Align My Items, Outfits, Capsules, For Sale, Dashboard, Shopping List, and Settings icon identity and dimensions across Dashboard, capsule-result, favorites, my-items, uncapsulated, for-sale, and for-repair surfaces. +- Keep active-state behavior stable for capsule-result tabs: Outfits is active only for the outfits tab, while Capsules represents capsule items and gaps. +- Restyle `.language-menu` as an elevated light glass surface consistent with the auth panel and cookie banner. +- Preserve the existing EN/RU-only language switcher behavior and MVP v1 locale scope. + +Out of scope: + +- New navigation destinations, route changes, data-provider behavior, or copy changes. +- Real auth/provider integration changes. +- ES-AR activation or language persistence changes outside the existing next-intl flow. +- Redesign of the approved dashboard/sidebar layout beyond icon and dropdown consistency. + +## User Scenarios & Testing _(mandatory)_ + +### User Story 1 - See Stable Sidebar Iconography (Priority: P1) + +An authenticated user moves between wardrobe screens and sees the same navigation icon set, size, and alignment in every sidebar or menu state. + +**Why this priority**: Navigation drift makes the app feel unfinished and breaks the premium visual consistency required for Stage 1 review. + +**Independent Test**: Open Dashboard, My Items, Capsule Result, Favourites, For Sale, For Repair, and Uncapsulated, then compare sidebar/menu SVG markup and icon bounding boxes for shared navigation labels. + +**Acceptance Scenarios**: + +1. **Given** the user is on Dashboard, **When** they compare My Items, Outfits, Capsules, For Sale, Dashboard, Shopping List, and Settings icons against the same labels on other authenticated screens, **Then** the icon artwork is identical. +2. **Given** the user is on Favourites, **When** they inspect For Sale, Dashboard, Shopping List, and Settings entries, **Then** the icons keep the same 18px rendered dimensions and alignment as Dashboard. +3. **Given** the user is on capsule-result, **When** they switch between outfits, items, and gaps tabs, **Then** Outfits and Capsules keep stable icon identity without double-active or mismatched icons. + +--- + +### User Story 2 - Open a Consistent Language Menu (Priority: P1) + +An authenticated or unauthenticated user opens the language selector and sees a light elevated glass popup matching the auth and cookie surfaces instead of a dark menu. + +**Why this priority**: The language dropdown is global chrome; a mismatched dark surface creates visible inconsistency across the interface. + +**Independent Test**: Open the top-right language menu and inspect computed styles for background, blur, shadow, border, and visible EN/RU options. + +**Acceptance Scenarios**: + +1. **Given** the language selector is closed, **When** the user opens it, **Then** the dropdown uses a light translucent glass background, elevated shadow, blur, and border aligned with auth/cookie popup styling. +2. **Given** the menu is open, **When** options render, **Then** only EN and RU remain available and no ES-AR option appears. + +## Negative Scenarios _(mandatory — required by SENAR; waive explicitly if none apply)_ + +1. **Given** a wardrobe screen uses a local sidebar implementation, **When** the menu renders, **Then** it must not introduce a local icon variant for a shared Dashboard navigation label. +2. **Given** capsule-result is on the gaps tab, **When** active navigation state is calculated, **Then** Capsules remains the active entry and Outfits does not become active. +3. **Given** the language menu opens over an authenticated dashboard background, **When** users inspect it visually, **Then** it must not fall back to the previous dark popup style or expose inactive ES-AR locale controls. + +## Requirements _(mandatory)_ + +### Functional Requirements + +- **FR-001**: Shared authenticated navigation labels MUST use Dashboard icon artwork wherever those labels are duplicated. +- **FR-002**: Shared sidebar, bottom navigation, and More-sheet icon boxes MUST keep consistent rendered dimensions across affected screens. +- **FR-003**: My Items MUST use the same Dashboard My Items icon on Dashboard, Outfits, Capsules, and other wardrobe surfaces. +- **FR-004**: Outfits and Capsules MUST use the same Dashboard icons across capsule-result and wardrobe sidebars. +- **FR-005**: For Sale MUST use the same Dashboard For Sale icon on Favourites and related wardrobe menus. +- **FR-006**: Dashboard, Shopping List, and Settings icons MUST keep consistent sizing across Favourites and other duplicate menus. +- **FR-007**: Capsule-result active-state logic MUST keep Outfits active only for the outfits tab and Capsules active for capsule items and gaps tabs. +- **FR-008**: The language dropdown MUST use the same elevated light glass surface pattern as auth and cookie popups. +- **FR-009**: The language dropdown MUST keep EN/RU as the only active MVP v1 locale options. +- **FR-010**: Product behavior, route structure, mock providers, and i18n persistence MUST remain unchanged except for the visual polish above. + +### Key Entities + +- **Dashboard Icon Set**: Shared SVG icon definitions exported by the dashboard navigation component and reused by local authenticated menu implementations. +- **Authenticated Sidebar Entry**: A repeated navigation item that may appear in desktop sidebar, mobile bottom navigation, or More sheet. +- **Language Menu**: Global next-intl locale dropdown rendered by `LanguageSwitcher` and styled through `.language-menu`. + +## Success Criteria _(mandatory)_ + +### Measurable Outcomes + +- **SC-001**: Browser verification shows matching SVG markup and 18px rendered icon boxes for shared navigation labels across affected routes. +- **SC-002**: Language menu computed styles show a light glass background, blur, elevated shadow, and border consistent with auth/cookie surfaces. +- **SC-003**: Local checks pass: lint, typecheck, build, feature-memory guard, and whitespace diff check. +- **SC-004**: GitHub PR checks for baseline, guard, OSV, and AI Review complete successfully before merge readiness. diff --git a/.specify/specs/021-sidebar-language-polish/tasks.md b/.specify/specs/021-sidebar-language-polish/tasks.md new file mode 100644 index 0000000..a0fd7b0 --- /dev/null +++ b/.specify/specs/021-sidebar-language-polish/tasks.md @@ -0,0 +1,50 @@ +# Tasks: Sidebar Icons and Language Menu Polish + +**Input**: `.specify/specs/021-sidebar-language-polish/spec.md`, `plan.md` + +## Phase 1: Setup + +- [x] T001 Refresh GitHub state with `git fetch --all --prune`. +- [x] T002 Compare local `main` with `origin/main` and create branch `codex/sidebar-language-fixes` from current `origin/main`. +- [x] T003 Inspect Dashboard navigation icon definitions and duplicate wardrobe sidebar/menu implementations. +- [x] T004 Inspect existing auth, cookie, and language menu CSS surfaces. + +## Phase 2: Implementation + +- [x] T005 Export and reuse Dashboard icon types for duplicate wardrobe menus. +- [x] T006 Replace local shared navigation icon variants in capsule-result, favorites, for-sale, for-repair, my-items, and uncapsulated shells with Dashboard icon names. +- [x] T007 Keep capsule-result active-state behavior stable for outfits, capsule items, and gaps tabs. +- [x] T008 Restyle `.language-menu` with the elevated light glass surface used by auth and cookie popups. +- [x] T009 Preserve EN/RU-only language switcher behavior and avoid ES-AR exposure. + +## Phase 3: Verification + +- [x] T010 Run `npm run lint`. +- [x] T011 Run `npm run typecheck`. +- [x] T012 Run `npm run build`. +- [x] T013 Run `npm run ci:check`. +- [x] T014 Run `git diff --check`. +- [x] T015 Browser-check shared navigation SVG markup and icon dimensions across Dashboard, My Items, capsule-result, Favourites, For Sale, For Repair, and Uncapsulated routes. +- [x] T016 Browser-check language menu computed style and console cleanliness. +- [x] T017 Open PR #42. +- [x] T018 Trigger Codex review with `@codex review`. +- [x] T019 Add this SENAR feature memory after guard identified the missing spec/plan/tasks update. + +## Process Memory + +### Dead Ends + +- A stale local Next.js dev server initially served old CSS chunks on port 3000; restarting the dev server was required before the language menu style verification reflected the current files. +- Starting a second Next.js dev server on another port was blocked because the same app directory already had an active dev instance. + +### Decisions + +- Treat Dashboard navigation as the canonical icon source for shared authenticated labels because it already matched the requested reference state. +- Keep local wardrobe sidebar components in place for this PR and only replace their shared icon source, limiting the blast radius to the requested visual consistency fix. +- Keep capsule-result tab active-state logic unchanged except for making the icon source shared. +- Style `.language-menu` through global CSS so every current `LanguageSwitcher` instance receives the same auth/cookie-like glass treatment. +- Add a dedicated `021-sidebar-language-polish` feature memory package because product app files changed after the SENAR guard layer shipped. + +### Known Issues + +- Several wardrobe screens still maintain local sidebar/menu models. They now share Dashboard icons, but a future cleanup can migrate them to the fully shared authenticated navigation frame. diff --git a/app/src/app/globals.css b/app/src/app/globals.css index f8602a4..8ebf0bb 100644 --- a/app/src/app/globals.css +++ b/app/src/app/globals.css @@ -830,7 +830,7 @@ textarea { padding: 8px; border: 1px solid rgba(255, 255, 255, 0.72); border-radius: var(--radius-md); - background: rgba(46, 46, 46, 0.92); + background: rgba(255, 255, 255, 0.38); box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.42), 0 22px 70px rgba(0, 0, 0, 0.26); @@ -899,7 +899,8 @@ textarea { } .auth-panel, -.cookie-banner { +.cookie-banner, +.language-menu { border-color: rgba(255, 255, 255, 0.72); background: rgba(255, 255, 255, 0.38); box-shadow: diff --git a/app/src/components/capsule-result/CapsuleResultShell.tsx b/app/src/components/capsule-result/CapsuleResultShell.tsx index 43f80cd..ceb3872 100644 --- a/app/src/components/capsule-result/CapsuleResultShell.tsx +++ b/app/src/components/capsule-result/CapsuleResultShell.tsx @@ -3,6 +3,10 @@ import { useLocale, useTranslations } from "next-intl"; import { useRouter, useSearchParams } from "next/navigation"; import { useMemo, useState } from "react"; +import { + DashboardIcon, + type DashboardIconName, +} from "@/components/dashboard/DashboardNavigation"; import { LanguageSwitcher } from "@/components/landing/LanguageSwitcher"; import { signOutAction } from "@/features/auth/actions"; import { Link } from "@/i18n/navigation"; @@ -205,24 +209,24 @@ export function CapsuleResultShell({ snapshot }: CapsuleResultShellProps) {