Skip to content

Instantly share code, notes, and snippets.

@adnanalbeda
Last active August 6, 2023 04:45
Show Gist options
  • Save adnanalbeda/5ad3e9fe5748bfcb2444610428574123 to your computer and use it in GitHub Desktop.
Save adnanalbeda/5ad3e9fe5748bfcb2444610428574123 to your computer and use it in GitHub Desktop.
TailwindPlugins
import flattenColorPalette from "tailwindcss/lib/util/flattenColorPalette";
import plugin from "tailwindcss/plugin";
const scrollGradientPlugin = plugin(
({ addUtilities, theme, e, matchUtilities }) => {
addUtilities({
".scroll-gradient-y": {
/* variants */
/* size */
"--tw-scroll-gradient-size": "8px",
"--tw-scroll-gradient-spread": "24px",
/* colors */
"--tw-scroll-gradient-more": "#00000050",
"--tw-scroll-gradient-bg": "#00000000",
"--tw-scroll-gradient-end": "var(--tw-scroll-gradient-bg)",
/* gradient style */
background:
"linear-gradient(var(--tw-scroll-gradient-end) 33%,#00000000)," +
"linear-gradient(#00000000, var(--tw-scroll-gradient-end) 66%) " +
"0 100%," +
"radial-gradient(farthest-side at 50% 0, var(--tw-scroll-gradient-more), var(--tw-scroll-gradient-bg))," +
"radial-gradient(farthest-side at 50% 100%,var(--tw-scroll-gradient-more),var(--tw-scroll-gradient-bg)) " +
"0 100%", // expand
backgroundRepeat: "no-repeat",
backgroundAttachment: "local, local, scroll, scroll",
backgroundSize:
"100% var(--tw-scroll-gradient-spread), " +
"100% var(--tw-scroll-gradient-spread), " +
"100% var(--tw-scroll-gradient-size), " +
"100% var(--tw-scroll-gradient-size)",
backgroundColor: "var(--tw-scroll-gradient-bg)",
},
});
addUtilities({
".scroll-gradient-sm": {
"--tw-scroll-gradient-size": "4px",
"--tw-scroll-gradient-spread": "12px",
},
".scroll-gradient-md": {
"--tw-scroll-gradient-size": "12px",
"--tw-scroll-gradient-spread": "36px",
},
".scroll-gradient-lg": {
"--tw-scroll-gradient-size": "16px",
"--tw-scroll-gradient-spread": "48px",
},
});
matchUtilities(
{
"scroll-gradient-more": (value) => ({
"--tw-scroll-gradient-more": value,
}),
},
{
values: flattenColorPalette(theme("colors")),
type: "color",
}
);
matchUtilities(
{
"scroll-gradient-bg": (value) => ({
"--tw-scroll-gradient-bg": value,
"--tw-scroll-gradient-end": value,
}),
},
{
values: flattenColorPalette(theme("colors")),
type: "color",
}
);
matchUtilities(
{
"scroll-gradient-end": (value) => ({
"--tw-scroll-gradient-end": value,
}),
},
{
values: flattenColorPalette(theme("colors")),
type: "color",
}
);
}
);
export default scrollGradientPlugin;
import plugin from "tailwindcss/plugin";
const selector = [
" ", // for all children and sub-children
">", // direct children
"~",
"+",
];
const pseudoVariants = [
// generic
"first-child",
"last-child",
"only-child",
"empty",
"first-of-type",
"last-of-type",
"only-of-type",
"hover",
"focus-within",
// Links
"link",
"visited",
// UI
"enabled",
"disabled",
"focus",
"focus-visible",
"active",
"read-only",
"checked",
"valid",
"invalid",
"in-range",
"out-of-range",
"required",
"optional",
];
const elementsTags = [
"a",
"abbr",
"acronym",
"address",
"applet",
"area",
"article",
"aside",
"audio",
"b",
"base",
"basefont",
"bdi",
"bdo",
"bgsound",
"big",
"blink",
"blockquote",
"body",
"br",
"button",
"canvas",
"caption",
"center",
"cite",
"code",
"col",
"colgroup",
"content",
"data",
"datalist",
"dd",
"decorator",
"del",
"details",
"dfn",
"dir",
"div",
"dl",
"dt",
"element",
"em",
"embed",
"fieldset",
"figcaption",
"figure",
"font",
"footer",
"form",
"frame",
"frameset",
"h1",
"h2",
"h3",
"h4",
"h5",
"h6",
"head",
"header",
"hgroup",
"hr",
"html",
"i",
"iframe",
"img",
"input",
"ins",
"isindex",
"kbd",
"keygen",
"label",
"legend",
"li",
"link",
"listing",
"main",
"map",
"mark",
"marquee",
"menu",
"menuitem",
"meta",
"meter",
"nav",
"nobr",
"noframes",
"noscript",
"object",
"ol",
"optgroup",
"option",
"output",
"p",
"param",
"plaintext",
"pre",
"progress",
"q",
"rp",
"rt",
"ruby",
"s",
"samp",
"script",
"section",
"select",
"shadow",
"small",
"source",
"spacer",
"span",
"strike",
"strong",
"style",
"sub",
"summary",
"sup",
"table",
"tbody",
"td",
"template",
"textarea",
"tfoot",
"th",
"thead",
"time",
"title",
"tr",
"track",
"tt",
"u",
"ul",
"var",
"video",
"wbr",
"xmp",
];
const elementSelectorValues = elementsTags.reduce(
(p, c) => {
p[c] = c;
return p;
},
{
DEFAULT: "*",
}
);
const selectorsPlugin = plugin(({ matchVariant, addVariant }) => {
for (let i = 0; i < selector.length; i++) {
if (!i) {
matchVariant(
"*",
(value) => {
return "& ".concat(value);
},
{
values: elementSelectorValues,
}
);
pseudoVariants.forEach((v) => {
matchVariant(
"*".concat(v),
(value) => {
return "& ".concat(value, ":", v);
},
{
values: elementSelectorValues,
}
);
});
} else {
matchVariant(
selector[i],
(value) => {
return "& ".concat(selector[i], " ", value);
},
{
values: elementSelectorValues,
}
);
pseudoVariants.forEach((v) => {
matchVariant(
selector[i].concat(v),
(value) => {
return "& ".concat(selector[i], " ", value, ":", v);
},
{
values: elementSelectorValues,
}
);
});
}
}
matchVariant(
"nth",
(value) => {
return `&:nth-child(${value})`;
},
{
values: {
DEFAULT: "n", // Default value for `nth:`
"2n": "2n", // `nth-2n:utility` will generate `:nth-child(2n)` CSS selector
"3n": "3n",
"4n": "4n",
"5n": "5n",
"6n": "6n",
"7n": "7n",
"8n": "8n",
"9n": "9n",
even: "even",
odd: "odd",
},
}
);
for (let i = 0; i < selector.length; i++) {
if (!i) {
matchVariant(
"*nth",
(value) => {
return "& ".concat(value, `:nth-child(${value})`);
},
{
values: elementSelectorValues,
}
);
} else {
matchVariant(
selector[i],
(value) => {
return "& ".concat(selector[i], " ", value);
},
{
values: elementSelectorValues,
}
);
pseudoVariants.forEach((v) => {
matchVariant(
selector[i].concat(v),
(value) => {
return "& ".concat(selector[i], " ", value, ":", v);
},
{
values: elementSelectorValues,
}
);
});
}
}
});
export default selectorsPlugin;
type ClassNames = string | string[];
type Key = string | number;
export type Recognize<K extends Key, V = ClassNames> = Partial<Record<K, V>>;
export const recognize = <T extends Key, V = ClassNames>(
value: Recognize<T, V>
) => value;
export const defineVariants = <K extends Key>(variants: Recognize<K>) =>
variants;
export type RecognizeSlot<K extends Key, SK extends Key> = Recognize<
SK,
Recognize<K, ClassNames>
>;
export const defineSlots = <K extends Key, SK extends Key>(
variants: RecognizeSlot<K, SK>
) => variants;
// === === === VARIANTS === === ===
export type SizeVariantKeys =
| 0
| "xs"
| "sm"
| "md"
| "lg"
| "xl"
| "2x"
| "3x"
| "4x"
| "5x"
| "6x"
| "7x"
| "8x";
export type SizeVariants<
T = ClassNames,
K extends Key = SizeVariantKeys
> = Recognize<K, T>;
export const defineSizeVariants = <
K extends Key = SizeVariantKeys,
V = ClassNames
>(
variants: SizeVariants<V, K>
) => variants;
export type StyleVariantKeys = "primary" | "secondary" | "tertiary";
export type StyleVariants<
T = ClassNames,
K extends Key = StyleVariantKeys
> = Recognize<K, T>;
export const defineStyleVariants = <
K extends Key = StyleVariantKeys,
V = ClassNames
>(
variants: StyleVariants<V, K>
) => variants;
export type ColorVariantKeys =
| StyleVariantKeys
| "accent"
| "brand"
| "success"
| "warning"
| "danger"
| "info"
| "light"
| "dark";
export type ColorVariants<
T = ClassNames,
K extends Key = ColorVariantKeys
> = Recognize<K, T>;
export const defineColorVariants = <
K extends Key = ColorVariantKeys,
V = ClassNames
>(
variants: ColorVariants<V, K>
) => variants;
// === === === SLOTS === === ===
export type SizeSlots<
K extends Key,
SK extends Key = SizeVariantKeys
> = RecognizeSlot<K, SK>;
export const defineSizeSlots = <
K extends Key,
SK extends Key = SizeVariantKeys
>(
variants: SizeSlots<K, SK>
) => variants;
export type StyleSlots<
K extends Key,
SK extends Key = StyleVariantKeys
> = RecognizeSlot<K, SK>;
export const defineStyleSlots = <
K extends Key,
SK extends Key = StyleVariantKeys
>(
variants: StyleSlots<K, SK>
) => variants;
export type ColorSlots<
K extends Key,
SK extends Key = ColorVariantKeys
> = RecognizeSlot<K, SK>;
export const defineColorSlots = <
K extends Key,
SK extends Key = ColorVariantKeys
>(
variants: ColorSlots<K, SK>
) => variants;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment