framework icon indicating copy to clipboard operation
framework copied to clipboard

tailwind

Open Fil opened this issue 1 year ago • 9 comments

Adds a tailwind plugin to esbuild.build for css files.

I could not find how to pass a custom configuration directly, so I'm currently creating an intermediate root/.observablehq/cache/tailwind.config.js to direct tailwind to the project files, so it can analyze the "content" that might contain relevant class names.

And you can use it like so in your page.md:

<div class="tw-rounded-xl tw-p-8 tw-text-lg tw-font-mono tw-bg-black tw-text-white">
  Hello, tailwind
</div>

This intermediate file imports {src}/tailwind.config.js if it exists, allowing the user to configure tailwind, for example by setting prefix: "".

Here's another example with a custom src/tailwind.config.js file:

/** @type {import('tailwindcss').Config} */
export default {
  theme: {
    colors: {
      "almost-white": "#fefefe",
      "bubble-gum": "#ff77e9",
    }
  },
  plugins: []
};

You can then use the new colors:

<div class="tw-rounded-xl tw-p-8 tw-text-lg tw-font-mono tw-bg-bubble-gum tw-text-almost-white">
  Hello, tailwind
</div>

The way tailwind works, is by scanning all the "content" files (in our case, the markdown, js, and page loaders), for strings that match its classnames, and then builds the corresponding styles.

TODO:

  • [ ] revise in light of v4 https://tailwindcss.com/blog/tailwindcss-v4
  • [x] figure out dark mode (using the "selector" strategy, I guess)
    • [ ] adopt an automatic "dark/light" class that reflects the color-scheme property (#1780)
  • [x] fix tests
  • [x] figure out hashing
    • [x] fix live preview
  • [ ] make the tailwind config part of the framework config
  • [ ] adopt tailwind’s grid? maybe slightly adapted?
  • [ ] customize breakpoints
    • [ ] use @container breakpoints, adapt to the true available size (depending on toc)
  • [ ] fix everything that is reset
    • [ ] h1…h6 (dirty patch for now)
    • [ ] lists
    • [ ] others?
  • [ ] add tests
  • [x] document

closes #595 supersedes #596

Fil avatar Oct 17 '24 10:10 Fil

Here's a solution for dark mode:

Add darkMode: ["variant", "&:where([class~=dark], [class~=dark] *)"] to the default tailwind config, then add a javascript class toggle on the root.

```js
document.querySelector("html").classList.toggle("dark", dark);
```

<div class="
  tw-bg-white dark:tw-bg-black
  tw-text-red-600 dark:tw-text-emerald-600
">
  TEST DARK MODE
</div>

it could be better (I think framework should add the darkclass on the root in parallel with the color-scheme property), but it works. The standard tailwind color classes work in dark mode out of the box, so that's good too.

We should also coordinate this with #1638

Fil avatar Oct 17 '24 13:10 Fil

Another thing to figure out is the hash. I don't think we want to update the css each time any md or js file changes… so maybe we have to watch all these files for changes in the list of statically analyzable "potential tailwind class names" that they contain.

Fil avatar Oct 19 '24 08:10 Fil

In preview we could generate a tailwind.css that is specific to just the current page (+ any imported local modules) rather than continuously trying to recompute it for the entire app.

mbostock avatar Oct 21 '24 20:10 mbostock

I've updated the logic a bit, now we have continuous updating of a separate tailwind.css

(It's still not limited to the current page, because I don't know how to pass an object configuration—it seems it only wants a file-based configuration).

I've had to blocklist the grid classes, since they conflict with ours. I guess it's going to be a fork in the road: continue with our own grid, or switch to tailwind's. The difference is that in tailwind you have to be explicit about your breakpoints.

Speaking of breakpoints we should make sure we use the same. DONE

Fil avatar Oct 25 '24 10:10 Fil

I've now tested tailwind plugins, it just works. For example,

yarn add --dev @tailwindcss/typography

then in docs/tailwind.config.js:

import typography from "@tailwindcss/typography";

export default {
  plugins: [ typography ]
};

Fil avatar Oct 25 '24 10:10 Fil

Do we need to change the default breakpoints for tailwind? Users may find that surprising.

CobusT avatar Oct 25 '24 19:10 CobusT

These are the breakpoints of framework, my assumption here is that users are working inside “main” so the reference for sizes is the width of main.

Here's a way to test:

## breakpoints

<ul>
  <li><span class="text-red-500">&lt;sm</span> (always on)</li>
  <li><span class="sm:text-red-500">sm</span></li>
  <li><span class="md:text-red-500">md</span></li>
  <li><span class="lg:text-red-500">lg</span></li>
  <li><span class="xl:text-red-500">xl</span></li>
</ul>

if we leave tailwind's breakpoints unchanged, these element light up at very "random" places.

(It's the same issue that the tailwindcss-container-queries plugin addresses.)

Fil avatar Oct 25 '24 19:10 Fil

These are the breakpoints of framework, my assumption here is that users are working inside “main” so the reference for sizes is the width of main.

That probably makes sense, then. If they want to reset it they can do that in their own config file, but this change is probably more good than unexpected :-)

CobusT avatar Oct 25 '24 20:10 CobusT

The reference is here, with an example showing the contorsions you have to do when you have a sidebar. https://v1.tailwindcss.com/docs/breakpoints

In our case it's even more complicated, because the space available to draw stuff (which I believe is what should drive the definitions of sm, md, lg), depends on whether the TOC is shown, and on the themes used (e.g. wide). And that's not only a function of css and the page width… I have a hunch that the @container approach might not be fully correct either because the toc is an aside, so we have to substract its width from the value. But we're already using this container for our own grids, so maybe I'm missing something?

(I don't like the way the TOC works, and the fact that it is not visible at all on smaller screens is also problematic, so it might be the final draw telling that we have to rewrite it with tailwind.)

Fil avatar Oct 25 '24 20:10 Fil