Skip to content

Latest commit

 

History

History
186 lines (149 loc) · 5.4 KB

icons.md

File metadata and controls

186 lines (149 loc) · 5.4 KB

Custom Icons

You can provide custom sidebar & header icons for your stories. Page stories can also provide iconized navigation tabs.

PhoenixStorybook gives you the ability to render icons with 2 different providers:

  • FontAwesome which offers a decent set of free icons and a lot of additional styles with paid plans
  • HeroIcons wich offer hundreds of free high quality icons
  • Local which offers the ability to use locally defined icons within the application

Declaring an icon

Whenever you provide an icon to the storybook, you should follow the following structure:

{icon_provider, icon_name, :icon_style, additional_css_classes}

# or for local icons, which don't support :icon_style
{icon_provider, icon_name, additional_css_classes}

The two last tuple elements are optional.

{:fa, "book"} # note that the FontAwesome icon name omits the fa- prefix
{:fa, "book", :solid} # same than previous one, :solid is the default style
{:fa, "skull", :duotone} # only for FontAwesome paid users
{:fa, "skull", :duotone, "psb-px-2"}
{:hero, "cake"} # for all HeroIcons
{:hero, "cake", :outline} # same than previous one, :outline is the default style
{:hero, "cake", :outline, "psb-w-2 psb-h-2"}
{:local, "hero-cake"} # for custom or core-component-generated icons
{:local, "hero-cake", "psb-w-2 psb-h-2"}, # styles are not supported: 3rd elem is custom css

FontAwesome icons

PhoenixStorybook is built with a very small subset of FontAwesome free icons. If you want to use other FontAwesome icons you need to provide a valid FontAwesome kit id.

When configuring your kit, please make sure you pick Web Fonts & CSS Only options.

It can be either free or paid, so you also need to configure your FontAwesome plan.

# lib/my_app_web/storybook.ex
defmodule MyAppWeb.Storybook do
  use PhoenixStorybook,
    otp_app: :my_app,
    font_awesome_plan: :pro, # default value is :free
    font_awesome_kit_id: "foo8b41bar4625",
end

HeroIcons

HeroIcons are supported in two flavors: by using heroicons_elixir or directly using heroicons CSS resources.

heroicons_elixir

Add heroicons dependency in your mix.exs file.

defp deps do
  [
    {:heroicons, "~> 0.5.0"}
  ]
end

You can now use whichever HeroIcon icon you want, based on the library function names.

{:hero, "cake"} # for all HeroIcons
{:hero, "cake", :outline} # same than previous one, :outline is the default style
{:hero, "cake", :outline, "psb-w-2 psb-h-2"}

heroicons CSS

Phoenix framework now encourages the use of Heroicons as raw CSS classes rather than relying on an Elixir package.

Put tailwindlabs/heroicons dependency in your mix file:

defp deps do
  [
    {
      :heroicons,
      github: "tailwindlabs/heroicons",
      tag: "v2.2.0",
      sparse: "optimized",
      app: false,
      compile: false,
      depth: 1
    }
  ]
end

and declare a plugin in tailwind.config.js:

plugins: [
  plugin(function ({ matchComponents, theme }) {
    let iconsDir = path.join(__dirname, "../deps/heroicons/optimized");
    let values = {};
    let icons = [
      ["", "/24/outline"],
      ["-solid", "/24/solid"],
      ["-mini", "/20/solid"],
      ["-micro", "/16/solid"],
    ];
    icons.forEach(([suffix, dir]) => {
      fs.readdirSync(path.join(iconsDir, dir)).forEach((file) => {
        let name = path.basename(file, ".svg") + suffix;
        values[name] = { name, fullPath: path.join(iconsDir, dir, file) };
      });
    });
    matchComponents(
      {
        hero: ({ name, fullPath }) => {
          let content = fs
            .readFileSync(fullPath)
            .toString()
            .replace(/\r?\n|\r/g, "");
          let size = theme("spacing.6");
          if (name.endsWith("-mini")) {
            size = theme("spacing.5");
          } else if (name.endsWith("-micro")) {
            size = theme("spacing.4");
          }
          return {
            [`--hero-${name}`]: `url('data:image/svg+xml;utf8,${content}')`,
            "-webkit-mask": `var(--hero-${name})`,
            mask: `var(--hero-${name})`,
            "mask-repeat": "no-repeat",
            "background-color": "currentColor",
            "vertical-align": "middle",
            display: "inline-block",
            width: size,
            height: size,
          };
        },
      },
      { values }
    );
  }),
],

Then you can use Heroicons as local icons:

{:local, "hero-cake"} # for custom or core-component-generated icons
{:local, "hero-cake", "psb-w-2 psb-h-2"}, # styles are not supported: 3rd

Local

Use whichever icons you want, as long as they can be rendered via a span class tag.

{:local, "my-icon", "psb-w-2 psb-h-2"}

will be rendered as:

<span class="my-icon psb-w-2 psb-h-2"></span>

Custom CSS

The last tuple argument is an optional CSS class list you can pass to improve icon rendering. Since the icon is rendered within the storybook layout, and not within your components sandbox, you should use CSS classes supported by the storybook.

  • any psb-w-* or psb-h-* class (TailwindCSS classes for height & width prefixed by psb-)
  • any psb-p-* or psb-m-* class (padding & margin)
  • any psb-text-color-###
  • any fa-* (FontAwesome modifiers)