typed.tw
Typed Tailwind ·Typed Tailwind brings types to Tailwind CSS by generating TypeScript classes (example) whose methods let you use the utility classes generated from your Tailwind config:
Try it live at typed.tw!
Jump to: Why · Usage · Examples · FAQ · Credits · License
Why
I wanted to combine the 2 great things in Front End engineering nowadays: static typing and functional CSS. Turn out, they get along very well. The constraint and predictability of utilities classes makes them ideal candidates to be statically typed as methods of a TypeScript class.
Is it more than just code completion? Yes. Code completion is just suggestion. Static typing enforces the correctness of your code styling, so you can do things like defining better API, automated code refactoring, and errors (like using undefined colors) can be caught at compile time.
Usage
- Go to typed.tw (or typed-tailwind.com if you can't access .tw domain) and paste your Tailwind configuration into the first panel.
- Save the generated file in the second panel to your codebase.
- Import the
Tw
function from that file and use its (chain-able) methods:
// In practice, the file should be imported using absolute path
import { Tw } from "./tw";
const Foo = () => (
<p className={Tw().textBlue().fontBold().$()}>
Bold, blue text
</p>
);
Example usages:
- https://github.com/dvkndn/typed.tw/search?l=TSX&q=Tw%28%29
- https://github.com/dvkndn/otf.show/search?l=TSX&q=Tw%28%29
Compile time usage with Webpack
Above is a run time usage. It allows you to easily add Typed Tailwind to many projects and build systems (e.g. it works with CRA without ejecting). However, it has some problems:
- The bundled JS is bigger because it includes the whole generated TypeScript class that reflects all possible values from your Tailwind configuration, even if you don't use them.
- It's a little bit slower for users because class names are looked up and concatenated at run time.
- Other tools like PurgeCSS cannot process the code out of the box.
Therefore, we have a typed-tailwind-loader to apply all Tw()...$()
calls at compile time (as a part of your webpack build process, to be exact). This eliminates all 3 issues above.
- Learn more at the package folder.
- See a working example at examples/webpack.
Examples
- With Webpack: Please see the examples/webpack folder.
- With CRA: The typed.tw web app actually uses CRA itself. Its source code is in the web folder. Please see its style definition and a sample usage.
- With Next.js: The otf.show web app is a real-life open source project that uses Typed Tailwind and Next.js. Please see its style definition and a sample usage.
FAQ
- Where to put the generated file?
- Does it work without TypeScript?
- Does it work with PurgeCSS?
- Does it work with custom plugins?
- Does it work with custom classes?
- Is there any performance issue?
- The generated code style doesn't match ours. Can I reformat it?
Where to put the generated file?
The file should be imported from many places in your codebase so place it where you can take advantage of absolute imports. For example, if you are using CRA and your baseUrl
is the src
folder then you can place the file at src/tw/index.ts
.
import { Tw } from "tw";
Does it work without TypeScript?
Yes. You can always compile the generated file to JS, optionally with a declaration file:
tsc --declaration style.ts
This way, you still get full code completion, just no compile time type checking.
Does it work with PurgeCSS?
Yes. Please see Compile time usage with Webpack section. If you can't follow that, try remove unused values to reduce the bundled size.
Does it work with custom plugins?
It's not officially supported yet but could work if your plugins are defined as inline anonymous functions (like in the docs). Also see: Does it work with custom classes.
Does it work with custom classes?
Yes. The result is simply a source file, so feel free to modify it anyway you want:
// style.ts
class Tailwind {
/* ... */
// Add your custom ones:
textShadow(): Tailwind { return this.add("text-shadow"); }
}
Is there any performance issue?
Out of the box, maybe, because styling are applied at run-time, on render to be specific. However, you can use it at compile time to eliminate all of these issues.
If you can't modify your build config, or if you don't use webpack, it helps a little bit by moving the calls out of the renders. The work is still done at run time, but just once at start-up instead of every render.
const styles = Tw().fontBold().textBlue().$();
const Foo = () => <p className={styles} />;
The generated code style doesn't match ours. Can I reformat it?
Yes. The generated code should be checked into your source control so you can (and should) format it with your code formatter. In other words, just judge it as your own source code.
Credits
- @nhducit and @trungfinity for their help in the implementation design.
- anduin.design/style/ for the inspiration.
Alternatives
- re-tailwind Tailwind CSS in ReasonML
Simplify method chain
The current API calls are like this:
Would it be better to have something simpler.
The implementation could be done with Proxy.
Consider providing a cli for local generation
I set up a quick script to avoid using the web service:
Usage:
Maybe it would be handy to include something like this to
typed-tailwind-convert
?build(deps): bump postcss from 7.0.21 to 7.0.36
Bumps postcss from 7.0.21 to 7.0.36.
Release notes
Sourced from postcss's releases.
Changelog
Sourced from postcss's changelog.
Commits
67e3d7b
Release 7.0.36 version54cbf3c
Backport ReDoS vulnerabilities from PostCSS 812832f3
Release 7.0.35 version4455ef6
Use OpenCollective in fundinge867c79
Add migration guide to PostCSS 8 error32a22a9
Release 7.0.34 version2293982
Lock build targets2c3a111
Release 7.0.33 version4105f21
Use yaspeller instead of yaspeller-cic8d02a0
Revert yaspeller-ci removalDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase
.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebase
will rebase this PR@dependabot recreate
will recreate this PR, overwriting any edits that have been made to it@dependabot merge
will merge this PR after your CI passes on it@dependabot squash and merge
will squash and merge this PR after your CI passes on it@dependabot cancel merge
will cancel a previously requested merge and block automerging@dependabot reopen
will reopen this PR if it is closed@dependabot close
will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually@dependabot ignore this major version
will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this minor version
will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this dependency
will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)@dependabot use these labels
will set the current labels as the default for future PRs for this repo and language@dependabot use these reviewers
will set the current reviewers as the default for future PRs for this repo and language@dependabot use these assignees
will set the current assignees as the default for future PRs for this repo and language@dependabot use this milestone
will set the current milestone as the default for future PRs for this repo and languageYou can disable automated security fix PRs for this repo from the Security Alerts page.
Parse config with custom logic defined outside of module export
Test case: https://gist.github.com/dvkndn/ab434cae1ee42528723f05159172f69f
As far as I remember it's because typed.tw only parses the part inside module.export.. which is so wrong..
build(deps): bump terser from 4.3.9 to 4.8.1
Bumps terser from 4.3.9 to 4.8.1.
Changelog
Sourced from terser's changelog.
... (truncated)
Commits
Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase
.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebase
will rebase this PR@dependabot recreate
will recreate this PR, overwriting any edits that have been made to it@dependabot merge
will merge this PR after your CI passes on it@dependabot squash and merge
will squash and merge this PR after your CI passes on it@dependabot cancel merge
will cancel a previously requested merge and block automerging@dependabot reopen
will reopen this PR if it is closed@dependabot close
will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually@dependabot ignore this major version
will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this minor version
will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this dependency
will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)@dependabot use these labels
will set the current labels as the default for future PRs for this repo and language@dependabot use these reviewers
will set the current reviewers as the default for future PRs for this repo and language@dependabot use these assignees
will set the current assignees as the default for future PRs for this repo and language@dependabot use this milestone
will set the current milestone as the default for future PRs for this repo and languageYou can disable automated security fix PRs for this repo from the Security Alerts page.
build(deps): bump eventsource from 1.0.7 to 1.1.1
Bumps eventsource from 1.0.7 to 1.1.1.
Changelog
Sourced from eventsource's changelog.
Commits
aa7a408
1.1.156d489e
chore: rebuild polyfill4a951e5
docs: update history for 1.1.1f9f6416
fix: strip sensitive headers on redirect to different origin9dd0687
1.1.049497ba
Update history for 1.1.0 (#146)3a38537
Update history for #13646fe04e
Merge pull request #136 from icy-fish/master9a4190f
Fix issue: reconnection only happends for 1 time after connection drops61e1b19
test: destroy both proxied request and response on closeDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase
.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebase
will rebase this PR@dependabot recreate
will recreate this PR, overwriting any edits that have been made to it@dependabot merge
will merge this PR after your CI passes on it@dependabot squash and merge
will squash and merge this PR after your CI passes on it@dependabot cancel merge
will cancel a previously requested merge and block automerging@dependabot reopen
will reopen this PR if it is closed@dependabot close
will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually@dependabot ignore this major version
will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this minor version
will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this dependency
will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)@dependabot use these labels
will set the current labels as the default for future PRs for this repo and language@dependabot use these reviewers
will set the current reviewers as the default for future PRs for this repo and language@dependabot use these assignees
will set the current assignees as the default for future PRs for this repo and language@dependabot use this milestone
will set the current milestone as the default for future PRs for this repo and languageYou can disable automated security fix PRs for this repo from the Security Alerts page.
build(deps): bump async from 2.6.3 to 2.6.4
Bumps async from 2.6.3 to 2.6.4.
Changelog
Sourced from async's changelog.
Commits
c6bdaca
Version 2.6.48870da9
Update built files4df6754
update changelog8f7f903
Fix prototype pollution vulnerability (#1828)Maintainer changes
This version was pushed to npm by hargasinski, a new releaser for async since your current version.
Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase
.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebase
will rebase this PR@dependabot recreate
will recreate this PR, overwriting any edits that have been made to it@dependabot merge
will merge this PR after your CI passes on it@dependabot squash and merge
will squash and merge this PR after your CI passes on it@dependabot cancel merge
will cancel a previously requested merge and block automerging@dependabot reopen
will reopen this PR if it is closed@dependabot close
will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually@dependabot ignore this major version
will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this minor version
will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this dependency
will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)@dependabot use these labels
will set the current labels as the default for future PRs for this repo and language@dependabot use these reviewers
will set the current reviewers as the default for future PRs for this repo and language@dependabot use these assignees
will set the current assignees as the default for future PRs for this repo and language@dependabot use this milestone
will set the current milestone as the default for future PRs for this repo and languageYou can disable automated security fix PRs for this repo from the Security Alerts page.
build(deps): bump url-parse from 1.4.7 to 1.5.10
Bumps url-parse from 1.4.7 to 1.5.10.
Commits
8cd4c6c
1.5.10ce7a01f
[fix] Improve handling of empty port0071490
[doc] Update JSDoc commenta7044e3
[minor] Use more descriptive variable named547792
[security] Add credits for CVE-2022-0691ad23357
1.5.90e3fb54
[fix] Strip all control characters from the beginning of the URL61864a8
[security] Add credits for CVE-2022-0686bb0104d
1.5.8d5c6479
[fix] Handle the case where the port is specified but emptyDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase
.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebase
will rebase this PR@dependabot recreate
will recreate this PR, overwriting any edits that have been made to it@dependabot merge
will merge this PR after your CI passes on it@dependabot squash and merge
will squash and merge this PR after your CI passes on it@dependabot cancel merge
will cancel a previously requested merge and block automerging@dependabot reopen
will reopen this PR if it is closed@dependabot close
will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually@dependabot ignore this major version
will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this minor version
will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this dependency
will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)@dependabot use these labels
will set the current labels as the default for future PRs for this repo and language@dependabot use these reviewers
will set the current reviewers as the default for future PRs for this repo and language@dependabot use these assignees
will set the current assignees as the default for future PRs for this repo and language@dependabot use this milestone
will set the current milestone as the default for future PRs for this repo and languageYou can disable automated security fix PRs for this repo from the Security Alerts page.
build(deps): bump url-parse from 1.4.7 to 1.5.7
Bumps url-parse from 1.4.7 to 1.5.7.
Commits
8b3f5f2
1.5.7ef45a13
[fix] Readd the empty userinfo tourl.href
(#226)88df234
[doc] Add soft deprecation notice78e9f2f
[security] Fix nitse6fa434
[security] Add credits for incorrect handling of userinfo vulnerability4c9fa23
1.5.67b0b8a6
Merge pull request #223 from unshiftio/fix/at-sign-handling-in-userinfoe4a5807
1.5.5193b44b
[minor] Simplify whitespace regex319851b
[fix] Remove CR, HT, and LFDependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase
.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebase
will rebase this PR@dependabot recreate
will recreate this PR, overwriting any edits that have been made to it@dependabot merge
will merge this PR after your CI passes on it@dependabot squash and merge
will squash and merge this PR after your CI passes on it@dependabot cancel merge
will cancel a previously requested merge and block automerging@dependabot reopen
will reopen this PR if it is closed@dependabot close
will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually@dependabot ignore this major version
will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this minor version
will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this dependency
will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)@dependabot use these labels
will set the current labels as the default for future PRs for this repo and language@dependabot use these reviewers
will set the current reviewers as the default for future PRs for this repo and language@dependabot use these assignees
will set the current assignees as the default for future PRs for this repo and language@dependabot use this milestone
will set the current milestone as the default for future PRs for this repo and languageYou can disable automated security fix PRs for this repo from the Security Alerts page.
build(deps): bump follow-redirects from 1.9.0 to 1.14.8
Bumps follow-redirects from 1.9.0 to 1.14.8.
Commits
3d81dc3
Release version 1.14.8 of the npm package.62e546a
Drop confidential headers across schemes.2ede36d
Release version 1.14.7 of the npm package.8b347cb
Drop Cookie header across domains.6f5029a
Release version 1.14.6 of the npm package.af706be
Ignore null headers.d01ab7a
Release version 1.14.5 of the npm package.40052ea
Make compatible with Node 17.86f7572
Fix: clear internal timer on request abort to avoid leakage2e1eaf0
Keep Authorization header on subdomain redirects.Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase
.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebase
will rebase this PR@dependabot recreate
will recreate this PR, overwriting any edits that have been made to it@dependabot merge
will merge this PR after your CI passes on it@dependabot squash and merge
will squash and merge this PR after your CI passes on it@dependabot cancel merge
will cancel a previously requested merge and block automerging@dependabot reopen
will reopen this PR if it is closed@dependabot close
will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually@dependabot ignore this major version
will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this minor version
will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this dependency
will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)@dependabot use these labels
will set the current labels as the default for future PRs for this repo and language@dependabot use these reviewers
will set the current reviewers as the default for future PRs for this repo and language@dependabot use these assignees
will set the current assignees as the default for future PRs for this repo and language@dependabot use this milestone
will set the current milestone as the default for future PRs for this repo and languageYou can disable automated security fix PRs for this repo from the Security Alerts page.
build(deps): bump ajv from 6.10.2 to 6.12.6
Bumps ajv from 6.10.2 to 6.12.6.
Release notes
Sourced from ajv's releases.
Commits
fe59143
6.12.6d580d3e
Merge pull request #1298 from ajv-validator/fix-urlfd36389
fix: regular expression for "url" format490e34c
docs: link to v7-beta branch9cd93a1
docs: note about v7 in readme877d286
Merge pull request #1262 from b4h0-c4t/refactor-opt-object-typef1c8e45
6.12.5764035e
Merge branch 'ChALkeR-chalker/fix-comma'3798160
Merge branch 'chalker/fix-comma' of git://github.com/ChALkeR/ajv into ChALkeR...a3c7eba
Merge branch 'refactor-opt-object-type' of github.com:b4h0-c4t/ajv into refac...Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting
@dependabot rebase
.Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR:
@dependabot rebase
will rebase this PR@dependabot recreate
will recreate this PR, overwriting any edits that have been made to it@dependabot merge
will merge this PR after your CI passes on it@dependabot squash and merge
will squash and merge this PR after your CI passes on it@dependabot cancel merge
will cancel a previously requested merge and block automerging@dependabot reopen
will reopen this PR if it is closed@dependabot close
will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually@dependabot ignore this major version
will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this minor version
will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)@dependabot ignore this dependency
will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)@dependabot use these labels
will set the current labels as the default for future PRs for this repo and language@dependabot use these reviewers
will set the current reviewers as the default for future PRs for this repo and language@dependabot use these assignees
will set the current assignees as the default for future PRs for this repo and language@dependabot use this milestone
will set the current milestone as the default for future PRs for this repo and languageYou can disable automated security fix PRs for this repo from the Security Alerts page.