Skip to content

Icons

Icons renders tags detected for public/favicon.svg, public/favicon.png, and public/apple-touch-icon.png. It does not render a tag for public/favicon.ico; browsers discover that fallback path automatically.

prop type default required description
icons Record<string, IconTag | false> {} No Per-href overrides. A value replaces or adds an entry; false removes the matching detected public icon.
<Icons />
<Icons
icons={{
"/favicon.png": false,
"/campaign.png": {
rel: "icon",
href: "/campaign.png",
sizes: "32x32",
type: "image/png",
media: "dark",
},
}}
/>

Runtime entries merge by href. The map key wins over an href inside its value. media: "light" and media: "dark" expand to the matching prefers-color-scheme media query.

---
import type { IconTag } from "../integration/public-icons";
import config from "virtual:eminence-astro-suite/head-tags";
interface Props {
/**
* Late-bound `<link>` tag overrides.
* These are merged over detected public icon tags from the virtual module.
*/
/**
* Per-href overrides keyed by the tag's `href` value.
* An `IconTag` value replaces the matching detected tag or adds a new one.
* `false` removes the matching detected tag from the rendered output.
*/
icons?: Record<string, IconTag | false>;
}
const { icons: overrideIcons } = Astro.props;
const iconTagsMap = new Map<string, IconTag>();
for (const iconTag of config.icons ?? []) {
iconTagsMap.set(iconTag.href, iconTag);
}
for (const [href, iconTag] of Object.entries(overrideIcons ?? {})) {
if (iconTag === false) {
iconTagsMap.delete(href);
} else {
iconTagsMap.set(href, { ...iconTag, href });
}
}
const iconTagsToRender = Array.from(iconTagsMap.values());
const resolveMedia = (media: IconTag["media"]): string | undefined => {
if (media === undefined) {
return undefined;
}
if (media === "light" || media === "dark") {
return `(prefers-color-scheme: ${media})`;
}
return media;
};
---
{
iconTagsToRender.map(({ media, ...iconTag }) => (
<link {...iconTag} media={resolveMedia(media)} />
))
}