|
| 1 | +<?php |
| 2 | +/** |
| 3 | + * The panel's icons: a coloured plate with a mark on it. |
| 4 | + * |
| 5 | + * The same recipe the site uses (my-app/src/components/Icon3d.tsx) written for |
| 6 | + * the server: a plate with a diagonal gradient, a gloss across its top half, a |
| 7 | + * shadow underneath and a rim inside the edge, with the mark in white on top. |
| 8 | + * Two copies rather than one, because the panel is PHP served from a different |
| 9 | + * machine and shares no build with the site -- the same trade the content |
| 10 | + * defaults already make. |
| 11 | + * |
| 12 | + * Every id inside is suffixed, because six plates on a page all defining |
| 13 | + * "plate" would every one of them paint with whichever the browser read last. |
| 14 | + * |
| 15 | + * Only where the icon is big enough to carry it. The bin on a table row and |
| 16 | + * the chevron on a summary stay hairlines: a plate at sixteen pixels is a |
| 17 | + * coloured square with something indistinct on it. |
| 18 | + */ |
| 19 | + |
| 20 | +/** Light end, dark end. The dark end is also the shadow. */ |
| 21 | +const ADMIN_ICON_TONES = [ |
| 22 | + 'gold' => ['#f6dc84', '#c9a227'], |
| 23 | + 'bronze' => ['#e6a860', '#a85f22'], |
| 24 | + 'navy' => ['#2b3a72', '#0a0e20'], |
| 25 | + 'green' => ['#5ee08a', '#128c3e'], |
| 26 | + 'plum' => ['#d08bd6', '#7b2f86'], |
| 27 | + 'slate' => ['#9fb0cc', '#465a7e'], |
| 28 | +]; |
| 29 | + |
| 30 | +/** The mark, drawn in a 24-unit box, and the plate it sits on by default. */ |
| 31 | +function admin_icon_glyphs(): array |
| 32 | +{ |
| 33 | + return [ |
| 34 | + 'chart' => ['navy', '<rect x="3" y="12" width="4" height="8" rx="1" fill="currentColor" stroke="none"/><rect x="10" y="4" width="4" height="16" rx="1" fill="currentColor" stroke="none"/><rect x="17" y="9" width="4" height="11" rx="1" fill="currentColor" stroke="none"/>'], |
| 35 | + 'clipboard' => ['gold', '<rect x="5" y="4" width="14" height="17" rx="2"/><rect x="8.5" y="2" width="7" height="4" rx="1"/><line x1="8" y1="11" x2="16" y2="11"/><line x1="8" y1="15" x2="16" y2="15"/>'], |
| 36 | + 'car' => ['bronze', '<path d="M3 13l1.4-4.2A2 2 0 0 1 6.3 7.5h11.4a2 2 0 0 1 1.9 1.3L21 13"/><rect x="2.5" y="13" width="19" height="5" rx="1.5"/><circle cx="7" cy="18.5" r="1.4"/><circle cx="17" cy="18.5" r="1.4"/>'], |
| 37 | + 'inbox' => ['plum', '<path d="M3 12h5l1.5 3h5L16 12h5"/><path d="M5.5 5h13l2.5 7v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-7l2.5-7z"/>'], |
| 38 | + 'card' => ['green', '<rect x="3" y="6" width="18" height="13" rx="2"/><path d="M3 10h18"/><circle cx="16.5" cy="14.5" r="1"/>'], |
| 39 | + 'trend' => ['slate', '<path d="M3 17l6-6 4 4 8-8"/><path d="M15 7h6v6"/>'], |
| 40 | + 'pencil' => ['gold', '<path d="M4 20h4l10-10a2.8 2.8 0 0 0-4-4L4 16v4z"/><line x1="13.5" y1="6.5" x2="17.5" y2="10.5"/>'], |
| 41 | + 'pin' => ['bronze', '<path d="M12 21s7-6.2 7-11a7 7 0 1 0-14 0c0 4.8 7 11 7 11z"/><circle cx="12" cy="10" r="2.5"/>'], |
| 42 | + // The dashboard's counters. |
| 43 | + 'rupee' => ['green', '<path d="M7 5h10"/><path d="M7 9h10"/><path d="M14.5 5c0 3-2.2 4-5 4h-2.5l7.5 10"/>'], |
| 44 | + 'wallet' => ['bronze', '<path d="M3 8.5A2.5 2.5 0 0 1 5.5 6H18a2 2 0 0 1 2 2v1"/><rect x="3" y="9" width="18" height="10" rx="2.5"/><circle cx="16.5" cy="14" r="1.2"/>'], |
| 45 | + 'scales' => ['navy', '<path d="M12 4v16"/><path d="M6 8h12"/><path d="M4 16l2.5-6L9 16a2.6 2.6 0 0 1-5 0z"/><path d="M15 16l2.5-6L20 16a2.6 2.6 0 0 1-5 0z"/>'], |
| 46 | + ]; |
| 47 | +} |
| 48 | + |
| 49 | +/** |
| 50 | + * One icon, as markup. |
| 51 | + * |
| 52 | + * @param string $name a key of admin_icon_glyphs() |
| 53 | + * @param int $size rendered edge to edge, shadow included |
| 54 | + * @param string|null $tone overrides the glyph's own plate colour |
| 55 | + */ |
| 56 | +function admin_icon3d(string $name, int $size = 30, ?string $tone = null, string $class = 'ns-ico3d'): string |
| 57 | +{ |
| 58 | + static $n = 0; |
| 59 | + $n++; |
| 60 | + |
| 61 | + $glyphs = admin_icon_glyphs(); |
| 62 | + if (!isset($glyphs[$name])) { |
| 63 | + return ''; |
| 64 | + } |
| 65 | + |
| 66 | + [$defaultTone, $paths] = $glyphs[$name]; |
| 67 | + $key = $tone !== null && isset(ADMIN_ICON_TONES[$tone]) ? $tone : $defaultTone; |
| 68 | + [$light, $dark] = ADMIN_ICON_TONES[$key]; |
| 69 | + $uid = 'i' . $n; |
| 70 | + |
| 71 | + return '<svg class="' . htmlspecialchars($class, ENT_QUOTES) . '" width="' . $size . '" height="' . $size . '"' |
| 72 | + . ' viewBox="0 0 48 48" aria-hidden="true" focusable="false">' |
| 73 | + . '<defs>' |
| 74 | + . '<linearGradient id="plate-' . $uid . '" x1="0.15" y1="0" x2="0.85" y2="1">' |
| 75 | + . '<stop offset="0%" stop-color="' . $light . '"/><stop offset="100%" stop-color="' . $dark . '"/></linearGradient>' |
| 76 | + . '<linearGradient id="gloss-' . $uid . '" x1="0" y1="0" x2="0" y2="1">' |
| 77 | + . '<stop offset="0%" stop-color="#fff" stop-opacity="0.5"/><stop offset="100%" stop-color="#fff" stop-opacity="0"/></linearGradient>' |
| 78 | + . '<filter id="drop-' . $uid . '" x="-30%" y="-20%" width="160%" height="160%">' |
| 79 | + . '<feDropShadow dx="0" dy="2" stdDeviation="2" flood-color="' . $dark . '" flood-opacity="0.45"/></filter>' |
| 80 | + . '</defs>' |
| 81 | + . '<g filter="url(#drop-' . $uid . ')">' |
| 82 | + . '<rect x="3" y="2" width="42" height="42" rx="13" fill="url(#plate-' . $uid . ')"/>' |
| 83 | + . '<rect x="4" y="3" width="40" height="40" rx="12" fill="none" stroke="#fff" stroke-opacity="0.28"/>' |
| 84 | + . '<rect x="5" y="4" width="38" height="20" rx="11" fill="url(#gloss-' . $uid . ')"/>' |
| 85 | + . '</g>' |
| 86 | + . '<g transform="translate(12 11)" fill="none" stroke="#fff" stroke-width="1.7"' |
| 87 | + . ' stroke-linecap="round" stroke-linejoin="round" color="#fff">' . $paths . '</g>' |
| 88 | + . '</svg>'; |
| 89 | +} |
0 commit comments