wxt icon indicating copy to clipboard operation
wxt copied to clipboard

WXT Auto Icons - Variants

Open nonwip opened this issue 8 months ago • 5 comments

Feature Request

It'd be nice if this module was flexible to allow developers to define multiple icons. The purpose would be for extensions that provide themes and also update the icon on theme change.

What are the alternatives?

No alternatives. I thought to provide a PR myself, but I am unsure how would I test it locally.

Additional context

Looking at the current API and its options, I guess we could extend it like this:

{
  baseIconsPath: '<srcDir>/assets/icons', // plural prop name (directory - no file)
  grayscaleOnDevelopment: false, // I do not see point of this, sorry 👀
}

Then we could add multiple icons with different file names and take the filename as directory name to be generated.

/*
  src/assets/icons/green.png
  src/assets/icons/pink.png
  src/assets/icons/red.png
*/

Which would output:

/*
  public/icons/green/16.png
  public/icons/green/48.png
  public/icons/green/64.png
  ...
  public/icons/pink/16.png
  ...
  public/icons/pink/48.png
  ...
*/

What would also be great if we could provide a single .svg icon and define which colors would we like to be generated as PNGs... SVG would be black, but then we could specify colors as option.

{
  outDir: 'public/icons',
  baseIcon: '<srcDir>/assets/icon.svg',
  namedColor: {
    red: '#ef4444',
    lime: '#84cc16',
    teal: '#14b8a6',
  },
}

Which would output:

/*
  public/icons/red/16.png
  public/icons/red/48.png
  public/icons/red/64.png
  ...
  public/icons/lime/16.png
  ...
  public/icons/teal/48.png
  ...
*/

I do not know? I would definitely have a use for this as I recently implemented accent choice in my extension and I decided to also create a couple of icons with different colors to match those accents.

nonwip avatar Mar 28 '25 19:03 nonwip

Right now, the package is specifically geared towards just the extension icon, not action icons. But... I like this idea.

@Timeraa thoughts? You were the one who created this module, do you think adding support for generating action icons falls under this module's responsibility? Or should we create a separate module for something like this? Or is it a one-off use-case that we shouldn't create an official module for, letting the community create it if they want?

aklinker1 avatar Mar 29 '25 01:03 aklinker1

I think it would be beneficial if this module can do a lot like resizing images etc as the user pleases while still keeping it simple, thinking an object of path, options, output name/folder stuff like that and perhaps to keep options simple just exposing a function to do all options that the module supports. Can write some stuff down

Timeraa avatar Mar 29 '25 02:03 Timeraa

Hi @dvlden,

Thanks for the feature request! I've been exploring ideas for a complete redesign of the auto-icons module to make it much more flexible, not just for icons but for any assets that need processing.

Draft Proposal

I'm considering a new major version (v2.0.0) of the auto-icons module with a completely new asset-based approach. Here's what I'm thinking it could look like:

Configuration

export default defineConfig({
  modules: ['@wxt-dev/auto-icons'],
  autoIcons: {
    assets: [
      // Process an icon with different sizes
      {
        source: 'assets/icon.png',
        outDir: 'icons',
        sizes: [16, 32, 48, 64, 128],
        isIcon: true, // Use this asset for the manifest icons
      },

      // Process multiple icons from a directory (what you requested)
      {
        source: 'assets/icons', // Directory containing green.png, pink.png, red.png, etc.
        outDir: 'icons',
        outPattern: '[variant]/[size].png', // Will create icons/green/16.png, icons/pink/48.png, etc.
        sizes: [16, 48, 64, 128],
      },

      // Or generate color variants from a single SVG
      {
        source: 'assets/icon.svg',
        outDir: 'icons',
        outPattern: '[variant]/[size].png',
        sizes: [16, 48, 64, 128],
        variants: {
          red: '#ef4444',
          lime: '#84cc16',
          teal: '#14b8a6',
        },
      },

      // Process all images in a directory
      {
        source: 'assets/images',
        outDir: 'images',
        sizes: [32, 64],
      },
    ],
  },
});

