Description
Added in v3.2.0
Allows you to define components, using CSS-in-JS
Setup
tailwind.config.js
const { Components } = require('@area17/a17-tailwind-plugins');
module.exports = {
...
plugins: [Components],
theme: {
components: {
".rich-text": {
selectors: {
h2: "f-h2 mt-40",
h3: "f-h3 mt-40",
h4: "f-h4 mt-40",
p: "f-body mt-20",
ul: "f-body mt-20 list-disc pl-16",
"ul ul": "mt-0",
code: "inline-block f-code text-code bg-code px-4 py-2 mt-20",
"* code": "inline-block mt-0",
pre: "block mt-20 f-code text-code bg-code p-8 max-h-400 overflow-y-scroll",
"code + pre": "mt-0",
a: "text-accent underline",
"a:hover": "text-primary",
"a:focus": "text-primary",
hr: "border-tertiary my-40"
}
},
}
}
...
};
Config object keys
theme.components
is essentially a object of
selectors
. Each entry can either be set to a string of classes
to @apply
, or an object containing apply
,
attributes
, selectors
,
breakpoints
and variants
keys:
tailwind.config.js
selector: {
apply: "",
attributes: {},
selectors: {},
breakpoints: {}
}
Every child selector can also be set to a string of classes to
@apply
, or an object containing apply
,
attributes
, selectors
,
breakpoints
and variants
keys.
Comma separated values and psuedo selectors will also be correctly parsed:
tailwind.config.js
components: {
".rich-text, .wysiwyg": {
selectors: {
a: "text-accent underline",
"a:hover, a:focus": "text-primary"
}
},
}
Output
Using a config like:
tailwind.config.js
components: {
".rich-text": {
selectors: {
p: "f-body mt-20",
a: "text-accent underline",
"a:hover": "text-primary",
"a:focus": "text-primary",
}
},
}
You would get an output like:
app.css
.rich-text p {
margin-top: 1.25rem;
font-family: var(--sans);
font-size: 0.875rem;
line-height: 1.7;
-moz-osx-font-smoothing: grayscale;
-webkit-font-smoothing: antialiased;
--bold-weight: 600;
}
.rich-text p b, .rich-text p strong {
font-weight: var(--bold-weight);
font-weight: var(--bold-weight);
}
@media (min-width: 650px) {
.rich-text p {
font-size: 1rem;
}
}
.rich-text a {
color: var(--blue-03);
text-decoration: underline;
}
.rich-text a:hover {
color: var(--grey-90);
}
.rich-text a:focus {
color: var(--grey-90);
}
You could also style that link like:
tailwind.config.js
components: {
".rich-text": {
selectors: {
p: "f-body mt-20",
a: {
apply: "text-accent underline",
"selectors": {
":hover, :focus": "text-primary",
}
}
}
},
}
More complex example:
tailwind.config.js
components: {
".btn": {
apply: "f-body flex justify-center items-center m-0 border-2 appearance-none",
attributes: {
"--padding-x": "16px",
"--min-xy": "42px",
"--icon-xy": "24px",
"--icon-pad": "8px",
"min-width": "var(--min-xy)",
height: "var(--min-xy)",
"padding-right": "var(--padding-x)",
"padding-left": "var(--padding-x)",
"transition": "color 200ms ease-in-out, background-color 200ms ease-in-out, border 200ms ease-in-out"
},
breakpoints: {
lg: {
attributes: {
"--padding-x": "24px",
"--min-xy": "48px"
}
}
},
selectors: {
":hover": {
apply: "cursor-pointer"
},
"svg": {
apply: "inline-block"
}
},
"variants": {
"primary": {
attributes: {
"border-color": "var(--grey-90)",
"background-color": "var(--grey-54)",
color: "var(--white)"
},
selectors: {
":hover, :focus, :active": {
attributes: {
"background-color": "var(--grey-90)",
color: "var(--white)"
}
},
":focus, :active": {
attributes: {
"border-color": "var(--blue-05)"
}
},
":focus[data-focus-method='key']": {
attributes: {
"outline-color": "var(--blue-05) !important"
}
}
}
},
"secondary": {
attributes: {
"border-color": "var(--grey-90)",
"background-color": "var(--white)",
color: "var(--grey-90)"
},
selectors: {
":hover, :focus, :active": {
attributes: {
"background-color": "var(--grey-54)"
}
},
":focus, :active": {
attributes: {
"border-color": "var(--blue-05)"
}
},
":focus[data-focus-method='key']": {
attributes: {
"outline-color": "var(--blue-05) !important"
}
}
}
}
}
},
".rich-text": {
breakpoints: {
md: {
selectors: {
"> *:not(pre)": {
attributes: {
"max-width": "80%"
}
}
}
},
lg: {
selectors: {
"> *:not(pre)": {
attributes: {
"max-width": "60%"
}
}
}
}
},
selectors: {
h1: "f-h1",
h2: "f-h2 mt-40",
h3: "f-h3 mt-40",
h4: "f-h4 mt-40",
p: "f-body mt-20",
ul": "f-body mt-20 list-disc pl-16",
"ul ul": "mt-0",
code: "inline-block f-code text-code bg-code px-4 py-2 mt-20",
"* code": "inline-block mt-0",
pre: "block mt-20 f-code text-code bg-code p-8 max-h-400 overflow-y-scroll",
"code + pre": "mt-0",
a: {
apply: "text-accent underline",
selectors: {
":hover, :focus": {
apply: "text-primary"
}
}
},
hr: "border-tertiary my-40"
}
}
}
Your Tailwind build will error out if you @apply
classes that
aren't defined or if you use @screen
with breakpoints that
don't exist.
Note: this plugin doesn't attempt to validate your input.