// 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" },
});