- arrow-right
- arrow-up-right
- bot
- chart
- check
- clock
- code
- file
- globe
- layers
- lock
- minus
- plus
- search
- shield
- sparkles
- star
- users
- zap
Astro UI
Icon.
Twenty Lucide glyphs as inline SVG, sized and labelled through props.
ContentAtomNo dependencies Lucide, ISC
Using Claude Code? Give it the agent prompt and skip these steps.
-
Import the foundation once
foundation.css holds the tokens every component reads.
--- // src/layouts/Layout.astro import "../styles/foundation.css"; --- -
Use it
--- import Icon from "../components/viewership/icon/Icon.astro"; --- <Icon />
Props 4
| Prop | Type | Default | Description |
|---|---|---|---|
name | IconName | · | Glyph key: arrow-right, check, zap, layers, shield and more. See `icons.ts`. |
size | number | 20 | Width and height in pixels. |
strokeWidth | number | 1.75 | Stroke weight. |
label | string | · | Accessible name. Omit to mark the icon decorative. |
Source 2 files
---
/**
* Icon: a small set of Lucide glyphs (ISC) as inline SVG.
*
* Decorative by default (aria-hidden). Pass `label` when the icon carries
* meaning on its own. Sections use it for feature icons and list ticks;
* `name` accepts any key in `icons.ts`, so add glyphs there.
*
* @example
* <Icon name="zap" />
* <Icon name="check" size={16} label="Included" />
*/
import { iconPaths, type IconName } from "./icons";
interface Props {
name: IconName;
size?: number;
strokeWidth?: number;
/** Accessible name. Omit for decorative icons. */
label?: string;
class?: string;
}
const { name, size = 20, strokeWidth = 1.75, label, class: className } = Astro.props;
---
<svg
class:list={["vs-icon", className]}
width={size}
height={size}
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width={strokeWidth}
stroke-linecap="round"
stroke-linejoin="round"
role={label ? "img" : undefined}
aria-label={label}
aria-hidden={label ? undefined : "true"}
focusable="false"
set:html={iconPaths[name]}
/>
<style>
.vs-icon {
flex: none;
vertical-align: middle;
}
</style> /** Lucide (ISC) glyph bodies, 24x24 viewBox, stroke-based. Add keys here to extend Icon. */
export const iconNames = [
"arrow-right",
"arrow-up-right",
"bot",
"chart",
"check",
"clock",
"code",
"file",
"globe",
"layers",
"lock",
"mail",
"minus",
"plus",
"search",
"shield",
"sparkles",
"star",
"users",
"zap",
] as const;
export type IconName = (typeof iconNames)[number];
export const iconPaths: Record<IconName, string> = {
"arrow-right": '<path d="M5 12h14"/><path d="m12 5 7 7-7 7"/>',
"arrow-up-right": '<path d="M7 7h10v10"/><path d="M7 17 17 7"/>',
bot: '<path d="M12 8V4H8"/><rect width="16" height="12" x="4" y="8" rx="2"/><path d="M2 14h2"/><path d="M20 14h2"/><path d="M15 13v2"/><path d="M9 13v2"/>',
chart: '<path d="M3 3v16a2 2 0 0 0 2 2h16"/><path d="M18 17V9"/><path d="M13 17V5"/><path d="M8 17v-3"/>',
check: '<path d="M20 6 9 17l-5-5"/>',
clock: '<circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/>',
code: '<path d="m16 18 6-6-6-6"/><path d="m8 6-6 6 6 6"/>',
file: '<path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M10 13H8"/><path d="M16 17H8"/><path d="M16 13h-2"/>',
globe: '<circle cx="12" cy="12" r="10"/><path d="M12 2a14.5 14.5 0 0 0 0 20 14.5 14.5 0 0 0 0-20"/><path d="M2 12h20"/>',
layers: '<path d="m12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83Z"/><path d="m22 17.65-9.17 4.16a2 2 0 0 1-1.66 0L2 17.65"/><path d="m22 12.65-9.17 4.16a2 2 0 0 1-1.66 0L2 12.65"/>',
lock: '<rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/>',
mail: '<rect width="20" height="16" x="2" y="4" rx="2"/><path d="m22 7-8.97 5.7a1.94 1.94 0 0 1-2.06 0L2 7"/>',
minus: '<path d="M5 12h14"/>',
plus: '<path d="M5 12h14"/><path d="M12 5v14"/>',
search: '<circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/>',
shield: '<path d="M20 13c0 5-3.5 7.5-7.66 8.95a1 1 0 0 1-.67-.01C7.5 20.5 4 18 4 13V6a1 1 0 0 1 1-1c2 0 4.5-1.2 6.24-2.72a1.17 1.17 0 0 1 1.52 0C14.51 3.81 17 5 19 5a1 1 0 0 1 1 1z"/>',
sparkles: '<path d="M9.937 15.5A2 2 0 0 0 8.5 14.063l-6.135-1.582a.5.5 0 0 1 0-.962L8.5 9.936A2 2 0 0 0 9.937 8.5l1.582-6.135a.5.5 0 0 1 .963 0L14.063 8.5A2 2 0 0 0 15.5 9.937l6.135 1.581a.5.5 0 0 1 0 .964L15.5 14.063a2 2 0 0 0-1.437 1.437l-1.582 6.135a.5.5 0 0 1-.963 0z"/><path d="M20 3v4"/><path d="M22 5h-4"/><path d="M4 17v2"/><path d="M5 18H3"/>',
star: '<polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"/>',
users: '<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/>',
zap: '<path d="M4 14a1 1 0 0 1-.78-1.63l9.9-10.2a.5.5 0 0 1 .86.46l-1.92 6.02A1 1 0 0 0 13 10h7a1 1 0 0 1 .78 1.63l-9.9 10.2a.5.5 0 0 1-.86-.46l1.92-6.02A1 1 0 0 0 11 14z"/>',
}; Ported from Lucide, ISC. Notices.
Used by Feature BentoPricing ColumnsPricing RowsPricing CommissionPricing Toggle