๐ฆนโโ๏ธ Twin blends the magic of Tailwind with the flexibility of css-in-js (emotion, styled-components, solid-styled-components, stitches and goober) at build time.
MIT License
Bot releases are hidden (Show)
Published by ben-rogerson about 1 year ago
Not a fan of the virtual dom?
Try Twin's new SolidJS preset ๐
Read more at #817
Published by ben-rogerson over 1 year ago
Note: Twin will now autoload a tailwind.config.ts
config file if found when a tailwind.config.[.js/.cjs]
doesn't exist.
// tailwind.config.ts
// generate with: `npx tailwindcss init --ts`
import type { Config } from 'tailwindcss'
export default {
content: ['*'],
theme: {
extend: {},
},
plugins: [],
} satisfies Config
// tailwind.config.js
// generate with: `npx tailwindcss init --esm`
/** @type {import('tailwindcss').Config} */
export default {
content: ['*'],
theme: {
extend: {},
},
plugins: [],
}
// Classic tailwind.config.js for comparison
// generate with: `npx tailwindcss init`
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ['*'],
theme: {
extend: {},
},
plugins: [],
}
Published by ben-rogerson over 1 year ago
๐ This version adds support for [email protected] - enjoy!
Read the official tailwind release notes for info on all the new goodies.
Install twin and tailwind latest:
npm i -D twin.macro@latest tailwindcss@latest
pnpm i -D twin.macro@latest tailwindcss@latest
yarn add -D twin.macro@latest tailwindcss@latest
Published by ben-rogerson almost 2 years ago
@apply
support in plugins #770@screen
ย inability to grab complexย theme.screensย values #763 - Thanks @minzojianpieces.some is not a function
ย error #767Published by ben-rogerson almost 2 years ago
This patch contains a fix for stitches:
animation-x
classes #758And mostly fixes for arbitrary variant usage:
[@page]:m-0
#759Reminder: Update tailwind to latest also or you'll probably see a pieces.some is not a function
error:
# `[email protected]` requires `tailwindcss@>=3.2.0`
npm i twin.macro@latest tailwindcss@latest
Published by ben-rogerson almost 2 years ago
aria-xxx
, data-xxx
and min-xxx
- check the official tailwindcss release posts for more infotailwindcss
to peerDependencies
tailwindcss
tailwind.config.js
https://github.com/ben-rogerson/twin.macro/pull/693
not-
versions of many common variants, eg: not-empty:
,:not-focus:
,:not-required:
ref
tailwind.config.js
config
- more at docs/config
tailwind.config.cjs
has been added as a fallback https://github.com/ben-rogerson/twin.macro/commit/9e7a7df14d0e254350af7ec08d9b6e5a5689d4b0
!
prefix on groups, eg: first:!(block mt-5)
hasLogColors: false
to remove log coloring https://github.com/ben-rogerson/twin.macro/commit/bbaec9d490cabf6b6cfd23b484d3fb10a743621c
The new tailwind-container-queries plugin works with twin but there are some browser and version requirements:
debugPlugins
was removed and rolled into another existing option: debug: true
container
has been aligned with tailwind - no longer has a custom margin valueTwins custom "short css" has been deprecated in favour of Tailwind arbitrary properties:
tw`backgroundColor[red]` // short css (no dash next to the `[`)
tw`[backgroundColor:red]` // Updated to an arbitrary property
In Emotion, using before:
or after:
variants may trigger a console error like this:
You seem to be using a value for 'content' without quotes, try replacing it with `content: '"var(--tw-content)"'`
Update one or both of the packages below to avoid this error (version is when error was fixed):
In arbitrary variants/properties without parent selectors, Twin now needs to add the parent selector for you in order to create a compatible class to run through tailwindcss.
If twin miscalculates where the parent selector should be added then you'll need to add the parent selector yourself.
Twin now replaces all spaces with underscores in arbitrary variants, so to keep any underscores in the output we can escape them:
// Bad
<div class="[.header__menu]:block">...</div>
// Good
<div class="[.header\_\_menu]:block">...</div>
Previously in many instances, escaping required a double backslash before the character (\\
).
Now we'll only need a single backslash:
tw`after:content-['\a0']`
When theme is used within an arbitrary value or property and there is a DEFAULT value found, the theme value will now return the default value automatically:
// tailwind.config.js
module.exports = {
theme: { colors: { black: { DEFAULT: "redish" } } },
}
// Usage
tw`bg-[theme(colors.black)]` // Arbitrary value
tw`[background-color:theme(colors.black)]` // Arbitrary property
// โ โ โ โ โ โ
({ "backgroundColor": "redish" }); // < DEFAULT key returned
({ "backgroundColor": "redish" }); // < DEFAULT key returned
The theme import now won't return the DEFAULT
option automatically.
We can still select the DEFAULT value by specifying it, eg: themecolors.black.DEFAULT
.
This makes it possible to grab whole objects from the config without automatically returning the DEFAULT
value:
// tailwind.config.js
module.exports = {
theme: { colors: { black: { DEFAULT: "redish", another: 'greenish' } } },
}
// Usage
import { theme } from 'twin.macro'
theme`colors.black`
// โ โ โ โ โ โ
// Whole object returned
({
"DEFAULT": "redish",
"another": "greenish"
});
DaisyUI often styles their components based on classNames, eg: .btn.loading { ... }
This means in some situations we have to add classNames to the jsx element to add their modifier styling
Some discussion here and at #760
If you're noticing build issues after upgrading, try updating your Vite config with the updated build target:
optimizeDeps: {
esbuildOptions: {
target: "es2020",
},
},
If youโre kicking ass with twin - especially if youโre in a team - then please consider supporting this project.
It will really help out with the continued development of twin - cheers! ๐ป
A huge thanks and shout out to all the rc
contributors helping with features, fixes and bug testing over the past year - you folks are awesome ๐๐
@omaemae, @ChrisEbert, @Macksi, @atxiii, @mohammadsiyou, @MatthiasDunker, @lguima, @EduardoBautista, @HaidarEzio, @ajmnz
Full Changelog: https://github.com/ben-rogerson/twin.macro/compare/2.8.2...3.0.0
Published by ben-rogerson about 2 years ago
Install release candidate 5:
npm install twin.macro@rc
Published by ben-rogerson about 2 years ago
Minor rc release with a few patches:
Big thanks to everyone who has helped with testing ๐
Published by ben-rogerson about 2 years ago
Minor rc release with a couple small patches:
before:content-['...']
https://github.com/ben-rogerson/twin.macro/commit/a0c5a2d999d0a921c93ab5e535f2e7de2c95496a
Features and fixes
peerDependencies
meaning you can install new versions of tailwindcss as soon as they're releasedhasLogColors: false
added to your twin configPublished by ben-rogerson over 2 years ago
Install release candidate 3:
npm install twin.macro@rc
Features and fixes
!
prefix #702Published by ben-rogerson over 2 years ago
Release candidate 2 is ready for testing!
Help test the release with:
npm install twin.macro@rc
Features and fixes
[color:black]
) #700border-y
property #692Published by ben-rogerson over 2 years ago
Help out by testing the next major version of Twin:
npm install twin.macro@rc
Full Changelog: https://github.com/ben-rogerson/twin.macro/compare/2.8.2...3.0.0-rc.1
Published by ben-rogerson almost 3 years ago
This patch contains a few changes for those using the styled-components
preset.
โ ๏ธ Possible breaking changes
babel-plugin-styled-components
- Setup info โ
styled
import preset import "styled-components/macro"
to import "styled-components"
- More info โ
Edit: Try the new rc
with the latest changes npm i twin.macro@rc
Published by ben-rogerson about 3 years ago
The star feature of this release is the addition of a new variant that creates a custom selector for classes.
Usage is easy, just add the selector within square brackets and prefix it on any class (or round-bracketed set):
// Style child elements with the strong tag from the parent container
;<div tw="[strong]:text-red-500">
<strong>I'm red</strong>
</div>
Before this feature, the styling above would need help from the css prop:
// Style child elements with the strong tag from the parent container
;<div css={{ strong: tw`text-red-500` }}>
<strong>I'm red</strong>
</div>
There are a wide range of uses for Arbitrary Variants:
// Style the current element based on a theming/scoping className
;<body className="dark-theme">
<div tw="[.dark-theme &]:(bg-black text-white)">I'm dark theme</div>
</body>
// Add custom height queries
;<div tw="[@media (min-height: 800px)]:hidden">
I'm shown only on smaller window heights
</div>
// Add custom group selectors
;<button className="group" disabled>
<span tw="[.group:disabled &]:text-gray-500">I'm gray</span>
</button>
// Use custom at-rules like @supports
;<div tw="[@supports (display: grid)]:grid">I'm grid</div>
// Style the current element based on a dynamic className
;const Component = ({ isLarge }) => <div className={isLarge && 'is-large'} tw="text-base [&.is-large]:text-lg">...</div>
I hope you enjoy using this powerful feature!
<Menu.Item tw="block">
) (#534)bg-color
classes from trumping bg-opacity-x
classes (#552)peer
class is used as a tailwind class (#551):root
using addBase
in plugins (#521)container
class (#518)Published by ben-rogerson about 3 years ago
This release brings the same special features we all love from the Tailwind JIT release! (v2.2.0-2.2.7) ๐๐ฎ
As this is the same feature set as Tailwind, you can read some more information about each feature in the Tailwind release notes.
peer-*:
variants for styling sibling elements (PR)first-letter:
and first-line:
pseudo-elements (PR)selection:
for styling text selections (PR)marker:
for styling list markers (PR)autofill:
, in-range:
, out-of-range:
, first-letter:
, first-line:
, only:
, empty:
, selection:
, marker:
, rtl:
and ltr:
(PR)Check the variant config for a full list โ
Add a slash opacity value to set the opacity on any color classes:
tw`bg-black/50`
// โ โ โ โ โ โ
({
"backgroundColor": "rgba(0, 0, 0, 0.5)"
});
This slash value comes from your opacity setting in your tailwind config.
For custom slash opacity values, use square brackets:
tw`bg-black/[.22]`
tw`bg-black/[--my-opacity-variable]`
The "dash square bracket" syntax adds custom values on just about every dynamic class (like bg-[xxx]
, not block
):
tw`col-start-[73] placeholder-[#aabbcc] object-[50%]`
// โ โ โ โ โ โ
({
"gridColumnStart": "73",
"::placeholder": {
"--tw-placeholder-opacity": "1",
"color": "rgba(170, 187, 204, var(--tw-placeholder-opacity))"
},
"objectPosition": "50%"
});
This feature almost replace twin's "short css" feature but short css is still great for more obscure css as you can specify custom properties too:
tw`--my-var[red]`
tw`-webkit-gradient[gradient here]`
You can now specify border color and border width on a specific border direction:
// Colors
tw`border-t-gray-50`;
tw`border-b-red-500`;
// โ โ โ โ โ โ
({
"--tw-border-opacity": "1",
"borderTopColor": "rgba(249, 250, 251, var(--tw-border-opacity))"
});
({
"--tw-border-opacity": "1",
"borderBottomColor": "rgba(239, 68, 68, var(--tw-border-opacity))"
});
// Widths
tw`border-t-4`;
tw`border-b-4`;
// โ โ โ โ โ โ
({
"borderTopWidth": "4px"
});
({
"borderBottomWidth": "4px"
});
before:
and after:
variants now automatically add content: ''
(PR)No more requirement for the content
class every time we use pseudo classestransform
or filter
to make your actual transform or filter classes work (Possible breaking change - check Adams PR notes)transform-cpu
classThis class uses translateX
and translateY
instead of translate3d
which is added by transform-gpu
tw`caret-red-500`
)If youโre kicking ass with twin - especially if youโre in a team - then please consider becoming a sponsor.
It will really help out with the continued development of twin - cheers! ๐ป