diff --git a/src/definitions/collections/form.less b/src/definitions/collections/form.less index 3d1a331eb4..3e10dc6f7c 100755 --- a/src/definitions/collections/form.less +++ b/src/definitions/collections/form.less @@ -176,6 +176,10 @@ line-height: @textAreaLineHeight; resize: @textAreaResize; min-height: @actionTextareaMinHeight; + &:focus-visible when not (@textAreaFocusVisibleOutline = none) { + outline: @textAreaFocusVisibleOutline; + outline-offset: @textAreaFocusVisibleOutlineOffset; + } } .ui.input > textarea { flex: 1 1 auto; @@ -439,6 +443,26 @@ background: @inputFocusBackground; box-shadow: @inputFocusBoxShadow; } +& when not (@inputFocusVisibleOutline = none) { + .ui.form input:not([type]):focus-visible, + .ui.form input[type="color"]:focus-visible, + .ui.form input[type="date"]:focus-visible, + .ui.form input[type="datetime-local"]:focus-visible, + .ui.form input[type="email"]:focus-visible, + .ui.form input[type="month"]:focus-visible, + .ui.form input[type="number"]:focus-visible, + .ui.form input[type="password"]:focus-visible, + .ui.form input[type="search"]:focus-visible, + .ui.form input[type="tel"]:focus-visible, + .ui.form input[type="time"]:focus-visible, + .ui.form input[type="text"]:focus-visible, + .ui.form input[type="file"]:focus-visible, + .ui.form input[type="url"]:focus-visible, + .ui.form input[type="week"]:focus-visible { + outline: @inputFocusVisibleOutline; + outline-offset: @inputFocusVisibleOutlineOffset; + } +} & when (@variationInputAction) { .ui.form .ui.action.input:not([class*="left action"]) { & input:not([type]):focus, diff --git a/src/definitions/elements/button.less b/src/definitions/elements/button.less index 3b6c61f0c2..bd65832ff1 100755 --- a/src/definitions/elements/button.less +++ b/src/definitions/elements/button.less @@ -89,6 +89,12 @@ background-image: @focusBackgroundImage; box-shadow: @focusBoxShadow; } +& when not (@focusVisibleOutline = none) { + .ui.button:focus-visible { + outline: @focusVisibleOutline; + outline-offset: @focusVisibleOutlineOffset; + } +} .ui.button:focus .icon { opacity: @iconFocusOpacity; diff --git a/src/definitions/elements/input.less b/src/definitions/elements/input.less index aba6f96e17..ece3023395 100755 --- a/src/definitions/elements/input.less +++ b/src/definitions/elements/input.less @@ -64,6 +64,10 @@ transition: @iconTransition; cursor: pointer; } + &:focus-visible when not (@focusVisibleOutline = none) { + outline: @focusVisibleOutline; + outline-offset: @focusVisibleOutlineOffset; + } } /* -------------------- diff --git a/src/definitions/modules/calendar.less b/src/definitions/modules/calendar.less index 527dab04e3..a320d1619e 100644 --- a/src/definitions/modules/calendar.less +++ b/src/definitions/modules/calendar.less @@ -39,7 +39,14 @@ .ui.calendar .calendar:focus, .ui.calendar.popup:focus { - outline: 0; + outline: @focusOutline; +} +& when not (@focusVisibleOutline = none) { + .ui.calendar .calendar:focus-visible, + .ui.calendar.popup:focus-visible { + outline: @focusVisibleOutline; + outline-offset: @focusVisibleOutlineOffset; + } } /******************************* diff --git a/src/definitions/modules/checkbox.less b/src/definitions/modules/checkbox.less index 94a5eb16ef..151f5149fa 100755 --- a/src/definitions/modules/checkbox.less +++ b/src/definitions/modules/checkbox.less @@ -42,6 +42,10 @@ font-size: @relativeMedium; line-height: @checkboxLineHeight; min-width: @checkboxSize; + &:focus-visible when not (@focusVisibleOutline = none) { + outline: @focusVisibleOutline; + outline-offset: @focusVisibleOutlineOffset; + } } /* HTML Checkbox */ @@ -56,6 +60,10 @@ z-index: 3; width: @checkboxSize; height: @checkboxSize; + &:focus-visible when not (@inputFocusVisibleOutline = none) { + outline: @inputFocusVisibleOutline; + outline-offset: @inputFocusVisibleOutlineOffset; + } } .ui.checkbox label { @@ -64,6 +72,10 @@ display: block; outline: none; font-size: @labelFontSize; + &:focus-visible when not (@labelFocusVisibleOutline = none) { + outline: @labelFocusVisibleOutline; + outline-offset: @labelFocusVisibleOutlineOffset; + } } .ui.checkbox@{notInvisible} label { diff --git a/src/definitions/modules/dropdown.less b/src/definitions/modules/dropdown.less index ec10ef6d7d..e5597225a0 100755 --- a/src/definitions/modules/dropdown.less +++ b/src/definitions/modules/dropdown.less @@ -48,6 +48,10 @@ transition: @transition; user-select: none; -webkit-tap-highlight-color: rgb(0 0 0 / 0); + &:focus-visible when not (@focusVisibleOutline = none) { + outline: @focusVisibleOutline; + outline-offset: @focusVisibleOutlineOffset; + } } /******************************* @@ -77,6 +81,10 @@ transition: @menuTransition; z-index: @menuZIndex; will-change: transform, opacity; + &:focus-visible when not (@menuFocusVisibleOutline = none) { + outline: @menuFocusVisibleOutline; + outline-offset: @menuFocusVisibleOutlineOffset; + } } .ui.dropdown .menu > * { @@ -405,7 +413,7 @@ select.ui.dropdown { word-wrap: break-word; line-height: 1em; white-space: normal; - outline: 0; + outline: none; transform: rotateZ(0); min-width: @selectionMinWidth; min-height: @selectionMinHeight; @@ -417,6 +425,10 @@ select.ui.dropdown { border: @selectionBorder; border-radius: @selectionBorderRadius; transition: @selectionTransition; + &:focus-visible when not (@selectionFocusVisibleOutline = none) { + outline: @selectionFocusVisibleOutline; + outline-offset: @selectionFocusVisibleOutlineOffset; + } } .ui.selection.dropdown.visible, .ui.selection.dropdown.active { @@ -454,6 +466,10 @@ select.ui.dropdown { width: @menuMinWidth; box-shadow: @selectionMenuBoxShadow; transition: @selectionMenuTransition; + &:focus-visible when not (@selectionMenuFocusVisibleOutline = none) { + outline: @selectionMenuFocusVisibleOutline; + outline-offset: @selectionMenuFocusVisibleOutlineOffset; + } } .ui.selection.dropdown@{notPointing}@{notFloating} > .menu { border-top-width: 0; @@ -743,6 +759,10 @@ select.ui.dropdown { outline: none; -webkit-tap-highlight-color: rgb(255 255 255 / 0); padding: inherit; + &:focus-visible when not (@searchFocusVisibleOutline = none) { + outline: @searchFocusVisibleOutline; + outline-offset: @searchFocusVisibleOutlineOffset; + } } /* Text Layering */ diff --git a/src/definitions/modules/flyout.less b/src/definitions/modules/flyout.less index 753826e6cc..e83a931f80 100644 --- a/src/definitions/modules/flyout.less +++ b/src/definitions/modules/flyout.less @@ -44,6 +44,10 @@ z-index: @topLayer; background: #fff; outline: none; + &:focus-visible when not (@focusVisibleOutline = none) { + outline: @focusVisibleOutline; + outline-offset: @focusVisibleOutlineOffset; + } } /* GPU Layers for Child Elements */ @@ -73,9 +77,13 @@ .ui.flyout > .close:focus, .ui.flyout > .close:hover { opacity: 1; - outline: none; + outline: @focusOutline; } } +.ui.flyout > .close:focus-visible when not (@closeFocusVisibleOutline = none) { + outline: @closeFocusVisibleOutline; + outline-offset: @closeFocusVisibleOutlineOffset; +} /* -------------- Header diff --git a/src/definitions/modules/modal.less b/src/definitions/modules/modal.less index 5d084b14b8..e68d72fe8c 100755 --- a/src/definitions/modules/modal.less +++ b/src/definitions/modules/modal.less @@ -42,6 +42,10 @@ user-select: text; will-change: top, left, margin, transform, opacity; outline: none; + &:focus-visible when not (@focusVisibleOutline = none) { + outline: @focusVisibleOutline; + outline-offset: @focusVisibleOutlineOffset; + } } .ui.modal > :first-child@{notClose}:not(.dimmer), @@ -86,9 +90,13 @@ .ui.modal > .close:focus, .ui.modal > .close:hover { opacity: 1; - outline: none; + outline: @focusOutline; } } +.ui.modal > .close:focus-visible when not (@closeFocusVisibleOutline = none) { + outline: @closeFocusVisibleOutline; + outline-offset: @closeFocusVisibleOutlineOffset; +} /* -------------- Header diff --git a/src/definitions/modules/search.less b/src/definitions/modules/search.less index 853ef24812..3762f8cc32 100755 --- a/src/definitions/modules/search.less +++ b/src/definitions/modules/search.less @@ -184,6 +184,12 @@ background: @promptFocusBackground; color: @promptFocusColor; } +& when not (@focusVisibleOutline = none) { + .ui.search > .prompt:focus-visible { + outline: @focusVisibleOutline; + outline-offset: @focusVisibleOutlineOffset; + } +} & when (@variationSearchLoading) { /* -------------------- diff --git a/src/definitions/modules/slider.less b/src/definitions/modules/slider.less index 17a783bfe6..2ee0068cfe 100644 --- a/src/definitions/modules/slider.less +++ b/src/definitions/modules/slider.less @@ -34,7 +34,13 @@ } .ui.slider@{notCheckbox}:focus { - outline: 0; + outline: @focusOutline; +} +& when not (@focusVisibleOutline = none) { + .ui.slider@{notCheckbox}:focus-visible { + outline: @focusVisibleOutline; + outline-offset: @focusVisibleOutlineOffset; + } } .ui.slider .inner { diff --git a/src/themes/default/collections/form.variables b/src/themes/default/collections/form.variables index 2b27d412b9..da916f6155 100644 --- a/src/themes/default/collections/form.variables +++ b/src/themes/default/collections/form.variables @@ -92,6 +92,8 @@ @inputFocusColor: @selectedTextColor; @inputFocusBoxShadow: @inputFocusPointerSize 0 0 0 @selectedBorderColor inset; @inputFocusBorderRadius: @inputBorderRadius; +@inputFocusVisibleOutline: @focusVisibleOutline; +@inputFocusVisibleOutlineOffset: @focusVisibleOutlineOffset; /* Text Area Focus */ @textAreaFocusBackground: @inputFocusBackground; @@ -99,6 +101,8 @@ @textAreaFocusColor: @inputFocusColor; @textAreaFocusBoxShadow: @inputFocusBoxShadow; @textAreaFocusBorderRadius: @inputFocusBorderRadius; +@textAreaFocusVisibleOutline: @focusVisibleOutline; +@textAreaFocusVisibleOutlineOffset: @focusVisibleOutlineOffset; /* Disabled */ @disabledLabelOpacity: @disabledOpacity; diff --git a/src/themes/default/globals/site.variables b/src/themes/default/globals/site.variables index 62fa2e1938..9186d2a9f3 100755 --- a/src/themes/default/globals/site.variables +++ b/src/themes/default/globals/site.variables @@ -1131,6 +1131,9 @@ /* ------------------- Focus -------------------- */ +@focusOutline: none; +@focusVisibleOutline: none; +@focusVisibleOutlineOffset: 0; /* --- Colors --- */ @primaryColorFocus: if(iscolor(@primaryColor), saturate(darken(@primaryColor, 8), 20, relative), @primaryColor); diff --git a/src/themes/default/modules/checkbox.variables b/src/themes/default/modules/checkbox.variables index 1157a8aab6..eb3ba7fcf2 100644 --- a/src/themes/default/modules/checkbox.variables +++ b/src/themes/default/modules/checkbox.variables @@ -50,6 +50,10 @@ @checkboxFocusBorderColor: @focusedFormMutedBorderColor; @checkboxFocusCheckColor: @selectedTextColor; @labelFocusColor: @selectedTextColor; +@labelFocusVisibleOutline: @focusVisibleOutline; +@labelFocusVisibleOutlineOffset: @focusVisibleOutlineOffset; +@inputFocusVisibleOutline: @focusVisibleOutline; +@inputFocusVisibleOutlineOffset: @focusVisibleOutlineOffset; /* Active */ @labelActiveColor: @selectedTextColor; diff --git a/src/themes/default/modules/dropdown.variables b/src/themes/default/modules/dropdown.variables index 4d94766c63..2ed7bb4d2e 100755 --- a/src/themes/default/modules/dropdown.variables +++ b/src/themes/default/modules/dropdown.variables @@ -32,6 +32,8 @@ @menuPadding: 0; @menuTop: 100%; @menuTextAlign: left; +@menuFocusVisibleOutline: @focusVisibleOutline; +@menuFocusVisibleOutlineOffset: @focusVisibleOutlineOffset; @menuBorderWidth: 1px; @menuBorderColor: @borderColor; @@ -202,6 +204,10 @@ @selectionFocusBorderColor: @focusedFormMutedBorderColor; @selectionFocusBoxShadow: none; @selectionFocusMenuBoxShadow: @raisedShadow; +@selectionFocusVisibleOutline: @focusVisibleOutline; +@selectionFocusVisibleOutlineOffset: @focusVisibleOutlineOffset; +@selectionMenuFocusVisibleOutline: @focusVisibleOutline; +@selectionMenuFocusVisibleOutlineOffset: @focusVisibleOutlineOffset; /* Visible */ @selectionVisibleTextFontWeight: @normal; @@ -227,6 +233,8 @@ -------------- */ @searchMinWidth: ""; +@searchFocusVisibleOutline: @focusVisibleOutline; +@searchFocusVisibleOutlineOffset: @focusVisibleOutlineOffset; /* Search Selection */ @searchSelectionLineHeight: @inputLineHeight; diff --git a/src/themes/default/modules/flyout.variables b/src/themes/default/modules/flyout.variables index 6e04b5c997..31ee70a0fd 100644 --- a/src/themes/default/modules/flyout.variables +++ b/src/themes/default/modules/flyout.variables @@ -11,6 +11,10 @@ @duration: 500ms; @easing: @defaultEasing; +/* Focus */ +@closeFocusVisibleOutline: @focusVisibleOutline; +@closeFocusVisibleOutlineOffset: @focusVisibleOutlineOffset; + /* Dimmer */ @dimmerColor: rgb(0 0 0 / 0.4); @dimmerTransition: all @duration; diff --git a/src/themes/default/modules/modal.variables b/src/themes/default/modules/modal.variables index 8cf13307ce..aa8c444f15 100755 --- a/src/themes/default/modules/modal.variables +++ b/src/themes/default/modules/modal.variables @@ -16,6 +16,8 @@ @closeOpacityDimmed: 0.1; @closeSize: 1.25em; @closeColor: @white; +@closeFocusVisibleOutline: @focusVisibleOutline; +@closeFocusVisibleOutlineOffset: @focusVisibleOutlineOffset; @closeHitbox: 2.25rem; @closeDistance: 0.25rem;