loopable / web /src /ui /icons.tsx
fsanyoto's picture
Deploy AIOS web (React glide grid + FastAPI slice)
609fb78 verified
Raw
History Blame Contribute Delete
3.45 kB
// ---------------------------------------------------------------------------
// 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>
);
}