Icons
How to add SVG icons under apps/presentation/public/icons in the SHOPin storefront accelerator and use them in UI (see Component for where components live).
Add the file
- Path:
apps/presentation/public/icons/<icon-name>.svg - Naming: kebab-case (e.g.
cart.svg,chevron-left.svg).
Prepare the SVG
Before committing, make the asset safe to use as a component:
- ViewBox — Include a
viewBox(e.g.viewBox="0 0 24 24") so scaling stays correct. - No hardcoded size — Drop fixed
width/height; size with CSS (e.g.className="size-5"). - Color — Prefer
currentColorforfill/strokeso utilities liketext-gray-700or token-based classes control color. - Accessibility — For decorative icons, use
aria-hidden="true"in markup or at the call site. When the icon carries meaning, expose it to assistive tech (e.g.role="img"andaria-label).
Usage
Icons are imported from the public folder and rendered as components (exact behaviour depends on Next.js / bundler SVG config).
Import:
TSX
import CartIcon from '@/public/icons/cart.svg'
Decorative (purely visual):
TSX
<CartIcon className="size-5 text-gray-700" aria-hidden="true" />
Semantic (meaningful to assistive tech):
TSX
<CartIcon
className="size-6 text-[hsl(var(--shopin-primary))]"
role="img"
aria-label="Cart"
/>
- Decorative:
aria-hidden="true"so screen readers skip the glyph when text or context already explains the control. - Semantic:
role="img"andaria-label(or equivalent) when the icon alone conveys information.
Storybook
You can use the same @/public/icons/... import pattern in stories under apps/storybook when Storybook’s build treats SVG imports like the presentation app. If imports fail, align Storybook’s webpack/Vite (or framework) config with the presentation app rather than duplicating assets.
Related
- Component — UI layout, Storybook stories, tokens
- Feature — Feature-scoped UI and imports
- General workflow rules