Icon

Displays SVG icons with unified styling and accessibility support.

The icon component allows you to inject inline SVGs efficiently. It automatically cleans up the SVG source to ensure Tailwind classes take precedence, handles accessibility attributes, and visual warning for missing files.

Go/HTML template
1{{ partial "ui/icon" (dict 
2  "name" "pizza"
3  "class" "size-7 text-red-400" 
4)}}

Reference

The icon partial accepts a dictionary with the following terms:

name
"name" "pizza" — (string, required)
The filename of the svg icon inside assets/icons/
(excluding the .svg extension).
class
"class" "size-7 text-red-400" — (string, optional)
Tailwind/CSS classes to override the global defaults.
These are appended to the base .ks-icon class.
ariaHidden
"ariaHidden" "false" — (string, optional)
Whether to hide the icon from screen readers.
If the icon provides semantic meaning, set to "false".
Default: "true".
role
"role" "presentation" — (string, optional)
Defines the semantic role of the SVG.
Default: "img".
focusable
"focusable" "true"— (string, optional)
Defines if the SVG can receive focus
Default: "false".
attributes
"attributes" `id="logo"` — (string, optional)
Any custom HTML attributes to inject directly into the <svg>
(e.g. IDs or data attributes).

Usage

  1. Place your .svg files inside the assets/icons/ directory.
  2. Define your global base styles in the file assets/css/components/_icon.css
Tailwind CSS assets/css/components/_icon.css
1@layer components {
2  .ks-icon {
3    @apply size-4;
4  }
5}

Tips & tricks

You can use the icon partial inside Markdown by creating a wrapper shortcode.

Go/HTML template /layouts/_shortcodes/icon.html
1{{ partial "ui/icon" (dict 
2  "name"  (.Get "name") 
3  "class" (.Get "class")
4) }}

and use it in your content:

Markdown
1A pizza slice: 
2{{< icon name="pizza" class="size-7 text-red-400" >}}

Manual Installation

Create the partial:

Go/HTML template layouts/_partials/ui/icon.html
 1{{- /*
 2  KEYSTONE UI: ICON PARTIAL
 3  -------------------------
 4  Renders an SVG icon from `assets/icons/*.svg``.
 5  Automatically handles accessibility and class merging.
 6
 7  ARGUMENTS (dict):
 8  - "name"       (string, required) : Filename without extension (e.g., "github")
 9  - "class"      (string, optional) : Tailwind/CSS classes to append
10  - "ariaHidden" (string, optional) : Default "true". Set "false" if semantic.
11  - "role"       (string, optional) : Default "img".
12  - "focusable"  (string, optional) : Default "false".
13  - "attributes" (string, optional) : Any other raw HTML attributes (e.g. "id='my-icon'")
14
15  Documentation:
16  https://keystone-ui.oxypteros.com/docs/components/icon
17*/}}
18
19{{- $customClass := "ks-icon" }}
20{{- $name := .name -}}
21{{- $class := .class | default "" -}}
22{{- $finalClass := $customClass -}}
23{{- with $class -}}
24  {{- $finalClass = printf "%s %s" $customClass . -}}
25{{- end -}}
26
27{{- /* A11y Defaults */}}
28{{- $ariaHidden := .ariaHidden | default "true" -}}
29{{- $focusable := .focusable | default "false" -}}
30{{- $role := .role | default "img" -}}
31{{- $attributes := .attributes | default "" | safeHTMLAttr -}}
32
33{{- /* Load icon */}}
34{{- $icon := resources.Get (printf "icons/%s.svg" $name) -}}
35{{- with $icon }}
36  {{- $content := .Content -}}
37
38  {{- /*
39    Clean up:
40    - (?i) Case insensitive
41    - \s+ matches one or more whitespace (space, tab, newline)
42    - ["'] matches single OR double quotes
43    - [^"']* matches content inside the quotes
44  */}}
45  {{- $pattern := `(?i)\s+(class)=["'][^"']*["']` -}}
46  {{- $content := replaceRE $pattern "" $content -}}
47
48  {{- /* Inject attributes */}}
49  {{- $finalAttrs :=  printf ` class="%s %s" aria-hidden="%s" focusable="%s" role="%s" %s` $customClass $class $ariaHidden $focusable $role $attributes -}}
50
51  {{- $content = replace $content "<svg" (printf "<svg%s" $finalAttrs) -}}
52  {{- $content | safeHTML -}}
53{{- else }}
54  {{- warnf "Keystone UI: Icon '%s' not found in assets/icons/" $name -}}
55  {{- if hugo.IsServer }}
56    <svg
57      xmlns="http://www.w3.org/2000/svg"
58      viewBox="0 0 24 24"
59      width="24"
60      height="24"
61      fill="none"
62      stroke="currentColor"
63      stroke-width="2"
64      stroke-linecap="round"
65      stroke-linejoin="round"
66      class="{{ $finalClass }} rounded-sm border border-red-500 bg-red-100 text-red-500"
67      aria-label="Missing Icon: {{ $name }}"
68      role="img"
69    >
70      <path d="M18 6 6 18" />
71      <path d="m6 6 12 12" />
72    </svg>
73  {{- end }}
74{{- end }}

Add into your Tailwind/CSS file add:

Tailwind CSS
1@layer components {
2  .ks-icon {
3    @apply size-4;
4  }
5}
© 2025