'How to write a Tailwind class plugin that takes a palette colour as an optional parameter
I have this style:
box-shadow: 0 0 0 100px white inset;
But I don't want white
hard-coded in - I want to make a Tailwind plugin in my tailwind.config.js
called bg-shadow
that accepts the colour as an optional third argument, like so:
<input class="bg-shadow" /> <!-- defaults to white -->
<input class="bg-shadow-primary-500" /> <!-- specify the colour -->
Having read through the Tailwind docs on plugins, I am none the wiser as to how to achieve this!
Solution 1:[1]
You could do this with a pretty simple plugin using matchUtilities
and flattenColorPalette
.
In tailwind.config.js
:
const plugin = require("tailwindcss/plugin");
const { default: flattenColorPalette } = require("tailwindcss/lib/util/flattenColorPalette");
module.exports = {
...
plugins: [
plugin(({ matchUtilities, theme }) => {
matchUtilities(
{
"bg-shadow": (value) => ({
boxShadow: `0 0 0 100px ${value} inset`
})
},
{
values: flattenColorPalette(theme("colors")),
type: "color"
}
);
})
]
};
Solution 2:[2]
After studying this plugin (credit where credit's due) I have this now working as follows:
// tailwind.bg-shadow.plugin.js
const plugin = require("tailwindcss/plugin");
const formatShadow = (color) => `0 0 0 100px ${color} inset`;
module.exports = plugin.withOptions(
({className = "bg-shadow"} = {}) => {
return ({e, addUtilities, theme, variants}) => {
const colors = theme("colors");
const caretColors = Object.keys(colors).reduce((acc, key) => {
if (typeof colors[key] === "string") {
return {
...acc,
[`.${className}-${e(key)}`]: {
"box-shadow": formatShadow(colors[key])
},
};
}
const colorShades = Object.keys(colors[key]);
return {
...acc,
...colorShades.reduce(
(a, shade) => ({
...a,
[`.${className}-${e(key)}-${shade}`]: {
"box-shadow": formatShadow(colors[key][shade])
},
}),
{}
),
};
}, {});
addUtilities(caretColors, variants("bg-shadowColor"));
};
},
() => ({
variants: {caretColor: ["dark", "active"]},
})
);
And usage in tailwind.config.js
:
module.exports = {
...
plugins: [
require('./tailwind.bg-shadow.plugin')
],
}
Solution 3:[3]
There are a few ways for you to extend box shadow.
Easier without a plugin, just configuration
Demo: https://play.tailwindcss.com/2mrdK51h8U?file=config
boxShadow
property exists for you to extend.
module.exports = {
theme: {
extend: {
boxShadow: '0 0 0 100px white inset',
colors: {
'primary-500': '5px 5px 15px 5px rgba(0,0,0,0.42)',
}
// Or do it in one shot
// boxShadow: {
// DEFAULT: '0 0 0 100px white inset;',
// 'primary-500': '5px 5px 15px 5px rgba(0,0,0,0.42)',
// },
},
},
plugins: [],
}
You can either extend boxShadow
and colors
separately or do it in one shot as shown above.
The downside is that, you need to use shadow-*
prefix.
So let's check out the next option, using a plugin.
Using a plugin
Demo: https://play.tailwindcss.com/hJaWBntnq0?file=config
You can create a plugin that lets you or users to provide shadow colors.
matchUtilities lets you provide dynamic values (similar to addUtilities
) using custom colors.
The second arg for theme(themeName, defaultThemeValue)
is a default configuration you can provide in case users didn't provided their own.
const plugin = require('tailwindcss/plugin')
// This is in-case a user didn't extend `bgShadowColors`.
const defaultBgShadowColors = {
DEFAULT: '0 0 0 100px red inset',
'primary-100': '5px 5px 15px 5px rgba(0,0,0,0.12)',
'primary-200': '5px 5px 15px 5px rgba(0,0,0,0.20)',
'primary-300': '5px 5px 15px 5px rgba(0,0,0,0.22)',
'primary-400': '5px 5px 15px 5px rgba(0,0,0,0.32)',
'primary-500': '5px 5px 15px 5px rgba(0,0,0,0.42)',
'primary-600': '5px 5px 15px 5px rgba(0,0,0,0.62)',
'primary-700': '5px 5px 15px 5px rgba(0,0,0,0.82)',
}
const bgShadowPlugin = plugin(function ({ matchUtilities, theme }) {
// Refer to https://tailwindcss.com/docs/plugins#dynamic-utilities
matchUtilities(
{
'bg-shadow': (value) => ({
'box-shadow': value,
}),
},
// If user hasn't extended `bgShadowColors`, then use `defaultBgShadowColors`
{ values: theme('bgShadowColors', defaultBgShadowColors) }
)
})
module.exports = {
theme: {
extend: {
bgShadowColors: {
DEFAULT: '0 0 0 100px red inset',
'primary-100': '5px 5px 15px 5px rgba(0,0,0,0.12)',
'primary-200': '5px 5px 15px 5px rgba(0,0,0,0.20)',
'primary-300': '5px 5px 15px 5px rgba(0,0,0,0.22)',
'primary-400': '5px 5px 15px 5px rgba(0,0,0,0.32)',
'primary-500': '5px 5px 15px 5px rgba(0,0,0,0.42)',
'primary-600': '5px 5px 15px 5px rgba(0,0,0,0.62)',
'primary-700': '5px 5px 15px 5px rgba(0,0,0,0.82)',
},
},
},
plugins: [bgShadowPlugin],
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Chris Koelle |
Solution 2 | joshcomley |
Solution 3 | dance2die |