// A tiny geometric icon set drawn from plain Views. // // The app ships no vector-icon dependency and emoji render differently on // every platform (and can't take the accent colour), so these are built from // borders and rectangles instead: monochrome, tintable, pixel-identical on // Android and web, and zero bytes of new dependency. import { StyleSheet, View } from "react-native"; import { C } from "../lib/theme"; export type IconName = | "today" | "next" | "waiting" | "someday" | "projects" | "review" | "settings" | "flag" | "repeat" | "tag" | "plus" | "close" | "chevron"; type Props = { name: IconName; size?: number; color?: string; /** Used to carve the crescent out of the "someday" moon. */ bg?: string; }; export default function Icon({ name, size = 22, color = C.textSecondary, bg = C.bg }: Props) { const box = { width: size, height: size }; const w = 1.7; // one consistent stroke weight across the whole set switch (name) { case "today": return ( ); case "next": return ( ); case "waiting": return ( {/* hour hand, then minute hand — anchored at the dial centre */} ); case "someday": return ( ); case "projects": return ( ); case "review": return ( {/* an open ring plus an arrowhead reads as "cycle" without an SVG path */} ); case "settings": // Sliders, not a cog: three strokes with offset knobs stays legible at 20px. return ( {[0.62, 0.3, 0.48].map((knob, i) => ( ))} ); case "flag": return ( {/* Pole plus a pennant — reads as a priority flag at 20px where a detailed banner outline would smear into a blob. */} ); case "repeat": return ( {/* Two offset bars with opposing arrowheads: a loop, without the anti-aliasing mush a thin circular arc gets at this size. */} ); case "tag": return ( ); case "close": return ( ); case "plus": return ( ); case "chevron": return ( ); } } const s = StyleSheet.create({ center: { alignItems: "center", justifyContent: "center" }, sliderRow: { justifyContent: "center" }, });