Skip to content

Commit

Permalink
refactor: use css outline & new useFocusVisibleClassName() hook t…
Browse files Browse the repository at this point in the history
…o draw visible focus (#5876) (#6131)
  • Loading branch information
eugpoloz authored Nov 23, 2023
1 parent d9ac49b commit e0e90a6
Show file tree
Hide file tree
Showing 77 changed files with 530 additions and 312 deletions.
28 changes: 15 additions & 13 deletions packages/vkui/src/components/Avatar/Avatar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -81,37 +81,39 @@ export const Avatar = ({
className,
gradientColor,
initials,
fallbackIcon,
fallbackIcon: fallbackIconProp,
children,
...restProps
}: AvatarProps) => {
const gradientName =
typeof gradientColor === 'number' ? COLORS_NUMBER_TO_TEXT_MAP[gradientColor] : gradientColor;
const isGradientNotCustom = gradientName && gradientName !== 'custom';
const rewrittenFallbackIcon = initials ? undefined : fallbackIcon;

const fallbackIcon = initials ? (
<div
className={styles['Avatar__initials']}
style={{
fontSize: getInitialsFontSize(size),
}}
>
{initials}
</div>
) : (
fallbackIconProp
);

return (
<ImageBase
{...restProps}
size={size}
fallbackIcon={rewrittenFallbackIcon}
fallbackIcon={fallbackIcon}
className={classNames(
styles['Avatar'],
gradientName && styles['Avatar--has-gradient'],
isGradientNotCustom && gradientStyles[gradientName],
className,
)}
>
{initials && (
<div
className={styles['Avatar__initials']}
style={{
fontSize: getInitialsFontSize(size),
}}
>
{initials}
</div>
)}
{children}
</ImageBase>
);
Expand Down
5 changes: 0 additions & 5 deletions packages/vkui/src/components/Clickable/Clickable.module.css
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
.Clickable__host {
cursor: pointer;
}

.Clickable__host:focus,
.Clickable__host:focus-visible {
outline: none;
}
12 changes: 7 additions & 5 deletions packages/vkui/src/components/Clickable/Clickable.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import * as React from 'react';
import { classNames } from '@vkontakte/vkjs';
import { useFocusVisible } from '../../hooks/useFocusVisible';
import {
type FocusVisibleModeProps,
useFocusVisibleClassName,
} from '../../hooks/useFocusVisibleClassName';
import { callMultiple } from '../../lib/callMultiple';
import { FocusVisible, FocusVisibleMode } from '../FocusVisible/FocusVisible';
import { RootComponent, RootComponentProps } from '../RootComponent/RootComponent';
import styles from './Clickable.module.css';

export interface ClickableProps<T> extends RootComponentProps<T> {
export interface ClickableProps<T> extends RootComponentProps<T>, FocusVisibleModeProps {
baseClassName?: string;
focusVisibleMode?: FocusVisibleMode;
}

/**
Expand All @@ -31,16 +33,16 @@ const RealClickable = <T,>({
...restProps
}: ClickableProps<T>) => {
const { focusVisible, onBlur, onFocus } = useFocusVisible();
const focusVisibleClassNames = useFocusVisibleClassName({ focusVisible, mode: focusVisibleMode });

return (
<RootComponent
baseClassName={classNames(baseClassName, styles['Clickable__host'])}
baseClassName={classNames(baseClassName, focusVisibleClassNames, styles['Clickable__host'])}
onBlur={callMultiple(onBlur, restProps.onBlur)}
onFocus={callMultiple(onFocus, restProps.onFocus)}
{...restProps}
>
{children}
<FocusVisible visible={focusVisible} mode={focusVisibleMode} />
</RootComponent>
);
};
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
98 changes: 0 additions & 98 deletions packages/vkui/src/components/FocusVisible/FocusVisible.module.css

This file was deleted.

35 changes: 0 additions & 35 deletions packages/vkui/src/components/FocusVisible/FocusVisible.tsx

This file was deleted.

18 changes: 11 additions & 7 deletions packages/vkui/src/components/FormField/FormField.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
-webkit-tap-highlight-color: transparent;
isolation: isolate;
border-radius: var(--vkui--size_border_radius--regular);
outline: none;
}

.FormField--sizeY-compact {
Expand Down Expand Up @@ -86,9 +85,9 @@
}

/**
* [start]
* CMP:
* FormItem
* [start]
*/
:global(.vkuiInternalFormItem--status-error) .FormField__border,
.FormField--status-error .FormField__border {
Expand Down Expand Up @@ -123,11 +122,6 @@
z-index: var(--vkui_internal--z_index_form_field_border_hover);
}

/* stylelint-disable-next-line @project-tools/stylelint-atomic, selector-max-universal */
.FormField *:focus {
outline: none;
}

/**
* CMP:
* ModalCardBase
Expand Down Expand Up @@ -207,3 +201,13 @@
border-bottom-left-radius: var(--vkui--size_border_radius--regular);
border-bottom-right-radius: var(--vkui--size_border_radius--regular);
}

/**
* useFocusVisibleClassName()
*/
/* increase specificity for selects */
.FormField--focus-visible.FormField--focus-visible.FormField--focus-visible {
outline: var(--vkui_internal--outline);
outline-width: var(--vkui--size_border--regular);
outline-offset: calc(-1 * var(--vkui--size_border--regular));
}
11 changes: 8 additions & 3 deletions packages/vkui/src/components/FormField/FormField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import * as React from 'react';
import { classNames } from '@vkontakte/vkjs';
import { useAdaptivity } from '../../hooks/useAdaptivity';
import { useExternRef } from '../../hooks/useExternRef';
import { useFocusVisibleClassName } from '../../hooks/useFocusVisibleClassName';
import { useFocusWithin } from '../../hooks/useFocusWithin';
import { SizeType } from '../../lib/adaptivity';
import { HasComponent, HasRootRef } from '../../types';
import { FocusVisible } from '../FocusVisible/FocusVisible';
import styles from './FormField.module.css';

const sizeYClassNames = {
Expand Down Expand Up @@ -65,10 +65,15 @@ export const FormField = ({
...restProps
}: FormFieldOwnProps) => {
const elRef = useExternRef(getRootRef);
const focusWithin = useFocusWithin(elRef);
const { sizeY = 'none' } = useAdaptivity();
const [hover, setHover] = React.useState(false);

const focusWithin = useFocusWithin(elRef);
const focusVisibleClassNames = useFocusVisibleClassName({
focusVisible: focusWithin,
mode: styles['FormField--focus-visible'],
});

const handleMouseEnter = (e: MouseEvent) => {
e.stopPropagation();
setHover(true);
Expand All @@ -92,6 +97,7 @@ export const FormField = ({
sizeY !== SizeType.REGULAR && sizeYClassNames[sizeY],
disabled && styles['FormField--disabled'],
!disabled && hover && styles['FormField--hover'],
focusVisibleClassNames,
className,
)}
>
Expand All @@ -103,7 +109,6 @@ export const FormField = ({
</span>
)}
<span aria-hidden className={styles['FormField__border']} />
<FocusVisible thin visible={focusWithin} mode="outline" />
</Component>
);
};
35 changes: 35 additions & 0 deletions packages/vkui/src/components/Image/Image.e2e-playground.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,3 +86,38 @@ export const ImagePlayground = (props: ComponentPlaygroundProps) => {
</ComponentPlayground>
);
};

export const ImageFocusVisiblePlayground = (props: ComponentPlaygroundProps) => (
<ComponentPlayground
{...props}
propSets={[
{
size: [72],
src: [base64Image],
},
]}
>
{(props: ImageProps) => <Image onClick={() => null} {...props} />}
</ComponentPlayground>
);

export const ImageFocusVisibleOverlayPlayground = (props: ComponentPlaygroundProps) => (
<ComponentPlayground
{...props}
propSets={[
{
size: [72],
src: [base64Image],
children: [
<React.Fragment key="overlay-base">
<Image.Overlay theme="light" visibility="always">
<IconExampleForOverlayBasedOnImageBaseSize />
</Image.Overlay>
</React.Fragment>,
],
},
]}
>
{(props: ImageProps) => <Image {...props} />}
</ComponentPlayground>
);
Loading

0 comments on commit e0e90a6

Please sign in to comment.