Files
supabase/apps/design-system/content/docs/icons.mdx
T
Ivan Vasilov 1cd1ebfc7f chire: Sort imports in all packages, cms, design-system and ui-library apps (#41610)
Sorted all imports in all packages, `cms`, `design-system` and
`ui-library` apps by running `pnpm format` on them.

All changes in this PR are done by the script.
2026-02-05 13:54:10 +01:00

123 lines
4.3 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: Icons
description: Icons make actions and navigation across Supabase easier.
---
## Principles
1. Paired: Icons should accompany text, as they aren’t often obvious enough on their own.
2. Clear: Icons should be legible at small sizes and unembellished. Let the text do the heavy lifting.
3. Consistent: Use the same icons for similar actions throughout Supabase. This makes the app easier to use.
## Tints
Use classes just like you would for [text](color-usage#text) to tint icons. For example:
```jsx
<BucketAdd className="text-foreground-muted" />
```
Just like text, don’t tint icons with `text-destructive` for destructive actions. There should be a confirmation dialog right after which can handle the destructive styling.
## UI icons
We rely on [Lucide](https://lucide.dev/icons/) for any standard UI icon needs.
## Custom icons
Create and use custom icons when Lucide doesn’t have the icon you need. Tap on an icon below to copy the JSX, SVG, or import path.
<Icons />
### Usage
```jsx
import { BucketAdd, InsertCode, ReplaceCode } from 'icons'
function app() {
return (
<>
<ReplaceCode className="text-light" strokeWidth={1} size={16} />
<InsertCode className="text-light" strokeWidth={1} size={16} />
<BucketAdd size={24} className="text-foreground-muted" />
</>
)
}
```
**Default props**: All icons have `strokeWidth={2}` and `size={24}` by default. Override these props as needed for your use case.
### Adding new custom icons
Follow these steps to add a new custom icon to the Supabase icon library.
1. **Create SVG file**: Add your SVG file to `packages/icons/src/raw-icons/` with a kebab-case name (e.g., `my-new-icon.svg`). Make sure it has follows these exact requirements:
- Exported at 24x24px with `viewBox="0 0 24 24"`
- Uses `stroke="currentColor"` for strokes (no hardcoded colors)
- Uses `stroke-width="1.5"` unless there is a good reason to deviate
- Uses `fill="none"` for fills (no hardcoded colors)
- Icon content is optically centered and around 18x18px within the 24x24 frame
- Any unnecessary elements like `<clipPath>`, `<defs>`, and `<g>` wrappers have been removed
- SVG structure is as simple as possible with just `<path>` elements
Leave attributes like `stroke-width` as they are. The conversion to camel-case for React compatibility (e.g. `strokeWidth`) is handled by the below build process.
2. **Build the component**: Run `npm run build:icons` from inside the `packages/icons` directory
3. **Use the icon**: Import and use like any other icon:
```tsx
import { MyNewIcon } from 'icons'
;<MyNewIcon size={16} strokeWidth={1} />
```
The icon name is automatically made available in camel-case, determined by the kebab-case input SVG. For example, `my-new-icon.svg` will become available as `MyNewIcon`.
### SVG design guidelines
Icons should:
- Always be exported 24x24px
- Have an icon inside that frame that’s around 18x18px(ish)
- Use clean, simple paths without unnecessary wrapper elements
#### Bad example ❌
Notice the hardcoded colors, unnecessary backgrounds, and complex structure:
```svg
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="24" height="24" fill="#1E1E1E" /> <!-- ❌ Hardcoded color -->
<path d="M..." fill="#404040" /> <!-- ❌ Hardcoded color -->
<path d="M..." stroke="#EDEDED" stroke-linecap="round" /> <!-- ❌ Hardcoded color -->
</svg>
```
#### Good example ✅
Clean structure with `currentColor` and proper attributes:
```svg
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<path d="M6 7C6 4.2 8.2 2 11 2H13C15.8 2 18 4.2 18 7" />
<path d="M4.5 11H19.5" />
<path d="M6 11L6.8 20C6.9 21.1 7.9 22 9 22H12" />
</svg>
```
{/* This is still wrong: */}
```svg
<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<path d="M6 7C6 4.2 8.2 2 11 2H13C15.8 2 18 4.2 18 7" />
<path d="M4.5 11H19.5" />
<path d="M6 11L6.8 20C6.9 21.1 7.9 22 9 22H12" />
</svg>
```
### Troubleshooting
If your SVG specifies `stroke-width` attributes, they will override the component's `strokeWidth` prop. Remove stroke attributes from individual paths to let the component control them.