feat: use :focus-visible, add setting to enable/disable it (#1775)
* feat: use :focus-visible, add setting to enable it * add the ids back * css cleanup
This commit is contained in:
parent
836b0e341f
commit
cc62000b21
|
@ -72,6 +72,7 @@
|
||||||
"file-api": "^0.10.4",
|
"file-api": "^0.10.4",
|
||||||
"file-drop-element": "0.2.0",
|
"file-drop-element": "0.2.0",
|
||||||
"file-loader": "^6.0.0",
|
"file-loader": "^6.0.0",
|
||||||
|
"focus-visible": "^5.1.0",
|
||||||
"form-data": "^3.0.0",
|
"form-data": "^3.0.0",
|
||||||
"glob": "^7.1.6",
|
"glob": "^7.1.6",
|
||||||
"indexeddb-getall-shim": "^1.3.6",
|
"indexeddb-getall-shim": "^1.3.6",
|
||||||
|
|
|
@ -28,6 +28,25 @@
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style id="theFocusVisibleStyle" media="all">
|
||||||
|
/* :focus-visible styles */
|
||||||
|
/* polyfill */
|
||||||
|
.js-focus-visible :focus:not(.focus-visible) {
|
||||||
|
outline: none !important; /* important to win the specificity war */
|
||||||
|
}
|
||||||
|
.js-focus-visible :focus:not(.focus-visible).focus-after::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* standard version */
|
||||||
|
:focus:not(:focus-visible) {
|
||||||
|
outline: none !important; /* important to win the specificity war */
|
||||||
|
}
|
||||||
|
:focus:not(:focus-visible).focus-after::after {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
<noscript>
|
<noscript>
|
||||||
<style>
|
<style>
|
||||||
.hidden-from-ssr {
|
.hidden-from-ssr {
|
||||||
|
|
|
@ -68,6 +68,18 @@
|
||||||
bind:checked="$reduceMotion" on:change="onChange(event)">
|
bind:checked="$reduceMotion" on:change="onChange(event)">
|
||||||
Reduce motion in UI animations
|
Reduce motion in UI animations
|
||||||
</label>
|
</label>
|
||||||
|
<label class="setting-group">
|
||||||
|
<input type="checkbox" id="choice-always-show-focus-ring"
|
||||||
|
bind:checked="$alwaysShowFocusRing" on:change="onChange(event)">
|
||||||
|
Always show
|
||||||
|
<Tooltip
|
||||||
|
text="focus ring"
|
||||||
|
tooltipText={
|
||||||
|
"The focus ring is the outline showing the currently focused element. By default, it's only " +
|
||||||
|
"shown when using the keyboard (not mouse or touch), but you may choose to always show it."
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
<label class="setting-group">
|
<label class="setting-group">
|
||||||
<input type="checkbox" id="choice-disable-tap-on-status"
|
<input type="checkbox" id="choice-disable-tap-on-status"
|
||||||
bind:checked="$disableTapOnStatus" on:change="onChange(event)">
|
bind:checked="$disableTapOnStatus" on:change="onChange(event)">
|
||||||
|
|
11
src/routes/_store/observers/focusRingObservers.js
Normal file
11
src/routes/_store/observers/focusRingObservers.js
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
const style = process.browser && document.getElementById('theFocusVisibleStyle')
|
||||||
|
|
||||||
|
export function focusRingObservers (store) {
|
||||||
|
if (!process.browser) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
store.observe('alwaysShowFocusRing', alwaysShowFocusRing => {
|
||||||
|
style.setAttribute('media', alwaysShowFocusRing ? 'only x' : 'all') // disable or enable the style
|
||||||
|
})
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ import { setupLoggedInObservers } from './setupLoggedInObservers'
|
||||||
import { logOutObservers } from './logOutObservers'
|
import { logOutObservers } from './logOutObservers'
|
||||||
import { touchObservers } from './touchObservers'
|
import { touchObservers } from './touchObservers'
|
||||||
import { grayscaleObservers } from './grayscaleObservers'
|
import { grayscaleObservers } from './grayscaleObservers'
|
||||||
|
import { focusRingObservers } from './focusRingObservers'
|
||||||
import { leftRightFocusObservers } from './leftRightFocusObservers'
|
import { leftRightFocusObservers } from './leftRightFocusObservers'
|
||||||
|
|
||||||
export function observers (store) {
|
export function observers (store) {
|
||||||
|
@ -17,6 +18,7 @@ export function observers (store) {
|
||||||
resizeObservers(store)
|
resizeObservers(store)
|
||||||
touchObservers(store)
|
touchObservers(store)
|
||||||
logOutObservers(store)
|
logOutObservers(store)
|
||||||
|
focusRingObservers(store)
|
||||||
grayscaleObservers(store)
|
grayscaleObservers(store)
|
||||||
leftRightFocusObservers(store)
|
leftRightFocusObservers(store)
|
||||||
setupLoggedInObservers(store)
|
setupLoggedInObservers(store)
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { observe } from 'svelte-extras'
|
||||||
import { isKaiOS } from '../_utils/userAgent/isKaiOS'
|
import { isKaiOS } from '../_utils/userAgent/isKaiOS'
|
||||||
|
|
||||||
const persistedState = {
|
const persistedState = {
|
||||||
|
alwaysShowFocusRing: false,
|
||||||
autoplayGifs: false,
|
autoplayGifs: false,
|
||||||
composeData: {},
|
composeData: {},
|
||||||
currentInstance: null,
|
currentInstance: null,
|
||||||
|
|
|
@ -17,3 +17,7 @@ export const importCustomElementsPolyfill = () => import(
|
||||||
export const importIntl = () => import(
|
export const importIntl = () => import(
|
||||||
/* webpackChunkName: '$polyfill$-intl' */ 'intl'
|
/* webpackChunkName: '$polyfill$-intl' */ 'intl'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
export const importFocusVisible = () => import(
|
||||||
|
/* webpackChunkName: '$polyfill$-focus-visible' */ 'focus-visible'
|
||||||
|
)
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
import {
|
import {
|
||||||
importCustomElementsPolyfill,
|
importCustomElementsPolyfill,
|
||||||
|
importFocusVisible,
|
||||||
importIndexedDBGetAllShim,
|
importIndexedDBGetAllShim,
|
||||||
importIntersectionObserver,
|
importIntersectionObserver,
|
||||||
importIntl,
|
importIntl,
|
||||||
importRequestIdleCallback
|
importRequestIdleCallback
|
||||||
} from './asyncPolyfills'
|
} from './asyncPolyfills'
|
||||||
|
import { supportsSelector } from './supportsSelector'
|
||||||
|
|
||||||
export function loadPolyfills () {
|
export function loadPolyfills () {
|
||||||
return Promise.all([
|
return Promise.all([
|
||||||
|
@ -12,6 +14,7 @@ export function loadPolyfills () {
|
||||||
typeof requestIdleCallback === 'undefined' && importRequestIdleCallback(),
|
typeof requestIdleCallback === 'undefined' && importRequestIdleCallback(),
|
||||||
!IDBObjectStore.prototype.getAll && importIndexedDBGetAllShim(),
|
!IDBObjectStore.prototype.getAll && importIndexedDBGetAllShim(),
|
||||||
typeof customElements === 'undefined' && importCustomElementsPolyfill(),
|
typeof customElements === 'undefined' && importCustomElementsPolyfill(),
|
||||||
process.env.LEGACY && typeof Intl === 'undefined' && importIntl()
|
process.env.LEGACY && typeof Intl === 'undefined' && importIntl(),
|
||||||
|
!supportsSelector(':focus-visible') && importFocusVisible()
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
13
src/routes/_utils/supportsSelector.js
Normal file
13
src/routes/_utils/supportsSelector.js
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
// See https://stackoverflow.com/a/8533927
|
||||||
|
export function supportsSelector (selector) {
|
||||||
|
const style = document.createElement('style')
|
||||||
|
document.head.appendChild(style)
|
||||||
|
try {
|
||||||
|
style.sheet.insertRule(selector + '{}', 0)
|
||||||
|
} catch (e) {
|
||||||
|
return false
|
||||||
|
} finally {
|
||||||
|
document.head.removeChild(style)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
|
@ -1,6 +1,4 @@
|
||||||
|
:focus {
|
||||||
|
|
||||||
*:focus {
|
|
||||||
outline: var(--focus-width) solid var(--focus-outline);
|
outline: var(--focus-width) solid var(--focus-outline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4254,6 +4254,11 @@ flush-write-stream@^1.0.0:
|
||||||
inherits "^2.0.3"
|
inherits "^2.0.3"
|
||||||
readable-stream "^2.3.6"
|
readable-stream "^2.3.6"
|
||||||
|
|
||||||
|
focus-visible@^5.1.0:
|
||||||
|
version "5.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/focus-visible/-/focus-visible-5.1.0.tgz#4b9d40143b865f53eafbd93ca66672b3bf9e7b6a"
|
||||||
|
integrity sha512-nPer0rjtzdZ7csVIu233P2cUm/ks/4aVSI+5KUkYrYpgA7ujgC3p6J7FtFU+AIMWwnwYQOB/yeiOITxFeYIXiw==
|
||||||
|
|
||||||
for-in@^1.0.2:
|
for-in@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
|
resolved "https://registry.yarnpkg.com/for-in/-/for-in-1.0.2.tgz#81068d295a8142ec0ac726c6e2200c30fb6d5e80"
|
||||||
|
|
Loading…
Reference in a new issue