frigate/web/src/components/Button.jsx

115 lines
4.6 KiB
React
Raw Normal View History

import { h, Fragment } from 'preact';
import Tooltip from './Tooltip';
import { useCallback, useRef, useState } from 'preact/hooks';
2021-01-09 20:26:46 +03:00
2021-02-02 07:28:25 +03:00
const ButtonColors = {
blue: {
contained: 'bg-blue-500 focus:bg-blue-400 active:bg-blue-600 ring-blue-300',
2021-02-04 21:36:46 +03:00
outlined:
'text-blue-500 border-2 border-blue-500 hover:bg-blue-500 hover:bg-opacity-20 focus:bg-blue-500 focus:bg-opacity-40 active:bg-blue-500 active:bg-opacity-40',
text: 'text-blue-500 hover:bg-blue-500 hover:bg-opacity-20 focus:bg-blue-500 focus:bg-opacity-40 active:bg-blue-500 active:bg-opacity-40',
iconOnly: 'text-blue-500 hover:text-blue-200',
2021-02-02 07:28:25 +03:00
},
red: {
contained: 'bg-red-500 focus:bg-red-400 active:bg-red-600 ring-red-300',
2021-02-04 21:36:46 +03:00
outlined:
'text-red-500 border-2 border-red-500 hover:bg-red-500 hover:bg-opacity-20 focus:bg-red-500 focus:bg-opacity-40 active:bg-red-500 active:bg-opacity-40',
text: 'text-red-500 hover:bg-red-500 hover:bg-opacity-20 focus:bg-red-500 focus:bg-opacity-40 active:bg-red-500 active:bg-opacity-40',
iconOnly: 'text-red-500 hover:text-red-200',
2021-02-02 07:28:25 +03:00
},
yellow: {
contained: 'bg-yellow-500 focus:bg-yellow-400 active:bg-yellow-600 ring-yellow-300',
outlined:
'text-yellow-500 border-2 border-yellow-500 hover:bg-yellow-500 hover:bg-opacity-20 focus:bg-yellow-500 focus:bg-opacity-40 active:bg-yellow-500 active:bg-opacity-40',
text: 'text-yellow-500 hover:bg-yellow-500 hover:bg-opacity-20 focus:bg-yellow-500 focus:bg-opacity-40 active:bg-yellow-500 active:bg-opacity-40',
iconOnly: 'text-yellow-500 hover:text-yellow-200',
},
2021-02-02 07:28:25 +03:00
green: {
contained: 'bg-green-500 focus:bg-green-400 active:bg-green-600 ring-green-300',
2021-02-04 21:36:46 +03:00
outlined:
'text-green-500 border-2 border-green-500 hover:bg-green-500 hover:bg-opacity-20 focus:bg-green-500 focus:bg-opacity-40 active:bg-green-500 active:bg-opacity-40',
text: 'text-green-500 hover:bg-green-500 hover:bg-opacity-20 focus:bg-green-500 focus:bg-opacity-40 active:bg-green-500 active:bg-opacity-40',
iconOnly: 'text-green-500 hover:text-green-200',
2021-02-02 07:28:25 +03:00
},
gray: {
contained: 'bg-gray-500 focus:bg-gray-400 active:bg-gray-600 ring-gray-300',
outlined:
'text-gray-500 border-2 border-gray-500 hover:bg-gray-500 hover:bg-opacity-20 focus:bg-gray-500 focus:bg-opacity-40 active:bg-gray-500 active:bg-opacity-40',
text: 'text-gray-500 hover:bg-gray-500 hover:bg-opacity-20 focus:bg-gray-500 focus:bg-opacity-40 active:bg-gray-500 active:bg-opacity-40',
iconOnly: 'text-gray-500 hover:text-gray-200',
},
2021-02-02 07:28:25 +03:00
disabled: {
contained: 'bg-gray-400',
2021-02-04 21:36:46 +03:00
outlined:
'text-gray-500 border-2 border-gray-500 hover:bg-gray-500 hover:bg-opacity-20 focus:bg-gray-500 focus:bg-opacity-40 active:bg-gray-500 active:bg-opacity-40',
text: 'text-gray-500 hover:bg-gray-500 hover:bg-opacity-20 focus:bg-gray-500 focus:bg-opacity-40 active:bg-gray-500 active:bg-opacity-40',
iconOnly: 'text-gray-500 hover:text-gray-200',
2021-02-02 07:28:25 +03:00
},
black: {
contained: '',
outlined: '',
text: 'text-black dark:text-white',
iconOnly: '',
},
};
2021-02-02 07:28:25 +03:00
const ButtonTypes = {
contained: 'text-white shadow focus:shadow-xl hover:shadow-md',
outlined: '',
text: 'transition-opacity',
iconOnly: 'transition-opacity',
2021-02-02 07:28:25 +03:00
};
export default function Button({
children,
className = '',
color = 'blue',
disabled = false,
ariaCapitalize = false,
2021-02-02 07:28:25 +03:00
href,
type = 'contained',
...attrs
}) {
const [hovered, setHovered] = useState(false);
const ref = useRef();
2021-02-05 02:19:47 +03:00
let classes = `whitespace-nowrap flex items-center space-x-1 ${className} ${ButtonTypes[type]} ${
2021-02-02 07:28:25 +03:00
ButtonColors[disabled ? 'disabled' : color][type]
2021-05-28 20:13:48 +03:00
} font-sans inline-flex font-bold uppercase text-xs px-1.5 md:px-2 py-2 rounded outline-none focus:outline-none ring-opacity-50 transition-shadow transition-colors ${
disabled ? 'cursor-not-allowed' : `${type == 'iconOnly' ? '' : 'focus:ring-2'} cursor-pointer`
2021-02-02 07:28:25 +03:00
}`;
if (disabled) {
classes = classes.replace(/(?:focus|active|hover):[^ ]+/g, '');
}
2022-02-26 22:11:00 +03:00
const handleMousenter = useCallback(() => {
setHovered(true);
}, []);
2022-02-26 22:11:00 +03:00
const handleMouseleave = useCallback(() => {
setHovered(false);
}, []);
2021-02-02 07:28:25 +03:00
const Element = href ? 'a' : 'div';
2021-01-09 20:26:46 +03:00
return (
<Fragment>
<Element
role="button"
aria-disabled={disabled ? 'true' : 'false'}
tabindex="0"
className={classes}
href={href}
ref={ref}
onmouseenter={handleMousenter}
onmouseleave={handleMouseleave}
{...attrs}
>
{children}
</Element>
{hovered && attrs['aria-label'] ? <Tooltip text={attrs['aria-label']} relativeTo={ref} capitalize={ariaCapitalize} /> : null}
</Fragment>
2021-01-09 20:26:46 +03:00
);
}