Skip to content

Commit d4fcd2e

Browse files
authored
Add new ring utilities for custom focus styles and rounded outlines (#2747)
* Add ring utilities * Remove redundant shadows, add 5% and 95% to opacity scale * Undo changes to build file * Update boxShadow.test.js
1 parent d39ecc5 commit d4fcd2e

14 files changed

+26960
-1856
lines changed

__tests__/fixtures/tailwind-output-flagged.css

+6,912-462
Large diffs are not rendered by default.

__tests__/fixtures/tailwind-output-important.css

+6,912-462
Large diffs are not rendered by default.

__tests__/fixtures/tailwind-output-no-color-opacity.css

+6,048-462
Large diffs are not rendered by default.

__tests__/fixtures/tailwind-output.css

+6,912-462
Large diffs are not rendered by default.

__tests__/plugins/boxShadow.test.js

+8-4
Original file line numberDiff line numberDiff line change
@@ -45,16 +45,20 @@ test('box shadow can use DEFAULT keyword and negative prefix syntax', () => {
4545
{
4646
utilities: {
4747
'.shadow': {
48-
'box-shadow': '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',
48+
'--box-shadow': '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',
49+
'box-shadow': 'var(--box-shadow)',
4950
},
5051
'.shadow-md': {
51-
'box-shadow': '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
52+
'--box-shadow': '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
53+
'box-shadow': 'var(--box-shadow)',
5254
},
5355
'.-shadow': {
54-
'box-shadow': 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)',
56+
'--box-shadow': 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)',
57+
'box-shadow': 'var(--box-shadow)',
5558
},
5659
'.-shadow-md': {
57-
'box-shadow': '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
60+
'--box-shadow': '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
61+
'box-shadow': 'var(--box-shadow)',
5862
},
5963
},
6064
variants: ['responsive'],

src/corePluginList.js

+5
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ export const corePluginList = [
6969
'inset',
7070
'resize',
7171
'boxShadow',
72+
'ringWidth',
73+
'ringOffsetColor',
74+
'ringOffsetWidth',
75+
'ringColor',
76+
'ringOpacity',
7277
'fill',
7378
'stroke',
7479
'strokeWidth',

src/plugins/boxShadow.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ export default function () {
88
return [
99
nameClass('shadow', modifier),
1010
{
11-
'box-shadow': value,
11+
'--box-shadow': value,
12+
'box-shadow': 'var(--box-shadow)',
1213
},
1314
]
1415
})

src/plugins/index.js

+5
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,11 @@ export { default as pointerEvents } from './pointerEvents'
8585
export { default as position } from './position'
8686
export { default as preflight } from './preflight'
8787
export { default as resize } from './resize'
88+
export { default as ringColor } from './ringColor'
89+
export { default as ringOffsetColor } from './ringOffsetColor'
90+
export { default as ringOffsetWidth } from './ringOffsetWidth'
91+
export { default as ringOpacity } from './ringOpacity'
92+
export { default as ringWidth } from './ringWidth'
8893
export { default as rotate } from './rotate'
8994
export { default as scale } from './scale'
9095
export { default as skew } from './skew'

src/plugins/ringColor.js

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import _ from 'lodash'
2+
import flattenColorPalette from '../util/flattenColorPalette'
3+
import nameClass from '../util/nameClass'
4+
import { toRgba } from '../util/withAlphaVariable'
5+
6+
export default function () {
7+
return function ({ addUtilities, theme, variants }) {
8+
const colors = flattenColorPalette(theme('ringColor'))
9+
const utilities = _.fromPairs(
10+
_.map(_.omit(colors, 'DEFAULT'), (value, modifier) => {
11+
try {
12+
const [r, g, b, a] = toRgba(value)
13+
return [
14+
nameClass('ring', modifier),
15+
{
16+
'--ring-opacity': a === undefined ? '1' : a,
17+
'--ring-color': `rgba(${r}, ${g}, ${b}, var(--ring-opacity))`,
18+
},
19+
]
20+
} catch (_error) {
21+
return [
22+
nameClass('ring', modifier),
23+
{
24+
'--ring-color': value,
25+
},
26+
]
27+
}
28+
})
29+
)
30+
addUtilities(utilities, variants('ringColor'))
31+
}
32+
}

src/plugins/ringOffsetColor.js

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import _ from 'lodash'
2+
import flattenColorPalette from '../util/flattenColorPalette'
3+
import nameClass from '../util/nameClass'
4+
5+
export default function () {
6+
return function ({ addUtilities, theme, variants }) {
7+
const colors = flattenColorPalette(theme('ringOffsetColor'))
8+
const utilities = _.fromPairs(
9+
_.map(colors, (value, modifier) => {
10+
return [
11+
nameClass('ring-offset', modifier),
12+
{
13+
'--ring-offset-color': value,
14+
},
15+
]
16+
})
17+
)
18+
addUtilities(utilities, variants('ringOffsetColor'))
19+
}
20+
}

src/plugins/ringOffsetWidth.js

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import _ from 'lodash'
2+
import nameClass from '../util/nameClass'
3+
4+
export default function () {
5+
return function ({ addUtilities, theme, variants }) {
6+
const utilities = _.fromPairs(
7+
_.map(theme('ringOffsetWidth'), (value, modifier) => {
8+
return [
9+
nameClass('ring-offset', modifier),
10+
{
11+
'--ring-offset-width': value,
12+
},
13+
]
14+
})
15+
)
16+
addUtilities(utilities, variants('ringOffsetWidth'))
17+
}
18+
}

src/plugins/ringOpacity.js

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
import _ from 'lodash'
2+
import nameClass from '../util/nameClass'
3+
4+
export default function () {
5+
return function ({ addUtilities, theme, variants }) {
6+
const utilities = _.fromPairs(
7+
_.map(_.omit(theme('ringOpacity'), 'DEFAULT'), (value, modifier) => {
8+
return [
9+
nameClass('ring-opacity', modifier),
10+
{
11+
'--ring-opacity': value,
12+
},
13+
]
14+
})
15+
)
16+
addUtilities(utilities, variants('ringOpacity'))
17+
}
18+
}

src/plugins/ringWidth.js

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import _ from 'lodash'
2+
import nameClass from '../util/nameClass'
3+
import { toRgba } from '../util/withAlphaVariable'
4+
5+
export default function () {
6+
return function ({ addUtilities, theme, variants }) {
7+
function safeCall(callback, defaultValue) {
8+
try {
9+
return callback()
10+
} catch (_error) {
11+
return defaultValue
12+
}
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+
19+
const utilities = _.fromPairs(
20+
_.map(theme('ringWidth'), (value, modifier) => {
21+
return [
22+
nameClass('ring', modifier),
23+
{
24+
'--ring-width': value,
25+
'--ring-color-default': ringColorDefault,
26+
'box-shadow': [
27+
`0 0 0 var(--ring-offset-width, 0) var(--ring-offset-color, #fff)`,
28+
`0 0 0 calc(var(--ring-width) + var(--ring-offset-width, 0px)) var(--ring-color, var(--ring-color-default))`,
29+
`var(--box-shadow, 0 0 #0000)`,
30+
].join(', '),
31+
},
32+
]
33+
})
34+
)
35+
addUtilities(utilities, variants('ringWidth'))
36+
}
37+
}

stubs/defaultConfig.stub.js

+31-3
Original file line numberDiff line numberDiff line change
@@ -125,16 +125,13 @@ module.exports = {
125125
8: '8px',
126126
},
127127
boxShadow: {
128-
xs: '0 0 0 1px rgba(0, 0, 0, 0.05)',
129128
sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
130129
DEFAULT: '0 1px 3px 0 rgba(0, 0, 0, 0.1), 0 1px 2px 0 rgba(0, 0, 0, 0.06)',
131130
md: '0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06)',
132131
lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
133132
xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)',
134133
'2xl': '0 25px 50px -12px rgba(0, 0, 0, 0.25)',
135134
inner: 'inset 0 2px 4px 0 rgba(0, 0, 0, 0.06)',
136-
outline: '0 0 0 3px rgba(147, 197, 253, 0.5)',
137-
solid: '0 0 0 2px currentColor',
138135
none: 'none',
139136
},
140137
container: {},
@@ -498,6 +495,7 @@ module.exports = {
498495
},
499496
opacity: {
500497
0: '0',
498+
5: '0.05',
501499
10: '0.1',
502500
20: '0.2',
503501
25: '0.25',
@@ -509,6 +507,7 @@ module.exports = {
509507
75: '0.75',
510508
80: '0.8',
511509
90: '0.9',
510+
95: '0.95',
512511
100: '1',
513512
},
514513
order: {
@@ -536,6 +535,30 @@ module.exports = {
536535
padding: (theme) => theme('spacing'),
537536
placeholderColor: (theme) => theme('colors'),
538537
placeholderOpacity: (theme) => theme('opacity'),
538+
ringColor: (theme) => ({
539+
DEFAULT: theme('colors.blue.500'),
540+
...theme('colors'),
541+
}),
542+
ringOffsetColor: (theme) => theme('colors'),
543+
ringOffsetWidth: {
544+
0: '0',
545+
1: '1px',
546+
2: '2px',
547+
4: '4px',
548+
8: '8px',
549+
},
550+
ringOpacity: (theme) => ({
551+
DEFAULT: '0.5',
552+
...theme('opacity'),
553+
}),
554+
ringWidth: {
555+
DEFAULT: '3px',
556+
0: '0',
557+
1: '1px',
558+
2: '2px',
559+
4: '4px',
560+
8: '8px',
561+
},
539562
rotate: {
540563
'-180': '-180deg',
541564
'-90': '-90deg',
@@ -794,6 +817,11 @@ module.exports = {
794817
pointerEvents: ['responsive'],
795818
position: ['responsive'],
796819
resize: ['responsive'],
820+
ringColor: ['responsive'],
821+
ringOffsetColor: ['responsive'],
822+
ringOffsetWidth: ['responsive'],
823+
ringOpacity: ['responsive'],
824+
ringWidth: ['responsive', 'focus'],
797825
rotate: ['responsive', 'hover', 'focus'],
798826
scale: ['responsive', 'hover', 'focus'],
799827
skew: ['responsive', 'hover', 'focus'],

0 commit comments

Comments
 (0)