0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-02-17 22:04:19 -05:00

refactor(console): improve tabs used in mdx files

This commit is contained in:
Charles Zhao 2022-05-07 15:18:21 +08:00
parent def900b3fa
commit 56d610bae9
No known key found for this signature in database
GPG key ID: 4858774754C92DF2
2 changed files with 61 additions and 27 deletions

View file

@ -0,0 +1,32 @@
@use '@/scss/underscore' as _;
.container {
width: 100%;
ul {
border-bottom: 1px solid var(--color-divider);
display: flex;
margin: _.unit(1) 0;
padding: 0;
li {
list-style: none;
margin-right: _.unit(6);
padding-bottom: _.unit(1);
font: var(--font-subhead-2);
color: var(--color-caption);
cursor: pointer;
}
li[aria-selected='true'] {
color: var(--color-primary);
border-bottom: 2px solid var(--color-primary);
margin-bottom: -1px;
outline: none;
}
}
.hidden {
display: none;
}
}

View file

@ -6,9 +6,10 @@
*/ */
import { Nullable } from '@silverhand/essentials'; import { Nullable } from '@silverhand/essentials';
import React, { useState, isValidElement, type ReactElement, cloneElement } from 'react'; import React, { useState, isValidElement, type ReactElement, cloneElement, useRef } from 'react';
import type { Props as TabItemProps } from '../TabItem'; import type { Props as TabItemProps } from '../TabItem';
import * as styles from './index.module.scss';
type Props = { type Props = {
className?: string; className?: string;
@ -35,20 +36,11 @@ const Tabs = ({ className, children }: Props): JSX.Element => {
label, label,
})); }));
const [selectedValue, setSelectedValue] = useState<string>(); const [selectedIndex, setSelectedIndex] = useState(0);
const tabReferences: Array<Nullable<HTMLLIElement>> = []; const tabReferences = useRef<Array<Nullable<HTMLLIElement>>>(
// eslint-disable-next-line @typescript-eslint/ban-types
const handleTabChange = ( Array.from<null>({ length }).fill(null)
event: React.FocusEvent<HTMLLIElement> | React.MouseEvent<HTMLLIElement> );
) => {
const newTab = event.currentTarget;
const newTabIndex = tabReferences.indexOf(newTab);
const newTabValue = values[newTabIndex]?.value;
if (newTabValue !== selectedValue) {
setSelectedValue(newTabValue);
}
};
const handleKeydown = (event: React.KeyboardEvent<HTMLLIElement>) => { const handleKeydown = (event: React.KeyboardEvent<HTMLLIElement>) => {
// eslint-disable-next-line @silverhand/fp/no-let // eslint-disable-next-line @silverhand/fp/no-let
@ -56,17 +48,19 @@ const Tabs = ({ className, children }: Props): JSX.Element => {
switch (event.key) { switch (event.key) {
case 'ArrowRight': { case 'ArrowRight': {
const nextTab = tabReferences.indexOf(event.currentTarget) + 1; const nextTab = tabReferences.current.indexOf(event.currentTarget) + 1;
// eslint-disable-next-line @silverhand/fp/no-mutation // eslint-disable-next-line @silverhand/fp/no-mutation
focusElement = tabReferences[nextTab] ?? tabReferences[0] ?? null; focusElement = tabReferences.current[nextTab] ?? tabReferences.current[0] ?? null;
break; break;
} }
case 'ArrowLeft': { case 'ArrowLeft': {
const previousTab = tabReferences.indexOf(event.currentTarget) - 1; const previousTab = tabReferences.current.indexOf(event.currentTarget) - 1;
// eslint-disable-next-line @silverhand/fp/no-mutation // eslint-disable-next-line @silverhand/fp/no-mutation
focusElement = focusElement =
tabReferences[previousTab] ?? tabReferences[tabReferences.length - 1] ?? null; tabReferences.current[previousTab] ??
tabReferences.current[tabReferences.current.length - 1] ??
null;
break; break;
} }
default: default:
@ -77,27 +71,35 @@ const Tabs = ({ className, children }: Props): JSX.Element => {
}; };
return ( return (
<div> <div className={styles.container}>
<ul role="tablist" aria-orientation="horizontal" className={className}> <ul role="tablist" aria-orientation="horizontal" className={className}>
{values.map(({ value, label }) => ( {values.map(({ value, label }, index) => (
<li <li
key={value} key={value}
ref={(tabControl) => tabReferences.concat(tabControl)} ref={(element) => {
// eslint-disable-next-line @silverhand/fp/no-mutation
tabReferences.current[index] = element;
}}
role="tab" role="tab"
tabIndex={selectedValue === value ? 0 : -1} tabIndex={selectedIndex === index ? 0 : -1}
aria-selected={selectedValue === value} aria-selected={selectedIndex === index}
onKeyDown={handleKeydown} onKeyDown={handleKeydown}
onFocus={handleTabChange} onFocus={() => {
onClick={handleTabChange} setSelectedIndex(index);
}}
onClick={() => {
setSelectedIndex(index);
}}
> >
{label ?? value} {label ?? value}
</li> </li>
))} ))}
</ul> </ul>
<div> <div>
{verifiedChildren.map((tabItem) => {verifiedChildren.map((tabItem, index) =>
cloneElement(tabItem, { cloneElement(tabItem, {
key: tabItem.props.value, key: tabItem.props.value,
className: index === selectedIndex ? undefined : styles.hidden,
}) })
)} )}
</div> </div>