mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
94 lines
2.6 KiB
TypeScript
94 lines
2.6 KiB
TypeScript
import React, { useState, HTMLAttributes } from 'react';
|
|
import { PopoverContent } from '../Tooltip/Tooltip';
|
|
import { GrafanaTheme2, SelectableValue } from '@grafana/data';
|
|
import { ToolbarButtonVariant, ToolbarButton } from '../Button';
|
|
import { ClickOutsideWrapper } from '../ClickOutsideWrapper/ClickOutsideWrapper';
|
|
import { css } from '@emotion/css';
|
|
import { useStyles2 } from '../../themes/ThemeContext';
|
|
import { Menu } from '../Menu/Menu';
|
|
import { MenuItem } from '../Menu/MenuItem';
|
|
|
|
export interface Props<T> extends HTMLAttributes<HTMLButtonElement> {
|
|
className?: string;
|
|
options: Array<SelectableValue<T>>;
|
|
value?: SelectableValue<T>;
|
|
onChange: (item: SelectableValue<T>) => void;
|
|
tooltipContent?: PopoverContent;
|
|
narrow?: boolean;
|
|
variant?: ToolbarButtonVariant;
|
|
}
|
|
|
|
/**
|
|
* @internal
|
|
* A temporary component until we have a proper dropdown component
|
|
*/
|
|
export const ButtonSelect = React.memo(<T,>(props: Props<T>) => {
|
|
const { className, options, value, onChange, narrow, variant, ...restProps } = props;
|
|
const [isOpen, setIsOpen] = useState<boolean>(false);
|
|
const styles = useStyles2(getStyles);
|
|
|
|
const onCloseMenu = () => {
|
|
setIsOpen(false);
|
|
};
|
|
|
|
const onToggle = (event: React.MouseEvent) => {
|
|
event.stopPropagation();
|
|
event.preventDefault();
|
|
setIsOpen(!isOpen);
|
|
};
|
|
|
|
const onChangeInternal = (item: SelectableValue<T>) => {
|
|
onChange(item);
|
|
setIsOpen(false);
|
|
};
|
|
|
|
return (
|
|
<div className={styles.wrapper}>
|
|
<ToolbarButton
|
|
className={className}
|
|
isOpen={isOpen}
|
|
onClick={onToggle}
|
|
narrow={narrow}
|
|
variant={variant}
|
|
{...restProps}
|
|
>
|
|
{value?.label || value?.value}
|
|
</ToolbarButton>
|
|
{isOpen && (
|
|
<div className={styles.menuWrapper}>
|
|
<ClickOutsideWrapper onClick={onCloseMenu} parent={document}>
|
|
<Menu>
|
|
{options.map((item) => (
|
|
<MenuItem
|
|
key={`${item.value}`}
|
|
label={(item.label || item.value) as string}
|
|
ariaLabel={(item.label || item.value) as string}
|
|
onClick={() => onChangeInternal(item)}
|
|
active={item.value === value?.value}
|
|
/>
|
|
))}
|
|
</Menu>
|
|
</ClickOutsideWrapper>
|
|
</div>
|
|
)}
|
|
</div>
|
|
);
|
|
});
|
|
|
|
ButtonSelect.displayName = 'ButtonSelect';
|
|
|
|
const getStyles = (theme: GrafanaTheme2) => {
|
|
return {
|
|
wrapper: css`
|
|
position: relative;
|
|
display: inline-flex;
|
|
`,
|
|
menuWrapper: css`
|
|
position: absolute;
|
|
z-index: ${theme.zIndex.dropdown};
|
|
top: ${theme.spacing(4)};
|
|
right: 0;
|
|
`,
|
|
};
|
|
};
|