| // --------------------------------------------------------------------------- | |
| // ui / icons.tsx β EXIT wave 2 (W2-6). | |
| // | |
| // The three glyphs the page primitives need, as SVG paths. Owner constant: NO | |
| // EMOJIS anywhere in the UI β a check mark typed as a character is an emoji on | |
| // most platforms and renders in the system's colour, not the palette's. | |
| // | |
| // Deliberately NOT importing `customer-grid/iconShapes`: `ui/` is the shared | |
| // presentation layer and must not depend on the grid (the direction W2-5 spent | |
| // its amendment lines getting right). Three paths do not justify inverting a | |
| // 400-line module; if this set grows past a handful, hoist iconShapes the way | |
| // `viz/` was hoisted rather than letting it creep. | |
| // | |
| // `currentColor` throughout, so tone comes from the CSS token on the parent and | |
| // no colour is ever written here. | |
| // --------------------------------------------------------------------------- | |
| function Glyph({ d, size, className }: { d: string; size: number; className?: string }) { | |
| return ( | |
| <svg | |
| className={className} | |
| width={size} | |
| height={size} | |
| viewBox="0 0 24 24" | |
| aria-hidden="true" | |
| focusable="false" | |
| > | |
| <path d={d} fill="currentColor" /> | |
| </svg> | |
| ); | |
| } | |
| /** Material "download" β the tray with the arrow into it. */ | |
| export function DownloadIcon({ size = 15 }: { size?: number }) { | |
| return ( | |
| <Glyph | |
| className="pg-icon" | |
| size={size} | |
| d="M12 15.6 6.8 10.4l1.4-1.4 2.8 2.8V3h2v8.8l2.8-2.8 1.4 1.4zM5 20a2 2 0 0 1-2-2v-3h2v3h14v-3h2v3a2 2 0 0 1-2 2z" | |
| /> | |
| ); | |
| } | |
| /** Material "check" β a passing validation leg. */ | |
| export function CheckIcon({ size = 14 }: { size?: number }) { | |
| return ( | |
| <Glyph className="pg-icon" size={size} d="M9.6 17.6 4 12l1.4-1.4 4.2 4.2 9-9L20 7.2z" /> | |
| ); | |
| } | |
| /** Material "priority_high" β a failing one. Not a cross: a failed | |
| * reconciliation is "look at this", not "this was deleted". */ | |
| export function AlertIcon({ size = 14 }: { size?: number }) { | |
| return ( | |
| <Glyph | |
| className="pg-icon" | |
| size={size} | |
| d="M11 15h2v2h-2zm0-10h2v8h-2z" | |
| /> | |
| ); | |
| } | |
| /** | |
| * β WAVE 32 Β· T20/T23 β THE BELL. One drawing, for every surface that means "you will be told". | |
| * | |
| * β STROKED, NOT FILLED, so it is a sibling of the shell's nav glyphs rather than of the three | |
| * solid page-primitive marks above β and it takes a `className` for the same reason: the Inbox | |
| * head sizes it through `.alerts-bell` while a menu row sizes it through the menu's own rule. | |
| * | |
| * β IT LIVES HERE BECAUSE TWO SURFACES NEED IT β the Inbox module's header (T20) and the view | |
| * menu's "Alert me about new records" row (T23). It was drawn inline inside `AlertsPane.tsx`; a | |
| * second hand-copy in the view rail is how a product ends up with two bells that differ by a | |
| * stroke width, and `shell/Brand.tsx` records the version of that mistake that shipped. | |
| */ | |
| export function BellIcon({ size = 16, className }: { size?: number; className?: string }) { | |
| return ( | |
| <svg | |
| className={className} | |
| width={size} | |
| height={size} | |
| viewBox="0 0 16 16" | |
| aria-hidden="true" | |
| focusable="false" | |
| fill="none" | |
| stroke="currentColor" | |
| strokeWidth={1.3} | |
| strokeLinecap="round" | |
| strokeLinejoin="round" | |
| > | |
| <path d="M8 2.2a3.6 3.6 0 0 1 3.6 3.6v2.4l1.2 2H3.2l1.2-2V5.8A3.6 3.6 0 0 1 8 2.2Z" /> | |
| <path d="M6.6 12.6a1.5 1.5 0 0 0 2.8 0" /> | |
| </svg> | |
| ); | |
| } | |