|
1 | 1 | import { describe, test } from 'vitest'
|
2 | 2 | import { compile } from '..'
|
3 | 3 | import plugin from '../plugin'
|
| 4 | +import { flattenColorPalette } from './flatten-color-palette' |
4 | 5 |
|
5 | 6 | const css = String.raw
|
6 | 7 |
|
@@ -230,6 +231,272 @@ test('Variants in CSS overwrite variants from plugins', async ({ expect }) => {
|
230 | 231 | `)
|
231 | 232 | })
|
232 | 233 |
|
| 234 | +describe('theme callbacks', () => { |
| 235 | + test('tuple values from the config overwrite `@theme default` tuple-ish values from the CSS theme', async ({ |
| 236 | + expect, |
| 237 | + }) => { |
| 238 | + let input = css` |
| 239 | + @theme default { |
| 240 | + --font-size-base: 0rem; |
| 241 | + --font-size-base--line-height: 1rem; |
| 242 | + --font-size-md: 0rem; |
| 243 | + --font-size-md--line-height: 1rem; |
| 244 | + --font-size-xl: 0rem; |
| 245 | + --font-size-xl--line-height: 1rem; |
| 246 | + } |
| 247 | + @theme { |
| 248 | + --font-size-base: 100rem; |
| 249 | + --font-size-md--line-height: 101rem; |
| 250 | + } |
| 251 | + @tailwind utilities; |
| 252 | + @config "./config.js"; |
| 253 | + ` |
| 254 | + |
| 255 | + let compiler = await compile(input, { |
| 256 | + loadConfig: async () => ({ |
| 257 | + theme: { |
| 258 | + extend: { |
| 259 | + fontSize: { |
| 260 | + base: ['200rem', { lineHeight: '201rem' }], |
| 261 | + md: ['200rem', { lineHeight: '201rem' }], |
| 262 | + xl: ['200rem', { lineHeight: '201rem' }], |
| 263 | + }, |
| 264 | + |
| 265 | + // Direct access |
| 266 | + lineHeight: ({ theme }) => ({ |
| 267 | + base: theme('fontSize.base[1].lineHeight'), |
| 268 | + md: theme('fontSize.md[1].lineHeight'), |
| 269 | + xl: theme('fontSize.xl[1].lineHeight'), |
| 270 | + }), |
| 271 | + |
| 272 | + // Tuple access |
| 273 | + typography: ({ theme }) => ({ |
| 274 | + '[class~=lead-base]': { |
| 275 | + fontSize: theme('fontSize.base')[0], |
| 276 | + ...theme('fontSize.base')[1], |
| 277 | + }, |
| 278 | + '[class~=lead-md]': { |
| 279 | + fontSize: theme('fontSize.md')[0], |
| 280 | + ...theme('fontSize.md')[1], |
| 281 | + }, |
| 282 | + '[class~=lead-xl]': { |
| 283 | + fontSize: theme('fontSize.xl')[0], |
| 284 | + ...theme('fontSize.xl')[1], |
| 285 | + }, |
| 286 | + }), |
| 287 | + }, |
| 288 | + }, |
| 289 | + |
| 290 | + plugins: [ |
| 291 | + plugin(function ({ addUtilities, theme }) { |
| 292 | + addUtilities({ |
| 293 | + '.prose': { |
| 294 | + ...theme('typography'), |
| 295 | + }, |
| 296 | + }) |
| 297 | + }), |
| 298 | + ], |
| 299 | + }), |
| 300 | + }) |
| 301 | + |
| 302 | + expect(compiler.build(['leading-base', 'leading-md', 'leading-xl', 'prose'])) |
| 303 | + .toMatchInlineSnapshot(` |
| 304 | + ":root { |
| 305 | + --font-size-base: 100rem; |
| 306 | + --font-size-md--line-height: 101rem; |
| 307 | + } |
| 308 | + .prose { |
| 309 | + [class~=lead-base] { |
| 310 | + font-size: 100rem; |
| 311 | + line-height: 201rem; |
| 312 | + } |
| 313 | + [class~=lead-md] { |
| 314 | + font-size: 200rem; |
| 315 | + line-height: 101rem; |
| 316 | + } |
| 317 | + [class~=lead-xl] { |
| 318 | + font-size: 200rem; |
| 319 | + line-height: 201rem; |
| 320 | + } |
| 321 | + } |
| 322 | + .leading-base { |
| 323 | + line-height: 201rem; |
| 324 | + } |
| 325 | + .leading-md { |
| 326 | + line-height: 101rem; |
| 327 | + } |
| 328 | + .leading-xl { |
| 329 | + line-height: 201rem; |
| 330 | + } |
| 331 | + " |
| 332 | + `) |
| 333 | + }) |
| 334 | +}) |
| 335 | + |
| 336 | +describe('theme overrides order', () => { |
| 337 | + test('user theme > js config > default theme', async ({ expect }) => { |
| 338 | + let input = css` |
| 339 | + @theme default { |
| 340 | + --color-red: red; |
| 341 | + } |
| 342 | + @theme { |
| 343 | + --color-blue: blue; |
| 344 | + } |
| 345 | + @tailwind utilities; |
| 346 | + @config "./config.js"; |
| 347 | + ` |
| 348 | + |
| 349 | + let compiler = await compile(input, { |
| 350 | + loadConfig: async () => ({ |
| 351 | + theme: { |
| 352 | + extend: { |
| 353 | + colors: { |
| 354 | + red: 'very-red', |
| 355 | + blue: 'very-blue', |
| 356 | + }, |
| 357 | + }, |
| 358 | + }, |
| 359 | + }), |
| 360 | + }) |
| 361 | + |
| 362 | + expect(compiler.build(['bg-red', 'bg-blue'])).toMatchInlineSnapshot(` |
| 363 | + ":root { |
| 364 | + --color-blue: blue; |
| 365 | + } |
| 366 | + .bg-blue { |
| 367 | + background-color: var(--color-blue, blue); |
| 368 | + } |
| 369 | + .bg-red { |
| 370 | + background-color: very-red; |
| 371 | + } |
| 372 | + " |
| 373 | + `) |
| 374 | + }) |
| 375 | + |
| 376 | + test('user theme > js config > default theme (with nested object)', async ({ expect }) => { |
| 377 | + let input = css` |
| 378 | + @theme default { |
| 379 | + --color-slate-100: #000100; |
| 380 | + --color-slate-200: #000200; |
| 381 | + --color-slate-300: #000300; |
| 382 | + } |
| 383 | + @theme { |
| 384 | + --color-slate-400: #100400; |
| 385 | + --color-slate-500: #100500; |
| 386 | + } |
| 387 | + @tailwind utilities; |
| 388 | + @config "./config.js"; |
| 389 | + @plugin "./plugin.js"; |
| 390 | + ` |
| 391 | + |
| 392 | + let compiler = await compile(input, { |
| 393 | + loadConfig: async () => ({ |
| 394 | + theme: { |
| 395 | + extend: { |
| 396 | + colors: { |
| 397 | + slate: { |
| 398 | + 200: '#200200', |
| 399 | + 400: '#200400', |
| 400 | + 600: '#200600', |
| 401 | + }, |
| 402 | + }, |
| 403 | + }, |
| 404 | + }, |
| 405 | + }), |
| 406 | + |
| 407 | + loadPlugin: async () => { |
| 408 | + return plugin(({ matchUtilities, theme }) => { |
| 409 | + matchUtilities( |
| 410 | + { |
| 411 | + 'hover-bg': (value) => { |
| 412 | + return { |
| 413 | + '&:hover': { |
| 414 | + backgroundColor: value, |
| 415 | + }, |
| 416 | + } |
| 417 | + }, |
| 418 | + }, |
| 419 | + { values: flattenColorPalette(theme('colors')) }, |
| 420 | + ) |
| 421 | + }) |
| 422 | + }, |
| 423 | + }) |
| 424 | + |
| 425 | + expect( |
| 426 | + compiler.build([ |
| 427 | + 'bg-slate-100', |
| 428 | + 'bg-slate-200', |
| 429 | + 'bg-slate-300', |
| 430 | + 'bg-slate-400', |
| 431 | + 'bg-slate-500', |
| 432 | + 'bg-slate-600', |
| 433 | + 'hover-bg-slate-100', |
| 434 | + 'hover-bg-slate-200', |
| 435 | + 'hover-bg-slate-300', |
| 436 | + 'hover-bg-slate-400', |
| 437 | + 'hover-bg-slate-500', |
| 438 | + 'hover-bg-slate-600', |
| 439 | + ]), |
| 440 | + ).toMatchInlineSnapshot(` |
| 441 | + ":root { |
| 442 | + --color-slate-100: #000100; |
| 443 | + --color-slate-300: #000300; |
| 444 | + --color-slate-400: #100400; |
| 445 | + --color-slate-500: #100500; |
| 446 | + } |
| 447 | + .bg-slate-100 { |
| 448 | + background-color: var(--color-slate-100, #000100); |
| 449 | + } |
| 450 | + .bg-slate-200 { |
| 451 | + background-color: #200200; |
| 452 | + } |
| 453 | + .bg-slate-300 { |
| 454 | + background-color: var(--color-slate-300, #000300); |
| 455 | + } |
| 456 | + .bg-slate-400 { |
| 457 | + background-color: var(--color-slate-400, #100400); |
| 458 | + } |
| 459 | + .bg-slate-500 { |
| 460 | + background-color: var(--color-slate-500, #100500); |
| 461 | + } |
| 462 | + .bg-slate-600 { |
| 463 | + background-color: #200600; |
| 464 | + } |
| 465 | + .hover-bg-slate-100 { |
| 466 | + &:hover { |
| 467 | + background-color: #000100; |
| 468 | + } |
| 469 | + } |
| 470 | + .hover-bg-slate-200 { |
| 471 | + &:hover { |
| 472 | + background-color: #200200; |
| 473 | + } |
| 474 | + } |
| 475 | + .hover-bg-slate-300 { |
| 476 | + &:hover { |
| 477 | + background-color: #000300; |
| 478 | + } |
| 479 | + } |
| 480 | + .hover-bg-slate-400 { |
| 481 | + &:hover { |
| 482 | + background-color: #100400; |
| 483 | + } |
| 484 | + } |
| 485 | + .hover-bg-slate-500 { |
| 486 | + &:hover { |
| 487 | + background-color: #100500; |
| 488 | + } |
| 489 | + } |
| 490 | + .hover-bg-slate-600 { |
| 491 | + &:hover { |
| 492 | + background-color: #200600; |
| 493 | + } |
| 494 | + } |
| 495 | + " |
| 496 | + `) |
| 497 | + }) |
| 498 | +}) |
| 499 | + |
233 | 500 | describe('default font family compatibility', () => {
|
234 | 501 | test('overriding `fontFamily.sans` sets `--default-font-family`', async ({ expect }) => {
|
235 | 502 | let input = css`
|
|
0 commit comments