♻️ (tooltip) refactoring to react-aria (vol.6) (#2771)

* ♻️ (tooltip) refactoring to react-aria (vol.6)

* Release notes
This commit is contained in:
Matiss Janis Aboltins
2024-06-03 11:56:39 +01:00
committed by GitHub
parent c92266fd7f
commit 0e86dea544
10 changed files with 252 additions and 251 deletions

View File

@@ -28,9 +28,9 @@ import { styles, theme } from '../../style';
import { tokens } from '../../tokens'; import { tokens } from '../../tokens';
import { Button } from '../common/Button'; import { Button } from '../common/Button';
import { Menu } from '../common/Menu'; import { Menu } from '../common/Menu';
import { Popover } from '../common/Popover';
import { Text } from '../common/Text'; import { Text } from '../common/Text';
import { View } from '../common/View'; import { View } from '../common/View';
import { Tooltip } from '../tooltips';
function getFileDescription(file) { function getFileDescription(file) {
if (file.state === 'unknown') { if (file.state === 'unknown') {
@@ -84,11 +84,13 @@ function FileMenu({ onDelete, onClose }) {
} }
function FileMenuButton({ state, onDelete }) { function FileMenuButton({ state, onDelete }) {
const triggerRef = useRef(null);
const [menuOpen, setMenuOpen] = useState(false); const [menuOpen, setMenuOpen] = useState(false);
return ( return (
<View> <View>
<Button <Button
ref={triggerRef}
type="bare" type="bare"
aria-label="Menu" aria-label="Menu"
onClick={e => { onClick={e => {
@@ -98,19 +100,18 @@ function FileMenuButton({ state, onDelete }) {
> >
<SvgDotsHorizontalTriple style={{ width: 16, height: 16 }} /> <SvgDotsHorizontalTriple style={{ width: 16, height: 16 }} />
</Button> </Button>
{menuOpen && (
<Tooltip <Popover
position="bottom-right" triggerRef={triggerRef}
style={{ padding: 0 }} isOpen={menuOpen}
onOpenChange={() => setMenuOpen(false)}
>
<FileMenu
state={state}
onDelete={onDelete}
onClose={() => setMenuOpen(false)} onClose={() => setMenuOpen(false)}
> />
<FileMenu </Popover>
state={state}
onDelete={onDelete}
onClose={() => setMenuOpen(false)}
/>
</Tooltip>
)}
</View> </View>
); );
} }

View File

@@ -1,4 +1,4 @@
import React, { type ComponentProps, useState } from 'react'; import React, { type ComponentProps, useRef, useState } from 'react';
import { type AccountEntity } from 'loot-core/types/models'; import { type AccountEntity } from 'loot-core/types/models';
@@ -10,10 +10,10 @@ import { type CSSProperties, styles, theme } from '../../style';
import { Button } from '../common/Button'; import { Button } from '../common/Button';
import { Menu } from '../common/Menu'; import { Menu } from '../common/Menu';
import { Modal, ModalTitle } from '../common/Modal'; import { Modal, ModalTitle } from '../common/Modal';
import { Popover } from '../common/Popover';
import { View } from '../common/View'; import { View } from '../common/View';
import { type CommonModalProps } from '../Modals'; import { type CommonModalProps } from '../Modals';
import { Notes } from '../Notes'; import { Notes } from '../Notes';
import { Tooltip } from '../tooltips';
type AccountMenuModalProps = { type AccountMenuModalProps = {
modalProps: CommonModalProps; modalProps: CommonModalProps;
@@ -155,6 +155,7 @@ function AdditionalAccountMenu({
onClose, onClose,
onReopen, onReopen,
}: AdditionalAccountMenuProps) { }: AdditionalAccountMenuProps) {
const triggerRef = useRef(null);
const [menuOpen, setMenuOpen] = useState(false); const [menuOpen, setMenuOpen] = useState(false);
const itemStyle: CSSProperties = { const itemStyle: CSSProperties = {
...styles.mediumText, ...styles.mediumText,
@@ -169,6 +170,7 @@ function AdditionalAccountMenu({
return ( return (
<View> <View>
<Button <Button
ref={triggerRef}
type="bare" type="bare"
aria-label="Menu" aria-label="Menu"
onClick={() => { onClick={() => {
@@ -180,47 +182,44 @@ function AdditionalAccountMenu({
height={17} height={17}
style={{ color: 'currentColor' }} style={{ color: 'currentColor' }}
/> />
{menuOpen && ( <Popover
<Tooltip triggerRef={triggerRef}
position="bottom-left" isOpen={menuOpen}
style={{ padding: 0 }} placement="bottom start"
onClose={() => { onOpenChange={() => setMenuOpen(false)}
>
<Menu
getItemStyle={getItemStyle}
items={[
account.closed
? {
name: 'reopen',
text: 'Reopen account',
icon: SvgLockOpen,
iconSize: 15,
}
: {
name: 'close',
text: 'Close account',
icon: SvgClose,
iconSize: 15,
},
]}
onMenuSelect={name => {
setMenuOpen(false); setMenuOpen(false);
switch (name) {
case 'close':
onClose?.(account.id);
break;
case 'reopen':
onReopen?.(account.id);
break;
default:
throw new Error(`Unrecognized menu option: ${name}`);
}
}} }}
> />
<Menu </Popover>
getItemStyle={getItemStyle}
items={[
account.closed
? {
name: 'reopen',
text: 'Reopen account',
icon: SvgLockOpen,
iconSize: 15,
}
: {
name: 'close',
text: 'Close account',
icon: SvgClose,
iconSize: 15,
},
]}
onMenuSelect={name => {
setMenuOpen(false);
switch (name) {
case 'close':
onClose?.(account.id);
break;
case 'reopen':
onReopen?.(account.id);
break;
default:
throw new Error(`Unrecognized menu option: ${name}`);
}
}}
/>
</Tooltip>
)}
</Button> </Button>
</View> </View>
); );

View File

@@ -1,5 +1,5 @@
// @ts-strict-ignore // @ts-strict-ignore
import React, { type ComponentProps, useState } from 'react'; import React, { type ComponentProps, useRef, useState } from 'react';
import { type CategoryGroupEntity } from 'loot-core/src/types/models'; import { type CategoryGroupEntity } from 'loot-core/src/types/models';
@@ -11,10 +11,10 @@ import { type CSSProperties, styles, theme } from '../../style';
import { Button } from '../common/Button'; import { Button } from '../common/Button';
import { Menu } from '../common/Menu'; import { Menu } from '../common/Menu';
import { Modal, ModalTitle } from '../common/Modal'; import { Modal, ModalTitle } from '../common/Modal';
import { Popover } from '../common/Popover';
import { View } from '../common/View'; import { View } from '../common/View';
import { type CommonModalProps } from '../Modals'; import { type CommonModalProps } from '../Modals';
import { Notes } from '../Notes'; import { Notes } from '../Notes';
import { Tooltip } from '../tooltips';
type CategoryGroupMenuModalProps = { type CategoryGroupMenuModalProps = {
modalProps: CommonModalProps; modalProps: CommonModalProps;
@@ -155,6 +155,7 @@ export function CategoryGroupMenuModal({
} }
function AdditionalCategoryGroupMenu({ group, onDelete, onToggleVisibility }) { function AdditionalCategoryGroupMenu({ group, onDelete, onToggleVisibility }) {
const triggerRef = useRef(null);
const [menuOpen, setMenuOpen] = useState(false); const [menuOpen, setMenuOpen] = useState(false);
const itemStyle: CSSProperties = { const itemStyle: CSSProperties = {
...styles.mediumText, ...styles.mediumText,
@@ -170,6 +171,7 @@ function AdditionalCategoryGroupMenu({ group, onDelete, onToggleVisibility }) {
<View> <View>
{!group.is_income && ( {!group.is_income && (
<Button <Button
ref={triggerRef}
type="bare" type="bare"
aria-label="Menu" aria-label="Menu"
onClick={() => { onClick={() => {
@@ -181,52 +183,47 @@ function AdditionalCategoryGroupMenu({ group, onDelete, onToggleVisibility }) {
height={17} height={17}
style={{ color: 'currentColor' }} style={{ color: 'currentColor' }}
/> />
{menuOpen && ( <Popover
<Tooltip triggerRef={triggerRef}
position="bottom-left" isOpen={menuOpen}
style={{ padding: 0 }} placement="bottom start"
onClose={() => { onOpenChange={() => setMenuOpen(false)}
setMenuOpen(false); >
<Menu
style={{
...styles.mediumText,
color: theme.formLabelText,
}} }}
> getItemStyle={getItemStyle}
<Menu items={
style={{ [
...styles.mediumText, {
color: theme.formLabelText, name: 'toggleVisibility',
}} text: group.hidden ? 'Show' : 'Hide',
getItemStyle={getItemStyle} icon: group.hidden ? SvgViewShow : SvgViewHide,
items={ iconSize: 16,
[ },
...(!group.is_income && [
Menu.line,
{ {
name: 'toggleVisibility', name: 'delete',
text: group.hidden ? 'Show' : 'Hide', text: 'Delete',
icon: group.hidden ? SvgViewShow : SvgViewHide, icon: SvgTrash,
iconSize: 16, iconSize: 15,
}, },
...(!group.is_income && [ ]),
Menu.line, ].filter(i => i != null) as ComponentProps<typeof Menu>['items']
{ }
name: 'delete', onMenuSelect={itemName => {
text: 'Delete', setMenuOpen(false);
icon: SvgTrash, if (itemName === 'delete') {
iconSize: 15, onDelete();
}, } else if (itemName === 'toggleVisibility') {
]), onToggleVisibility();
].filter(i => i != null) as ComponentProps<
typeof Menu
>['items']
} }
onMenuSelect={itemName => { }}
setMenuOpen(false); />
if (itemName === 'delete') { </Popover>
onDelete();
} else if (itemName === 'toggleVisibility') {
onToggleVisibility();
}
}}
/>
</Tooltip>
)}
</Button> </Button>
)} )}
</View> </View>

View File

@@ -1,5 +1,5 @@
// @ts-strict-ignore // @ts-strict-ignore
import React, { useState } from 'react'; import React, { useRef, useState } from 'react';
import { type CategoryEntity } from 'loot-core/src/types/models'; import { type CategoryEntity } from 'loot-core/src/types/models';
@@ -12,10 +12,10 @@ import { type CSSProperties, styles, theme } from '../../style';
import { Button } from '../common/Button'; import { Button } from '../common/Button';
import { Menu } from '../common/Menu'; import { Menu } from '../common/Menu';
import { Modal, ModalTitle } from '../common/Modal'; import { Modal, ModalTitle } from '../common/Modal';
import { Popover } from '../common/Popover';
import { View } from '../common/View'; import { View } from '../common/View';
import { type CommonModalProps } from '../Modals'; import { type CommonModalProps } from '../Modals';
import { Notes } from '../Notes'; import { Notes } from '../Notes';
import { Tooltip } from '../tooltips';
type CategoryMenuModalProps = { type CategoryMenuModalProps = {
modalProps: CommonModalProps; modalProps: CommonModalProps;
@@ -147,6 +147,7 @@ function AdditionalCategoryMenu({
onDelete, onDelete,
onToggleVisibility, onToggleVisibility,
}) { }) {
const triggerRef = useRef(null);
const [menuOpen, setMenuOpen] = useState(false); const [menuOpen, setMenuOpen] = useState(false);
const itemStyle: CSSProperties = { const itemStyle: CSSProperties = {
...styles.mediumText, ...styles.mediumText,
@@ -161,6 +162,7 @@ function AdditionalCategoryMenu({
return ( return (
<View> <View>
<Button <Button
ref={triggerRef}
type="bare" type="bare"
aria-label="Menu" aria-label="Menu"
onClick={() => { onClick={() => {
@@ -172,42 +174,39 @@ function AdditionalCategoryMenu({
height={17} height={17}
style={{ color: 'currentColor' }} style={{ color: 'currentColor' }}
/> />
{menuOpen && ( <Popover
<Tooltip triggerRef={triggerRef}
position="bottom-left" isOpen={menuOpen}
style={{ padding: 0 }} placement="bottom start"
onClose={() => { onOpenChange={() => setMenuOpen(false)}
>
<Menu
getItemStyle={getItemStyle}
items={[
!categoryGroup?.hidden && {
name: 'toggleVisibility',
text: category.hidden ? 'Show' : 'Hide',
icon: category.hidden ? SvgViewShow : SvgViewHide,
iconSize: 16,
},
!categoryGroup?.hidden && Menu.line,
{
name: 'delete',
text: 'Delete',
icon: SvgTrash,
iconSize: 15,
},
]}
onMenuSelect={itemName => {
setMenuOpen(false); setMenuOpen(false);
if (itemName === 'delete') {
onDelete();
} else if (itemName === 'toggleVisibility') {
onToggleVisibility();
}
}} }}
> />
<Menu </Popover>
getItemStyle={getItemStyle}
items={[
!categoryGroup?.hidden && {
name: 'toggleVisibility',
text: category.hidden ? 'Show' : 'Hide',
icon: category.hidden ? SvgViewShow : SvgViewHide,
iconSize: 16,
},
!categoryGroup?.hidden && Menu.line,
{
name: 'delete',
text: 'Delete',
icon: SvgTrash,
iconSize: 15,
},
]}
onMenuSelect={itemName => {
setMenuOpen(false);
if (itemName === 'delete') {
onDelete();
} else if (itemName === 'toggleVisibility') {
onToggleVisibility();
}
}}
/>
</Tooltip>
)}
</Button> </Button>
</View> </View>
); );

View File

@@ -40,9 +40,9 @@ import { Modal } from '../common/Modal';
import { Select } from '../common/Select'; import { Select } from '../common/Select';
import { Stack } from '../common/Stack'; import { Stack } from '../common/Stack';
import { Text } from '../common/Text'; import { Text } from '../common/Text';
import { Tooltip } from '../common/Tooltip';
import { View } from '../common/View'; import { View } from '../common/View';
import { StatusBadge } from '../schedules/StatusBadge'; import { StatusBadge } from '../schedules/StatusBadge';
import { Tooltip } from '../tooltips';
import { SimpleTransactionsTable } from '../transactions/SimpleTransactionsTable'; import { SimpleTransactionsTable } from '../transactions/SimpleTransactionsTable';
import { BetweenAmountInput } from '../util/AmountInput'; import { BetweenAmountInput } from '../util/AmountInput';
import { DisplayId } from '../util/DisplayId'; import { DisplayId } from '../util/DisplayId';
@@ -415,33 +415,29 @@ function ActionEditor({ action, editorStyle, onChange, onDelete, onAdd }) {
} }
function StageInfo() { function StageInfo() {
const [open, setOpen] = useState();
return ( return (
<View style={{ position: 'relative', marginLeft: 5 }}> <View style={{ position: 'relative', marginLeft: 5 }}>
<View <Tooltip
onMouseEnter={() => setOpen(true)} content={
onMouseLeave={() => setOpen(false)} <>
The stage of a rule allows you to force a specific order. Pre rules
always run first, and post rules always run last. Within each stage
rules are automatically ordered from least to most specific.
</>
}
placement="bottom start"
style={{
...styles.tooltip,
padding: 10,
color: theme.pageTextLight,
maxWidth: 450,
lineHeight: 1.5,
}}
> >
<SvgInformationOutline <SvgInformationOutline
style={{ width: 11, height: 11, color: theme.pageTextLight }} style={{ width: 11, height: 11, color: theme.pageTextLight }}
/> />
</View> </Tooltip>
{open && (
<Tooltip
position="bottom-left"
style={{
padding: 10,
color: theme.pageTextLight,
maxWidth: 450,
lineHeight: 1.5,
}}
>
The stage of a rule allows you to force a specific order. Pre rules
always run first, and post rules always run last. Within each stage
rules are automatically ordered from least to most specific.
</Tooltip>
)}
</View> </View>
); );
} }

View File

@@ -20,10 +20,10 @@ import { Link } from '../common/Link';
import { Menu } from '../common/Menu'; import { Menu } from '../common/Menu';
import { Modal } from '../common/Modal'; import { Modal } from '../common/Modal';
import { Paragraph } from '../common/Paragraph'; import { Paragraph } from '../common/Paragraph';
import { Popover } from '../common/Popover';
import { View } from '../common/View'; import { View } from '../common/View';
import { FormField, FormLabel } from '../forms'; import { FormField, FormLabel } from '../forms';
import { type CommonModalProps } from '../Modals'; import { type CommonModalProps } from '../Modals';
import { Tooltip } from '../tooltips';
import { COUNTRY_OPTIONS } from './countries'; import { COUNTRY_OPTIONS } from './countries';
@@ -103,6 +103,7 @@ export function GoCardlessExternalMsg({
>(null); >(null);
const [menuOpen, setMenuOpen] = useState<boolean>(false); const [menuOpen, setMenuOpen] = useState<boolean>(false);
const data = useRef<GoCardlessToken | null>(null); const data = useRef<GoCardlessToken | null>(null);
const triggerRef = useRef(null);
const { const {
data: bankOptions, data: bankOptions,
@@ -230,6 +231,7 @@ export function GoCardlessExternalMsg({
Link bank in browser &rarr; Link bank in browser &rarr;
</Button> </Button>
<Button <Button
ref={triggerRef}
type="bare" type="bare"
onClick={() => setMenuOpen(true)} onClick={() => setMenuOpen(true)}
aria-label="Menu" aria-label="Menu"
@@ -239,28 +241,27 @@ export function GoCardlessExternalMsg({
height={15} height={15}
style={{ transform: 'rotateZ(90deg)' }} style={{ transform: 'rotateZ(90deg)' }}
/> />
{menuOpen && (
<Tooltip <Popover
position="bottom-right" triggerRef={triggerRef}
width={200} isOpen={menuOpen}
style={{ padding: 0 }} style={{ width: 200 }}
onClose={() => setMenuOpen(false)} onOpenChange={() => setMenuOpen(false)}
> >
<Menu <Menu
onMenuSelect={item => { onMenuSelect={item => {
if (item === 'reconfigure') { if (item === 'reconfigure') {
onGoCardlessInit(); onGoCardlessInit();
} }
}} }}
items={[ items={[
{ {
name: 'reconfigure', name: 'reconfigure',
text: 'Set new API secrets', text: 'Set new API secrets',
}, },
]} ]}
/> />
</Tooltip> </Popover>
)}
</Button> </Button>
</View> </View>
</View> </View>

View File

@@ -23,6 +23,7 @@ import { useStableCallback } from '../../hooks/useStableCallback';
import { SvgExpandArrow } from '../../icons/v0'; import { SvgExpandArrow } from '../../icons/v0';
import { theme } from '../../style'; import { theme } from '../../style';
import { Button } from '../common/Button'; import { Button } from '../common/Button';
import { Popover } from '../common/Popover';
import { Search } from '../common/Search'; import { Search } from '../common/Search';
import { View } from '../common/View'; import { View } from '../common/View';
import { TableHeader, Cell, SelectCell, useTableNavigator } from '../table'; import { TableHeader, Cell, SelectCell, useTableNavigator } from '../table';
@@ -102,6 +103,7 @@ export const ManagePayees = forwardRef(
const [filter, setFilter] = useState(''); const [filter, setFilter] = useState('');
const table = useRef(null); const table = useRef(null);
const scrollTo = useRef(null); const scrollTo = useRef(null);
const triggerRef = useRef(null);
const resetAnimation = useRef(false); const resetAnimation = useRef(false);
const [orphanedOnly, setOrphanedOnly] = useState(false); const [orphanedOnly, setOrphanedOnly] = useState(false);
@@ -233,6 +235,7 @@ export const ManagePayees = forwardRef(
> >
<View style={{ flexShrink: 0 }}> <View style={{ flexShrink: 0 }}>
<Button <Button
ref={triggerRef}
type="bare" type="bare"
style={{ marginRight: 10 }} style={{ marginRight: 10 }}
disabled={buttonsDisabled} disabled={buttonsDisabled}
@@ -245,7 +248,14 @@ export const ManagePayees = forwardRef(
plural(selected.items.size, 'payee', 'payees')} plural(selected.items.size, 'payee', 'payees')}
<SvgExpandArrow width={8} height={8} style={{ marginLeft: 5 }} /> <SvgExpandArrow width={8} height={8} style={{ marginLeft: 5 }} />
</Button> </Button>
{menuOpen && (
<Popover
triggerRef={triggerRef}
isOpen={menuOpen}
placement="bottom start"
style={{ width: 250 }}
onOpenChange={() => setMenuOpen(false)}
>
<PayeeMenu <PayeeMenu
payeesById={payeesById} payeesById={payeesById}
selectedPayees={selected.items} selectedPayees={selected.items}
@@ -253,7 +263,7 @@ export const ManagePayees = forwardRef(
onDelete={onDelete} onDelete={onDelete}
onMerge={onMerge} onMerge={onMerge}
/> />
)} </Popover>
</View> </View>
<View <View
style={{ style={{

View File

@@ -4,7 +4,6 @@ import { SvgDelete, SvgMerge } from '../../icons/v0';
import { theme } from '../../style'; import { theme } from '../../style';
import { Menu } from '../common/Menu'; import { Menu } from '../common/Menu';
import { View } from '../common/View'; import { View } from '../common/View';
import { Tooltip } from '../tooltips';
type PayeeMenuProps = { type PayeeMenuProps = {
payeesById: Record<PayeeEntity['id'], PayeeEntity>; payeesById: Record<PayeeEntity['id'], PayeeEntity>;
@@ -27,57 +26,50 @@ export function PayeeMenu({
); );
return ( return (
<Tooltip <Menu
position="bottom" onMenuSelect={type => {
width={250} onClose();
style={{ padding: 0 }} switch (type) {
onClose={onClose} case 'delete':
> onDelete();
<Menu break;
onMenuSelect={type => { case 'merge':
onClose(); onMerge();
switch (type) { break;
case 'delete': default:
onDelete();
break;
case 'merge':
onMerge();
break;
default:
}
}}
footer={
<View
style={{
padding: 3,
fontSize: 11,
fontStyle: 'italic',
color: theme.pageTextSubdued,
}}
>
{[...selectedPayees]
.slice(0, 4)
.map(id => payeesById[id].name)
.join(', ') + (selectedPayees.size > 4 ? ', and more' : '')}
</View>
} }
items={[ }}
{ footer={
icon: SvgDelete, <View
name: 'delete', style={{
text: 'Delete', padding: 3,
disabled: isDisabled, fontSize: 11,
}, fontStyle: 'italic',
{ color: theme.pageTextSubdued,
icon: SvgMerge, }}
iconSize: 9, >
name: 'merge', {[...selectedPayees]
text: 'Merge', .slice(0, 4)
disabled: isDisabled || selectedPayees.size < 2, .map(id => payeesById[id].name)
}, .join(', ') + (selectedPayees.size > 4 ? ', and more' : '')}
Menu.line, </View>
]} }
/> items={[
</Tooltip> {
icon: SvgDelete,
name: 'delete',
text: 'Delete',
disabled: isDisabled,
},
{
icon: SvgMerge,
iconSize: 9,
name: 'merge',
text: 'Merge',
disabled: isDisabled || selectedPayees.size < 2,
},
Menu.line,
]}
/>
); );
} }

View File

@@ -1,5 +1,5 @@
// @ts-strict-ignore // @ts-strict-ignore
import React, { useState, useMemo, type CSSProperties } from 'react'; import React, { useRef, useState, useMemo, type CSSProperties } from 'react';
import { import {
type ScheduleStatusType, type ScheduleStatusType,
@@ -18,11 +18,11 @@ import { SvgCheck } from '../../icons/v2';
import { theme } from '../../style'; import { theme } from '../../style';
import { Button } from '../common/Button'; import { Button } from '../common/Button';
import { Menu } from '../common/Menu'; import { Menu } from '../common/Menu';
import { Popover } from '../common/Popover';
import { Text } from '../common/Text'; import { Text } from '../common/Text';
import { View } from '../common/View'; import { View } from '../common/View';
import { PrivacyFilter } from '../PrivacyFilter'; import { PrivacyFilter } from '../PrivacyFilter';
import { Table, TableHeader, Row, Field, Cell } from '../table'; import { Table, TableHeader, Row, Field, Cell } from '../table';
import { Tooltip } from '../tooltips';
import { DisplayId } from '../util/DisplayId'; import { DisplayId } from '../util/DisplayId';
import { StatusBadge } from './StatusBadge'; import { StatusBadge } from './StatusBadge';
@@ -60,6 +60,7 @@ function OverflowMenu({
status: ScheduleStatusType; status: ScheduleStatusType;
onAction: SchedulesTableProps['onAction']; onAction: SchedulesTableProps['onAction'];
}) { }) {
const triggerRef = useRef(null);
const [open, setOpen] = useState(false); const [open, setOpen] = useState(false);
const getMenuItems = () => { const getMenuItems = () => {
@@ -96,6 +97,7 @@ function OverflowMenu({
return ( return (
<View> <View>
<Button <Button
ref={triggerRef}
type="bare" type="bare"
aria-label="Menu" aria-label="Menu"
onClick={e => { onClick={e => {
@@ -109,22 +111,20 @@ function OverflowMenu({
style={{ transform: 'rotateZ(90deg)' }} style={{ transform: 'rotateZ(90deg)' }}
/> />
</Button> </Button>
{open && (
<Tooltip <Popover
position="bottom-right" triggerRef={triggerRef}
width={150} isOpen={open}
style={{ padding: 0 }} onOpenChange={() => setOpen(false)}
onClose={() => setOpen(false)} >
> <Menu
<Menu onMenuSelect={name => {
onMenuSelect={name => { onAction(name, schedule.id);
onAction(name, schedule.id); setOpen(false);
setOpen(false); }}
}} items={getMenuItems()}
items={getMenuItems()} />
/> </Popover>
</Tooltip>
)}
</View> </View>
); );
} }

View File

@@ -0,0 +1,6 @@
---
category: Maintenance
authors: [MatissJanis]
---
Migrating native `Tooltip` component to react-aria Tooltip/Popover (vol.6)