-
-
Notifications
You must be signed in to change notification settings - Fork 102
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Docs]: Help wanted! #475
Comments
The first instruction states to "use the shim," but then later docs states that the shim is even not recommended. However, that same second docs do have explanations for using Shim Mode, Library Mode, Twind instance Mode, and more. Also, I am unsure if using the shim means I am on an older version? |
All is well-documented for use with Gatsby, Lit, Next.js, React, Remix, SvelteKit, and Web Components. But where is the documentation for vanilla JS? |
Hello there @cvladan, I also experienced the same frustrations at the beginning. Especially when the first docs I read about Twind is their old documentation until I found out there was another doc site for Twind. All latest features and best practices are laid out on that new site. You can follow usage of either the basic if your site can utilize javascript |
Can you provide an example of how to use twind in library mode. |
There is already a code sample in the docs that I linked, the idea is to create the usual twind config file. Then create another file that will use that twind config and export // twind.js
import {
twind,
virtual,
cssom,
tx as tx$,
injectGlobal as injectGlobal$,
keyframes as keyframes$,
} from '@twind/core'
// import the twind config
import config from './twind.config'
export const tw = /* #__PURE__ */ twind(
config,
typeof document === 'undefined' ? virtual() : cssom('style[data-library]'),
)
export const tx = /* #__PURE__ */ tx$.bind(tw)
export const injectGlobal = /* #__PURE__ */ injectGlobal$.bind(tw)
export const keyframes = /* #__PURE__ */ keyframes$.bind(tw) Then use it in your components: <script>
import { tw } from 'twind.js'
</script>
<h1 class="{tw`text-lg text-blue-500`}">Ahoy!</h1> This will generate the tailwind styles on runtime so no need to bundle up css during build. Users will also won't have access to the twind instance unless it is explicitly exported in package.json |
Is this vanilla JS without build tools? I need to improve some old HTML site. |
Twind CDN should work without any build tools, the steps in the docs are pretty straightforward. |
Thanks for the suggestion! However, I have already written several times, in the issue description and in the previous comment, that I'm actually interested in how to load it from my site, locally, not from CDN. I posted my implementation at the top loading it from unpkg.com, which is both ugly and not very elegant, but I'm shocked that not a single example shows a simple local deployment in vanilla JS. Twind's CDN is definitely not local. No need to worry. Apparently nobody really uses it, and it's going down that "abandoned" road. |
To load it locally in your site you need to build all the presets and your config into something like esbuild that will output the compiled and tree-shook Js. I run Twind from a compiled static Js on ALL my sites. I just use a super simple esbuild script. My script build logic looks like this: const esbuild = require('esbuild');
await esbuild.build({
entryPoints: ['_app.js'],
outfile: 'public/_assets/js/_app.js',
bundle: true,
minify: true,
sourcemap: false,
}); And here's a sample // twind
import { install, injectGlobal } from '@twind/core';
import presetAutoprefix from '@twind/preset-autoprefix';
import presetTailwind from '@twind/preset-tailwind';
import presetLineClamp from '@twind/preset-line-clamp';
install({
presets: [presetAutoprefix(), presetTailwind(), presetLineClamp()],
darkMode: 'class',
hash: false,
theme: {
screens: {
'sm': '640px',
'md': '768px',
'lg': '960px',
},
extend: {
colors: ({ theme }) => ({
brand: theme('colors.rose'),
}),
fontFamily: ({ theme }) => ({
sans: ['Inter', ...theme('fontFamily.sans')],
}),
},
},
rules: [
[ 'text-wrap-(unset|wrap|nowrap|balance)', 'textWrap' ],
],
});
injectGlobal`
@layer base {
hr { @apply border-gray-500/25; }
}
` This outputs the static Js and works great ALL my sites:
NOTE: These sites are ALL static HTML. The only build process is 11ty (njk -> html) and esbuild. You can also view the source of all these sites on GitHub from my profile repo list or from footer links on each individual site. P.S. <!doctype html>
<html lang="en" class="bg-transparent antialiased">
<head>
<meta charset="utf-8" />
<meta http-equiv="x-ua-compatible" content="ie=edge" />
<title>Twind + CDN + Auto Dark</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
<link href="https://fonts.gstatic.com" rel="preconnect" />
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@100..900&display=swap" rel="stylesheet" />
<script>
// color mode init
if (localStorage.getItem('color-mode') === 'dark' || (window.matchMedia('(prefers-color-scheme: dark)').matches && !localStorage.getItem('color-mode'))) {
document.documentElement.classList.add('dark');
}
</script>
</head>
<body class="bg-gray-50 text-gray-700 !block" style="display: none;">
<div id="app" class="min-h-screen flex-(& col)" x-cloak>
<header class="px-4 flex-none">
<div class="mx-auto border-(b gray-500/25) py-4 max-w-7xl">
<nav class="flex-(& col) items-center gap-3 md:(flex-row justify-between)">
<a href="#" class="text-brand-500"><iconify-icon icon="mdi:google-podcast" inline="false" class="iconify text-4xl"></iconify-icon></a>
<ul class="flex items-center gap-6">
<li><a href="#" class="motion-safe:(transition) hover:(text-brand-500)">Nav</a></li>
<li><a href="#" class="motion-safe:(transition) hover:(text-brand-500)">Nav</a></li>
<li>
<button class="color-mode text-xl flex items-center motion-safe:(transition) hover:(text-brand-500)" aria-label="Toggle color mode">
<span class="block dark:(hidden)"><iconify-icon icon="mdi:weather-sunny" inline="false" class="iconify"></iconify-icon> <span class="sr-only">Switch to dark mode</span></span>
<span class="hidden dark:(block)"><iconify-icon icon="mdi:weather-night" inline="false" class="iconify"></iconify-icon> <span class="sr-only">Switch to light mode</span></span>
</button>
</li>
</ul>
</nav>
</div>
</header>
<main class="py-8 px-4 flex-1 md:(py-16)">
<section class="mx-auto max-w-7xl">
<article class="space-y-8">
<h1 class="text-xl leading-tight font-black lg:(text-[calc(2.5vw)] tracking-tight)">Twind Example <small class="flex items-center gap-3 text-(base gray-400) tracking-normal font-bold before:(w-5 h-1 bg-current opacity-30 content-[''])">Module + CDN + Auto Dark</small></h1>
<p>Paragraph...</p>
<hr />
<p class="flex-(& wrap) items-center gap-2">
<span class="w-full">Some dynamic buttons:</span>
<a href="#" class="btn-brand">Brand</a>
<a href="#" class="btn-gray">Gray</a>
<a href="#" class="btn-rose">Rose</a>
</p>
</article>
</section>
</main>
<footer class="px-4 text-(gray-500 sm center) flex-none md:(text-end)">
<div class="mx-auto border-(t gray-500/25) py-4 max-w-7xl">Footer info</div>
</footer>
</div>
<script type="module">
// color mode
const toggleColorMode = function() {
if (document.documentElement.classList.contains('dark')) {
document.documentElement.classList.remove('dark');
localStorage.setItem('color-mode', 'light')
return;
}
document.documentElement.classList.add('dark');
localStorage.setItem('color-mode', 'dark');
};
document.querySelectorAll('.color-mode').forEach(btn => {
btn.addEventListener('click', toggleColorMode);
});
// icons
import 'https://esm.run/iconify-icon';
// twind
import { install, injectGlobal, autoDarkColor } from 'https://esm.run/@twind/core';
import presetAutoprefix from 'https://esm.run/@twind/preset-autoprefix';
import presetTailwind from 'https://esm.run/@twind/preset-tailwind';
install({
presets: [presetAutoprefix(), presetTailwind()],
darkMode: 'class',
darkColor: autoDarkColor,
hash: false,
theme: {
extend: {
colors: ({ theme }) => ({
brand: theme('colors.indigo'),
}),
fontFamily: ({ theme }) => ({
sans: ['Inter', ...theme('fontFamily.sans')],
}),
},
},
rules: [
['text-wrap-(unset|wrap|nowrap|balance)', 'textWrap'],
['btn-', ({ $$ }) => `py-1.5 px-3 bg-${$$}-200 text-${$$}-800 inline-flex items-center gap-1.5 rounded-md motion-safe:(transition) hover:(bg-${$$}-700 text-${$$}-50 ring-(4 ${$$}-500/50))`],
],
});
// global css
injectGlobal`
@layer base {
hr { @apply border-gray-500/25; }
}
`
</script>
</body>
</html> |
Thanks @craigerskine . Finally a proper answer. I was hoping that with the heaps of code they have, the Twind authors themselves could have made an esbuilt JS that I could just copy to my site. I guess vanilla JS isn't trendy anymore. Eh. |
You could probably use jsdelivr to pre-compile it for you using their examples as well: https://twind.style/installation#browser-usage Just grab the resulting code from this link and create your own local js file. Then you can adjust the config with syntax like this: <script>
twind.install({
presets: [twind.presetAutoprefix(/* options */), twind.presetTailwind(/* options */)],
/* tailwind config */
})
</script> |
Actually, the last one is not working. That's how I hit a wall initially, because it simply doesn't work. Just including the grabbed resulting code from jsdelivr and placing the local script into the head. Even from CDN I get errors... Can you try and test it, please?
In Firefox, error is little bit different: |
Yeah... seems like a bug with the tailwind preset. Since @sastan has been MIA for quite awhile now, it may not get fixed unless someone else picks up the reigns. You are really going out of your way to use Twind in a way it wasn't really intended to be used. It's way easier to just use the module syntax over esm/skypack cdn or compile it yourself. I understand you want something static, but you can use a SSG to get the same result, plus have a WAAAAY easier time dealing with Js packages and much cleaner source. |
@craigerskine what's your plans with v3.4 coming out? |
Honestly, I've built things with Twind v0 that will never need upgrading. Basic CSS stuff. I love some of the updates to Tailwind and v3 in general, but some of the stuff on the horizon I just do not need. I'm OK with just creating Twind rules to add stuff I might need. For example: // twind config
rules: [
// .text-wrap-balance
['text-wrap-(unset|wrap|nowrap|balance)', 'textWrap'],
] I feel like I can just use the existing Twind v1 for many many years. I'm hopeful that Tailwind will eventually switch to a CSS-in-JS model. They are already almost there with their CDN playground. It's only a matter of time. And with stuff like UnoCSS and MasterCSS breaking into this space, Tailwind will need to keep pace. I really hope Twind is not done though. The grouping syntax alone is just too good. |
Hey folks. This issue hasn't received any traction for 90 days, so we're going to close this for housekeeping. If this is still an ongoing issue, please do consider contributing a Pull Request to resolve it. Further discussion is always welcome even with the issue closed. If anything actionable is posted in the comments, we'll consider reopening it. ⓘ |
Documentation Is:
Confusing
Link to relevant page or pages
Everywhere
Please Explain in Detail...
Really. There are two sites with documentation, and both have a lot of conflicting information. Moreover, there is a discussion about the performance impact of loading - Notes on Twind runtime performance. And now, how can a person implement it simply?
All that is needed is a simple and straightforward way to render Tailwind CSS locally. What should I download, and how do I run it? It's really confusing. Why philosophize about Twind CDN and the like and skip the most basic vanilla JS application from the local?
This works when pulled from online, but I'm pretty sure it's not the most optimal version, and I don't see a way to copy these files locally and have them work.
Please, someone with more experience tell me. Simply, I want the same thing as above, but to load scripts locally - or one script if possible.
Which script should I download? There are 700 of them in 700 variations.
Maybe I'll give up.
It was supposed to be simple, but it turned out to be 100 times more complicated.
Help wanted!
Your Proposal for Changes
Dunno. Just to run away?
Alternatives considered
No response
The text was updated successfully, but these errors were encountered: