Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion apps/design-system/components/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ function Icons() {
<DropdownMenuTrigger asChild>
<GridItem>
<icon.component
strokeWidth={1.5}
size={21}
className="group-data-[state=open]:scale-125 transition-all"
/>
Expand Down
35 changes: 25 additions & 10 deletions apps/design-system/content/docs/icons.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -45,31 +45,36 @@ function app() {
}
```

**Default props**: All icons have `strokeWidth={2}` and `size={24}` by default. Override these props as needed for your use case.
**Default props**: All icons default to `size={24}`. Stroke and fill defaults come from the source SVG's root attributes (e.g. `stroke-width="1"` in the source becomes the component's default `strokeWidth`). 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:
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 follows these requirements:

- Exported at 24x24px with `viewBox="0 0 24 24"`
- Exported at 24×24px 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 `stroke-width="1.5"` (deviate based on optical weight if necessary)
- Uses `fill="none"` for fills (no hardcoded colors)
- Icon content is optically centered and around 18x18px within the 24x24 frame
- Icon content is optically centered and around 18×18px within the 24×24 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.
For **fill-only icons** (e.g. logos that use shapes instead of strokes), add `stroke="none"` to the root `<svg>` element. The build will propagate this so the component never renders an unwanted stroke.

Leave attributes like `stroke-width` as they are. The root SVG's `fill`, `stroke`, `stroke-width`, `stroke-linecap`, and `stroke-linejoin` attributes are automatically propagated as the component's defaults by the build process. The conversion to camel-case for React compatibility (e.g. `strokeWidth`) is also handled automatically.

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} />
```

```tsx
<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`.
Expand All @@ -78,8 +83,8 @@ The icon name is automatically made available in camel-case, determined by the k

Icons should:

- Always be exported 24x24px
- Have an icon inside that frame that’s around 18x18px(ish)
- Always be exported 24×24px
- Have an icon inside that frame that’s around 18×18px(ish)
- Use clean, simple paths without unnecessary wrapper elements

#### Bad example ❌
Expand All @@ -94,7 +99,7 @@ Notice the hardcoded colors, unnecessary backgrounds, and complex structure:
</svg>
```

#### Good example ✅
#### Good example (stroke icon)

Clean structure with `currentColor` and proper attributes:

Expand All @@ -106,6 +111,16 @@ Clean structure with `currentColor` and proper attributes:
</svg>
```

#### Good example (fill-only icon / logo) ✅

Note `stroke="none"` on the root to prevent unwanted strokes, and `fill="currentColor"` on each path:

```svg
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="none" xmlns="http://www.w3.org/2000/svg">
<path d="M..." fill="currentColor" />
</svg>
```

{/* This is still wrong: */}

```svg
Expand Down
4 changes: 2 additions & 2 deletions apps/docs/components/GuidesSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ function AiTools({ className }: { className?: string }) {
rel="noreferrer noopener"
className="flex items-center gap-1.5 text-xs text-foreground-lighter hover:text-foreground transition-colors"
>
<Chatgpt size={14} strokeWidth={0} />
<Chatgpt size={14} />
Ask ChatGPT
</a>
<a
Expand All @@ -72,7 +72,7 @@ function AiTools({ className }: { className?: string }) {
rel="noreferrer noopener"
className="flex items-center gap-1.5 text-xs text-foreground-lighter hover:text-foreground transition-colors"
>
<Claude size={14} strokeWidth={0} />
<Claude size={14} />
Ask Claude
</a>
</div>
Expand Down
6 changes: 3 additions & 3 deletions apps/studio/components/interfaces/LogDrains/AnimatedLogos.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,18 +13,18 @@ export const AnimatedLogos = () => {
{
id: 'datadog',
name: 'Datadog',
icon: <Datadog fill="currentColor" strokeWidth={0} size={iconSize} />,
icon: <Datadog fill="currentColor" size={iconSize} />,
},
{
id: 'loki',
name: 'Loki',
icon: <Grafana fill="currentColor" strokeWidth={0} size={iconSize} />,
icon: <Grafana fill="currentColor" size={iconSize} />,
},
{ id: 'https', name: 'HTTPS', icon: <BracesIcon size={iconSize} /> },
{
id: 'sentry',
name: 'Sentry',
icon: <Sentry fill="currentColor" strokeWidth={0} size={iconSize} />,
icon: <Sentry fill="currentColor" size={iconSize} />,
},
]

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,20 @@ export const LOG_DRAIN_TYPES = [
value: 'otlp',
name: 'OpenTelemetry Protocol (OTLP)',
description: 'Send logs to any OpenTelemetry Protocol (OTLP) compatible endpoint',
icon: <Otlp {...iconProps} fill="currentColor" strokeWidth={0} />,
icon: <Otlp {...iconProps} fill="currentColor" />,
},
{
value: 'datadog',
name: 'Datadog',
description: 'Datadog is a monitoring service for cloud-scale applications',
icon: <Datadog {...iconProps} fill="currentColor" strokeWidth={0} />,
icon: <Datadog {...iconProps} fill="currentColor" />,
},
{
value: 'loki',
name: 'Loki',
description:
'Loki is an open-source log aggregation system designed to store and query logs from multiple sources',
icon: <Grafana {...iconProps} fill="currentColor" strokeWidth={0} />,
icon: <Grafana {...iconProps} fill="currentColor" />,
},
{
value: 's3',
Expand All @@ -47,20 +47,20 @@ export const LOG_DRAIN_TYPES = [
name: 'Sentry',
description:
'Sentry is an application monitoring service that helps developers identify and debug performance issues and errors',
icon: <Sentry {...iconProps} fill="currentColor" strokeWidth={0} />,
icon: <Sentry {...iconProps} fill="currentColor" />,
},
{
value: 'axiom',
name: 'Axiom',
description:
'Axiom is a data platform designed to efficiently collect, store, and analyze event and telemetry data at massive scale.',
icon: <Axiom {...iconProps} fill="currentColor" strokeWidth={0} />,
icon: <Axiom {...iconProps} fill="currentColor" />,
},
{
value: 'last9',
name: 'Last9',
description: 'Last9 is an observability platform for monitoring and telemetry data',
icon: <Last9 {...iconProps} fill="currentColor" strokeWidth={0} />,
icon: <Last9 {...iconProps} fill="currentColor" />,
},
] as const

Expand Down
Loading
Loading