Data display
MaxIconSet
Max's own SVG icons, exported as DC.MaxIcons: integration and channel logos, message delivery states, and the appearance-picker tiles.
Guidelines#
Everything else comes from Lucide.
Use it for the things Lucide has no icon for: connected accounts and CRMs (Google, Outlook, LinkedIn, WhatsApp, HubSpot, Salesforce, Slack, Zoho, Notion), data providers (Apollo, Explorium, GetLeads), message status ticks in the Unibox, and the option tiles in Settings › Appearance.
What you provide:
- Logo icons take
{ className, size }, withsizedefaulting to 16px. They keep their brand colours.MailIconis the exception: it strokes incurrentColor. - Message states take
{ className, size }, withsizedefaulting to 14px, and areshrink-0.IconMessageSent: a single check.IconMessageDelivered: a double check whose first tick istext-muted-foreground.IconMessageRead: a double check intext-green-500 dark:text-green-400.IconMessageFailed.
- The tiles (
IconThemeSystem,IconThemeLight,IconThemeDark,IconSplashCursor,IconSplashCursorDisabled) are 79.86 × 51.14 illustrations. They take SVG props and nosize, so set their width with a class.IconThemeSystemfills withprimary, falling back tomuted-foregroundinside an uncheckedgroup. The splash tiles havedark:fills.
Anatomy: the page shows every export at 24px (the tiles at 24px tall), with the export name beside it.
Don't recolour brand logos. Don't use the tiles as inline icons: they are option previews.
Facts#
| Group | Data display |
|---|---|
| Product | Max |
| Kind | Showcase page (tokens and patterns, not a single export) |
| Source | max-agent: src/components/icons/ |
Example#
The code of the preview above: plain React.createElement against window.DigitalCrew, with realistic data.
<div id="root" class="p-6"></div>
<script>
(function () {
var h = React.createElement, DC = window.DigitalCrew, I = DC.Icons;
// Brand and message-state icons take size (px); the theme and splash tiles are
// 79.86 × 51.14 illustrations sized by className, shown here 24px tall.
var TILES = ["IconThemeSystem", "IconThemeLight", "IconThemeDark", "IconSplashCursor", "IconSplashCursorDisabled"];
var GROUPS = [
["Integrations and channels", Object.keys(DC.MaxIcons).filter(function (n) { return /Icon$/.test(n); })],
["Message delivery states", Object.keys(DC.MaxIcons).filter(function (n) { return /^IconMessage/.test(n); })],
["Appearance tiles", Object.keys(DC.MaxIcons).filter(function (n) { return TILES.indexOf(n) >= 0; })]
];
function Item(props) {
var Icon = DC.MaxIcons[props.name], tile = TILES.indexOf(props.name) >= 0;
return h("div", { className: "flex items-center gap-3 rounded-lg border bg-card px-3 py-2.5" },
h("div", { className: "flex h-6 min-w-6 items-center justify-center" },
tile ? h(Icon, { className: "h-6 w-auto", style: { height: 24, width: "auto" } }) : h(Icon, { size: 24 })),
h("code", { className: "min-w-0 break-all font-mono text-xs leading-tight" }, props.name));
}
function App() {
return h("div", { className: "space-y-5" },
GROUPS.map(function (g) {
return h("section", { key: g[0], className: "space-y-2" },
h("p", { className: "text-xs font-semibold uppercase tracking-wider text-muted-foreground" }, g[0] + " · " + g[1].length),
h("div", { className: "grid grid-cols-4 gap-2" }, g[1].map(function (n) { return h(Item, { key: n, name: n }); })));
}));
}
ReactDOM.createRoot(document.getElementById("root")).render(h(DC.TooltipProvider, { delayDuration: 80 }, h(App)));
})();
</script>