diff --git a/README.md b/README.md index 56395c9..e198d95 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,7 @@ plugins: [ require("@tailwindcss/forms")({ strategy: 'base', // only generate global styles strategy: 'class', // only generate classes + disableOutlines: true, // don't generate outlines and rings, defaults to false }), ], ``` @@ -120,3 +121,5 @@ plugins: [ When using the `base` strategy, form elements are styled globally, and no `form-{name}` classes are generated. When using the `class` strategy, form elements are not styled globally, and instead must be styled using the generated `form-{name}` classes. + +When `disableOutlines` is set to `true`, this plugin won't generate any outlines and rings in focused states. diff --git a/src/index.d.ts b/src/index.d.ts index 1918866..3380874 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -1,4 +1,4 @@ -declare function plugin(options?: Partial<{ strategy: 'base' | 'class' }>): { handler: () => void } +declare function plugin(options?: Partial<{ strategy: 'base' | 'class', disableOutlines: boolean }>): { handler: () => void } declare namespace plugin { const __isOptionsFunction: true diff --git a/src/index.js b/src/index.js index 04a3992..324937d 100644 --- a/src/index.js +++ b/src/index.js @@ -9,9 +9,25 @@ function resolveColor(color, opacityVariableName) { return color.replace('', `var(${opacityVariableName}, 1)`) } -const forms = plugin.withOptions(function (options = { strategy: undefined }) { +/** + * @template T + * @param {boolean} bool + * @param {T} value + */ +function maybe(bool, value) { + return bool ? value : undefined +} + +function getEmptyRule() { + return { base: [], class: [], styles: {} } +} + +const forms = plugin.withOptions(function ( + options = { strategy: undefined, disableOutlines: undefined } +) { return function ({ addBase, addComponents, theme }) { const strategy = options.strategy === undefined ? ['base', 'class'] : [options.strategy] + const disableOutlines = options.disableOutlines === undefined ? false : options.disableOutlines const rules = [ { @@ -50,24 +66,25 @@ const forms = plugin.withOptions(function (options = { strategy: undefined }) { 'font-size': baseFontSize, 'line-height': baseLineHeight, '--tw-shadow': '0 0 #0000', - '&:focus': { - outline: '2px solid transparent', - 'outline-offset': '2px', - '--tw-ring-inset': 'var(--tw-empty,/*!*/ /*!*/)', - '--tw-ring-offset-width': '0px', - '--tw-ring-offset-color': '#fff', - '--tw-ring-color': resolveColor( - theme('colors.blue.600', colors.blue[600]), - '--tw-ring-opacity' - ), - '--tw-ring-offset-shadow': `var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)`, - '--tw-ring-shadow': `var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)`, - 'box-shadow': `var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)`, - 'border-color': resolveColor( - theme('colors.blue.600', colors.blue[600]), - '--tw-border-opacity' - ), - }, + '&:focus': + maybe({ + outline: '2px solid transparent', + 'outline-offset': '2px', + '--tw-ring-inset': 'var(--tw-empty,/*!*/ /*!*/)', + '--tw-ring-offset-width': '0px', + '--tw-ring-offset-color': '#fff', + '--tw-ring-color': resolveColor( + theme('colors.blue.600', colors.blue[600]), + '--tw-ring-opacity' + ), + '--tw-ring-offset-shadow': `var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color)`, + '--tw-ring-shadow': `var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color)`, + 'box-shadow': `var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)`, + 'border-color': resolveColor( + theme('colors.blue.600', colors.blue[600]), + '--tw-border-opacity' + ), + }) || {}, }, }, { @@ -215,7 +232,7 @@ const forms = plugin.withOptions(function (options = { strategy: undefined }) { 'border-radius': '100%', }, }, - { + maybe(!disableOutlines, { base: [`[type='checkbox']:focus`, `[type='radio']:focus`], class: ['.form-checkbox:focus', '.form-radio:focus'], styles: { @@ -232,7 +249,7 @@ const forms = plugin.withOptions(function (options = { strategy: undefined }) { '--tw-ring-shadow': `var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color)`, 'box-shadow': `var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)`, }, - }, + }) || getEmptyRule(), { base: [`[type='checkbox']:checked`, `[type='radio']:checked`], class: ['.form-checkbox:checked', '.form-radio:checked'], @@ -315,13 +332,13 @@ const forms = plugin.withOptions(function (options = { strategy: undefined }) { 'line-height': 'inherit', }, }, - { + maybe(!disableOutlines, { base: [`[type='file']:focus`], class: null, styles: { outline: [`1px solid ButtonText`, `1px auto -webkit-focus-ring-color`], }, - }, + }) || getEmptyRule(), ] const getStrategyRules = (strategy) =>