a7990e5bab
state jittering still seems to be an issue on rare occasion even though the button hitbox is no longer changing size.
210 lines
5.3 KiB
JavaScript
210 lines
5.3 KiB
JavaScript
// @flow
|
|
import type { Node } from 'react';
|
|
import React, { forwardRef, useRef } from 'react';
|
|
import Icon from 'component/common/icon';
|
|
import classnames from 'classnames';
|
|
import { NavLink } from 'react-router-dom';
|
|
import { formatLbryUrlForWeb } from 'util/url';
|
|
import { OutboundLink } from 'react-ga';
|
|
import * as PAGES from 'constants/pages';
|
|
import useCombinedRefs from 'effects/use-combined-refs';
|
|
|
|
type Props = {
|
|
id: ?string,
|
|
href: ?string,
|
|
title: ?string,
|
|
label: ?string,
|
|
largestLabel: ?string,
|
|
icon: ?string,
|
|
iconRight: ?string,
|
|
disabled: ?boolean,
|
|
children: ?Node,
|
|
navigate: ?string,
|
|
className: ?string,
|
|
description: ?string,
|
|
type: string,
|
|
button: ?string, // primary, secondary, alt, link
|
|
iconSize?: number,
|
|
iconColor?: string,
|
|
activeClass?: string,
|
|
innerRef: ?any,
|
|
// Events
|
|
onClick: ?(any) => any,
|
|
onMouseEnter: ?(any) => any,
|
|
onMouseLeave: ?(any) => any,
|
|
pathname: string,
|
|
emailVerified: boolean,
|
|
requiresAuth: ?boolean,
|
|
myref: any,
|
|
dispatch: any,
|
|
};
|
|
|
|
// use forwardRef to allow consumers to pass refs to the button content if they want to
|
|
// flow requires forwardRef have default type arguments passed to it
|
|
const Button = forwardRef<any, {}>((props: Props, ref: any) => {
|
|
const {
|
|
type = 'button',
|
|
onClick,
|
|
href,
|
|
title,
|
|
label,
|
|
largestLabel,
|
|
icon,
|
|
// This should rarely be used. Regular buttons should just use `icon`
|
|
// `iconRight` is used for the header (home) button with the LBRY icon and external links that are displayed inline
|
|
iconRight,
|
|
disabled,
|
|
children,
|
|
navigate,
|
|
className,
|
|
description,
|
|
button,
|
|
iconSize,
|
|
iconColor,
|
|
activeClass,
|
|
emailVerified,
|
|
requiresAuth,
|
|
myref,
|
|
dispatch, // <button> doesn't know what to do with dispatch
|
|
pathname,
|
|
...otherProps
|
|
} = props;
|
|
|
|
const combinedClassName = classnames(
|
|
'button',
|
|
button
|
|
? {
|
|
'button--primary': button === 'primary',
|
|
'button--secondary': button === 'secondary',
|
|
'button--alt': button === 'alt',
|
|
'button--inverse': button === 'inverse',
|
|
'button--close': button === 'close',
|
|
'button--disabled': disabled,
|
|
'button--link': button === 'link',
|
|
}
|
|
: 'button--no-style',
|
|
className
|
|
);
|
|
|
|
const innerRef = useRef(null);
|
|
const combinedRef = useCombinedRefs(ref, innerRef, myref);
|
|
const size = iconSize || (!label && !children) ? 18 : undefined; // Fall back to default
|
|
|
|
const content = (
|
|
<div className="button__content" style={{ border: `1px solid white` }}>
|
|
{/* style={{ border: `1px solid white` }} */}
|
|
<div style={{ border: `1px solid green` }}>
|
|
{icon && <Icon icon={icon} iconColor={iconColor} size={iconSize} />}
|
|
</div>
|
|
{
|
|
<div style={{ border: `1px solid blue` }}>
|
|
<span style={{ visibility: 'hidden' }}>
|
|
{largestLabel || label}
|
|
{label && (
|
|
// <div style={{ position: 'absolute', left: 0, right: 0, bottom: 0, top: 0, margin: 'auto' }}>
|
|
<div
|
|
style={{
|
|
position: 'relative',
|
|
left: '50%',
|
|
right: '50%',
|
|
transform: `translate(-50%, -50%)`,
|
|
border: `1px solid red`,
|
|
}}
|
|
>
|
|
<span className="button__label" style={{ visibility: 'visible' }}>
|
|
{label}
|
|
</span>
|
|
</div>
|
|
)}
|
|
</span>
|
|
</div>
|
|
}
|
|
{children && children}
|
|
{iconRight && <Icon icon={iconRight} iconColor={iconColor} size={size} />}
|
|
</span>
|
|
);
|
|
|
|
if (href) {
|
|
return (
|
|
<OutboundLink
|
|
eventLabel="outboundClick"
|
|
to={href}
|
|
target="_blank"
|
|
className={combinedClassName}
|
|
onClick={onClick}
|
|
{...otherProps}
|
|
>
|
|
{content}
|
|
</OutboundLink>
|
|
);
|
|
}
|
|
|
|
// Handle lbry:// uris passed in, or already formatted web urls
|
|
let path = navigate;
|
|
if (path) {
|
|
if (path.startsWith('lbry://')) {
|
|
path = formatLbryUrlForWeb(path);
|
|
} else if (!path.startsWith('/')) {
|
|
// Force a leading slash so new paths aren't appended on to the current path
|
|
path = `/${path}`;
|
|
}
|
|
}
|
|
|
|
if (requiresAuth && !emailVerified) {
|
|
return (
|
|
<NavLink
|
|
exact
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
}}
|
|
to={`/$/${PAGES.AUTH}?redirect=${pathname}`}
|
|
title={title}
|
|
disabled={disabled}
|
|
className={combinedClassName}
|
|
activeClassName={activeClass}
|
|
>
|
|
{content}
|
|
</NavLink>
|
|
);
|
|
}
|
|
|
|
return path ? (
|
|
<NavLink
|
|
exact
|
|
to={path}
|
|
title={title}
|
|
disabled={disabled}
|
|
onClick={(e) => {
|
|
e.stopPropagation();
|
|
if (onClick) {
|
|
onClick();
|
|
}
|
|
}}
|
|
className={combinedClassName}
|
|
activeClassName={activeClass}
|
|
{...otherProps}
|
|
>
|
|
{content}
|
|
</NavLink>
|
|
) : (
|
|
<button
|
|
ref={combinedRef}
|
|
title={title}
|
|
aria-label={description || label || title}
|
|
className={combinedClassName}
|
|
onClick={(e) => {
|
|
if (onClick) {
|
|
e.stopPropagation();
|
|
onClick(e);
|
|
}
|
|
}}
|
|
disabled={disabled}
|
|
type={type}
|
|
{...otherProps}
|
|
>
|
|
{content}
|
|
</button>
|
|
);
|
|
});
|
|
|
|
export default Button;
|