├── .gitignore ├── LICENSE ├── README.md ├── debug ├── .gitignore └── panda.config.ts ├── demo ├── .gitignore ├── app │ ├── globals.css │ ├── layout.tsx │ └── page.tsx ├── next-env.d.ts ├── package.json ├── panda.config.ts ├── pnpm-lock.yaml ├── postcss.config.cjs └── tsconfig.json ├── package.json ├── pnpm-lock.yaml ├── src ├── constants.ts ├── index.ts ├── preset.ts ├── recipe.ts ├── semantic-tokens.ts ├── tailwind.ts └── types.ts ├── tsconfig.json └── tsup.config.ts /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | node_modules 3 | .DS_Store -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Milan de Kruijf. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Downloads][npm-shield]][npm-url] 2 | [![Contributors][contributors-shield]][contributors-url] 3 | [![Forks][forks-shield]][forks-url] 4 | [![Stargazers][stars-shield]][stars-url] 5 | [![Issues][issues-shield]][issues-url] 6 | [![MIT License][license-shield]][license-url] 7 | [![LinkedIn][linkedin-shield]][linkedin-url] 8 | 9 | # 🐼 PandaCSS preset for typography 10 | 11 | A [🐼 PandaCSS](https://panda-css.com/) typography preset inspired by the [TailwindCSS typography plugin](https://tailwindcss.com/docs/typography-plugin) 12 | 13 | ## Installation 14 | 15 | ```bash 16 | npm install --save-dev pandacss-preset-typography 17 | ``` 18 | 19 | ## Usage 20 | 21 | Add the preset to your PandaCSS configuration (`panda.config.ts`) 22 | 23 | ```ts 24 | import { defineConfig } from "@pandacss/dev"; 25 | 26 | // Import the preset. The name can be anything you want 27 | import typographyPreset from "pandacss-preset-typography"; 28 | 29 | export default defineConfig({ 30 | presets: [ 31 | typographyPreset(), 32 | // Re-add the panda presets if you want to keep 33 | // the default keyframes, breakpoints, tokens 34 | // and textStyles provided by PandaCSS 35 | "@pandacss/dev/presets", 36 | ], 37 | }); 38 | ``` 39 | 40 | ## Prose 41 | 42 | The preset generates a `prose` recipe for you that you can use to add beautiful typographic defaults to any vanilla HTML you don’t control, like HTML rendered from Markdown, or pulled from a CMS. 43 | 44 | ### Usage 45 | 46 | You can provide 5 different sizes: `sm`, `base`, `lg`, `xl` and `2xl`. If you provide no options, the default size is set as `base` or as whatever you've set it as in the options. 47 | 48 | ```tsx 49 | // Import it from wherever you export panda to, also make sure 50 | // you change the name 'prose' if you've set a custom name. 51 | import { prose } from "@pandacss/out/recipes"; 52 | 53 | export function Page() { 54 | return
; 55 | } 56 | ``` 57 | 58 | ### Lead 59 | 60 | Just like in TailwindCSS, there's also an extra `.lead` class you can apply to any element within the scope of `prose` to get a nice lead paragraph. 61 | 62 | ### Options 63 | 64 | You can change the default options as shown below. 65 | 66 | ```ts 67 | ... 68 | presets: [ 69 | typographyPreset({ 70 | recipe: { 71 | // Name of the recipe export 72 | name: "prose", 73 | className: "prose", 74 | // Sizes you want to include 75 | sizes: ["sm", "base", "lg", "xl", "2xl"], 76 | defaultSize: "base", 77 | // Enable/disable not-prose functionality 78 | // just like in TailwindCSS 79 | notProse: false, 80 | // notProse: true, 81 | // notProse: { 82 | // className: "not-prose", 83 | // }, 84 | semanticTokens: { 85 | // defaults: true, 86 | defaults: { 87 | // Set a color palette to use for the defaults. 88 | // It only works with colors that have a numeric scale (11x) 89 | // from 50 to 950. (50, 100, 200, ..., 800, 900, 950). 90 | colorPalette: "slate", 91 | }, 92 | // The prefix to use for semantic tokens. 93 | // ex: --colors-18 | Until now, trying to style an article, document, or blog post with 19 | Tailwind has been a tedious task that required a keen eye for typography 20 | and a lot of complex custom CSS. 21 |
22 |23 | By default, Tailwind removes all of the default browser styling from 24 | paragraphs, headings, lists and more. This ends up being really useful 25 | for building application UIs because you spend less time undoing 26 | user-agent styles, but when you really are just trying to style 27 | some content that came from a rich-text editor in a CMS or a markdown 28 | file, it can be surprising and unintuitive. 29 |
30 |31 | We get lots of complaints about it actually, with people regularly 32 | asking us things like: 33 |
34 |35 |41 |36 | Why is Tailwind removing the default styles on my
40 |h1
{" "} 37 | elements? How do I disable this? What do you mean I lose all the other 38 | base styles too? 39 |
42 | We hear you, but we're not convinced that simply disabling our base
43 | styles is what you really want. You don't want to have to remove
44 | annoying margins every time you use a p
element in a piece
45 | of your dashboard UI. And I doubt you really want your blog posts to use
46 | the user-agent styles either — you want them to look awesome,
47 | not awful.
48 |
50 | The @tailwindcss/typography
plugin is our attempt to give
51 | you what you actually want, without any of the downsides of
52 | doing something stupid like disabling our base styles.
53 |
55 | It adds a new prose
class that you can slap on any block of
56 | vanilla HTML content and turn it into a beautiful, well-formatted
57 | document:
58 |
60 |
74 |
75 | 76 | For more information about how to use the plugin and the features it 77 | includes,{" "} 78 | 79 | read the documentation 80 | 81 | . 82 |
83 |86 | What follows from here is just a bunch of absolute nonsense I've written 87 | to dogfood the plugin itself. It includes every sensible typographic 88 | element I could think of, like bold text, unordered 89 | lists, ordered lists, code blocks, block quotes,{" "} 90 | and even italics. 91 |
92 |It's important to cover all of these use cases for a few reasons:
93 |Now we're going to try out another header style.
104 |106 | So that's a header for you — with any luck if we've done our job 107 | correctly that will look pretty reasonable. 108 |
109 |Something a wise person once told me about typography is:
110 |111 |116 |112 | Typography is pretty important if you don't want your stuff to look 113 | like trash. Make it good then it won't be bad. 114 |
115 |
117 | It's probably important that images look okay here by default as well: 118 |
119 |131 | Now I'm going to show you an example of an unordered list to make sure 132 | that looks good, too: 133 |
134 |And that's the end of this section.
140 |143 | Sometimes you have headings directly underneath each other. In those 144 | cases you often have to undo the top margin on the second heading 145 | because it usually looks better for the headings to be closer together 146 | than a paragraph followed by a heading should be. 147 |
148 |150 | When a heading comes after a paragraph, we need a bit more space, like I 151 | already mentioned above. Now let's see what a more complex list would 152 | look like. 153 |
154 |157 | 158 | I often do this thing where list items have headings. 159 | 160 |
161 |162 | For some reason I think this looks cool which is unfortunate because 163 | it's pretty annoying to get the styles right. 164 |
165 |166 | I often have two or three paragraphs in these list items, too, so 167 | the hard part is getting the spacing between the paragraphs, list 168 | item heading, and separate list items to all make sense. Pretty 169 | tough honestly, you could make a strong argument that you just 170 | shouldn't write this way. 171 |
172 |175 | Since this is a list, I need at least two items. 176 |
177 |178 | I explained what I'm doing already in the previous list item, but a 179 | list wouldn't be a list if it only had one item, and we really want 180 | this to look realistic. That's why I've added this second list item 181 | so I actually have something to look at when writing the styles. 182 |
183 |186 | It's not a bad idea to add a third item either. 187 |
188 |189 | I think it probably would've been fine to just use two items but 190 | three is definitely not worse, and since I seem to be having no 191 | trouble making up arbitrary things to type, I might as well include 192 | it. 193 |
194 |197 | After this sort of list I usually have a closing statement or paragraph, 198 | because it kinda looks weird jumping right to a heading. 199 |
200 |202 | I think most people are going to use{" "} 203 | highlight.js or{" "} 204 | Prism or something if they want to 205 | style their code blocks but it wouldn't hurt to make them look{" "} 206 | okay out of the box, even with no syntax highlighting. 207 |
208 |
209 | Here's what a default tailwind.config.js
file looks like at
210 | the time of writing:
211 |
213 |
214 | {`module.exports = {
215 | purge: [],
216 | theme: {
217 | extend: {},
218 | },
219 | variants: {},
220 | plugins: [],
221 | }`}
222 |
223 |
224 | Hopefully that looks good enough to you.
225 |227 | Nested lists basically always look bad which is why editors like Medium 228 | don't even let you do it, but I guess since some of you goofballs are 229 | going to do it we have to carry the burden of at least making it work. 230 |
231 |
274 | The most annoying thing about lists in Markdown is that{" "}
275 | <li>
elements aren't given a child{" "}
276 | <p>
tag unless there are multiple paragraphs in the
277 | list item. That means I have to worry about styling that annoying
278 | situation too.
279 |
283 | For example, here's another nested list. 284 |
285 |But this time with a second paragraph.
286 |<p>
tags
289 | 295 | But in this second top-level list item, they will. 296 |
297 |298 | This is especially annoying because of the spacing on this 299 | paragraph. 300 |
301 |
304 | As you can see here, because I've added a second line, this list
305 | item now has a <p>
tag.
306 |
This is the second line I'm talking about by the way.
308 |Finally here's another list item so it's more like a list.
311 |A closing list item, but with no nested list, because why not?
316 |And finally a sentence to close off this section.
319 |321 | I almost forgot to mention links, like{" "} 322 | 323 | this link to the Tailwind CSS website 324 | 325 | . We almost made them blue but that's so yesterday, so we went with dark 326 | gray, feels edgier. 327 |
328 |We even included table styles, check it out:
329 |Wrestler | 333 |Origin | 334 |Finisher | 335 |
---|---|---|
Bret "The Hitman" Hart | 340 |Calgary, AB | 341 |Sharpshooter | 342 |
Stone Cold Steve Austin | 345 |Austin, TX | 346 |Stone Cold Stunner | 347 |
Randy Savage | 350 |Sarasota, FL | 351 |Elbow Drop | 352 |
Vader | 355 |Boulder, CO | 356 |Vader Bomb | 357 |
Razor Ramon | 360 |Chuluota, FL | 361 |Razor's Edge | 362 |
366 | We also need to make sure inline code looks good, like if I wanted to
367 | talk about <span>
elements or tell you the good news
368 | about @tailwindcss/typography
.
369 |
code
in headings
372 | 374 | Even though it's probably a bad idea, and historically I've had a hard 375 | time making it look good. This{" "} 376 | "wrap the code blocks in backticks" trick works pretty well 377 | though really. 378 |
379 |
380 | Another thing I've done in the past is put a code
tag
381 | inside of a link, like if I wanted to tell you about the{" "}
382 |
383 | tailwindcss/docs
384 | {" "}
385 | repository. I don't love that there is an underline below the backticks
386 | but it is absolutely not worth the madness it would require to avoid it.
387 |
h4
yet
390 |
392 | But now we have. Please don't use h5
or h6
in
393 | your content, Medium only supports two heading levels for a reason, you
394 | animals. I honestly considered using a before
{" "}
395 | pseudo-element to scream at you if you use an h5
or{" "}
396 | h6
.
397 |
399 | We don't style them at all out of the box because h4
{" "}
400 | elements are already so small that they are the same size as the body
401 | copy. What are we supposed to do with an h5
, make it{" "}
402 | smaller than the body copy? No thanks.
403 |
h4
elements,
407 | either.
408 | 410 | Phew, with any luck we have styled the headings above this text and they 411 | look pretty good. 412 |
413 |414 | Let's add a closing paragraph here so things end with a decently sized 415 | block of text. I can't explain why I want things to end that way but I 416 | have to assume it's because I think things will look weird or unbalanced 417 | if there is a heading too close to the end of the document. 418 |
419 |420 | What I've written here is probably long enough, but adding this final 421 | sentence can't hurt. 422 |
423 |424 | Please press Ctrl + Shift + R to 425 | re-render an MDN page. 426 |
427 |