Stop suggesting legacy utilities (#19169)
It was already supposed to work this way — and it appeared via the tests that it did — but the tests weren't loading the design system normally so when we split the legacy utilities into a separate file it stopped testing this properly. The setup here is a bit iffy but the gist is: - We allow static utilities to be suggested by default - A static utility can *opt out* of suggestions by explicitly registering themselves to return none.
This commit is contained in:
parent
7537e34fd1
commit
3a4ab8201b
6 changed files with 74 additions and 36 deletions
|
|
@ -7576,7 +7576,6 @@ exports[`getClassList 1`] = `
|
|||
"max-w-min",
|
||||
"max-w-none",
|
||||
"max-w-px",
|
||||
"max-w-screen",
|
||||
"max-w-svh",
|
||||
"max-w-svw",
|
||||
"mb-0",
|
||||
|
|
|
|||
|
|
@ -581,6 +581,17 @@ describe.each([['default'], ['with-variant'], ['important'], ['prefix']])('%s',
|
|||
await expectCanonicalization(input, candidate, expected)
|
||||
})
|
||||
|
||||
test('`[overflow-wrap:break-word]` → `wrap-break-word`', async () => {
|
||||
let candidate = '[overflow-wrap:break-word]'
|
||||
let expected = 'wrap-break-word'
|
||||
|
||||
let input = css`
|
||||
@import 'tailwindcss';
|
||||
`
|
||||
|
||||
await expectCanonicalization(input, candidate, expected)
|
||||
})
|
||||
|
||||
test('`break-words` → `break-words` with custom implementation', async () => {
|
||||
let candidate = 'break-words'
|
||||
let expected = 'break-words'
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ export function registerLegacyUtilities(designSystem: DesignSystem) {
|
|||
['l', 'left'],
|
||||
['tl', 'top left'],
|
||||
]) {
|
||||
designSystem.utilities.suggest(`bg-gradient-to-${value}`, () => [])
|
||||
designSystem.utilities.static(`bg-gradient-to-${value}`, () => [
|
||||
decl('--tw-gradient-position', `to ${direction} in oklab`),
|
||||
decl('background-image', `linear-gradient(var(--tw-gradient-stops))`),
|
||||
|
|
@ -20,25 +21,34 @@ export function registerLegacyUtilities(designSystem: DesignSystem) {
|
|||
}
|
||||
|
||||
// Legacy `background-position` utilities for compatibility with v4.0 and earlier
|
||||
designSystem.utilities.suggest('bg-left-top', () => [])
|
||||
designSystem.utilities.static('bg-left-top', () => [decl('background-position', 'left top')])
|
||||
designSystem.utilities.suggest('bg-right-top', () => [])
|
||||
designSystem.utilities.static('bg-right-top', () => [decl('background-position', 'right top')])
|
||||
designSystem.utilities.suggest('bg-left-bottom', () => [])
|
||||
designSystem.utilities.static('bg-left-bottom', () => [
|
||||
decl('background-position', 'left bottom'),
|
||||
])
|
||||
designSystem.utilities.suggest('bg-right-bottom', () => [])
|
||||
designSystem.utilities.static('bg-right-bottom', () => [
|
||||
decl('background-position', 'right bottom'),
|
||||
])
|
||||
|
||||
// Legacy `object-position` utilities for compatibility with v4.0 and earlier
|
||||
designSystem.utilities.suggest('object-left-top', () => [])
|
||||
designSystem.utilities.static('object-left-top', () => [decl('object-position', 'left top')])
|
||||
designSystem.utilities.suggest('object-right-top', () => [])
|
||||
designSystem.utilities.static('object-right-top', () => [decl('object-position', 'right top')])
|
||||
designSystem.utilities.suggest('object-left-bottom', () => [])
|
||||
designSystem.utilities.static('object-left-bottom', () => [
|
||||
decl('object-position', 'left bottom'),
|
||||
])
|
||||
designSystem.utilities.suggest('object-right-bottom', () => [])
|
||||
designSystem.utilities.static('object-right-bottom', () => [
|
||||
decl('object-position', 'right bottom'),
|
||||
])
|
||||
|
||||
designSystem.utilities.suggest('max-w-screen', () => [])
|
||||
designSystem.utilities.functional('max-w-screen', (candidate) => {
|
||||
if (!candidate.value) return
|
||||
if (candidate.value.kind === 'arbitrary') return
|
||||
|
|
@ -47,18 +57,22 @@ export function registerLegacyUtilities(designSystem: DesignSystem) {
|
|||
return [decl('max-width', value)]
|
||||
})
|
||||
|
||||
designSystem.utilities.suggest('overflow-ellipsis', () => [])
|
||||
designSystem.utilities.static(`overflow-ellipsis`, () => [decl('text-overflow', `ellipsis`)])
|
||||
|
||||
designSystem.utilities.suggest('decoration-slice', () => [])
|
||||
designSystem.utilities.static(`decoration-slice`, () => [
|
||||
decl('-webkit-box-decoration-break', `slice`),
|
||||
decl('box-decoration-break', `slice`),
|
||||
])
|
||||
|
||||
designSystem.utilities.suggest('decoration-clone', () => [])
|
||||
designSystem.utilities.static(`decoration-clone`, () => [
|
||||
decl('-webkit-box-decoration-break', `clone`),
|
||||
decl('box-decoration-break', `clone`),
|
||||
])
|
||||
|
||||
designSystem.utilities.suggest('flex-shrink', () => [])
|
||||
designSystem.utilities.functional('flex-shrink', (candidate) => {
|
||||
if (candidate.modifier) return
|
||||
|
||||
|
|
@ -75,6 +89,7 @@ export function registerLegacyUtilities(designSystem: DesignSystem) {
|
|||
}
|
||||
})
|
||||
|
||||
designSystem.utilities.suggest('flex-grow', () => [])
|
||||
designSystem.utilities.functional('flex-grow', (candidate) => {
|
||||
if (candidate.modifier) return
|
||||
|
||||
|
|
@ -91,6 +106,9 @@ export function registerLegacyUtilities(designSystem: DesignSystem) {
|
|||
}
|
||||
})
|
||||
|
||||
designSystem.utilities.suggest('order-none', () => [])
|
||||
designSystem.utilities.static('order-none', () => [decl('order', '0')])
|
||||
|
||||
designSystem.utilities.suggest('break-words', () => [])
|
||||
designSystem.utilities.static('break-words', () => [decl('overflow-wrap', 'break-word')])
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,35 +1,36 @@
|
|||
import { expect, test } from 'vitest'
|
||||
import { __unstable__loadDesignSystem } from '.'
|
||||
import { buildDesignSystem } from './design-system'
|
||||
import plugin from './plugin'
|
||||
import { Theme, ThemeOptions } from './theme'
|
||||
import { ThemeOptions } from './theme'
|
||||
|
||||
const css = String.raw
|
||||
|
||||
function loadDesignSystem() {
|
||||
let theme = new Theme()
|
||||
theme.add('--spacing', '0.25rem')
|
||||
theme.add('--colors-red-500', 'red')
|
||||
theme.add('--colors-blue-500', 'blue')
|
||||
theme.add('--breakpoint-sm', '640px')
|
||||
theme.add('--aspect-video', '16 / 9')
|
||||
theme.add('--font-sans', 'sans-serif')
|
||||
theme.add('--font-weight-superbold', '900')
|
||||
theme.add('--text-xs', '0.75rem')
|
||||
theme.add('--text-xs--line-height', '1rem')
|
||||
theme.add('--perspective-dramatic', '100px')
|
||||
theme.add('--perspective-normal', '500px')
|
||||
theme.add('--opacity-background', '0.3')
|
||||
theme.add('--drop-shadow-sm', '0 1px 1px rgb(0 0 0 / 0.05)')
|
||||
theme.add('--inset-shadow-sm', 'inset 0 1px 1px rgb(0 0 0 / 0.05)')
|
||||
theme.add('--font-weight-bold', '700')
|
||||
theme.add('--container-md', '768px')
|
||||
theme.add('--container-lg', '1024px')
|
||||
return buildDesignSystem(theme)
|
||||
return __unstable__loadDesignSystem(`
|
||||
@theme {
|
||||
--spacing: 0.25rem;
|
||||
--colors-red-500: red;
|
||||
--colors-blue-500: blue;
|
||||
--breakpoint-sm: 640px;
|
||||
--aspect-video: 16 / 9;
|
||||
--font-sans: sans-serif;
|
||||
--font-weight-superbold: 900;
|
||||
--text-xs: 0.75rem;
|
||||
--text-xs--line-height: 1rem;
|
||||
--perspective-dramatic: 100px;
|
||||
--perspective-normal: 500px;
|
||||
--opacity-background: 0.3;
|
||||
--drop-shadow-sm: 0 1px 1px rgb(0 0 0 / 0.05);
|
||||
--inset-shadow-sm: inset 0 1px 1px rgb(0 0 0 / 0.05);
|
||||
--font-weight-bold: 700;
|
||||
--container-md: 768px;
|
||||
--container-lg: 1024px;
|
||||
}
|
||||
`)
|
||||
}
|
||||
|
||||
test('getClassList', () => {
|
||||
let design = loadDesignSystem()
|
||||
test('getClassList', async () => {
|
||||
let design = await loadDesignSystem()
|
||||
let classList = design.getClassList()
|
||||
let classNames = classList.flatMap(([name, meta]) => [
|
||||
name,
|
||||
|
|
@ -39,8 +40,8 @@ test('getClassList', () => {
|
|||
expect(classNames).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('Spacing utilities do not suggest bare values when not using the multiplier-based spacing scale', () => {
|
||||
let design = loadDesignSystem()
|
||||
test('Spacing utilities do not suggest bare values when not using the multiplier-based spacing scale', async () => {
|
||||
let design = await loadDesignSystem()
|
||||
|
||||
// Remove spacing scale
|
||||
design.theme.clearNamespace('--spacing', ThemeOptions.NONE)
|
||||
|
|
@ -58,22 +59,22 @@ test('Spacing utilities do not suggest bare values when not using the multiplier
|
|||
expect(classNames).not.toContain('p-4')
|
||||
})
|
||||
|
||||
test('Theme values with underscores are converted back to decimal points', () => {
|
||||
let design = loadDesignSystem()
|
||||
test('Theme values with underscores are converted back to decimal points', async () => {
|
||||
let design = await loadDesignSystem()
|
||||
let classes = design.getClassList()
|
||||
|
||||
expect(classes).toContainEqual(['inset-0.5', { modifiers: [] }])
|
||||
})
|
||||
|
||||
test('getVariants', () => {
|
||||
let design = loadDesignSystem()
|
||||
test('getVariants', async () => {
|
||||
let design = await loadDesignSystem()
|
||||
let variants = design.getVariants()
|
||||
|
||||
expect(variants).toMatchSnapshot()
|
||||
})
|
||||
|
||||
test('getVariants compound', () => {
|
||||
let design = loadDesignSystem()
|
||||
test('getVariants compound', async () => {
|
||||
let design = await loadDesignSystem()
|
||||
let variants = design.getVariants()
|
||||
let group = variants.find((v) => v.name === 'group')!
|
||||
|
||||
|
|
@ -130,16 +131,16 @@ test('variant selectors are in the correct order', async () => {
|
|||
`)
|
||||
})
|
||||
|
||||
test('The variant `has-force` does not crash', () => {
|
||||
let design = loadDesignSystem()
|
||||
test('The variant `has-force` does not crash', async () => {
|
||||
let design = await loadDesignSystem()
|
||||
let variants = design.getVariants()
|
||||
let has = variants.find((v) => v.name === 'has')!
|
||||
|
||||
expect(has.selectors({ value: 'force' })).toMatchInlineSnapshot(`[]`)
|
||||
})
|
||||
|
||||
test('Can produce CSS per candidate using `candidatesToCss`', () => {
|
||||
let design = loadDesignSystem()
|
||||
test('Can produce CSS per candidate using `candidatesToCss`', async () => {
|
||||
let design = await loadDesignSystem()
|
||||
design.invalidCandidates = new Set(['bg-[#fff]'])
|
||||
|
||||
expect(design.candidatesToCss(['underline', 'i-dont-exist', 'bg-[#fff]', 'bg-[#000]', 'text-xs']))
|
||||
|
|
|
|||
|
|
@ -31,6 +31,9 @@ export function getClassList(design: DesignSystem): ClassEntry[] {
|
|||
|
||||
// Static utilities only work as-is
|
||||
for (let utility of design.utilities.keys('static')) {
|
||||
let completions = design.utilities.getCompletions(utility)
|
||||
if (completions.length === 0) continue
|
||||
|
||||
let item = items.get(utility)
|
||||
item.fraction = false
|
||||
item.modifiers = []
|
||||
|
|
|
|||
|
|
@ -122,6 +122,12 @@ export class Utilities {
|
|||
}
|
||||
|
||||
getCompletions(name: string): SuggestionGroup[] {
|
||||
if (this.has(name, 'static')) {
|
||||
return (
|
||||
this.completions.get(name)?.() ?? [{ supportsNegative: false, values: [], modifiers: [] }]
|
||||
)
|
||||
}
|
||||
|
||||
return this.completions.get(name)?.() ?? []
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue