Files
marketplaces/docs/archive/UI-ICON-AUDIT.md
sdarbinyan 5374401257 docs: consolidate documentation and archive temporary reports
Step 1-2 (audit + plan): classified 35 project markdown files into
Core/Architecture/ADR/Temporary-audit/Sprint-report/Generated-review/
Duplicate/Obsolete/Historical. Agent-tooling files (.agents/skills/**,
.superpowers/**, docs/context/**, CLAUDE.md/GEMINI.md/AGENTS.md/
.github/copilot-instructions.md) explicitly out of scope — intentional
per-tool duplication, not documentation debt.

Step 3 (merge, no information lost):
- docs/PROJECT.md -> docs/PROJECT_INDEX.md, rewritten as the single
  entry point: system overview, living-doc index, archive pointer,
  current status, and a critical-finding callout up top.
- docs/backend/BACKEND-INTEGRATION.md -> docs/BACKEND_API.md,
  docs/backend/REMAINING-BACKEND-WORK.md ->
  docs/BACKEND_API_REMAINING_WORK.md (also folded in a legitimate
  uncommitted status update that had been sitting unstaged all
  session: categories marked DONE, order-creation endpoint noted done).
- RELEASE-NOTES.md merged into CHANGELOG.md (was a near-duplicate of
  the same release content in friendlier prose), then deleted.
- KNOWN-ISSUES.md: added item 13 (see below) and item 14 (missing
  canDeactivate on admin/products edit, from the archived PROJECT-STATE
  audit, re-verified still true); added a correction note to Fixed
  item 7.
- All cross-references to renamed/moved files fixed across every
  kept doc (grep+sed pass, then verified with a link-existence check
  across all 58 in-scope markdown files -> 0 broken links).

Step 4 (archive, nothing deleted without merging first): created
docs/archive/, moved 19 files there (3 root sprint reports, 1 platform
report, SPRINT-PLAN.md, and 14 one-off audit/review/report docs).
Added correction headers to the 3 archived docs whose conclusions were
affected by the finding below, rather than silently leaving them
misleading.

Step 5: docs/PROJECT_INDEX.md rewritten per the mission brief -
someone opening the repo should understand the whole system from it.

IMPORTANT FINDING (surfaced during this audit, not the mission's
primary goal but too significant to bury): pages/category/*,
pages/search/*, pages/item-detail/*, pages/info/**, pages/legal/**
(40+ files) are entirely unrouted dead code - app.routes.ts's
cmsContentRoutes is a literal empty array, and category/search/product
routes redirect to CatalogContainerComponent/
ProductDetailsContainerComponent, not these files. Confirmed against
app.routes.ts directly and cross-checked against FRONTEND.md's own
routing description. This means several fixes from earlier this cycle
(RC-Premium-01, RC STORE-01) and the dead-code cleanup sprint's
conclusion that these files were live were all wrong - documented as
KNOWN-ISSUES.md item 13, flagged at the top of PROJECT_INDEX.md, and
noted on the 3 archived docs whose conclusions it affects. No
application code was changed to fix this (out of scope per this
session's 'documentation only' constraint) - it needs a wire-it-up-or-
delete-it decision first.

Verification: tsc --noEmit clean, npm run build green, all markdown
links across 58 in-scope files resolve (checked programmatically).
No application/Angular/backend code modified.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-25 19:10:49 +04:00

111 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# RC UI Sprint — Icon & Visual Language Audit
Full-application audit and consolidation onto **one icon library** (Lucide, via
`@lucide/angular`) across storefront, Marketplace Builder, and backoffice. Before this
pass the app mixed three icon systems in the same screens: **PrimeIcons** (`pi pi-*`
CSS classes), **dozens of hand-rolled inline `<svg>` blocks** (often the same icon
redrawn from scratch at different sizes/colors), and **bare text glyphs** (`♥`, `⇄`,
`«`, `»`) standing in for icons entirely outside any icon system.
## Foundation
- Added `@lucide/angular` (the maintained package; the unscoped `lucide-angular` is
deprecated upstream — installed the correct one directly).
- One shared entry point for every icon: `app-icon` (`src/app/shared/ui/icon/`),
backed by a canonical `name → Lucide icon` registry (`icon-registry.ts`). Default
size 20px, default stroke-width 2 — the same visual weight everywhere unless a
call site explicitly overrides it for a specific context (e.g. a 48px empty-state
illustration vs. a 14px inline chevron).
- `app-icon` is decorative (`aria-hidden`) by default. An `ariaLabel` input exists for
the rare case an icon carries meaning with no adjacent text; in practice, the label
almost always belongs on the surrounding interactive element instead.
## Old icon → New icon → Reason
| Area | Old | New | Reason |
|---|---|---|---|
| Admin dashboard | `pi-file-edit`, `pi-heart`, `pi-clock`, `pi-question-circle`, `pi-check-circle`, `pi-save`, `pi-upload`, `pi-book`, `pi-bolt`, `pi-flag`, `pi-megaphone`, `pi-circle` (data-driven via `icon: 'pi-*'` fields) | `edit`, `heart`, `clock`, `help`, `checkCircle`, `save`, `upload`, `book`, `zap`, `flag`, `megaphone`, `circle` | PrimeIcons → Lucide; icon fields retyped `AppIconName` so an unmapped name is a compile error, not a silently blank icon |
| Backoffice shell (sidebar nav + topbar) | `pi-home`, `pi-box`, `pi-tags`, `pi-shopping-cart`, `pi-user`, `pi-credit-card`, `pi-star`, `pi-chart-bar`, `pi-sitemap`, `pi-users`, `pi-cog`, `pi-desktop`, `pi-chart-line`, `pi-sign-out`, `pi-bars`, `pi-search`, `pi-upload`, `pi-building`, `pi-bell` | `home`, `package`, `tags`, `cart`, `user`, `creditCard`, `star`, `chartBar`, `network`, `users`, `settings`, `monitor`, `chartLine`, `logOut`, `menu`, `search`, `upload`, `building`, `bell` | PrimeIcons → Lucide |
| Marketplace Builder (overview, nav, sections, HTML editor toolbar) | `pi-arrow-left/right-circle/up/down`, `pi-check-circle`, `pi-circle`, `pi-circle-fill`, `pi-question-circle`, `pi-desktop`, `pi-shop`, `pi-image`, `pi-th-large`, `pi-box`, `pi-images`, `pi-history`, `pi-megaphone`, `pi-verified`, `pi-code`, `pi-globe`, `pi-sliders-h`, `pi-compass`, `pi-copy`, `pi-trash`, `pi-list`, `pi-link`, `pi-table`, `pi-minus`, `pi-video`, **`pi-bars` reused for drag handles** | `arrowLeft/Right/Up/Down`, `checkCircle`, `circle`, `help`, `monitor`, `store`, `image`, `layoutGrid`, `package`, `images`, `history`, `megaphone`, `verified`, `code`, `globe`, `slidersHorizontal`, `compass`, `copy`, `trash`, `list`, `link`, `table`, `minus`, `video`, **new dedicated `grip` icon** | PrimeIcons → Lucide. `pi-bars` had been reused for both the hamburger menu **and** every drag-to-reorder handle — two unrelated meanings sharing one icon, exactly the "duplicated icon, different meaning" pattern the audit brief calls out. Added `GripVertical` as a distinct drag-handle icon. |
| Header (storefront) | Two hand-drawn magnifying-glass SVGs (`#576463` desktop / `#1e3c38` mobile — same icon, two different hardcoded colors), `♥`/`⇄` **text glyphs** for wishlist/compare, hand-drawn cart SVG, hand-drawn home/catalog mobile-menu icons, 3× duplicated inline chevron SVG | `search` (color via `currentColor`), `heart`, `scale`, `cart`, `home`, `layoutGrid`, `chevronRight` | Consolidates one icon drawn twice with two different colors into one; replaces bare text characters (`♥`/`⇄`) that weren't part of any icon system at all |
| Search page | Same magnifying-glass path hand-duplicated **4 times** (input icon, empty-query, no-results, no-query states) at 3 sizes/3 colors | `search` ×4, color preserved per state via a CSS `color` property on the wrapper | Textbook duplication — one icon, four copy-pasted SVGs |
| Cart | Trash/X/plus/minus inline SVGs, standalone `EmptyCartIconComponent` (an 80px duplicate of the same cart glyph, only used once), chat-bubble "login gate" icon, duplicated close-X icon (2 modals), duplicated refresh icon (QR expired/error) | `trash`, `x`, `plus`, `minus`, `cart` (inline, component deleted), `lock`, `x`, `refresh` | Removed a whole component that existed only to duplicate an icon already available; unified the "login required" icon with telegram-login's identical icon (same concept, was drawn twice) |
| Language/region selectors | 3× duplicated chevron SVG (language dropdown, currency dropdown, region dropdown — identical path, copy-pasted), map-pin SVG, crosshair "locate" SVG, globe SVG | `chevronDown` ×3, `mapPin`, `locate`, `globe` | Same chevron redrawn three times in two components |
| Items carousel, category/subcategories, item-detail | Hand-drawn star (hardcoded `#497671` fill), hand-drawn cart icon (×3 separate redraws across 3 files), no-image/package/grid empty-state illustrations, check/X status icons, thumbs-up/down vote icons, dynamic fill/stroke rating stars | `star` (with new `color` input + `.dx-star--filled` CSS class for the solid/outline toggle), `cart`, `image`/`package`/`layoutGrid`, `check`/`x`, `thumbsUp`/`thumbsDown` | The cart icon alone had been hand-drawn from scratch in 5 different files across this audit (header, items-carousel, subcategories, item-detail, cart) — now one icon, one registry entry |
| Shared `app-select` | Browser-native `<select>` dropdown indicator (renders differently per browser, no relation to the icon system) | `chevronDown` (native indicator hidden via `appearance: none`) | "Selects: replace browser default indicators" — this component is used by nearly every admin form, so the fix applies everywhere at once |
| Shared `app-pagination` | `&laquo;` / `&raquo;` HTML entities | `chevronLeft` / `chevronRight` | "Pagination: use proper chevrons" |
| Every native `<details>`/`<summary>` expander (7 call sites: admin product form ×4, page editor, builder widget panel) | Browser-default disclosure triangle (differs Chrome/Firefox/Safari) | Lucide `ChevronDown` path drawn via one global CSS rule (`details > summary::after`), rotated 180° on `[open]` | Covers all 7 expanders with a single CSS change rather than touching each template — no shared class existed to hang a component-based fix on |
## Consistency improvements
- **One icon family everywhere.** Zero PrimeIcons (`pi-*`) class usages remain
anywhere in the app (verified by full-repo sweep after each batch). PrimeIcons
(`primeicons` package) is still installed as a PrimeNG peer dependency but no
longer used directly for any icon in app code.
- **One default size/stroke-width.** `app-icon` defaults to 20px / stroke-width 2;
every call site that deviates does so for a legible, deliberate reason (48px empty-
state illustration, 14px inline chevron), not arbitrary per-instance sizing.
- **Color via `currentColor`, not hardcoded hex.** Every hand-rolled SVG that baked a
specific hex into its `fill`/`stroke` attribute now inherits color from its
surrounding CSS `color`, so hover/active/disabled states that already change text
color also correctly recolor the icon — previously several icons ignored those
states entirely because their color was hardcoded in the SVG markup.
- **Duplicated icons resolved to one instance:**
- Magnifying glass: was hand-drawn independently in header (×2), search page (×4).
Now one `search` icon everywhere.
- Shopping cart: was hand-drawn independently in header, items-carousel,
subcategories, item-detail, and cart (via the now-deleted
`EmptyCartIconComponent`). Now one `cart` icon everywhere.
- Chevron/dropdown arrow: was hand-drawn independently in language-selector (×2),
region-selector, and the builder mobile nav (×3). Now one `chevronDown`/
`chevronRight` everywhere.
- "Login required" icon (chat-bubble shape): was drawn identically in both
telegram-login and cart's login gate. Now one `lock` icon in both, matching the
actual semantic ("authentication required") better than a chat bubble did.
- **Bare text glyphs replaced with real icons.** `♥` and `⇄` in the header were plain
Unicode characters, not part of any icon system, inconsistent stroke weight and
optical size versus every other icon on the same toolbar. Now `heart` and `scale`.
- **Corrected a genuine meaning collision**, not just a style one: PrimeIcons'
`pi-bars` (hamburger lines) was reused in the Marketplace Builder for both the
mobile menu toggle *and* every drag-to-reorder handle. A user scanning the builder
UI would see the same glyph mean "open navigation" in the header and "drag this
row" in a list — added a dedicated `grip` icon (`GripVertical`) so the two concepts
are now visually distinct.
- **Icon-only buttons audited for accessible names.** Swept every button whose only
content is an icon; found three relying on `title` alone (not reliably announced by
screen readers) or nothing at all (region-selector detect-location, carousel
add-to-cart, subcategories add-to-cart) and added `aria-label` to all three.
- **Decorative icons intentionally kept as custom SVG (not migrated):**
- The **Telegram brand logo** (cart, telegram-login) — a brand mark, not a generic
icon; replacing it with a generic Lucide icon would misrepresent the brand.
- **`layout-switcher`'s grid-pattern preview icons** — these show the actual layout
being selected (2-column, compact grid, list, etc.) as a literal visual preview,
not a stand-in for a word. Lucide has no equivalent "this exact grid pattern"
icon set; redrawing them as generic layout icons would lose the preview function.
## Remaining issues / backlog
- **No sortable table columns exist anywhere in the app** to add sort-direction
icons to (every admin list table has static, non-interactive `<th>` labels). Adding
actual column-sort interactivity would be new functionality, out of scope for an
icon/visual-language pass — flagged here rather than invented.
- **Bundle size**: `app-icon` renders each Lucide icon as its own standalone Angular
component (the current `@lucide/angular` API — no tree-shakeable "icon font" or
sprite sheet). The initial bundle grew from the prior build's already-over-budget
~585 KB over the 700 KB target to ~760 KB over, mostly from icon components now
bundled eagerly in the admin shell/dashboard/builder (loaded on every admin route).
Worth a follow-up pass to lazy-load icon-heavy admin sections if bundle size becomes
a concrete problem.
- **No `docs/DESIGN.md` exists** in this repo (confirmed across all three RC sprints
this session). The `impeccable` design-quality hook flagged pre-existing font-size/
radius/color values against a document that doesn't exist — none of those findings
were introduced by this pass; they're pre-existing values in files this pass
touched for unrelated reasons (colors, radii, spacing untouched).
- **PrimeIcons (`primeicons` npm package) is still installed** — it's a transitive
dependency PrimeNG components may rely on internally (calendar, carousel nav
arrows rendered by `p-carousel`, etc.), so it wasn't removed from `package.json`.
No app code imports `pi-*` classes directly anymore, but a future pass could audit
whether PrimeNG's own internal icon usage (e.g. `p-carousel`'s built-in prev/next
arrows) should also be re-skinned to match, or left as PrimeNG's own visual
language since those are framework-owned, not hand-authored.