0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-01-20 21:32:31 -05:00

Merge pull request #753 from logto-io/charles-log-2331-improve-tabs-in-guide-mdx

refactor(console): improve tabs used in mdx files
This commit is contained in:
Charles Zhao 2022-05-07 17:54:23 +08:00 committed by GitHub
commit 0fa5f9db19
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
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 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 * as styles from './index.module.scss';
type Props = {
className?: string;
@ -35,20 +36,11 @@ const Tabs = ({ className, children }: Props): JSX.Element => {
label,
}));
const [selectedValue, setSelectedValue] = useState<string>();
const tabReferences: Array<Nullable<HTMLLIElement>> = [];
const handleTabChange = (
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 [selectedIndex, setSelectedIndex] = useState(0);
const tabReferences = useRef<Array<Nullable<HTMLLIElement>>>(
// eslint-disable-next-line @typescript-eslint/ban-types
Array.from<null>({ length }).fill(null)
);
const handleKeydown = (event: React.KeyboardEvent<HTMLLIElement>) => {
// eslint-disable-next-line @silverhand/fp/no-let
@ -56,17 +48,19 @@ const Tabs = ({ className, children }: Props): JSX.Element => {
switch (event.key) {
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
focusElement = tabReferences[nextTab] ?? tabReferences[0] ?? null;
focusElement = tabReferences.current[nextTab] ?? tabReferences.current[0] ?? null;
break;
}
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
focusElement =
tabReferences[previousTab] ?? tabReferences[tabReferences.length - 1] ?? null;
tabReferences.current[previousTab] ??
tabReferences.current[tabReferences.current.length - 1] ??
null;
break;
}
default:
@ -77,27 +71,35 @@ const Tabs = ({ className, children }: Props): JSX.Element => {
};
return (
<div>
<div className={styles.container}>
<ul role="tablist" aria-orientation="horizontal" className={className}>
{values.map(({ value, label }) => (
{values.map(({ value, label }, index) => (
<li
key={value}
ref={(tabControl) => tabReferences.concat(tabControl)}
ref={(element) => {
// eslint-disable-next-line @silverhand/fp/no-mutation
tabReferences.current[index] = element;
}}
role="tab"
tabIndex={selectedValue === value ? 0 : -1}
aria-selected={selectedValue === value}
tabIndex={selectedIndex === index ? 0 : -1}
aria-selected={selectedIndex === index}
onKeyDown={handleKeydown}
onFocus={handleTabChange}
onClick={handleTabChange}
onFocus={() => {
setSelectedIndex(index);
}}
onClick={() => {
setSelectedIndex(index);
}}
>
{label ?? value}
</li>
))}
</ul>
<div>
{verifiedChildren.map((tabItem) =>
{verifiedChildren.map((tabItem, index) =>
cloneElement(tabItem, {
key: tabItem.props.value,
className: index === selectedIndex ? undefined : styles.hidden,
})
)}
</div>