Stacks Icons are delivered via npm. Install them with npm i @stackoverflow/stacks-icons.
See https://icons.stackoverflow.design/ for the current V7 icons and spots. The maintained V6 manifest is available at https://v6.icons.stackoverflow.design/.
| Version | Branch | Documentation | Packages |
|---|---|---|---|
| V7 (current) | main |
https://icons.stackoverflow.design/ | @stackoverflow/stacks-icons and StackExchange.StacksIcons |
| V6 (maintenance) | v6 |
https://v6.icons.stackoverflow.design/ | @stackoverflow/stacks-icons, StackExchange.StacksIcons, and the internal StackExchange.StacksIcons.Legacy package |
v2.icons.stackoverflow.design redirects to the maintained V6 documentation. The production branch is retained during the initial V7 cutover but is not the current release line.
Using the library by importing a subpath (e.g. /icons) will allow for tree-shaking unused icons from your bundle.
// es6 / module syntax
import { IconAnswer } from "@stackoverflow/stacks-icons/icons";
import { SpotWave } from "@stackoverflow/stacks-icons/spots";
// both icons and spots are unescaped html strings
console.log(IconAnswer); // "<svg>...</svg>"
// require() syntax
const { Icons, Spots } = require("@stackoverflow/stacks-icons");
// `Icons` and `Spots` are objects mapped by <icon name, html string>
console.log(Icons); // { "IconAnswer": "<svg>...</svg>", ... }In certain cases where adding the raw svg markup to your html would cause bloat or if you need your markup to be more portable, consider using CSS icons. Note: Not all icons are available as CSS icons.
<!-- include the required css file -->
<link
rel="stylesheet"
href="/path/to/@stackoverflow/stacks-icons/dist/icons.css"
/>
<!-- add the "svg-icon-bg" class in addition the desired "iconNAME" class -->
<span class="svg-icon-bg iconAnswer"></span>
<!-- the icon's color matches the "currentColor", so changing the "color" property will change the icon color -->
<span class="svg-icon-bg iconAnswer" style="color: red;"></span>
<!-- add the "native" class to get native styles; these do not respect "currentColor" changes -->
<span class="svg-icon-bg iconAnswer native"></span>For performance / file size reasons, not all icons are available in css. You can add support for more CSS icons my editing the cssIcons value in config.yaml.
SVGs can include custom CSS animations. Named layers in Figma will be passed to the final file, converted from IDs to classes, and prefixed with the icon name to reduce collisions in production.
To add a new animation for an icon:
- Create a CSS file in
src/animations/[IconName].css - At build time, the SVG and CSS will be compiled into one minified file
- Use the Figma layer names (which become classes) to target elements for animation
/* Example: src/animations/IconSpin.css */
@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.spinning-layer {
animation: spin 1s linear infinite;
}
/* Always respect user motion preferences */
@media (prefers-reduced-motion: reduce) {
.spinning-layer {
animation: none;
/* For loading indicators, consider a subtle opacity fade instead */
}
}Stacks Icons also provides a NuGet package that targets net8.0.
See the dotnet/src/README.md file for more details.
Note This method is not intended to be used in production
If you include the browser.umd.js within your prototype’s body element (<script src="https://unpkg.com/@stackoverflow/stacks-icons/dist/browser.umd.js"></script>) you can render Stacks Icons in the browser using only the following format:
<svg data-icon="IconAnswer" class="native"></svg>
<svg data-spot="SpotSearch"></svg>This package looks out for elements that look like svg[data-icon]. If the icon doesn’t exist in Stacks, it will throw you an error in console. Anything in the class="" attribute will be passed to the included SVG e.g., native
First, you'll need a Figma personal access token. Once you have that, place it in a .env file in the root of the repo:
FIGMA_ACCESS_TOKEN="your_access_token_here"
FIGMA_FILE_KEY="Z5yoO4WH58QDHvmxwMWhr0"Install the necessary dependencies:
npm iRun the build:
npm run buildPreview the icons
npm run previewYou'll need to first run the general package build as outlined above, as the dotnet solution pulls the generated csharp files from the build directory.
You can then build the library locally via:
npm run build:nugetor run the unit tests with:
npm run test:nugetAll icons and spots are pulled directly from Figma via their API. The only way to add or update icons is by directly modifying the source Figma file and then publishing a new component release from within Figma.
To maintain readability you can format and sort the config yaml by using the command.
brew install yq # if you haven't already installed it
npm run format:configThe build process now supports mapping specific colors to CSS variables via the fills section in config.yaml. This allows for better theming and customization of icons:
fills:
"#FF0000": "var(--theme-primary-color)"
"#00FF00": "var(--theme-secondary-color)"Colors defined in the fills mapping will be automatically replaced during the build process using SVGO's plugin architecture, providing more reliable optimization than string replacement.
In order to expose a new icon to this repository, you'll need to convert it into a component then publish it by following these steps:
- Open the source Figma file
- Navigate to the newly added icon. Note the absense of the segmented diamond icon next to the icon name.
- Right click on the icon to open the context menu and select "Create component"
- Right click on the icon again to reopen the context menu and select "Main Component > Publish selected components"
- Within the "Publish libray" modal, select the icon(s) you'd like to publish
- Click "Publish"
In order to ensure that any new icons/spots in Figma are pulled into this repo, the definitions will need to be added to config.yaml. The structure uses Figma component properties as keys with their corresponding hash values:
definitions:
Icon/IconName:
Size=Default, Stack=False, Style=Default: ""
Size=Default, Stack=False, Style=Fill: ""
Size=Default, Stack=True, Style=Default: ""
Size=Default, Stack=True, Style=Fill: ""Icons can have various property combinations depending on their Figma component definition. Common properties include:
Size=Default(standard property for most icons)Stack=True|False(whether the icon has a stacked variant)Style=Default|Fill(visual style variant)Direction=Up|Down|Left|Right|UpLeft|UpRight|DownLeft|DownRight(for directional icons like Arrow, Chevron, Vote, Trend)Box=True|False(for boxed variants, e.g., some Arrow icons)Type=Default|Comment|Document|Dashboard|Review(for icons with type variants like Compose, Mod)Off=True|False(for toggle states, e.g., Flag, Notification)Open=True|False(for open/closed states, e.g., Mail)Service=CCPA|Facebook|GitHub|Google|Instagram|LinkedIn|Threads|X|YouTube(for service-specific icons)
Important: When adding new entries, ensure that:
- The property order matches Figma's component definition (usually Size, then Boolean properties, then Style)
- All entries are in alphabetical order for ease of reference
- The initial hash values can be left empty (
"")
To make adding new icons easier, you can use the sync script to programmatically update the config.yaml hashes:
npm run sync:figmaThis script will automatically fetch the latest components from Figma and update the hash values in config.yaml. Hashes will only update if the icon is already defined.
Once you run the first build process, it'll throw an error like the following:
ERROR Hash mismatch on 1 files. Expected hash values: "Icon/Answer": { "Size=Default, Stack=False, Style=Default": "UhYGuawhIoWxhzQLOu2XCwpBCK8a7p381CWsz/NYaDQ=" }
Take these hash values and use them as the values for the previously added entries. Re-run the build process and verify that your new icon is added correctly and has the correct contents.
When updating an existing icon, just update the corresponding hash value(s) for the property combination(s) that changed.
Optionally, you can generate a .pptx file which will contain the Size=64 and Spot/* assets as native vectors, allowing you to recolor and scale. We maintain a publicly available version of this for internal and external folks.
npm run build
# Not part of the main build process (yet)
npm run generate:powerpoint
V7 releases are prepared on main. The package version must match the immutable Git tag exactly. The release workflow publishes the npm package and the same NuGet artifact to both public NuGet.org and the internal Cloudsmith feed.
The initial stable V7 cutover already sets the package metadata to 7.0.0. After that change is merged, publish it by tagging the reviewed merge commit without incrementing the version again:
git fetch origin main
git tag v7.0.0 <verified-main-merge-sha>
git push origin refs/tags/v7.0.0For subsequent releases, update the package version before pushing its generated tag:
npm version [major|minor|patch]
# for beta releases instead use:
# npm version prerelease --preid beta
git push --follow-tagsThe GitHub packages action validates the tag and package metadata before publishing. Do not retry a partially completed release without first verifying which registries already contain the version; the manual workflow can skip npm when only the NuGet destinations need recovery.
V6 releases and the internal StackExchange.StacksIcons.Legacy package are maintained independently from the v6 branch.
Afterwards, make sure you mark a new GitHub Release based on what has changed.
This project follows SemVer. Versions including breaking changes to the visual api (e.g. icon drastically changes design or is removed) or code api should be marked major. Versions including new features (such as a new or updated icon) should be marked minor. Everything else is a patch release.
© Copyright 2025 Stack Exchange, Inc.
Unless otherwise stated, the contents of this folder are licensed under the Apache License, Version 2.0
Unless required by applicable law or agreed to in writing, software distributed under the Apache License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
The Stack Overflow name and logo, and associated brand elements, are the protected property of Stack Exchange, Inc. Acceptable use of Stack Overflow trademarks is governed by: https://policies.stackoverflow.co/company/trademark-guidance/. All other use of Stack Overflow trademarks is prohibited without prior written authorization, including without limitation, any use suggesting unauthorized endorsement by or affiliation with Stack Overflow.