# Icon Font Management This directory contains scripts and resources for managing the Bitwarden icon font (BWI). ## Overview The icon system uses Figma-exported SVG files that are converted into a web font using Fantasticon. SVG filenames directly become CSS class names (with the `bwi-` prefix added automatically), making the workflow simple and straightforward. ## Adding a New Icon Follow these steps to add a new icon to the icon font: ### 1. Export the Icon from Figma 1. Open the Figma icon file 2. Select the icon you want to export 3. Export as SVG with these settings: - **Outline stroke**: Enabled - **Include "id" attribute**: Disabled - **Simplify stroke**: Enabled 4. Name the file using kebab-case (e.g., `help.svg`, `star-filled.svg`, `add-circle.svg`) 5. Save the SVG file to `libs/assets/src/material-icons/` **Important:** The SVG filename directly becomes the CSS class name. For example, `help.svg` will generate the class `bwi-help`, and `star-filled.svg` will generate `bwi-star-filled`. Choose your filename carefully as it determines how developers will use the icon. ### 2. Generate the Icon Font Run the build script: ```bash npm run icons:build ``` This script will: 1. ✅ Generate the icon font files from all SVGs (woff2, woff, ttf, svg) 2. ✅ Update the SCSS with the new icon mappings 3. ✅ **Automatically update** `libs/components/src/shared/icon.ts` with the new icon 4. ✅ Clean up temporary build artifacts **Output files:** - `libs/angular/src/scss/bwicons/fonts/bwi-font.*` - Font files - `libs/angular/src/scss/bwicons/styles/style.scss` - Updated with new icon - `libs/components/src/shared/icon.ts` - Auto-generated TypeScript icon list (do not edit manually) **Note:** The TypeScript icon array is now auto-generated during the build process. You no longer need to manually add icons to `icon.ts`. ### 3. Add to Storybook Documentation Add your icon to the appropriate category in `libs/components/src/stories/icons/icon-data.ts`: ```typescript // Choose the appropriate category: // - statusIndicators // - bitwardenObjects // - actions // - directionalMenuIndicators // - miscObjects // - platformsAndLogos const actions = [ // ... existing icons ... { id: "bwi-your-new-icon", usage: "Detailed description of when and how to use this icon.", }, ]; ``` **Usage description guidelines:** - Start with what the icon indicates or does - Include context-specific guidance (mobile, desktop, toggle states, etc.) - Mention any variants or related icons - Note any accessibility considerations ### 4. Test Your Icon 1. **Visual verification**: Run Storybook to see your icon ```bash npm run storybook ``` Navigate to "Documentation / Icons" to verify your icon appears correctly 2. **Type checking**: Ensure TypeScript compiles without errors ```bash npm run test:types ``` 3. **Usage test**: Try using the icon in a component ```typescript ``` ## Migrating Icon Names Use the migration script when you need to **rename icon references across the entire codebase**. This is different from adding a new icon—it's for bulk-renaming existing icon class names. ### When to Use Migration - You're standardizing icon names to match new Figma conventions - You're replacing a legacy icon name with a new one - You need to update icon references in dozens or hundreds of files **Important:** This is NOT for adding new icons. Use the "Adding a New Icon" workflow above for that. ### How to Migrate Icon Names **1. Add the mapping to `migration-map.ts`** Open `scripts/material-icons/migration-map.ts` and add your mapping to the `BWI_TO_FIGMA` object: ```typescript export const BWI_TO_FIGMA: Record = { // ... existing mappings ... // Add your migration here "old-icon-name": "new-icon-name", }; ``` **Example:** ```typescript // Rename bwi-question-circle to bwi-help "question-circle": "help", // Rename bwi-spinner to bwi-loading "spinner": "loading", ``` **Note:** Do not include the `bwi-` prefix—the script adds it automatically. **2. Preview the changes (recommended)** Run the migration script in dry-run mode to see what will be changed: ```bash npm run icons:migrate -- --dry-run ``` This shows you all files and occurrences that will be updated without actually modifying anything. **3. Run the migration** Once you've verified the preview, run the actual migration: ```bash npm run icons:migrate ``` **4. Review the migration report** After migration completes, check `scripts/material-icons/migration-report.json` for a detailed report of all changes: ```json [ { "file": "apps/web/src/app/components/icon.component.html", "oldName": "bwi-question-circle", "newName": "bwi-help", "occurrences": 3 } // ... more entries ] ``` ### What Gets Updated The migration script searches and replaces icon names in: - TypeScript files (`.ts`) - HTML templates (`.html`) - SCSS/CSS files (`.scss`, `.css`) - Markdown documentation (`.md`, `.mdx`) In the following directories: - `apps/` - `libs/` - `bitwarden_license/` Excluding build/cache directories like `node_modules`, `dist`, `.git`, etc. ### Migration Workflow Example Complete workflow for renaming an icon: ```bash # 1. Add mapping to migration-map.ts # "spinner": "loading" # 2. Preview changes npm run icons:migrate -- --dry-run # 3. Run migration npm run icons:migrate # 4. Review migration-report.json # 5. Commit the changes git add . git commit -m "Migrate bwi-spinner to bwi-loading" ``` ## File Structure ``` scripts/material-icons/ ├── build-with-bwi-names.ts # Main build script ├── migrate-icon-names.ts # Migration script for bulk renames ├── migration-map.ts # Configuration for migration ├── migration-report.json # Generated migration report └── README.md # This file libs/assets/src/material-icons/ ├── help.svg # Figma-exported SVG files ├── star-filled.svg └── ... (all source SVG files) libs/angular/src/scss/bwicons/ ├── fonts/ │ ├── bwi-font.woff2 # Generated font files │ ├── bwi-font.woff │ ├── bwi-font.ttf │ └── bwi-font.svg └── styles/ └── style.scss # Generated SCSS with icon mappings libs/components/src/ ├── shared/ │ └── icon.ts # TypeScript icon types └── stories/icons/ └── icon-data.ts # Storybook documentation ``` ## Icon Naming Conventions The icon system uses a **direct naming approach**: the SVG filename becomes the CSS class name (with `bwi-` prefix added automatically). ### Naming Guidelines - **Use kebab-case**: `star-filled.svg`, not `starFilled.svg` or `star_filled.svg` - **Be descriptive**: Choose names that clearly indicate the icon's purpose - **Follow Figma**: Use names from the Figma design system when possible - **Consider usage**: The filename determines how developers reference the icon ### Examples | SVG Filename | Generated CSS Class | Usage Example | | ----------------------- | ------------------------ | --------------------------------- | | `help.svg` | `.bwi-help` | Help/question icons | | `star-filled.svg` | `.bwi-star-filled` | Filled star for favorites | | `add-circle.svg` | `.bwi-add-circle` | Add button with circle background | | `arrow-filled-down.svg` | `.bwi-arrow-filled-down` | Dropdown indicators | | `visibility-off.svg` | `.bwi-visibility-off` | Hide password toggle | ### Legacy Mappings Some icons have legacy mappings documented in `migration-map.ts` for historical reference. For example: - `bwi-question-circle` was migrated to `bwi-help` - `bwi-spinner` was migrated to `bwi-loading` - `bwi-plus` was migrated to `bwi-add` These mappings are only relevant if you're running migrations. New icons don't need any mappings. ## Troubleshooting ### Icon not appearing after build - Verify the SVG file is in `libs/assets/src/material-icons/` - Check that your SVG filename uses kebab-case and has the `.svg` extension - Run `npm run icons:build` again - Clear browser cache ### Wrong icon displaying - Verify the SVG filename matches what you expect (it becomes the CSS class) - Ensure you're using the correct `bwi-` class name in your component - Check for duplicate SVG files with similar names ### Font not updating - Delete the generated font files and rebuild: ```bash rm libs/angular/src/scss/bwicons/fonts/bwi-font.* npm run icons:build ``` ### TypeScript errors - Ensure you added the icon to `libs/components/src/shared/icon.ts` - Check that the icon name format matches: `bwi-icon-name` ## Advanced Usage ### Icon Sizing Classes Available utility classes (defined in `style.scss`): - `.bwi` - Base class (required) - `.bwi-sm` - Small (0.875em) - `.bwi-lg` - Large (~1.33em) - `.bwi-2x` - 2x size - `.bwi-3x` - 3x size - `.bwi-4x` - 4x size - `.bwi-fw` - Fixed width (~1.3em) ### Rotation & Animation - `.bwi-rotate-270` - Rotate 270 degrees - `.bwi-spin` - Animated spinning (for loading spinners) ### Example Usage ```html ``` ## Best Practices 1. **Icon Consistency**: Follow the existing Figma design system naming 2. **Semantic Naming**: Use descriptive filenames that clearly indicate the icon's purpose 3. **Documentation**: Always add usage guidelines to Storybook 4. **Accessibility**: Include proper ARIA labels when using icons without text 5. **SVG Optimization**: Export from Figma with strokes outlined 6. **Testing**: Verify icons in Storybook before committing ## Resources - [Fantasticon Documentation](https://github.com/tancredi/fantasticon) - [Icon Font Best Practices](https://css-tricks.com/examples/IconFont/) - Internal Figma Icon Library: [Link to your Figma file] ## Support For questions or issues: - Check the troubleshooting section above - Review existing icons in `libs/assets/src/material-icons/` - Consult the design team for icon naming conventions