fix: use pure CSS for focus effect (#1323)

* fix: use pure CSS for focus effect

fixes #1322

* apply elsewhere too

* fix comment
This commit is contained in:
Nolan Lawson 2019-07-08 09:42:45 -07:00 committed by GitHub
parent 9f3c05b121
commit 68343a7a09
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 26 additions and 66 deletions

View file

@ -2,8 +2,7 @@
{#each items as item (item.key)} {#each items as item (item.key)}
<li class="generic-dialog-list-item"> <li class="generic-dialog-list-item">
<button <button
class="generic-dialog-list-button" class="generic-dialog-list-button focus-after"
on:applyFocusStylesToParent="noop()"
on:click="fire('click', item)"> on:click="fire('click', item)">
<SvgIcon className="generic-dialog-list-item-svg" href={item.icon} /> <SvgIcon className="generic-dialog-list-item-svg" href={item.icon} />
<span class="generic-dialog-list-button-span"> <span class="generic-dialog-list-button-span">
@ -45,9 +44,6 @@
display: flex; display: flex;
flex-direction: row; flex-direction: row;
} }
.generic-dialog-list-button:focus {
outline: none; /* focus style is on parent instead */
}
.generic-dialog-list-button-span { .generic-dialog-list-button-span {
flex: 1; flex: 1;
margin-left: 20px; margin-left: 20px;
@ -93,13 +89,9 @@
</style> </style>
<script> <script>
import SvgIcon from '../../SvgIcon.html' import SvgIcon from '../../SvgIcon.html'
import { applyFocusStylesToParent } from '../../../_utils/events'
import noop from 'lodash-es/noop' import noop from 'lodash-es/noop'
export default { export default {
events: {
applyFocusStylesToParent
},
methods: { methods: {
noop noop
}, },

View file

@ -1,7 +1,7 @@
{#if type === 'video' || type === 'audio'} {#if type === 'video' || type === 'audio'}
<button id={elementId} <button id={elementId}
type="button" type="button"
class="play-video-button {$largeInlineMedia ? '' : 'fixed-size'} {type === 'audio' ? 'play-audio-button' : ''}" class="play-video-button focus-after {$largeInlineMedia ? '' : 'fixed-size'} {type === 'audio' ? 'play-audio-button' : ''}"
aria-label="Play video: {description}" aria-label="Play video: {description}"
style="width: {inlineWidth}px; height: {inlineHeight}px;"> style="width: {inlineWidth}px; height: {inlineHeight}px;">
<PlayVideoIcon /> <PlayVideoIcon />
@ -21,7 +21,7 @@
{:else} {:else}
<button id={elementId} <button id={elementId}
type="button" type="button"
class="show-image-button {$largeInlineMedia ? '' : 'fixed-size'}" class="show-image-button focus-after {$largeInlineMedia ? '' : 'fixed-size'}"
aria-label="Show image: {description}" aria-label="Show image: {description}"
title={description} title={description}
on:mouseover="set({mouseover: event})" on:mouseover="set({mouseover: event})"
@ -72,27 +72,11 @@
border-radius: 0; border-radius: 0;
border: none; border: none;
background: none; background: none;
position: relative;
} }
.play-audio-button { .play-audio-button {
background: var(--audio-bg); background: var(--audio-bg);
} }
/* the actual focus outline is not very visible, so use an ::after pseudo-element */
.play-video-button:focus, .show-image-button:focus {
outline: none;
}
.play-video-button:focus::after, .show-image-button:focus::after {
content: '';
position: absolute;
left: 0;
right: 0;
bottom: 0;
top: 0;
border: 2px solid var(--focus-outline);
}
.show-image-button { .show-image-button {
cursor: zoom-in; cursor: zoom-in;
} }

View file

@ -9,7 +9,6 @@
aria-posinset={index + 1} aria-posinset={index + 1}
aria-setsize={length} aria-setsize={length}
aria-label={ariaLabel} aria-label={ariaLabel}
on:applyFocusStylesToParent="noop()"
> >
<StatusHeader {notification} {notificationId} {status} {statusId} {timelineType} <StatusHeader {notification} {notificationId} {status} {statusId} {timelineType}
{account} {accountId} {uuid} isStatusInNotification="true" /> {account} {accountId} {uuid} isStatusInNotification="true" />
@ -26,9 +25,6 @@
padding: 10px 20px; padding: 10px 20px;
border-bottom: 1px solid var(--main-border); border-bottom: 1px solid var(--main-border);
} }
.notification-article:focus {
outline: none; /* focus is on the parent instead */
}
@media (max-width: 767px) { @media (max-width: 767px) {
.notification-article { .notification-article {
padding: 10px 10px; padding: 10px 10px;
@ -46,7 +42,6 @@
import { goto } from '../../../../__sapper__/client' import { goto } from '../../../../__sapper__/client'
import { composeNewStatusMentioning } from '../../_actions/mention' import { composeNewStatusMentioning } from '../../_actions/mention'
import { classname } from '../../_utils/classname' import { classname } from '../../_utils/classname'
import { applyFocusStylesToParent } from '../../_utils/events'
import noop from 'lodash-es/noop' import noop from 'lodash-es/noop'
import { createStatusOrNotificationUuid } from '../../_utils/createStatusOrNotificationUuid' import { createStatusOrNotificationUuid } from '../../_utils/createStatusOrNotificationUuid'
@ -77,6 +72,7 @@
className: ({ $underlineLinks }) => (classname( className: ({ $underlineLinks }) => (classname(
'notification-article', 'notification-article',
'shortcut-list-item', 'shortcut-list-item',
'focus-after',
$underlineLinks && 'underline-links' $underlineLinks && 'underline-links'
)) ))
}, },
@ -90,9 +86,6 @@
let { account } = this.get() let { account } = this.get()
await composeNewStatusMentioning(account) await composeNewStatusMentioning(account)
} }
},
events: {
applyFocusStylesToParent
} }
} }
</script> </script>

