Skip to content
This repository has been archived by the owner on Jul 13, 2023. It is now read-only.

anubra266/css-picons

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

64 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation


๐Ÿ˜Œ
css-picons



npm package npm  downloads NPM GitHub Repo stars

Use any icons with Pure CSS in CSS Panda

About

Use any icons with Pure CSS in CSS Panda. 'Twas Inspired by @unocss/preset-icons

Install

npm i -D @css-picons/config @iconify-json/[the-collection-you-want]

We use Iconify as our data source of icons. You need to install the corresponding iconset in devDependencies by following the @iconify-json/* pattern. For example, @iconify-json/mdi for Material Design Icons, @iconify-json/tabler for Tabler. You can refer to Icรดnes or Iconify for all the collections available.

If you prefer to install the all the icon sets available on Iconify at once (~130MB):

npm i -D @iconify/json

Even if you do this, only the ones used in your code will be packaged by panda. That's nice.

Configuration

In your panda.config.* file, import cssPicons from @css-picons/config, then add it to presets

import { cssPicons } from '@css-picons/config'
export default defineConfig({
  presets: [
    // ...
    cssPicons({
      // Specify all the icon sets you'll be using
      collections: ['mdi'],
    }),
  ],
})

Then make sure your theme is extendable, if you have configured it.

// panda.config.*
export default defineConfig({
  //...
  theme: {
    extend: {
      // ...
    },
  },
})

Usage

Now you can use it in your components in all the ways css-panda allows through the icon recipe which is exported from your design system. The icon name follows the format <collection>:<name>

import { icon } from '../panda/recipes'
return (
  <div
    className={cx(
      icon({ name: 'mdi:emoticon-happy' }),
      css({
        color: 'yellow.500',
        fontSize: '6xl',
      }),
    )}
  />
)

Result:

Usage in other ways

// A basic anchor icon from Phosphor icons
const className = icon({ name: 'ph:anchor-simple-thin' })
// An orange alarm from Material Design Icons
const className = cx(icon({ name: 'mdi:alarm' }), css({ color: 'orange.400' }))
// A large react logo
const className = cx(icon({ name: 'logos:react' }), css({ fontSize: '3xl' }))
// Sun in light mode, Moon in dark mode, from Carbon
const className = icon({ name: { base: 'carbon:sun', _dark: 'carbon:moon' } })
// Twemoji of laugh, turns to tear on hovering
const className = icon({
  name: {
    base: 'twemoji:grinning-face-with-smiling-eyes',
    _hover: 'twemoji:face-with-tears-of-joy',
  },
})

JSX

When using in jsx you might want to use it in a reusable component, in such cases you have to tell css-panda the name of the component so it can watch it when generating styles. An example:

function AppIcon(props: IconVariants) {
  return (
    <div
      className={cx(
        icon(props),
        css({
          fontSize: '6xl',
        }),
      )}
    />
  )
}
// Somewhere else
return <AppIcon name="mdi:emoticon-happy" />

You tell panda to watch the external component by using the jsx key in the config.

import { cssPicons } from '@css-picons/config'
export default defineConfig({
  presets: [
    // ...
    cssPicons({
      // ...
      jsx: 'AppIcon',
    }),
  ],
})

Note: Panda automatically tracks components named as the capitalized version of the identifier. e.g. If your identifier is daocons, a component called Daocons that consumes it will be automatically tracked. In this case, we automatically track components named Icon.

Identifier

By default, you export icon from recipes which is then consumed to render the icons. But you can change this in the config with the identifier key.

import { cssPicons } from '@css-picons/config'
export default defineConfig({
  presets: [
    // ...
    cssPicons({
      // ...
      identifier: 'cssIcon',
    }),
  ],
})

Then export and use the new identifier in your project instead.

import { cssIcon } from '../panda/recipes'
return (
  <div
    className={cx(
      cssIcon({ name: 'mdi:emoticon-happy' }),
      css({
        color: 'yellow.500',
        fontSize: '6xl',
      }),
    )}
  />
)

Extra Styles

You can provide extra styles to control the default behavior of the icons. You could make icons vertically aligned and inline by default by the following example:

import { cssPicons } from '@css-picons/config'
export default defineConfig({
  presets: [
    // ...
    cssPicons({
      // ...
      styles: {
        verticalAlign: 'middle',
        display: 'inline-block',
      },
    }),
  ],
})

Modes Overriding

By default, css-picons will choose the rendering modes automatically for each icon based on the icons' characteristics. You can read more in this blog post. In some cases, you may want to explicitly set the rendering modes for each icon.

  • ?bg for background-img - renders the icon as a background image
  • ?mask for mask - renders the icon as a mask image

For example, vscode-icons:file-type-light-pnpm, an icon with colors (the svg doesn't contain currentColor) that will be rendered as a background image. Use vscode-icons:file-type-light-pnpm?mask to render it as a mask image and bypass it's colors.

Default mode

You can also set the default mode in your config with the mode key. It's auto by default which means css-picons automatically selects a mode based on it's perception of the icon.

export default defineConfig({
  presets: [
    // ...
    cssPicons({
      // ...
      mode: 'mask',
    }),
  ],
})

Custom collections

You can also provide your own custom collections by passing a tuple.

The first item in the tuple is the collection's name.

The second can either be a function or an object.

Basic example

export default defineConfig({
  presets: [
    // ...
    cssPicons({
      // ...
      collections: [
        // ...
        [
          'custom',
          {
            circle: '<svg viewBox="0 0 120 120"><circle cx="60" cy="60" r="50"></circle></svg>',
          },
        ],
      ],
    }),
  ],
})

Then use it through the custom icon name:

import { icon } from '../panda/recipes'
return <div className={icon({ name: 'custom:circle' })} />

You can also provide a function that resolves to a string:

Read from file

export default defineConfig({
  presets: [
    // ...
    cssPicons({
      // ...
      collections: [
        // ...
        [
          'custom',
          {
            vite: () => fs.readFile('./public/vite.svg', 'utf-8'),
          },
        ],
      ],
    }),
  ],
})

Usage:

import { icon } from '../panda/recipes'
return <div className={icon({ name: 'custom:vite' })} />

Fetch icon svg from a remote server

// Native fetch is not defined in the node process
import fetch from 'node-fetch'

export default defineConfig({
  presets: [
    // ...
    cssPicons({
      // ...
      collections: [
        // ...
        [
          'solar',
          {
            'airbuds-outline': async () => {
              return await fetch('https://api.iconify.design/solar:airbuds-outline.svg?color=%23888888').then((res) =>
                res.text(),
              )
            },
          },
        ],
      ],
    }),
  ],
})

Usage:

import { icon } from '../panda/recipes'
return <div className={icon({ name: 'solar:airbuds-outline' })} />

Iconify JSON or function returning iconify JSON

import feIconsData from '@iconify-json/fe/icons.json'
import phIconsData from '@iconify-json/ph/icons.json'

export default defineConfig({
  presets: [
    // ...
    cssPicons({
      // ...
      collections: [
        // ...
        ['fe', feIconsData],
        ['ph', () => phIconsData],
      ],
    }),
  ],
})

Usage:

import { icon } from '../panda/recipes'
return <div className={icon({ name: 'fe:check-verified' })} />
return <div className={icon({ name: 'ph:alien' })} />

Dynamic import

export default defineConfig({
  presets: [
    // ...
    cssPicons({
      // ...
      collections: [
        // ...
        ['carbon', () => import('@iconify-json/carbon/icons.json').then((i) => i.default as any)],
      ],
    }),
  ],
})

Usage:

import { icon } from '../panda/recipes'
return <div className={icon({ name: 'carbon:build-tool' })} />

Fetch icons data from a remote server

// Native fetch is not defined in the node process

export default defineConfig({
  presets: [
    // ...
    cssPicons({
      // ...
      collections: [
        // ...
        [
          'circle-flags',
          async () => {
            //* fetch iconifyJson from a remote server:
            //! We use node-fetch package because we can't access the native fetch
            return await fetch(
              'https://raw.githubusercontent.com/iconify/icon-sets/master/json/circle-flags.json',
            ).then((res) => res.json())
          },
        ],
      ],
    }),
  ],
})

Usage:

import { icon } from '../panda/recipes'
return <div className={icon({ name: 'circle-flags:ng' })} />

Transforming icons

We provide a transform method which lets you transform icons when loading, for example adding fill attribute with currentColor.

export default defineConfig({
  presets: [
    // ...
    cssPicons({
      // ...
      transform(svg) {
        return svg.replace(/#fff/, 'currentColor')
      },
    }),
  ],
})

We also provide the collection and icon so you can streamline your transformations.

export default defineConfig({
  presets: [
    // ...
    cssPicons({
      // ...
      transform(svg) {
        // do not apply fill to this icons on this collection
        if (collection === 'custom' && icon === 'circle') return svg
        return svg.replace(/#fff/, 'currentColor')
      },
    }),
  ],
})