Choosing a symbol
SF Symbols are Apple's icon set. Herald draws them on buttons, badges and the issuer icon of a banner, and on the action buttons themselves, with control over weight, size, rendering mode, colours, a variable value and, on macOS 14 and later, motion effects. This page is for anyone who designs a banner template and wants an icon in it, and for agents that write templates. The names come from the SF Symbols app, or from Herald's own symbol search.
Every JSON example here is valid against the component schema. Examples use the fictional app example.bidbot or
the WebWatcher email issuer, and the $HERALD and $TOKEN variables from Connect.
Where a symbol can go#
A symbol is a property called symbol on a component or on an action. This section lists every place it can go and
what Herald does with it there, so you can choose where the icon belongs.
| Where | What the symbol does |
|---|---|
iconButton | It is the glyph of the button, and it is required. A plain name or an object with name and styling. |
button | It is drawn with the label, on the side placement picks. An action's own symbol wins over it. |
actions | Every button of the row gets it, unless that button's action has its own. |
issuerIcon | It is drawn instead of the app icon, at 62 percent of size. The app icon is drawn when the name is unknown. |
badge | It is drawn beside the value, before it (leading) or after it (trailing). |
| An action | It is the icon of that one button wherever the action appears. |
An actionRules rule | It gives the icon to every action the rule matches. |
Icons on individual action buttons#
A row of buttons often needs a different icon on each button. Set symbol on the action itself, and the button shows
it in any button or actions component. You can set it three ways:
- On an action you write inline, in a template or in a notification.
- On an action an
actionRulesrule adds withadd. - On an action the issuer declared, with a rule that matches it. This is how you give an icon to a button the app sent, without changing the app.
A rule's match is an action id, an action label (not case-sensitive) or * for every action. The rule's symbol
replaces the matched actions' symbol, and a symbol with an empty name removes it. Actions describes
rules in full.
{"actionRules": [
{"match": "markRead", "symbol": {"name": "checkmark.circle", "weight": "semibold"}},
{"match": "archive", "symbol": "archivebox"}]}
An icon-only button#
Set the symbol's placement to only to drop the label and show just the icon. The label is not lost: it stays as
the button's tooltip, so the button remains understandable on hover. Do this on the action, so the button is icon-only
wherever the action appears:
{"match": "archive", "symbol": {"name": "archivebox", "placement": "only"}}
For a round button that is always a single icon, use an iconButton instead. It has no
label to drop.
The symbol value#
A symbol is either a plain name, or an object that names the symbol and styles it. This section explains each part of the object, with the allowed values and the default for each, and shows how to find a valid name.
A plain name draws the symbol with the defaults of the place it is in:
"bell.badge"
An object adds styling:
{"name": "bell.badge", "weight": "semibold", "scale": "large", "placement": "leading",
"renderingMode": "palette", "colors": ["#FF3B30", "primary"], "variableValue": 0.6,
"effect": {"kind": "bounce", "trigger": "onChange", "speed": 1.5}}
| Property | Type | Default | Allowed values |
|---|---|---|---|
name | string | none | An SF Symbol name. It is required. |
weight | string | The component's own. | ultraLight, thin, light, regular, medium, semibold, bold, heavy, black. |
scale | string | medium | small, medium, large. The size relative to the text. |
placement | string | leading | leading, trailing, only. |
renderingMode | string | monochrome | monochrome, hierarchical, palette, multicolor. |
colors | array | The component's tint. | One to three colours. |
variableValue | number or string | none | A number from 0 to 1, or a {token}. |
effect | object | none | See Effects. |
Notes on each property:
namemay contain a{token}, which is how thereplaceeffect has something to swap.- An unknown name draws the component's default look. An
iconButtonshowsquestionmark.circle, abuttonshows its plain label and anissuerIconkeeps the app icon. - The validator warns that the name is not an SF Symbol on this Mac.
- An unknown name draws the component's default look. An
weightdefaults tosemiboldon buttons,boldon aniconButtonandregularelsewhere.placementsets the side of the label the symbol sits on, in abutton, anactionsrow or abadge.onlydrops the label.- An
iconButtonand anissuerIconignore it.
colorstakes values of these kinds:- A hex colour:
#RGB,#RGBA,#RRGGBBor#RRGGBBAA. - A keyword:
accent,primaryorsecondary. - A
{token}whose value is one of those. - More than three colours are ignored with a warning, and a colour that does not resolve is skipped.
- Hex colours get the same legibility adjustment as other components.
- With no
colors, a symbol uses the component's tint: thecolorof aniconButton, the accent of a button, or the text colour of a badge.
- A hex colour:
variableValueworks on symbols that have variable layers, such aswifi,speaker.wave.3andchart.bar.- A value above 1 up to 100 is read as a percentage, like the progress bar, so
{progress}can carry 0 to 100. - Other values are clamped to 0 to 1.
- A symbol without variable layers ignores it.
- A value above 1 up to 100 is read as a percentage, like the progress bar, so
Finding a name#
Names must match the SF Symbols on the Mac that shows the banner. Search them with Herald's own list, which uses the same categories and synonyms as the Designer's symbol browser, so an agent or a script finds real names without opening the SF Symbols app:
herald symbols envelope --limit 2
{"total": 32, "offset": 0, "limit": 2,
"symbols": [{"name": "envelope.front", "categories": ["communication"]},
{"name": "envelope.front.fill", "categories": ["communication", "multicolor"]}],
"categories": [{"key": "all", "title": "All", "icon": "square.grid.2x2", "count": 7779}]}
The search is GET /v1/symbols, also available as the MCP tool
list_symbols. It matches every word of the query against names, search terms and
synonyms, can narrow to one category, and pages through the results. The reply lists the categories with their
counts. In the Designer the same list is the symbol browser.
Rendering modes#
The rendering mode decides how the symbol's layers take colour. Pick it by how many colours you want.
| Mode | Colours used | Result |
|---|---|---|
monochrome | The first colour, else the tint. | One flat colour. |
hierarchical | The first colour, else the tint. | Layers take shades of that colour. |
palette | One colour: it, and the same colour at 55 percent for the second layer. Two or three: one per layer. None: the tint and the tint at 55 percent. | Each layer has its own colour. |
multicolor | None. colors is ignored. | The symbol's own colours. Not every symbol has any. |
The validator warns about two combinations:
palettewith nocolorsgets the warningpalette rendering needs 2 or 3 colours.multicolorwithcolorsgets a warning thatcolorsis ignored.
Static previews#
Static renders show the weight, scale, rendering mode, colours and variable value. They do not draw effects. Static
renders are POST /v1/preview, the MCP tool render_preview, and the rows of History. Effects run only in live
banners and in the Designer's live preview.
In the Designer#
The Designer shows a Symbol section in the inspector when you select a component that takes a symbol. It has a Name field with a picker, and rows for each property of the symbol object. Every change appears on the canvas and in the live preview at once.
The picker next to Name opens the symbol browser, either in a sheet or in a floating panel that stays beside the Designer. The browser has these parts:
- A sidebar with All symbols, Recents, Favourites and Apple's categories, each with a count.
- A search field that matches names, keywords and synonyms, such as
bin,mailoralert. - A grid size slider, and a star on a symbol to add it to your favourites.
- A preview that draws the selected symbol with the weight, mode and colours of the Symbol section, and the Use symbol button. A double-click on a symbol uses it as well.
The rows of the Symbol section are:
| Row | What it sets |
|---|---|
| Name | name. A name that is not an SF Symbol on this Mac shows a warning that the default look is drawn. |
| Weight and Scale | weight and scale. |
| Place | placement: Before, After or Only. Shown where it applies. |
| Mode | renderingMode: monochrome, hierarchical, palette or multicolor. |
| Color, Color 2, Color 3 | colors. Each takes a colour well, Accent, Primary, Secondary or a {token}. |
| Variable | variableValue: a number with a slider, or a {token}. |
| Effect, When, Speed | effect: its kind, trigger and speed. Cumulative and Reversing appear for variableColor. |
On the Actions tab, every action row has its own symbol picker and a Shows choice:
- Text removes the symbol.
- Icon and text keeps it before the label.
- Icon only sets
placementtoonly.
The choice writes the action's symbol, so it holds in every cell that shows the action. The live preview plays effects. Static previews, in the Designer's snapshot and in render_preview, show everything except the motion.