Skip to content

Commit

Permalink
refactor(v2): remove focus outline from mouse users (#3626)
Browse files Browse the repository at this point in the history
* refactor(v2): remove focus outline from mouse users

* Improvements

* Cleanup
  • Loading branch information
lex111 authored Oct 27, 2020
1 parent 4f64da8 commit 9837299
Show file tree
Hide file tree
Showing 5 changed files with 60 additions and 30 deletions.
3 changes: 3 additions & 0 deletions packages/docusaurus-theme-classic/src/theme/Layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,14 @@ import Footer from '@theme/Footer';
import LayoutProviders from '@theme/LayoutProviders';
import LayoutHead from '@theme/LayoutHead';
import type {Props} from '@theme/Layout';
import useKeyboardNavigation from '@theme/hooks/useKeyboardNavigation';
import './styles.css';

function Layout(props: Props): JSX.Element {
const {children, noFooter, wrapperClassName} = props;

useKeyboardNavigation();

return (
<LayoutProviders>
<LayoutHead {...props} />
Expand Down
32 changes: 2 additions & 30 deletions packages/docusaurus-theme-classic/src/theme/Tabs/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* LICENSE file in the root directory of this source tree.
*/

import React, {useState, Children, ReactElement, useEffect} from 'react';
import React, {useState, Children, ReactElement} from 'react';
import useUserPreferencesContext from '@theme/hooks/useUserPreferencesContext';
import type {Props} from '@theme/Tabs';

Expand All @@ -16,14 +16,12 @@ import styles from './styles.module.css';
const keys = {
left: 37,
right: 39,
tab: 9,
};

function Tabs(props: Props): JSX.Element {
const {block, children, defaultValue, values, groupId, className} = props;
const {tabGroupChoices, setTabGroupChoices} = useUserPreferencesContext();
const [selectedValue, setSelectedValue] = useState(defaultValue);
const [keyboardPress, setKeyboardPress] = useState(false);

if (groupId != null) {
const relevantTabGroupChoice = tabGroupChoices[groupId];
Expand Down Expand Up @@ -78,28 +76,6 @@ function Tabs(props: Props): JSX.Element {
}
};

const handleKeyboardEvent = (event) => {
if (event.metaKey || event.altKey || event.ctrlKey) {
return;
}

setKeyboardPress(true);
};

const handleMouseEvent = () => {
setKeyboardPress(false);
};

useEffect(() => {
window.addEventListener('keydown', handleKeyboardEvent);
window.addEventListener('mousedown', handleMouseEvent);

return () => {
window.removeEventListener('keydown', handleKeyboardEvent);
window.removeEventListener('mousedown', handleMouseEvent);
};
}, []);

return (
<div>
<ul
Expand All @@ -120,19 +96,15 @@ function Tabs(props: Props): JSX.Element {
className={clsx('tabs__item', styles.tabItem, {
'tabs__item--active': selectedValue === value,
})}
style={keyboardPress ? {} : {outline: 'none'}}
key={value}
ref={(tabControl) => tabRefs.push(tabControl)}
onKeyDown={(event) => {
handleKeydown(tabRefs, event.target, event);
handleKeyboardEvent(event);
}}
onFocus={() => changeSelectedValue(value)}
onClick={() => {
changeSelectedValue(value);
setKeyboardPress(false);
}}
onPointerDown={() => setKeyboardPress(false)}>
}}>
{label}
</li>
))}
Expand Down
10 changes: 10 additions & 0 deletions packages/docusaurus-theme-classic/src/theme/hooks/styles.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

body:not(.navigation-with-keyboard) *:not(input):focus {
outline: none;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import {useEffect} from 'react';

import './styles.css';

// This hook detect keyboard focus indicator to not show outline for mouse users
// Inspired by https://hackernoon.com/removing-that-ugly-focus-ring-and-keeping-it-too-6c8727fefcd2
function useKeyboardNavigation(): void {
useEffect(() => {
const keyboardFocusedClassName = 'navigation-with-keyboard';

function handleOutlineStyles(e: MouseEvent | KeyboardEvent) {
if (e.type === 'keydown' && (e as KeyboardEvent).key === 'Tab') {
document.body.classList.add(keyboardFocusedClassName);
}

if (e.type === 'mousedown') {
document.body.classList.remove(keyboardFocusedClassName);
}
}

document.addEventListener('keydown', handleOutlineStyles);
document.addEventListener('mousedown', handleOutlineStyles);

return () => {
document.body.classList.remove(keyboardFocusedClassName);
document.removeEventListener('keydown', handleOutlineStyles);
document.removeEventListener('mousedown', handleOutlineStyles);
};
}, []);
}

export default useKeyboardNavigation;
6 changes: 6 additions & 0 deletions packages/docusaurus-theme-classic/src/types.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,12 @@ declare module '@theme/hooks/useWindowSize' {
export default function useWindowSize(): WindowSize | undefined;
}

declare module '@theme/hooks/useKeyboardNavigation' {
const useKeyboardNavigation: () => void;

export default useKeyboardNavigation;
}

declare module '@theme/Layout' {
import type {ReactNode} from 'react';

Expand Down

0 comments on commit 9837299

Please sign in to comment.