From a362dd4668a11d7c86a742088ab61543b1e95e77 Mon Sep 17 00:00:00 2001 From: sdarbinyan Date: Mon, 20 Jul 2026 03:03:30 +0400 Subject: [PATCH] docs(icons): add UI icon & visual language audit Co-Authored-By: Claude Sonnet 5 --- docs/UI-ICON-AUDIT.md | 110 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 docs/UI-ICON-AUDIT.md diff --git a/docs/UI-ICON-AUDIT.md b/docs/UI-ICON-AUDIT.md new file mode 100644 index 0000000..b13d68c --- /dev/null +++ b/docs/UI-ICON-AUDIT.md @@ -0,0 +1,110 @@ +# 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 `` 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 `