View file

@ -5,7 +5,6 @@
aria-setsize={length} aria-setsize={length}
aria-label={ariaLabel} aria-label={ariaLabel}
on:recalculateHeight on:recalculateHeight
on:applyFocusStylesToParent="noop()"
> >
{#if showHeader} {#if showHeader}
<StatusHeader {...params} /> <StatusHeader {...params} />
@ -81,10 +80,6 @@
background-color: var(--status-direct-background); background-color: var(--status-direct-background);
} }
.status-article:focus {
outline: none; /* focus is on the parent instead */
}
.status-article.status-in-own-thread { .status-article.status-in-own-thread {
grid-template-areas: grid-template-areas:
"sidebar author-name" "sidebar author-name"
@ -139,7 +134,6 @@
import { LONG_POST_LENGTH, LONG_POST_TEXT } from '../../_static/statuses' import { LONG_POST_LENGTH, LONG_POST_TEXT } from '../../_static/statuses'
import { absoluteDateFormatter } from '../../_utils/formatters' import { absoluteDateFormatter } from '../../_utils/formatters'
import { composeNewStatusMentioning } from '../../_actions/mention' import { composeNewStatusMentioning } from '../../_actions/mention'
import { applyFocusStylesToParent } from '../../_utils/events'
import noop from 'lodash-es/noop' import noop from 'lodash-es/noop'
import { createStatusOrNotificationUuid } from '../../_utils/createStatusOrNotificationUuid' import { createStatusOrNotificationUuid } from '../../_utils/createStatusOrNotificationUuid'
import { statusHtmlToPlainText } from '../../_utils/statusHtmlToPlainText' import { statusHtmlToPlainText } from '../../_utils/statusHtmlToPlainText'
@ -300,6 +294,7 @@
className: ({ visibility, timelineType, isStatusInOwnThread, $underlineLinks, $disableTapOnStatus }) => (classname( className: ({ visibility, timelineType, isStatusInOwnThread, $underlineLinks, $disableTapOnStatus }) => (classname(
'status-article', 'status-article',
'shortcut-list-item', 'shortcut-list-item',
'focus-after',
timelineType !== 'direct' && visibility === 'direct' && 'status-direct', timelineType !== 'direct' && visibility === 'direct' && 'status-direct',
timelineType !== 'search' && 'status-in-timeline', timelineType !== 'search' && 'status-in-timeline',
isStatusInOwnThread && 'status-in-own-thread', isStatusInOwnThread && 'status-in-own-thread',
@ -346,9 +341,6 @@
shortcutScope, shortcutScope,
originalStatusEmojis originalStatusEmojis
}) })
},
events: {
applyFocusStylesToParent
} }
} }
</script> </script>

View file

@ -34,28 +34,6 @@ export function selectionChange (node, callback) {
} }
} }
// in some cases we apply focus styles to parent rather
// than the node itself because it shows up better
export function applyFocusStylesToParent (node) {
function onFocus () {
node.parentElement.classList.toggle('focus', true)
}
function onBlur () {
node.parentElement.classList.toggle('focus', false)
}
node.addEventListener('focus', onFocus)
node.addEventListener('blur', onBlur)
return {
destroy () {
node.removeEventListener('focus', onFocus)
node.removeEventListener('blur', onBlur)
}
}
}
export function resize (node, callback) { export function resize (node, callback) {
registerResizeListener(callback) registerResizeListener(callback)

View file

@ -251,3 +251,24 @@ textarea {
.inline-emoji { .inline-emoji {
font-family: PinaforeEmoji, sans-serif; font-family: PinaforeEmoji, sans-serif;
} }
/* Special class to make focus outlines easier to see in some odd
* cases where the outline would be clipped. */
.focus-after {
position: relative;
}
.focus-after:focus {
outline: none;
}
.focus-after:focus::after {
position: absolute;
left: 0;
right: 0;
bottom: 0;
top: 0;
content: '';
border: 2px solid var(--focus-outline);
pointer-events: none;
}