mirror of
https://github.com/supabase/supabase.git
synced 2026-06-20 10:32:40 +08:00
feat: custom bucket icons (#39280)
* chore: separate interfaces per bucket type * chore: reuse existing bucket creation modal for files * chore: allow external trigger for new bucket modal * chore: minor fixes * chore: full-size empty state * chore: files other tabs * fix: show tab bar when on file subroute * chore: use existing table component to list buckets * fix: tests * fix: build error * chore: remove future bucket type components from PR * fix: dependency * Couple of refactors to simplify implementation * Fix TS * chore: move s3 settings out to sidebar * fix: minor nits * fix: reuse existing loading spinners from schema visualiser * fix: loading for files * fix: prevent loading of table for zero buckets * chore: improved loading state * chore: shimmer on table * chore: copywriting on S3 * chore: improve empty states * fix: deprecated input instructions * fix: filter/search bucket table * chore: tidy * fix: tests * first commit * improve documentation and fix icon build error * change svg kebab case to camel case for React * copy nits * fix svg codeblock color * add bucket (normal) icon * add bucket icon to policies * add bucket icon to other storage bucket surfaces * fix spacing on empty state * fix inconsistent icons in home sections Make 1:1 with what we have in the sidebar with optically-correct strokeWidth. * fix icons Like the previous commit, this makes sure we use the same product icons as in the sidebar. * clearer bucket add icon naming * remove unused layouts * fix naming collision * Tinnnnyyy nit --------- Co-authored-by: Joshen Lim <joshenlimek@gmail.com>
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
Design resources for building consistent user experiences at Supabase.
|
||||
|
||||
## Getting Started
|
||||
## Getting started
|
||||
|
||||
First, make a copy of _.env.local.example_ and name it _env.local_. Then install any required packages and start the development server:
|
||||
|
||||
|
||||
@@ -11,14 +11,108 @@ description: Icons make actions and navigation across Supabase easier.
|
||||
|
||||
## Tints
|
||||
|
||||
Destructive actions, such as deleting an API key, don’t need to be [tinted](color-usage#text) with `text-destructive` because there should be a confirmation dialog as a failsafe right after.
|
||||
Use classes just like you would for [text](color-usage#text) to tint icons. For example:
|
||||
|
||||
## UI Icons
|
||||
```jsx
|
||||
<BucketAdd className="text-foreground-muted" />
|
||||
```
|
||||
|
||||
We rely on Lucide icons for most of our UI icons.
|
||||
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.
|
||||
|
||||
## Custom Icons
|
||||
## UI icons
|
||||
|
||||
Tap on an icon below to copy the JSX, SVG, or import path.
|
||||
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 { ReplaceCode, InsertCode, BucketAdd } 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
|
||||
|
||||
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 `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
|
||||
|
||||
Just leave attributes like `stroke-width` as they are. The conversion to camel-case (for React compatibility) 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:
|
||||
|
||||
```jsx
|
||||
import { MyNewIcon } from 'icons'
|
||||
;<MyNewIcon size={16} strokeWidth={1} />
|
||||
```
|
||||
|
||||
### 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.
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
}
|
||||
|
||||
[data-rehype-pretty-code-fragment] {
|
||||
@apply relative text-white;
|
||||
@apply relative;
|
||||
}
|
||||
|
||||
[data-rehype-pretty-code-fragment] code {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import dayjs from 'dayjs'
|
||||
import sumBy from 'lodash/sumBy'
|
||||
import { Archive, ChevronDown, Database, Key, Zap } from 'lucide-react'
|
||||
import { ChevronDown } from 'lucide-react'
|
||||
import { Auth, Database, Realtime, Storage } from 'icons'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useState } from 'react'
|
||||
@@ -200,7 +201,7 @@ const ProjectUsage = () => {
|
||||
<PanelHeader
|
||||
icon={
|
||||
<div className="rounded bg-surface-300 p-1.5 text-foreground-light shadow-sm">
|
||||
<Database strokeWidth={2} size={16} />
|
||||
<Database strokeWidth={1.5} size={16} />
|
||||
</div>
|
||||
}
|
||||
title="Database"
|
||||
@@ -226,7 +227,7 @@ const ProjectUsage = () => {
|
||||
<PanelHeader
|
||||
icon={
|
||||
<div className="rounded bg-surface-300 p-1.5 text-foreground-light shadow-sm">
|
||||
<Key strokeWidth={2} size={16} />
|
||||
<Auth strokeWidth={1.5} size={16} />
|
||||
</div>
|
||||
}
|
||||
title="Auth"
|
||||
@@ -252,7 +253,7 @@ const ProjectUsage = () => {
|
||||
<PanelHeader
|
||||
icon={
|
||||
<div className="rounded bg-surface-300 p-1.5 text-foreground-light shadow-sm">
|
||||
<Archive strokeWidth={2} size={16} />
|
||||
<Storage strokeWidth={1.5} size={16} />
|
||||
</div>
|
||||
}
|
||||
title="Storage"
|
||||
@@ -278,7 +279,7 @@ const ProjectUsage = () => {
|
||||
<PanelHeader
|
||||
icon={
|
||||
<div className="rounded bg-surface-300 p-1.5 text-foreground-light shadow-sm">
|
||||
<Zap strokeWidth={2} size={16} />
|
||||
<Realtime strokeWidth={1.5} size={16} />
|
||||
</div>
|
||||
}
|
||||
title="Realtime"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import dayjs from 'dayjs'
|
||||
import { Archive, ChevronDown, Code, Database, Key, Zap } from 'lucide-react'
|
||||
import { ChevronDown } from 'lucide-react'
|
||||
import Link from 'next/link'
|
||||
import { useRouter } from 'next/router'
|
||||
import { useMemo, useState } from 'react'
|
||||
@@ -77,7 +77,6 @@ type ServiceKey = 'db' | 'functions' | 'auth' | 'storage' | 'realtime'
|
||||
type ServiceEntry = {
|
||||
key: ServiceKey
|
||||
title: string
|
||||
icon: React.ReactNode
|
||||
href?: string
|
||||
route: string
|
||||
enabled: boolean
|
||||
@@ -159,7 +158,7 @@ export const ProjectUsageSection = () => {
|
||||
{
|
||||
key: 'db',
|
||||
title: 'Database requests',
|
||||
icon: <Database strokeWidth={1.5} size={16} className="text-foreground-lighter" />,
|
||||
|
||||
href: `/project/${projectRef}/editor`,
|
||||
route: '/logs/postgres-logs',
|
||||
enabled: true,
|
||||
@@ -167,14 +166,12 @@ export const ProjectUsageSection = () => {
|
||||
{
|
||||
key: 'functions',
|
||||
title: 'Functions requests',
|
||||
icon: <Code strokeWidth={1.5} size={16} className="text-foreground-lighter" />,
|
||||
route: '/logs/edge-functions-logs',
|
||||
enabled: true,
|
||||
},
|
||||
{
|
||||
key: 'auth',
|
||||
title: 'Auth requests',
|
||||
icon: <Key strokeWidth={1.5} size={16} className="text-foreground-lighter" />,
|
||||
href: `/project/${projectRef}/auth/users`,
|
||||
route: '/logs/auth-logs',
|
||||
enabled: authEnabled,
|
||||
@@ -182,7 +179,6 @@ export const ProjectUsageSection = () => {
|
||||
{
|
||||
key: 'storage',
|
||||
title: 'Storage requests',
|
||||
icon: <Archive strokeWidth={1.5} size={16} className="text-foreground-lighter" />,
|
||||
href: `/project/${projectRef}/storage/buckets`,
|
||||
route: '/logs/storage-logs',
|
||||
enabled: storageEnabled,
|
||||
@@ -190,7 +186,6 @@ export const ProjectUsageSection = () => {
|
||||
{
|
||||
key: 'realtime',
|
||||
title: 'Realtime requests',
|
||||
icon: <Zap strokeWidth={1.5} size={16} className="text-foreground-lighter" />,
|
||||
route: '/logs/realtime-logs',
|
||||
enabled: true,
|
||||
},
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { BucketAdd } from 'icons'
|
||||
import { CreateBucketModal } from './CreateBucketModal'
|
||||
import { BUCKET_TYPES } from './Storage.constants'
|
||||
|
||||
@@ -9,10 +10,13 @@ export const EmptyBucketState = ({ bucketType }: EmptyBucketStateProps) => {
|
||||
const config = BUCKET_TYPES[bucketType]
|
||||
|
||||
return (
|
||||
<aside className="mt-12 border border-dashed w-full bg-surface-100 rounded-lg px-4 py-10 flex flex-col gap-6 items-center text-center gap-1 text-balance">
|
||||
<div className="flex flex-col gap-1">
|
||||
<h3>Create {config.label}</h3>
|
||||
<p className="text-foreground-light text-sm">{config.valueProp}</p>
|
||||
<aside className="mt-12 border border-dashed w-full bg-surface-100 rounded-lg px-4 py-10 flex flex-col gap-y-4 items-center text-center gap-1 text-balance">
|
||||
<div className="flex flex-col gap-3 items-center text-center">
|
||||
<BucketAdd size={24} strokeWidth={1.5} className="text-foreground-muted" />
|
||||
<div className="flex flex-col gap-1">
|
||||
<h3>Create {config.label}</h3>
|
||||
<p className="text-foreground-light text-sm">{config.valueProp}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* [Joshen] We can render the individual bucket modals here instead - where each modal has its own trigger */}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import { PostgresPolicy } from '@supabase/postgres-meta'
|
||||
import { noop } from 'lodash'
|
||||
import { Archive } from 'lucide-react'
|
||||
|
||||
import { PolicyRow } from 'components/interfaces/Auth/Policies/PolicyTableRow/PolicyRow'
|
||||
import { Bucket } from 'data/storage/buckets-query'
|
||||
import { PolicyRow } from 'components/interfaces/Auth/Policies/PolicyTableRow/PolicyRow'
|
||||
|
||||
import { Bucket as BucketIcon } from 'icons'
|
||||
import {
|
||||
Badge,
|
||||
Button,
|
||||
@@ -41,7 +42,7 @@ export const StoragePoliciesBucketRow = ({
|
||||
<Card>
|
||||
<CardHeader className="flex flex-row w-full items-center justify-between gap-0 space-y-0">
|
||||
<div className="flex items-center gap-3">
|
||||
<Archive className="text-foreground-light" size={16} strokeWidth={1.5} />
|
||||
<BucketIcon className="text-foreground-muted" size={16} strokeWidth={1.5} />
|
||||
<CardTitle>{label}</CardTitle>
|
||||
{bucket?.public && <Badge variant="warning">Public</Badge>}
|
||||
</div>
|
||||
|
||||
@@ -52,18 +52,19 @@ export const Index: Record<string, any> = [`
|
||||
let { children } = iconNodes[iconName]
|
||||
children = children.map(({ name, attributes }) => [name, attributes])
|
||||
|
||||
const getSvg = () => readSvg(`${iconName}.svg`, iconsDir)
|
||||
const svgContent = readSvg(`${iconName}.svg`, iconsDir)
|
||||
const getSvg = () => svgContent
|
||||
// const { deprecated = false } = iconMetaData[iconName]
|
||||
const deprecated = false
|
||||
|
||||
const elementTemplate = template({ componentName, iconName, children, getSvg, deprecated })
|
||||
const output = pretty
|
||||
? prettier.format(elementTemplate, {
|
||||
singleQuote: true,
|
||||
trailingComma: 'all',
|
||||
printWidth: 100,
|
||||
parser: 'babel',
|
||||
})
|
||||
? await prettier.format(elementTemplate, {
|
||||
singleQuote: true,
|
||||
trailingComma: 'all',
|
||||
printWidth: 100,
|
||||
parser: 'babel',
|
||||
})
|
||||
: elementTemplate
|
||||
|
||||
const rawSvg = JSON.stringify(readSvg(`${iconName}.svg`, iconsDir))
|
||||
@@ -111,7 +112,7 @@ export const Index: Record<string, any> = [`
|
||||
}
|
||||
// TO DO -- END
|
||||
|
||||
Promise.all([writeIconFiles])
|
||||
Promise.all(writeIconFiles)
|
||||
|
||||
// TO DO -- START
|
||||
//
|
||||
|
||||
@@ -1,122 +1,31 @@
|
||||
# ./packages/icons
|
||||
|
||||
This package is for custom Supabase icons
|
||||
They can be used alongside any other icon packages
|
||||
This package contains custom Supabase icons that can be used alongside other icon libraries.
|
||||
|
||||
## example use
|
||||
## Documentation
|
||||
|
||||
**For complete documentation, usage examples, and guidelines, see the [Design System](../../apps/design-system/content/docs/icons.mdx)**
|
||||
|
||||
## Quick start
|
||||
|
||||
```jsx
|
||||
import { ReplaceCode, InsertCode } from 'icons'
|
||||
import { BucketAdd, Database, Auth } from 'icons'
|
||||
|
||||
function app() {
|
||||
function MyComponent() {
|
||||
return (
|
||||
<>
|
||||
<ReplaceCode className="text-light" strokeWidth={1} size={16} />
|
||||
<InsertCode className="text-light" strokeWidth={1} size={16} />
|
||||
<BucketAdd size={24} className="text-foreground-muted" />
|
||||
<Database size={16} strokeWidth={1} />
|
||||
<Auth size={20} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
## adding new icons
|
||||
### Adding new custom icons
|
||||
|
||||
Add new icons into ./src/raw-icons
|
||||
1. Add your SVG file to `src/raw-icons/` (kebab-case name)
|
||||
2. Run `npm run build:icons` in this directory
|
||||
3. Import and use your new icon
|
||||
|
||||
Make sure there are no inline stroke/border/fill colors (see below)
|
||||
|
||||
run this in ./packages/build-icons
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
```
|
||||
|
||||
This will output icons into ./src/icons and update import names/paths
|
||||
|
||||
### Design spec
|
||||
|
||||
Icons should:
|
||||
|
||||
- always be exported 24x24px,
|
||||
- and have an icon inside that frame that's around 18x18px(ish)
|
||||
|
||||
### ❌ bad example
|
||||
|
||||
Notice the stroke, stroke-linecap, fills, etc.
|
||||
These need to be in the parent <svg> so the react component can easily control it.
|
||||
The SVG child elements will then respect their parent's attributes.
|
||||
|
||||
```svg
|
||||
<svg
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 24 24"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect <-- silly backgrounds figma adds in
|
||||
width="24"
|
||||
height="24"
|
||||
fill="#1E1E1E"
|
||||
/>
|
||||
<path <-- silly backgrounds figma adds in
|
||||
d="M-20439
|
||||
-11141C-20439..."
|
||||
fill="#404040"
|
||||
/>
|
||||
<path
|
||||
d="M-20437 -11142H12131V-11144H-20437V-11142ZM12132 ...."
|
||||
fill="white"
|
||||
fill-opacity="0.1"
|
||||
/>
|
||||
<path
|
||||
d="M22.8437 8.69499L19.5369 12.0018L22.8438 15.3086..."
|
||||
stroke="#EDEDED"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<rect
|
||||
x="0.5"
|
||||
y="14.0625"
|
||||
width="16"
|
||||
height="8"
|
||||
rx="1"
|
||||
stroke="#EDEDED"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
<rect
|
||||
x="0.5"
|
||||
y="1.9375"
|
||||
width="16"
|
||||
height="8"
|
||||
rx="1"
|
||||
stroke="#EDEDED"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
```
|
||||
|
||||
✅ Good example
|
||||
|
||||
We've now cleaned it up, and the parent SVG element now has all the attributes for color and stroke width styling.
|
||||
We have also removed the redundant elements that figma adds in like background / artboard backgrounds.
|
||||
|
||||
```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"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
>
|
||||
<path d="M-20439 -11141C-20439..." />
|
||||
<path d="M-20437 -11142H12131V-11144H-20437V-11142ZM12132 ...."/>
|
||||
<path d="M22.8437 8.69499L19.5369 12.0018L22.8438 15.3086..." />
|
||||
<rect x="0.5" y="14.0625" width="16" height="8" rx="1" />
|
||||
<rect x="0.5" y="1.9375" width="16" height="8" rx="1" />
|
||||
</svg>
|
||||
```
|
||||
For detailed instructions, examples, and troubleshooting, see the [Design System](../../apps/design-system/content/docs/icons.mdx).
|
||||
|
||||
@@ -44,6 +44,26 @@ export const Index: Record<string, any> = [
|
||||
svg: "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" stroke=\"currentColor\"\n stroke-width=\"1\">\n <path\n d=\"M5.24121 15.0674H12.7412M5.24121 15.0674V18.0674H12.7412V15.0674M5.24121 15.0674V12.0674H12.7412V15.0674M15 7.60547V4.60547C15 2.94861 13.6569 1.60547 12 1.60547C10.3431 1.60547 9 2.94861 9 4.60547V7.60547M5.20898 9.60547L5.20898 19.1055C5.20898 20.21 6.10441 21.1055 7.20898 21.1055H16.709C17.8136 21.1055 18.709 20.21 18.709 19.1055V9.60547C18.709 8.5009 17.8136 7.60547 16.709 7.60547L7.20899 7.60547C6.10442 7.60547 5.20898 8.5009 5.20898 9.60547Z\" />\n</svg>",
|
||||
jsx: "import { Auth } from \"icons\"\n <Auth/>\n "
|
||||
},
|
||||
{
|
||||
name: "bucket-add",
|
||||
componentName: "BucketAdd",
|
||||
deprecated: false,
|
||||
raw: "import createSupabaseIcon from '../createSupabaseIcon';\n\n/**\n * @component @name BucketAdd\n * @description Supabase SVG icon component, renders SVG Element with children.\n *\n * @preview \n *\n * @param {Object} props - Supabase icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst BucketAdd = createSupabaseIcon('BucketAdd', [\n [\n 'path',\n {\n d: 'M6 7C6 4.2 8.2 2 11 2H13C15.8 2 18 4.2 18 7',\n stroke: 'currentColor',\n 'stroke-width': '1.5',\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n key: '9nyc2k',\n },\n ],\n [\n 'path',\n {\n d: 'M4.5 11H19.5',\n stroke: 'currentColor',\n 'stroke-width': '1.5',\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n key: 'fq7r7q',\n },\n ],\n [\n 'path',\n {\n d: 'M6 11L6.8 20C6.9 21.1 7.9 22 9 22H12',\n stroke: 'currentColor',\n 'stroke-width': '1.5',\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n key: 'f9mz1i',\n },\n ],\n [\n 'path',\n {\n d: 'M18 15.0249V22.0249',\n stroke: 'currentColor',\n 'stroke-width': '1.5',\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n key: '7kgnjd',\n },\n ],\n [\n 'path',\n {\n d: 'M14.5 18.5249H21.5',\n stroke: 'currentColor',\n 'stroke-width': '1.5',\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n key: '4i9ntd',\n },\n ],\n]);\n\nexport default BucketAdd;\n",
|
||||
component: React.lazy(() => import('icons/src/icons/bucket-add')),
|
||||
import: "import { BucketAdd } from 'icons'",
|
||||
svg: "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n<path d=\"M6 7C6 4.2 8.2 2 11 2H13C15.8 2 18 4.2 18 7\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n<path d=\"M4.5 11H19.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n<path d=\"M6 11L6.8 20C6.9 21.1 7.9 22 9 22H12\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n<path d=\"M18 15.0249V22.0249\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n<path d=\"M14.5 18.5249H21.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n</svg>\n",
|
||||
jsx: "import { BucketAdd } from \"icons\"\n <BucketAdd/>\n "
|
||||
},
|
||||
{
|
||||
name: "bucket",
|
||||
componentName: "Bucket",
|
||||
deprecated: false,
|
||||
raw: "import createSupabaseIcon from '../createSupabaseIcon';\n\n/**\n * @component @name Bucket\n * @description Supabase SVG icon component, renders SVG Element with children.\n *\n * @preview \n *\n * @param {Object} props - Supabase icons props and any valid SVG attribute\n * @returns {JSX.Element} JSX Element\n *\n */\nconst Bucket = createSupabaseIcon('Bucket', [\n [\n 'path',\n {\n d: 'M6 7C6 4.2 8.2 2 11 2H13C15.8 2 18 4.2 18 7',\n stroke: 'currentColor',\n 'stroke-width': '1.5',\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n key: '9nyc2k',\n },\n ],\n [\n 'path',\n {\n d: 'M4.5 11H19.5',\n stroke: 'currentColor',\n 'stroke-width': '1.5',\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n key: 'fq7r7q',\n },\n ],\n [\n 'path',\n {\n d: 'M18 11L17.2 20C17.1 21.1 16.1 22 15 22H9C7.9 22 6.9 21.1 6.8 20L6 11',\n stroke: 'currentColor',\n 'stroke-width': '1.5',\n 'stroke-linecap': 'round',\n 'stroke-linejoin': 'round',\n key: 'nfdgw2',\n },\n ],\n]);\n\nexport default Bucket;\n",
|
||||
component: React.lazy(() => import('icons/src/icons/bucket')),
|
||||
import: "import { Bucket } from 'icons'",
|
||||
svg: "<svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n<path d=\"M6 7C6 4.2 8.2 2 11 2H13C15.8 2 18 4.2 18 7\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n<path d=\"M4.5 11H19.5\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n<path d=\"M18 11L17.2 20C17.1 21.1 16.1 22 15 22H9C7.9 22 6.9 21.1 6.8 20L6 11\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n</svg>\n",
|
||||
jsx: "import { Bucket } from \"icons\"\n <Bucket/>\n "
|
||||
},
|
||||
{
|
||||
name: "database",
|
||||
componentName: "Database",
|
||||
|
||||
@@ -33,6 +33,33 @@ export const toKebabCase = (string: string) =>
|
||||
.toLowerCase()
|
||||
.trim()
|
||||
|
||||
/**
|
||||
* Converts kebab-case string to camelCase
|
||||
* @param {string} string
|
||||
* @returns {string} A camelCased string
|
||||
*/
|
||||
export const toCamelCase = (string: string) =>
|
||||
string.replace(/-([a-z])/g, (_, letter) => letter.toUpperCase()).trim()
|
||||
|
||||
/**
|
||||
* Converts kebab-case attributes to camelCase for React compatibility
|
||||
* @param {Record<string, string>} attrs
|
||||
* @returns {Record<string, string>} Attributes with camelCase keys
|
||||
*/
|
||||
export const convertAttributesToCamelCase = (
|
||||
attrs: Record<string, string>
|
||||
): Record<string, string> => {
|
||||
const converted: Record<string, string> = {}
|
||||
|
||||
for (const [key, value] of Object.entries(attrs)) {
|
||||
// Convert kebab-case to camelCase, but keep some special cases
|
||||
const camelKey = key.includes('-') ? toCamelCase(key) : key
|
||||
converted[camelKey] = value
|
||||
}
|
||||
|
||||
return converted
|
||||
}
|
||||
|
||||
const createLucideIcon = (iconName: string, iconNode: IconNode): LucideIcon => {
|
||||
const Component = forwardRef<SVGSVGElement, LucideProps>(
|
||||
(
|
||||
@@ -62,7 +89,9 @@ const createLucideIcon = (iconName: string, iconNode: IconNode): LucideIcon => {
|
||||
...rest,
|
||||
},
|
||||
[
|
||||
...iconNode.map(([tag, attrs]) => createElement(tag, attrs)),
|
||||
...iconNode.map(([tag, attrs]) =>
|
||||
createElement(tag, convertAttributesToCamelCase(attrs))
|
||||
),
|
||||
...(Array.isArray(children) ? children : [children]),
|
||||
]
|
||||
)
|
||||
|
||||
71
packages/icons/src/icons/bucket-add.ts
Normal file
71
packages/icons/src/icons/bucket-add.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
import createSupabaseIcon from '../createSupabaseIcon';
|
||||
|
||||
/**
|
||||
* @component @name BucketAdd
|
||||
* @description Supabase SVG icon component, renders SVG Element with children.
|
||||
*
|
||||
* @preview 
|
||||
*
|
||||
* @param {Object} props - Supabase icons props and any valid SVG attribute
|
||||
* @returns {JSX.Element} JSX Element
|
||||
*
|
||||
*/
|
||||
const BucketAdd = createSupabaseIcon('BucketAdd', [
|
||||
[
|
||||
'path',
|
||||
{
|
||||
d: 'M6 7C6 4.2 8.2 2 11 2H13C15.8 2 18 4.2 18 7',
|
||||
stroke: 'currentColor',
|
||||
'stroke-width': '1.5',
|
||||
'stroke-linecap': 'round',
|
||||
'stroke-linejoin': 'round',
|
||||
key: '9nyc2k',
|
||||
},
|
||||
],
|
||||
[
|
||||
'path',
|
||||
{
|
||||
d: 'M4.5 11H19.5',
|
||||
stroke: 'currentColor',
|
||||
'stroke-width': '1.5',
|
||||
'stroke-linecap': 'round',
|
||||
'stroke-linejoin': 'round',
|
||||
key: 'fq7r7q',
|
||||
},
|
||||
],
|
||||
[
|
||||
'path',
|
||||
{
|
||||
d: 'M6 11L6.8 20C6.9 21.1 7.9 22 9 22H12',
|
||||
stroke: 'currentColor',
|
||||
'stroke-width': '1.5',
|
||||
'stroke-linecap': 'round',
|
||||
'stroke-linejoin': 'round',
|
||||
key: 'f9mz1i',
|
||||
},
|
||||
],
|
||||
[
|
||||
'path',
|
||||
{
|
||||
d: 'M18 15.0249V22.0249',
|
||||
stroke: 'currentColor',
|
||||
'stroke-width': '1.5',
|
||||
'stroke-linecap': 'round',
|
||||
'stroke-linejoin': 'round',
|
||||
key: '7kgnjd',
|
||||
},
|
||||
],
|
||||
[
|
||||
'path',
|
||||
{
|
||||
d: 'M14.5 18.5249H21.5',
|
||||
stroke: 'currentColor',
|
||||
'stroke-width': '1.5',
|
||||
'stroke-linecap': 'round',
|
||||
'stroke-linejoin': 'round',
|
||||
key: '4i9ntd',
|
||||
},
|
||||
],
|
||||
]);
|
||||
|
||||
export default BucketAdd;
|
||||
49
packages/icons/src/icons/bucket.ts
Normal file
49
packages/icons/src/icons/bucket.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import createSupabaseIcon from '../createSupabaseIcon';
|
||||
|
||||
/**
|
||||
* @component @name Bucket
|
||||
* @description Supabase SVG icon component, renders SVG Element with children.
|
||||
*
|
||||
* @preview 
|
||||
*
|
||||
* @param {Object} props - Supabase icons props and any valid SVG attribute
|
||||
* @returns {JSX.Element} JSX Element
|
||||
*
|
||||
*/
|
||||
const Bucket = createSupabaseIcon('Bucket', [
|
||||
[
|
||||
'path',
|
||||
{
|
||||
d: 'M6 7C6 4.2 8.2 2 11 2H13C15.8 2 18 4.2 18 7',
|
||||
stroke: 'currentColor',
|
||||
'stroke-width': '1.5',
|
||||
'stroke-linecap': 'round',
|
||||
'stroke-linejoin': 'round',
|
||||
key: '9nyc2k',
|
||||
},
|
||||
],
|
||||
[
|
||||
'path',
|
||||
{
|
||||
d: 'M4.5 11H19.5',
|
||||
stroke: 'currentColor',
|
||||
'stroke-width': '1.5',
|
||||
'stroke-linecap': 'round',
|
||||
'stroke-linejoin': 'round',
|
||||
key: 'fq7r7q',
|
||||
},
|
||||
],
|
||||
[
|
||||
'path',
|
||||
{
|
||||
d: 'M18 11L17.2 20C17.1 21.1 16.1 22 15 22H9C7.9 22 6.9 21.1 6.8 20L6 11',
|
||||
stroke: 'currentColor',
|
||||
'stroke-width': '1.5',
|
||||
'stroke-linecap': 'round',
|
||||
'stroke-linejoin': 'round',
|
||||
key: 'nfdgw2',
|
||||
},
|
||||
],
|
||||
]);
|
||||
|
||||
export default Bucket;
|
||||
@@ -2,6 +2,8 @@ export { default as RESTApi } from './REST-api';
|
||||
export { default as ExampleTemplate } from './_example-template';
|
||||
export { default as ApiDocs } from './api-docs';
|
||||
export { default as Auth } from './auth';
|
||||
export { default as BucketAdd } from './bucket-add';
|
||||
export { default as Bucket } from './bucket';
|
||||
export { default as Database } from './database';
|
||||
export { default as Datadog } from './datadog';
|
||||
export { default as EdgeFunctions } from './edge-functions';
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"$schema": "../icon.schema.json",
|
||||
"contributors": ["it-is-not", "jguddas", "danielbayley", "ericfennis"],
|
||||
"tags": ["letter", "font size", "text", "formatting", "smaller"],
|
||||
"categories": ["text", "design"]
|
||||
}
|
||||
7
packages/icons/src/raw-icons/bucket-add.svg
Normal file
7
packages/icons/src/raw-icons/bucket-add.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" 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" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M4.5 11H19.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M6 11L6.8 20C6.9 21.1 7.9 22 9 22H12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M18 15.0249V22.0249" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M14.5 18.5249H21.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 736 B |
5
packages/icons/src/raw-icons/bucket.svg
Normal file
5
packages/icons/src/raw-icons/bucket.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" 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" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M4.5 11H19.5" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M18 11L17.2 20C17.1 21.1 16.1 22 15 22H9C7.9 22 6.9 21.1 6.8 20L6 11" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 529 B |
Reference in New Issue
Block a user