refactor: repo (#1070)

This commit is contained in:
Mo
2022-06-07 07:18:41 -05:00
committed by GitHub
parent 4c65784421
commit f4ef63693c
1102 changed files with 5786 additions and 3366 deletions

View File

@@ -0,0 +1,67 @@
import {
CSSProperties,
FunctionComponent,
KeyboardEventHandler,
ReactNode,
useCallback,
useEffect,
useRef,
} from 'react'
import { KeyboardKey } from '@/Services/IOService'
import { useListKeyboardNavigation } from '@/Hooks/useListKeyboardNavigation'
type MenuProps = {
className?: string
style?: CSSProperties | undefined
a11yLabel: string
children: ReactNode
closeMenu?: () => void
isOpen: boolean
initialFocus?: number
}
const Menu: FunctionComponent<MenuProps> = ({
children,
className = '',
style,
a11yLabel,
closeMenu,
isOpen,
initialFocus,
}: MenuProps) => {
const menuElementRef = useRef<HTMLMenuElement>(null)
const handleKeyDown: KeyboardEventHandler<HTMLMenuElement> = useCallback(
(event) => {
if (event.key === KeyboardKey.Escape) {
closeMenu?.()
return
}
},
[closeMenu],
)
useListKeyboardNavigation(menuElementRef, initialFocus)
useEffect(() => {
if (isOpen) {
setTimeout(() => {
menuElementRef.current?.focus()
})
}
}, [isOpen])
return (
<menu
className={`m-0 pl-0 list-style-none focus:shadow-none ${className}`}
onKeyDown={handleKeyDown}
ref={menuElementRef}
style={style}
aria-label={a11yLabel}
>
{children}
</menu>
)
}
export default Menu

View File

@@ -0,0 +1,77 @@
import { forwardRef, MouseEventHandler, ReactNode, Ref } from 'react'
import Icon from '@/Components/Icon/Icon'
import Switch from '@/Components/Switch/Switch'
import { SwitchProps } from '@/Components/Switch/SwitchProps'
import { IconType } from '@standardnotes/snjs'
import { FOCUSABLE_BUT_NOT_TABBABLE } from '@/Constants/Constants'
import { MenuItemType } from './MenuItemType'
type MenuItemProps = {
type: MenuItemType
children: ReactNode
onClick?: MouseEventHandler<HTMLButtonElement>
onChange?: SwitchProps['onChange']
onBlur?: (event: { relatedTarget: EventTarget | null }) => void
className?: string
checked?: boolean
icon?: IconType
iconClassName?: string
tabIndex?: number
}
const MenuItem = forwardRef(
(
{
children,
onClick,
onChange,
onBlur,
className = '',
type,
checked,
icon,
iconClassName,
tabIndex,
}: MenuItemProps,
ref: Ref<HTMLButtonElement>,
) => {
return type === MenuItemType.SwitchButton && typeof onChange === 'function' ? (
<li className="list-style-none" role="none">
<button
ref={ref}
className="sn-dropdown-item focus:bg-info-backdrop focus:shadow-none justify-between"
onClick={() => {
onChange(!checked)
}}
onBlur={onBlur}
tabIndex={typeof tabIndex === 'number' ? tabIndex : FOCUSABLE_BUT_NOT_TABBABLE}
role="menuitemcheckbox"
aria-checked={checked}
>
<span className="flex flex-grow items-center">{children}</span>
<Switch className="px-0" checked={checked} />
</button>
</li>
) : (
<li className="list-style-none" role="none">
<button
ref={ref}
role={type === MenuItemType.RadioButton ? 'menuitemradio' : 'menuitem'}
tabIndex={typeof tabIndex === 'number' ? tabIndex : FOCUSABLE_BUT_NOT_TABBABLE}
className={`sn-dropdown-item focus:bg-info-backdrop focus:shadow-none ${className}`}
onClick={onClick}
onBlur={onBlur}
{...(type === MenuItemType.RadioButton ? { 'aria-checked': checked } : {})}
>
{type === MenuItemType.IconButton && icon ? <Icon type={icon} className={iconClassName} /> : null}
{type === MenuItemType.RadioButton && typeof checked === 'boolean' ? (
<div className={`pseudo-radio-btn ${checked ? 'pseudo-radio-btn--checked' : ''} flex-shrink-0`}></div>
) : null}
{children}
</button>
</li>
)
},
)
export default MenuItem

View File

@@ -0,0 +1,9 @@
import { FunctionComponent } from 'react'
const MenuItemSeparator: FunctionComponent = () => (
<li className="list-style-none" role="none">
<div role="separator" className="h-1px my-2 bg-border" />
</li>
)
export default MenuItemSeparator

View File

@@ -0,0 +1,5 @@
export enum MenuItemType {
IconButton,
RadioButton,
SwitchButton,
}