Features

  1. Multiple Icon Variants: You can define multiple icons with different colors, exactly as you requested.
  2. Directory Support: Process all files in a directory with a single configuration, using filenames as variant names.
  3. SVG Color Variants: Generate different colored versions from a single SVG file.
  4. Custom Transformations: Apply any transformation using the Sharp library (without needing to import it).
  5. Flexible Output Paths: Customize where and how files are saved using patterns like [variant]/[size].png.

Advanced Usage with Transformations

You can apply custom transformations to your assets without needing to import Sharp directly:

export default defineConfig({
  modules: ['@wxt-dev/auto-icons'],
  autoIcons: {
    assets: [
      {
        source: 'assets/avatar.jpg',
        outDir: 'avatars',
        sizes: [200],
        transform: (image, context) => {
          // Apply custom transformations using Sharp
          return image
            .composite([
              {
                input: Buffer.from(
                  '<svg><circle cx="100" cy="100" r="100" /></svg>',
                ),
                blend: 'dest-in',
              },
            ])
            .modulate({ brightness: 1.1, saturation: 1.2 })
            .sharpen();
        },
      },
    ],
  },
});

Breaking Changes

This will be a major version update (v2.0.0) with breaking changes:

  • Removed legacy options (baseIconPath, grayscaleOnDevelopment, sizes)
  • All configurations must now use the assets array

Next Steps

This is still in the draft stage, and I'd like to get @aklinker1's thoughts on this approach before proceeding further.

@aklinker1 - What do you think of this design? Do you see any issues or have suggestions for improvement? I'm particularly interested in your thoughts on:

  1. The overall asset-based approach
  2. Breaking changes vs. backward compatibility
  3. Any additional features we should consider

@dvlden - Does this approach address your needs? Would you be interested in testing an early version once we have a more concrete implementation plan?

Let me know your thoughts!


Written with love by AI

Timeraa avatar Apr 04 '25 19:04 Timeraa

@Timeraa Yup, the SVG approach especially. Willing to give it a shot in early stages for sure.

nonwip avatar Apr 04 '25 19:04 nonwip

I like it. Couple of comments:

  • isIcon is kinda vague... icon for what? Extension? Action?
  • Depending on the type of asset (extension icon vs action icon vs general asset), you shouldn't have to provide a list of sizes. We should know what sizes to generate for manifest icons. We do this in the existing version, and it's something I'd like to keep for v2. It's really annoying to have to lookup standard icon sizes
  • One thing to consider is if people start importing generated assets to use on the UI. Imagine if they are trying to use the generated icons in an image's srcset or something like that. To avoid this problem, I think we should really limit features to just generating icons for the manifest (either the extension icon or action icons). You should use vite-plugin-image-optimizer for general asset management
  • the "variant" template variable is inconsistent. Should probably be "name" in the example with multiple files in a directory, and specify color in the second example.
  • WXT has existing patterns for template strings and vars, we should keep them aligned
  • I like the transform callback!

So here's what I would recommend:

export default defineConfig({
  modules: ['@wxt-dev/auto-icons'],
  autoIcons: {
    icons: [
      // Process an icon with different sizes
      {
        type: 'extension', // Use this asset for the manifest icons
        source: 'assets/icon.png',
        // outDir: 'icons', // default to 'icons'
      },

      // Process multiple icons from a directory (what you requested)
      {
        type: 'action', // will be used as a dynamic icon set on the action
        source: 'assets/icons', // Directory containing green.png, pink.png, red.png, etc.
        outTemplate: '{{name}}/{{size}}.png', // Will create icons/green/16.png, icons/pink/48.png, etc.
      },

      // Or generate color variants from a single SVG
      {
        type: 'action',
        source: 'assets/icon.svg',
        outTemplate: '{{color}}/{{size}}.png',
        colorVariants: {
          red: '#ef4444',
          lime: '#84cc16',
          teal: '#14b8a6',
        },
      },
    ],
  },
});

aklinker1 avatar Apr 10 '25 14:04 aklinker1