Skip to content

Commit 92bb81e

Browse files
authored
feat: transform hsl to hsla (tailwindlabs#3850)
* feat: transform `hsl` to `hsla` * feat: update plugins using `toRgba` * Test `gradientColorStops` * Add test for `ringWidth` * Add percentage symbol after Saturation and Lightness
1 parent b80b5bb commit 92bb81e

File tree

6 files changed

+134
-31
lines changed

6 files changed

+134
-31
lines changed

__tests__/plugins/gradientColorStops.test.js

Lines changed: 42 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ test('opacity variables are given to colors defined as closures', () => {
1717

1818
return `rgb(31,31,31)`
1919
},
20+
secondary: 'hsl(10, 50%, 50%)',
2021
},
2122
opacity: {
2223
50: '0.5',
@@ -33,23 +34,47 @@ test('opacity variables are given to colors defined as closures', () => {
3334
.process('@tailwind utilities', { from: undefined })
3435
.then((result) => {
3536
const expected = `
36-
.text-primary {
37-
--tw-text-opacity: 1;
38-
color: rgba(31,31,31,var(--tw-text-opacity))
39-
}
40-
.text-opacity-50 {
41-
--tw-text-opacity: 0.5
42-
}
43-
.from-primary {
44-
--tw-gradient-from: rgb(31,31,31);
45-
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to, rgba(31, 31, 31, 0))
46-
}
47-
.via-primary {
48-
--tw-gradient-stops: var(--tw-gradient-from), rgb(31,31,31), var(--tw-gradient-to, rgba(31, 31, 31, 0))
49-
}
50-
.to-primary {
51-
--tw-gradient-to: rgb(31,31,31)
52-
}
37+
.text-primary {
38+
--tw-text-opacity: 1;
39+
color: rgba(31, 31, 31, var(--tw-text-opacity));
40+
}
41+
42+
.text-secondary {
43+
--tw-text-opacity: 1;
44+
color: hsla(10, 50%, 50%, var(--tw-text-opacity));
45+
}
46+
47+
.text-opacity-50 {
48+
--tw-text-opacity: 0.5;
49+
}
50+
51+
.from-primary {
52+
--tw-gradient-from: rgb(31, 31, 31);
53+
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to, rgba(31, 31, 31, 0));
54+
}
55+
56+
.from-secondary {
57+
--tw-gradient-from: hsl(10, 50%, 50%);
58+
--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to, hsla(10, 50%, 50%, 0));
59+
}
60+
61+
.via-primary {
62+
--tw-gradient-stops: var(--tw-gradient-from), rgb(31, 31, 31),
63+
var(--tw-gradient-to, rgba(31, 31, 31, 0));
64+
}
65+
66+
.via-secondary {
67+
--tw-gradient-stops: var(--tw-gradient-from), hsl(10, 50%, 50%),
68+
var(--tw-gradient-to, hsla(10, 50%, 50%, 0));
69+
}
70+
71+
.to-primary {
72+
--tw-gradient-to: rgb(31, 31, 31);
73+
}
74+
75+
.to-secondary {
76+
--tw-gradient-to: hsl(10, 50%, 50%);
77+
}
5378
`
5479

5580
expect(result.css).toMatchCss(expected)

__tests__/plugins/ringWidth.test.js

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,51 @@ test('ring widths', () => {
6161
])
6262
})
6363

64+
test('ring widths with defaults and hsl value for ringColor', () => {
65+
const config = {
66+
theme: {
67+
ringWidth: {},
68+
ringOffsetWidth: {
69+
DEFAULT: '2px',
70+
},
71+
ringOffsetColor: {
72+
DEFAULT: 'pink',
73+
},
74+
ringColor: {
75+
DEFAULT: 'hsl(10, 50%, 50%)',
76+
},
77+
},
78+
variants: {
79+
ringColor: [],
80+
},
81+
}
82+
83+
const { utilities } = invokePlugin(plugin(), config)
84+
expect(utilities).toEqual([
85+
[
86+
{
87+
'*': {
88+
'--tw-ring-color': 'hsla(10, 50%, 50%, 0.5)',
89+
'--tw-ring-inset': 'var(--tw-empty,/*!*/ /*!*/)',
90+
'--tw-ring-offset-color': 'pink',
91+
'--tw-ring-offset-shadow': '0 0 #0000',
92+
'--tw-ring-offset-width': '2px',
93+
'--tw-ring-shadow': '0 0 #0000',
94+
},
95+
},
96+
{ respectImportant: false },
97+
],
98+
[
99+
{
100+
'.ring-inset': {
101+
'--tw-ring-inset': 'inset',
102+
},
103+
},
104+
undefined,
105+
],
106+
])
107+
})
108+
64109
test('ring widths with defaults', () => {
65110
const config = {
66111
theme: {

__tests__/withAlphaVariable.test.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,26 @@ test('it allows a closure to be passed', () => {
118118
'background-color': 'rgba(0, 0, 0, var(--tw-bg-opacity))',
119119
})
120120
})
121+
122+
test('it transforms rgb and hsl to rgba and hsla', () => {
123+
expect(
124+
withAlphaVariable({
125+
color: 'rgb(50, 50, 50)',
126+
property: 'background-color',
127+
variable: '--tw-bg-opacity',
128+
})
129+
).toEqual({
130+
'--tw-bg-opacity': '1',
131+
'background-color': 'rgba(50, 50, 50, var(--tw-bg-opacity))',
132+
})
133+
expect(
134+
withAlphaVariable({
135+
color: 'hsl(50, 50%, 50%)',
136+
property: 'background-color',
137+
variable: '--tw-bg-opacity',
138+
})
139+
).toEqual({
140+
'--tw-bg-opacity': '1',
141+
'background-color': 'hsla(50, 50%, 50%, var(--tw-bg-opacity))',
142+
})
143+
})

src/plugins/gradientColorStops.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import _ from 'lodash'
22
import flattenColorPalette from '../util/flattenColorPalette'
33
import nameClass from '../util/nameClass'
44
import toColorValue from '../util/toColorValue'
5-
import { toRgba } from '../util/withAlphaVariable'
5+
import { toRgba, toHsla } from '../util/withAlphaVariable'
66

77
export default function () {
88
return function ({ addUtilities, theme, variants }) {
@@ -16,8 +16,9 @@ export default function () {
1616
}
1717

1818
try {
19-
const [r, g, b] = toRgba(value)
20-
return `rgba(${r}, ${g}, ${b}, 0)`
19+
const isHSL = value.startsWith('hsl')
20+
const [i, j, k] = isHSL ? toHsla(value) : toRgba(value)
21+
return `${isHSL ? 'hsla' : 'rgba'}(${i}, ${j}, ${k}, 0)`
2122
} catch (_error) {
2223
return `rgba(255, 255, 255, 0)`
2324
}

src/plugins/ringWidth.js

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
import _ from 'lodash'
22
import nameClass from '../util/nameClass'
3-
import { toRgba } from '../util/withAlphaVariable'
3+
import { toHsla, toRgba } from '../util/withAlphaVariable'
44

55
export default function () {
66
return function ({ addUtilities, theme, variants }) {
7-
function safeCall(callback, defaultValue) {
7+
const ringColorDefault = (() => {
8+
const isHSL = (theme('ringColor.DEFAULT') || '').startsWith('hsl')
9+
const opacity = theme('ringOpacity.DEFAULT', '0.5')
810
try {
9-
return callback()
11+
const [i, j, k] = isHSL
12+
? toHsla(theme('ringColor.DEFAULT'))
13+
: toRgba(theme('ringColor.DEFAULT'))
14+
return `${isHSL ? 'hsla' : 'rgba'}(${i}, ${j}, ${k}, ${opacity})`
1015
} catch (_error) {
11-
return defaultValue
16+
return `rgba(147, 197, 253, ${opacity})`
1217
}
13-
}
14-
15-
const ringColorDefault = (([r, g, b]) => {
16-
return `rgba(${r}, ${g}, ${b}, ${theme('ringOpacity.DEFAULT', '0.5')})`
17-
})(safeCall(() => toRgba(theme('ringColor.DEFAULT')), ['147', '197', '253']))
18+
})()
1819

1920
addUtilities(
2021
{

src/util/withAlphaVariable.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ export function toRgba(color) {
1616
return [r, g, b, a === undefined && hasAlpha(color) ? 1 : a]
1717
}
1818

19+
export function toHsla(color) {
20+
const [h, s, l, a] = createColor(color).hsl().array()
21+
22+
return [h, `${s}%`, `${l}%`, a === undefined && hasAlpha(color) ? 1 : a]
23+
}
24+
1925
export default function withAlphaVariable({ color, property, variable }) {
2026
if (_.isFunction(color)) {
2127
return {
@@ -25,7 +31,9 @@ export default function withAlphaVariable({ color, property, variable }) {
2531
}
2632

2733
try {
28-
const [r, g, b, a] = toRgba(color)
34+
const isHSL = color.startsWith('hsl')
35+
36+
const [i, j, k, a] = isHSL ? toHsla(color) : toRgba(color)
2937

3038
if (a !== undefined) {
3139
return {
@@ -35,7 +43,7 @@ export default function withAlphaVariable({ color, property, variable }) {
3543

3644
return {
3745
[variable]: '1',
38-
[property]: `rgba(${r}, ${g}, ${b}, var(${variable}))`,
46+
[property]: `${isHSL ? 'hsla' : 'rgba'}(${i}, ${j}, ${k}, var(${variable}))`,
3947
}
4048
} catch (error) {
4149
return {

0 commit comments

Comments
 (0)