Dashboards redesign - improvments (#2313)

* Various minor style updates

* Various style improvements

* Update ExampleCards.tsx

* various minor improvements in dashbaords.

* revised dashboard widget header
This commit is contained in:
Sudheer Salavadi 2024-06-27 12:55:30 +02:00 committed by GitHub
parent 9be31d80db
commit 8b49be81b0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 156 additions and 129 deletions

View file

@ -1,5 +1,7 @@
import React from "react";
import {Button, Tooltip} from "UI";
import {Tooltip} from "UI";
import {Button} from "antd";
import { PlusOutlined } from '@ant-design/icons';
import AddCardSelectionModal from "Components/Dashboard/components/AddCardSelectionModal";
import {useStore} from "App/mstore";
@ -15,11 +17,10 @@ function CreateCardButton() {
<Tooltip delay={0} disabled={canAddMore}
title="The number of cards in one dashboard is limited to 30.">
<Button
type="primary"
disabled={!canAddMore}
variant="primary"
onClick={() => setOpen(true)}
icon="plus"
iconSize={24}
icon={<PlusOutlined />}
>
Add Card
</Button>

View file

@ -57,7 +57,7 @@ function DashboardEditModal(props: Props) {
/>
</Form.Field>
<Form.Field>
{/* <Form.Field>
<label>{'Description:'}</label>
<Input
className=""
@ -69,7 +69,7 @@ function DashboardEditModal(props: Props) {
maxLength={300}
autoFocus={!focusTitle}
/>
</Form.Field>
</Form.Field> */}
<Form.Field>
<div className="flex items-center">

View file

@ -20,6 +20,7 @@ interface IProps {
renderReport?: any;
}
type Props = IProps & RouteComponentProps;
const MAX_CARDS = 29;
@ -43,7 +44,7 @@ function DashboardHeader(props: Props) {
const onDelete = async () => {
if (
await confirm({
header: 'Confirm',
header: 'Delete Dashboard',
confirmButton: 'Yes, delete',
confirmation: `Are you sure you want to permanently delete this Dashboard?`,
})
@ -82,11 +83,11 @@ function DashboardHeader(props: Props) {
className="mr-3 select-none border-b border-b-borderColor-transparent hover:border-dotted hover:border-gray-medium cursor-pointer"
/>
</div>
<div className="flex items-center" style={{flex: 1, justifyContent: 'end'}}>
<div className="flex items-center gap-2" style={{flex: 1, justifyContent: 'end'}}>
<CreateCardButton disabled={canAddMore} />
<div className="mx-4"></div>
<div
className="flex items-center flex-shrink-0 justify-end"
className="flex items-center flex-shrink-0 justify-end dashboardDataPeriodSelector"
style={{width: 'fit-content'}}
>
<SelectDateRange
@ -94,9 +95,11 @@ function DashboardHeader(props: Props) {
period={period}
onChange={(period: any) => dashboardStore.setPeriod(period)}
right={true}
isAnt={true}
useButtonStyle={true}
/>
</div>
<div className="mx-4"/>
<div className="flex items-center flex-shrink-0">
<DashboardOptions
editHandler={onEdit}
@ -114,7 +117,7 @@ function DashboardHeader(props: Props) {
className="my-2 font-normal w-fit text-disabled-text border-b border-b-borderColor-transparent hover:border-dotted hover:border-gray-medium cursor-pointer"
onDoubleClick={() => onEdit(false)}
>
{dashboard?.description || 'Describe the purpose of this dashboard'}
{/* {dashboard?.description || 'Describe the purpose of this dashboard'} */}
</h2>
</Tooltip>
</div>

View file

@ -19,9 +19,9 @@ function ExCard({
style={{width: '100%', height: height || 286}}
>
<div className={'font-medium text-lg'}>{title}</div>
<div className={'flex flex-col gap-2 mt-2 cursor-pointer'} style={{
height: height ? height - 50 : 236,
}} onClick={() => onCard(type)}>{children}</div>
<div className={'flex flex-col gap-2 mt-2 cursor-pointer'}
style={{height: height ? height - 50 : 236,}}
onClick={() => onCard(type)}>{children}</div>
</div>
);
}

View file

@ -14,7 +14,7 @@ function DashboardOptions(props: Props) {
const { editHandler, deleteHandler, renderReport, isEnterprise, isTitlePresent } = props;
const menuItems = [
{ icon: 'pencil', text: 'Rename', onClick: () => editHandler(true) },
{ icon: 'text-paragraph', text: `${!isTitlePresent ? 'Add' : 'Edit'} Description`, onClick: () => editHandler(false) },
// { icon: 'text-paragraph', text: `${!isTitlePresent ? 'Add' : 'Edit'} Description`, onClick: () => editHandler(false) },
{ icon: 'users', text: 'Visibility & Access', onClick: editHandler },
{ icon: 'trash', text: 'Delete', onClick: deleteHandler },
{ icon: 'pdf-download', text: 'Download Report', onClick: renderReport, disabled: !isEnterprise, tooltipTitle: ENTERPRISE_REQUEIRED }
@ -23,7 +23,6 @@ function DashboardOptions(props: Props) {
return (
<ItemMenu
bold
label="More Options"
items={menuItems}
/>
);

View file

@ -42,7 +42,7 @@ function DashboardWidgetGrid(props: Props) {
show={list?.length === 0}
icon="no-metrics-chart"
title={
<div className="bg-white rounded">
<div className="bg-white rounded-lg">
<div className="border-b p-5">
<div className="text-2xl font-normal">
There are no cards in this dashboard

View file

@ -2,7 +2,8 @@ import React from 'react';
import SessionSearchField from 'Shared/SessionSearchField';
import AiSessionSearchField from 'Shared/SessionSearchField/AiSessionSearchField';
import SavedSearch from 'Shared/SavedSearch';
import { Button } from 'UI';
// import { Button } from 'UI';
import { Button } from 'antd';
import { connect } from 'react-redux';
import { clearSearch } from 'Duck/search';
import TagList from './components/TagList';
@ -41,10 +42,12 @@ const MainSearchBar = (props: Props) => {
<TagList />
<SavedSearch />
<Button
variant={hasSearch ? 'text-primary' : 'text'}
className="ml-auto font-medium"
// variant={hasSearch ? 'text-primary' : 'text'}
// className="ml-auto font-medium"
type='link'
disabled={!hasSearch}
onClick={() => props.clearSearch()}
className='ml-auto font-medium'
>
Clear Search
</Button>

View file

@ -7,8 +7,8 @@ import { useStore } from 'App/mstore';
import { observer } from 'mobx-react-lite';
import { FilterKey } from 'Types/filter/filterType';
import { addOptionsToFilter } from 'Types/filter/newFilter';
import { Button, Icon, confirm } from 'UI';
import { Typography } from 'antd';
import { Icon, confirm } from 'UI';
import { Button, Typography } from 'antd';
import { toast } from 'react-toastify';
function TagList(props: {
@ -44,9 +44,15 @@ function TagList(props: {
});
};
return (
<Button variant={'outline'} disabled={!tagWatchStore.tags.length} onClick={openModal}>
<Button
// variant={'outline'}
type='primary'
ghost
className='gap-1'
disabled={!tagWatchStore.tags.length}
onClick={openModal}>
<span>Tags</span>
<span className={'font-bold ml-1'}>{tagWatchStore.tags.length}</span>
<span className={'font-medium ml-1'}>{tagWatchStore.tags.length}</span>
</Button>
);
}

View file

@ -1,5 +1,6 @@
import React, { useEffect } from 'react';
import { Button, Icon } from 'UI';
import { Icon } from 'UI';
import { Button } from 'antd';
import { connect } from 'react-redux';
import { fetchList as fetchListSavedSearch } from 'Duck/search';
import cn from 'classnames';
@ -27,11 +28,14 @@ function SavedSearch(props: Props) {
return (
<div className={cn("flex items-center", { [stl.disabled] : list.size === 0})}>
<Button
variant="outline"
// variant="outline"
type='primary'
ghost
onClick={() => showModal(<SavedSearchModal />, { right: true, width: 450 })}
className='flex gap-1'
>
<span className="mr-1">Saved Search</span>
<span className="font-bold mr-2">{list.size}</span>
<span className="font-meidum">{list.size}</span>
<Icon name="ellipsis-v" color="teal" size="14" />
</Button>
{ savedSearch.exists() && (

View file

@ -1,6 +1,6 @@
import { DownOutlined } from '@ant-design/icons';
import Period from 'Types/app/period';
import { Dropdown, DatePicker } from 'antd';
import { Dropdown, Button } from 'antd';
import cn from 'classnames';
import { observer } from 'mobx-react-lite';
import React from 'react';
@ -20,14 +20,14 @@ interface Props {
timezone?: string;
isAnt?: boolean;
small?: boolean;
useButtonStyle?: boolean; // New prop to control button style
[x: string]: any;
}
function SelectDateRange(props: Props) {
const [isCustom, setIsCustom] = React.useState(false);
const [isCustomOpen, setIsCustomOpen] = React.useState(false);
const { right = false, period, disableCustom = false, timezone } = props;
const { right = false, period, disableCustom = false, timezone, useButtonStyle = false } = props;
let selectedValue = DATE_RANGE_OPTIONS.find(
(obj: any) => obj.value === period.rangeName
);
@ -41,13 +41,11 @@ function SelectDateRange(props: Props) {
setIsCustom(true);
}, 1);
} else {
// @ts-ignore
props.onChange(new Period({ rangeName: value }));
}
};
const onApplyDateRange = (value: any) => {
// @ts-ignore
const range = new Period({
rangeName: CUSTOM_RANGE,
start: value.start,
@ -61,34 +59,31 @@ function SelectDateRange(props: Props) {
const customRange = isCustomRange ? period.rangeFormatted() : '';
if (props.isAnt) {
const onAntUpdate = (val: any) => {
onChange(val);
const menuProps = {
items: options.map((opt) => ({
label: opt.label,
key: opt.value,
})),
defaultSelectedKeys: selectedValue?.value ? [selectedValue.value] : undefined,
onClick: (e: any) => {
onChange(e.key);
},
};
return (
<div className={'relative'}>
<Dropdown
menu={{
items: options.map((opt) => ({
label: opt.label,
key: opt.value,
})),
defaultSelectedKeys: selectedValue?.value
? [selectedValue.value]
: undefined,
onClick: (e: any) => {
onChange(e.key);
},
}}
onChange={onAntUpdate}
style={{ width: 170 }}
defaultValue={selectedValue?.value ?? undefined}
>
<div
className={'cursor-pointer flex items-center gap-2'}
>
<div>{isCustomRange ? customRange : selectedValue?.label}</div>
<DownOutlined />
</div>
<Dropdown menu={menuProps}>
{useButtonStyle ? (
<Button>
<span>{isCustomRange ? customRange : selectedValue?.label}</span>
<DownOutlined />
</Button>
) : (
<div className={'cursor-pointer flex items-center gap-2'}>
<span>{isCustomRange ? customRange : selectedValue?.label}</span>
<DownOutlined />
</div>
)}
</Dropdown>
{isCustom && (
<OutsideClickDetectingDiv
@ -99,10 +94,8 @@ function SelectDateRange(props: Props) {
) ||
e.target.parentElement.parentElement.classList[0]?.includes(
'-menu'
)
|| e.target.className.includes(
'ant-picker'
)
) ||
e.target.className.includes('ant-picker')
) {
return false;
}
@ -110,10 +103,7 @@ function SelectDateRange(props: Props) {
}}
>
<div
className={cn(
'absolute top-0 mt-10 z-40',
{ 'right-0': right }
)}
className={cn('absolute top-0 mt-10 z-40', { 'right-0': right })}
style={{
width: '770px',
fontSize: '14px',
@ -132,6 +122,7 @@ function SelectDateRange(props: Props) {
</div>
);
}
return (
<div className="relative">
<Select

View file

@ -12,7 +12,7 @@ interface Props {
function Pdf_download(props: Props) {
const { size = 14, width = size, height = size, fill = '' } = props;
return (
<svg viewBox="0 0 19 19" width={ `${ width }px` } height={ `${ height }px` } ><path d="M10.094 5.249a.594.594 0 0 0-1.188 0v4.504l-1.36-1.362a.595.595 0 0 0-.841.84l2.375 2.376a.596.596 0 0 0 .84 0l2.375-2.375a.595.595 0 0 0-.84-.841l-1.361 1.362V5.249Z"/><path d="M16.625 16.625V5.344L11.281 0H4.75a2.375 2.375 0 0 0-2.375 2.375v14.25A2.375 2.375 0 0 0 4.75 19h9.5a2.375 2.375 0 0 0 2.375-2.375ZM11.281 3.562a1.781 1.781 0 0 0 1.781 1.782h2.376v11.281a1.188 1.188 0 0 1-1.188 1.188h-9.5a1.187 1.187 0 0 1-1.188-1.188V2.375A1.188 1.188 0 0 1 4.75 1.187h6.531v2.375Z"/><path clipRule="evenodd" d="M15.58 13.49H3.42v4.37h1.789v-3.512H6.61c.282 0 .524.051.726.154.205.103.361.245.47.425.11.178.165.383.165.613 0 .226-.055.424-.164.593-.11.169-.266.3-.47.396-.203.093-.445.14-.727.14h-.554v1.191h2.37v-3.512h1.13c.238 0 .455.041.653.123a1.537 1.537 0 0 1 .854.88c.08.205.12.431.12.68v.148c0 .247-.04.474-.12.68a1.512 1.512 0 0 1-.849.88c-.193.08-.404.12-.635.121h2.046v-3.512h2.35v.654h-1.503v.808h1.365v.651h-1.365v1.399h3.108v-4.37Zm-9.524 1.512v1.013h.554c.12 0 .216-.02.29-.06a.367.367 0 0 0 .161-.167.547.547 0 0 0 .054-.244.668.668 0 0 0-.054-.267.431.431 0 0 0-.161-.198.496.496 0 0 0-.29-.077h-.554Zm3.512 2.207h-.295v-2.207h.283c.123 0 .233.021.328.065a.604.604 0 0 1 .24.195.88.88 0 0 1 .146.321c.033.127.05.275.05.444v.152c0 .225-.03.415-.089.569a.707.707 0 0 1-.256.345.696.696 0 0 1-.407.116Z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width={ `${ width }px` } height={ `${ height }px` } viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-file-down"><path d="M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"/><path d="M14 2v4a2 2 0 0 0 2 2h4"/><path d="M12 18v-6"/><path d="m9 15 3 3 3-3"/></svg>
);
}

View file

@ -12,7 +12,7 @@ interface Props {
function Pencil(props: Props) {
const { size = 14, width = size, height = size, fill = '' } = props;
return (
<svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M12.146.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1 0 .708l-10 10a.5.5 0 0 1-.168.11l-5 2a.5.5 0 0 1-.65-.65l2-5a.5.5 0 0 1 .11-.168l10-10zM11.207 2.5 13.5 4.793 14.793 3.5 12.5 1.207 11.207 2.5zm1.586 3L10.5 3.207 4 9.707V10h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.293l6.5-6.5zm-9.761 5.175-.106.106-1.528 3.821 3.821-1.528.106-.106A.5.5 0 0 1 5 12.5V12h-.5a.5.5 0 0 1-.5-.5V11h-.5a.5.5 0 0 1-.468-.325z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width={ `${ width }px` } height={ `${ height }px` } viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-file-pen-line"><path d="m18 5-2.414-2.414A2 2 0 0 0 14.172 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2"/><path d="M21.378 12.626a1 1 0 0 0-3.004-3.004l-4.01 4.012a2 2 0 0 0-.506.854l-.837 2.87a.5.5 0 0 0 .62.62l2.87-.837a2 2 0 0 0 .854-.506z"/><path d="M8 18h1"/></svg>
);
}

View file

@ -12,7 +12,7 @@ interface Props {
function Trash(props: Props) {
const { size = 14, width = size, height = size, fill = '' } = props;
return (
<svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6z"/><path d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1zM4.118 4 4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118zM2.5 3V2h11v1h-11z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width={ `${ width }px` } height={ `${ height }px` } viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-trash"><path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/></svg>
);
}

View file

@ -12,7 +12,8 @@ interface Props {
function Users(props: Props) {
const { size = 14, width = size, height = size, fill = '' } = props;
return (
<svg viewBox="0 0 16 16" width={ `${ width }px` } height={ `${ height }px` } ><path d="M15 14s1 0 1-1-1-4-5-4-5 3-5 4 1 1 1 1h8zm-7.978-1A.261.261 0 0 1 7 12.996c.001-.264.167-1.03.76-1.72C8.312 10.629 9.282 10 11 10c1.717 0 2.687.63 3.24 1.276.593.69.758 1.457.76 1.72l-.008.002a.274.274 0 0 1-.014.002H7.022zM11 7a2 2 0 1 0 0-4 2 2 0 0 0 0 4zm3-2a3 3 0 1 1-6 0 3 3 0 0 1 6 0zM6.936 9.28a5.88 5.88 0 0 0-1.23-.247A7.35 7.35 0 0 0 5 9c-4 0-5 3-5 4 0 .667.333 1 1 1h4.216A2.238 2.238 0 0 1 5 13c0-1.01.377-2.042 1.09-2.904.243-.294.526-.569.846-.816zM4.92 10A5.493 5.493 0 0 0 4 13H1c0-.26.164-1.03.76-1.724.545-.636 1.492-1.256 3.16-1.275zM1.5 5.5a3 3 0 1 1 6 0 3 3 0 0 1-6 0zm3-2a2 2 0 1 0 0 4 2 2 0 0 0 0-4z"/></svg>
<svg xmlns="http://www.w3.org/2000/svg" width={ `${ width }px` } height={ `${ height }px` } viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-users-round"><path d="M18 21a8 8 0 0 0-16 0"/><circle cx="10" cy="8" r="5"/><path d="M22 20c0-3.37-2-6.5-4-8a5 5 0 0 0-.45-8.3"/></svg>
);
}

View file

@ -1,7 +1,9 @@
import React from 'react';
import { Icon, Popover, Tooltip } from 'UI';
import styles from './itemMenu.module.css';
import cn from 'classnames';
import React from "react";
import { Icon, Popover, Tooltip } from "UI";
import { Dropdown, Menu, Button } from "antd";
import { MoreOutlined } from "@ant-design/icons";
import styles from "./itemMenu.module.css";
import cn from "classnames";
interface Item {
icon?: string;
@ -28,13 +30,13 @@ export default class ItemMenu extends React.PureComponent<Props> {
displayed: false,
};
handleEsc = (e: KeyboardEvent) => e.key === 'Escape' && this.closeMenu();
handleEsc = (e: KeyboardEvent) => e.key === "Escape" && this.closeMenu();
componentDidMount() {
document.addEventListener('keydown', this.handleEsc, false);
document.addEventListener("keydown", this.handleEsc, false);
}
componentWillUnmount() {
document.removeEventListener('keydown', this.handleEsc, false);
document.removeEventListener("keydown", this.handleEsc, false);
}
onClick = (callback: Function) => (e: React.MouseEvent<HTMLDivElement>) => {
@ -54,74 +56,69 @@ export default class ItemMenu extends React.PureComponent<Props> {
};
render() {
const { items, label = '', bold, sm } = this.props;
const { items, label, bold, sm } = this.props;
const { displayed } = this.state;
const parentStyles = label ? 'rounded px-2 py-2 hover:bg-gray-light' : '';
const parentStyles = label ? "hover:bg-gray-light" : "";
return (
<Popover
placement="bottom-end" // Set the placement to bottom-end for right alignment
render={() => (
<div
className={cn(styles.menu, { [styles.menuDim]: !bold })}
// data-displayed={displayed}
>
<div className={cn(styles.menu, 'rounded-lg', { [styles.menuDim]: !bold })}>
{items
.filter(({ hidden }) => !hidden)
.map(({ onClick, text, icon, disabled = false, tooltipTitle = '' }) => (
<Tooltip disabled={!disabled} title={tooltipTitle} delay={0}>
<div
key={text}
onClick={!disabled ? this.onClick(onClick) : () => {}}
className={disabled ? 'cursor-not-allowed' : ''}
role="menuitem"
>
<div className={cn(styles.menuItem, 'text-neutral-700', { disabled: disabled })}>
{icon && (
<div className={styles.iconWrapper}>
{/* @ts-ignore */}
<Icon name={icon} size="13" color="gray-dark" />
</div>
)}
<div>{text}</div>
.map(
({
onClick,
text,
icon,
disabled = false,
tooltipTitle = "",
}) => (
<Tooltip key={text} disabled={!disabled} title={tooltipTitle} delay={0}>
<div
onClick={!disabled ? this.onClick(onClick) : () => {}}
className={`${disabled ? "cursor-not-allowed" : ""}`}
role="menuitem"
>
<div className={cn(styles.menuItem, { disabled: disabled })}>
{icon && (
<div className={styles.iconWrapper}>
<Icon name={icon} size="13" color="gray-dark" />
</div>
)}
<div>{text}</div>
</div>
</div>
</div>
</Tooltip>
))}
</Tooltip>
)
)}
</div>
)}
>
<div
// onClick={this.toggleMenu}
className={cn(
'flex items-center cursor-pointer select-none',
!this.props.flat ? parentStyles : '',
{ 'bg-gray-light': !this.props.flat && displayed && label }
)}
<Button
className={cn("select-none", !this.props.flat ? parentStyles : "", {
"": !this.props.flat && displayed && label,
})}
>
{label && (
<span
className={cn('mr-1', bold ? 'font-medium color-gray-darkest' : 'color-gray-medium')}
>
<span className={cn("font-medium")}>
{label}
</span>
)}
{this.props.flat ? null : (
{!this.props.flat && (
<div
ref={(ref) => {
this.menuBtnRef = ref;
}}
className={cn('rounded-full flex items-center justify-center', {
'bg-gray-light': displayed,
'w-10 h-10': !label && !sm,
'w-8 h-8': sm,
})}
className={cn("rounded-full flex items-center justify-center")}
role="button"
>
<Icon name="ellipsis-v" size="16" />
<MoreOutlined />
</div>
)}
</div>
</Button>
</Popover>
);
}
}
}

View file

@ -45,9 +45,10 @@
/* top: 37px; */
min-width: 150px;
background-color: $white;
border-radius: 3px;
border: 1px solid rgba(34,36,38,.15);
box-shadow: 0 2px 3px 0 rgb(34 36 38 / 15%);
border-radius: 0.5rem;
& .menuItem {
@ -57,6 +58,7 @@
display: flex;
align-items: center;
border-bottom: 1px solid $gray-light;
& .iconWrapper {
width: 13px;
@ -66,6 +68,7 @@
&:hover {
background-color: $active-blue;
color: $teal;
}
&:last-child {

View file

@ -24,7 +24,7 @@ interface Props {
onClose?: () => void;
}
const Popover = ({ children, render, placement, onOpen, onClose }: Props) => {
const Popover = ({ children, render, placement = 'bottom-end', onOpen, onClose }: Props) => {
const [open, setOpen] = useState(false);
useEffect(() => {
@ -33,7 +33,7 @@ const Popover = ({ children, render, placement, onOpen, onClose }: Props) => {
} else {
onClose?.();
}
}, [open]);
}, [open, onOpen, onClose]);
const { x, y, reference, floating, strategy, context } = useFloating({
open,
@ -68,7 +68,7 @@ const Popover = ({ children, render, placement, onOpen, onClose }: Props) => {
>
<div
ref={floating}
className="rounded border shadow"
className="rounded-lg"
style={{
position: strategy,
top: y ?? 0,

View file

@ -10,6 +10,18 @@
background-color: var(--bg-teal);
}
:root{
--bg-teal: #394dfe;
}
.ant-btn{
border-radius: .5rem;
}
.ant-btn-primary{
background-color: var(--bg-teal);
}
.ml-15 { margin-left: 15px; }
.ph-10 { padding-left: 10px; padding-right: 10px; }
@ -404,4 +416,10 @@ p {
.chooseDashboardCards .ant-modal-content{
background-color: #efefef;
border-radius: 0.75rem;
max-height: 700px;
overflow: hidden;
}
.dashboardDataPeriodSelector .dashboardMoreOptionsLabel{
display: none;
}

View file

@ -1,4 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" class="bi bi-trash" viewBox="0 0 16 16">
<path d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6z"/>
<path fill-rule="evenodd" d="M14.5 3a1 1 0 0 1-1 1H13v9a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V4h-.5a1 1 0 0 1-1-1V2a1 1 0 0 1 1-1H6a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1h3.5a1 1 0 0 1 1 1v1zM4.118 4L4 4.059V13a1 1 0 0 0 1 1h6a1 1 0 0 0 1-1V4.059L11.882 4H4.118zM2.5 3V2h11v1h-11z"/>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-trash"><path d="M3 6h18"/><path d="M19 6v14c0 1-1 2-2 2H7c-1 0-2-1-2-2V6"/><path d="M8 6V4c0-1 1-2 2-2h4c1 0 2 1 2 2v2"/></svg>

Before

Width:  |  Height:  |  Size: 531 B

After

Width:  |  Height:  |  Size: 331 B

4
yarn.lock Normal file
View file

@ -0,0 +1,4 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1