UNPKG

2.06 kBTypeScriptView Raw
1/*
2 * Copyright 2020 Adobe. All rights reserved.
3 * This file is licensed to you under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License. You may obtain a copy
5 * of the License at http://www.apache.org/licenses/LICENSE-2.0
6 *
7 * Unless required by applicable law or agreed to in writing, software distributed under
8 * the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9 * OF ANY KIND, either express or implied. See the License for the specific language
10 * governing permissions and limitations under the License.
11 */
12
13import clsx from 'clsx';
14import {mergeProps} from '@react-aria/utils';
15import React, {ReactElement} from 'react';
16import {useFocusRing} from './useFocusRing';
17
18export interface FocusRingProps {
19 /** Child element to apply CSS classes to. */
20 children: ReactElement,
21 /** CSS class to apply when the element is focused. */
22 focusClass?: string,
23 /** CSS class to apply when the element has keyboard focus. */
24 focusRingClass?: string,
25 /**
26 * Whether to show the focus ring when something
27 * inside the container element has focus (true), or
28 * only if the container itself has focus (false).
29 * @default false
30 */
31 within?: boolean,
32 /** Whether the element is a text input. */
33 isTextInput?: boolean,
34 /** Whether the element will be auto focused. */
35 autoFocus?: boolean
36}
37
38/**
39 * A utility component that applies a CSS class when an element has keyboard focus.
40 * Focus rings are visible only when the user is interacting with a keyboard,
41 * not with a mouse, touch, or other input methods.
42 */
43export function FocusRing(props: FocusRingProps) {
44 let {children, focusClass, focusRingClass} = props;
45 let {isFocused, isFocusVisible, focusProps} = useFocusRing(props);
46 let child = React.Children.only(children);
47
48 return React.cloneElement(child, mergeProps(child.props, {
49 ...focusProps,
50 className: clsx({
51 [focusClass || '']: isFocused,
52 [focusRingClass || '']: isFocusVisible
53 })
54 }));
55}