Fix FAB style by dropping in react-tiny-fab source

This commit is contained in:
Haishan 2021-06-06 12:40:05 +08:00
parent 5ff2f89afb
commit 0b58242f73

View file

@ -1,10 +1,12 @@
// adapted from https://github.com/dericgw/react-tiny-fab/blob/master/src/index.tsx
import './rtf.css';
import * as React from 'react';
import { Action, Fab } from 'react-tiny-fab/dist';
import s from './Fab.module.scss';
const { useState } = React;
export function IsFetching({ children }: { children: React.ReactNode }) {
return <span className={s.spining}>{children}</span>;
}
@ -14,4 +16,143 @@ export const position = {
bottom: 10,
};
export { Fab, Action };
interface ABProps extends React.HTMLAttributes<HTMLButtonElement> {
text?: string;
onClick?: (e: React.FormEvent) => void;
'data-testid'?: string;
}
const AB: React.FC<ABProps> = ({ children, ...p }) => (
<button type="button" {...p} className="rtf--ab">
{children}
</button>
);
interface MBProps
extends Omit<React.HTMLAttributes<HTMLButtonElement>, 'tabIndex'> {
tabIndex?: number;
}
export const MB: React.FC<MBProps> = ({ children, ...p }) => (
<button type="button" className="rtf--mb" {...p}>
{children}
</button>
);
const defaultStyles: React.CSSProperties = { bottom: 24, right: 24 };
interface FabProps {
event?: 'hover' | 'click';
style?: React.CSSProperties;
alwaysShowTitle?: boolean;
icon?: React.ReactNode;
mainButtonStyles?: React.CSSProperties;
onClick?: (e: React.FormEvent) => void;
text?: string;
children?: React.ReactNode;
}
const Fab: React.FC<FabProps> = ({
event = 'hover',
style = defaultStyles,
alwaysShowTitle = false,
children,
icon,
mainButtonStyles,
onClick,
text,
...p
}) => {
const [isOpen, setIsOpen] = useState(false);
const ariaHidden = alwaysShowTitle || !isOpen;
const open = () => setIsOpen(true);
const close = () => setIsOpen(false);
const enter = () => event === 'hover' && open();
const leave = () => event === 'hover' && close();
const toggle = (e: React.FormEvent) => {
if (onClick) {
return onClick(e);
}
e.persist();
return event === 'click' ? (isOpen ? close() : open()) : null;
};
const actionOnClick = (
e: React.FormEvent,
userFunc: (e: React.FormEvent) => void
) => {
e.persist();
setIsOpen(false);
setTimeout(() => {
userFunc(e);
}, 1);
};
const rc = () =>
React.Children.map(children, (ch, i) => {
if (React.isValidElement<ABProps>(ch)) {
return (
<li className={`rtf--ab__c ${'top' in style ? 'top' : ''}`}>
{React.cloneElement(ch, {
'data-testid': `action-button-${i}`,
'aria-label': ch.props.text || `Menu button ${i + 1}`,
'aria-hidden': ariaHidden,
tabIndex: isOpen ? 0 : -1,
...ch.props,
onClick: (e: React.FormEvent) => {
if (ch.props.onClick) actionOnClick(e, ch.props.onClick);
},
})}
{ch.props.text && (
<span
className={`${'right' in style ? 'right' : ''} ${
alwaysShowTitle ? 'always-show' : ''
}`}
aria-hidden={ariaHidden}
>
{ch.props.text}
</span>
)}
</li>
);
}
return null;
});
return (
<ul
onMouseEnter={enter}
onMouseLeave={leave}
className={`rtf ${isOpen ? 'open' : 'closed'}`}
data-testid="fab"
style={style}
{...p}
>
<li className="rtf--mb__c">
<MB
onClick={toggle}
style={mainButtonStyles}
data-testid="main-button"
role="button"
aria-label="Floating menu"
tabIndex={0}
>
{icon}
</MB>
{text && (
<span
className={`${'right' in style ? 'right' : ''} ${
alwaysShowTitle ? 'always-show' : ''
}`}
aria-hidden={ariaHidden}
>
{text}
</span>
)}
<ul>{rc()}</ul>
</li>
</ul>
);
};
export { Fab, AB as Action };