diff --git a/packages/manager/src/components/ActionMenu/ActionMenu.tsx b/packages/manager/src/components/ActionMenu/ActionMenu.tsx index 7b3eaa66d1f..97602e5356f 100644 --- a/packages/manager/src/components/ActionMenu/ActionMenu.tsx +++ b/packages/manager/src/components/ActionMenu/ActionMenu.tsx @@ -6,7 +6,6 @@ import * as React from 'react'; import KebabIcon from 'src/assets/icons/kebab.svg'; import { TooltipIcon } from 'src/components/TooltipIcon'; import { convertToKebabCase } from 'src/utilities/convertToKebobCase'; - export interface Action { disabled?: boolean; id?: string; diff --git a/packages/manager/src/components/InlineMenuAction/InlineMenuAction.tsx b/packages/manager/src/components/InlineMenuAction/InlineMenuAction.tsx index 1f91db3d338..726585670ec 100644 --- a/packages/manager/src/components/InlineMenuAction/InlineMenuAction.tsx +++ b/packages/manager/src/components/InlineMenuAction/InlineMenuAction.tsx @@ -5,6 +5,11 @@ import { Link } from 'react-router-dom'; import { StyledActionButton } from 'src/components/Button/StyledActionButton'; +import { TanstackLink } from '../TanstackLink'; + +import type { TanstackLinkProps } from '../TanstackLink'; +import type { LinkProps as TanStackLinkProps } from '@tanstack/react-router'; + interface InlineMenuActionProps { /** Required action text */ actionText: string; @@ -24,6 +29,13 @@ interface InlineMenuActionProps { loading?: boolean; /** Optional onClick handler */ onClick?: (e: React.MouseEvent) => void; + /** Optional use the tanstackRouter */ + tanstackRouter?: { + linkType: TanstackLinkProps['linkType']; + params?: TanStackLinkProps['params']; + preload?: TanStackLinkProps['preload']; + to: TanStackLinkProps['to']; + }; /** Optional tooltip text for help icon */ tooltip?: string; /** Optional tooltip event handler for sending analytics */ @@ -39,12 +51,13 @@ export const InlineMenuAction = (props: InlineMenuActionProps) => { href, loading, onClick, + tanstackRouter, tooltip, tooltipAnalyticsEvent, ...rest } = props; - if (href) { + if (href && !tanstackRouter?.to) { return ( {actionText} @@ -52,19 +65,27 @@ export const InlineMenuAction = (props: InlineMenuActionProps) => { ); } - return ( - {actionText} + + ) : ( + + {actionText} ); }; diff --git a/packages/manager/src/components/TanstackLink.stories.tsx b/packages/manager/src/components/TanstackLink.stories.tsx index fc517ab986c..b4ceb1aa5af 100644 --- a/packages/manager/src/components/TanstackLink.stories.tsx +++ b/packages/manager/src/components/TanstackLink.stories.tsx @@ -5,9 +5,25 @@ import { TanstackLink } from './TanstackLink'; import type { TanstackLinkProps } from './TanstackLink'; import type { Meta, StoryObj } from '@storybook/react'; -export const ButtonPrimary: StoryObj = { +export const AsButtonPrimary: StoryObj = { render: () => ( - + + Home + + ), +}; + +export const AsButtonSecondary: StoryObj = { + render: () => ( + + Home + + ), +}; + +export const AsLink: StoryObj = { + render: () => ( + Home ), diff --git a/packages/manager/src/components/TanstackLink.tsx b/packages/manager/src/components/TanstackLink.tsx index 0fb8fb8f35d..5e8798df13b 100644 --- a/packages/manager/src/components/TanstackLink.tsx +++ b/packages/manager/src/components/TanstackLink.tsx @@ -1,27 +1,45 @@ -import { Link } from '@tanstack/react-router'; +import { LinkComponent } from '@tanstack/react-router'; +import { createLink } from '@tanstack/react-router'; import * as React from 'react'; import { Button } from 'src/components/Button/Button'; +import { omitProps } from 'src/utilities/omittedProps'; -import type { LinkProps } from '@tanstack/react-router'; -import type { ButtonProps } from 'src/components/Button/Button'; +import type { ButtonProps, ButtonType } from 'src/components/Button/Button'; -export interface TanstackLinkProps extends LinkProps { - buttonType: NonNullable; +export interface TanstackLinkProps + extends Omit { + linkType: 'link' | ButtonType; + tooltipAnalyticsEvent?: (() => void) | undefined; + tooltipText?: string; } -export const TanstackLink = ({ - buttonType, - children, - ...linkProps -}: TanstackLinkProps) => { +const LinkComponent = React.forwardRef( + (props, ref) => { + const _props = omitProps(props, ['linkType']); + + return - + ({ + ...(props.linkType === 'link' && { + '&:hover': { + textDecoration: 'underline', + }, + fontFamily: theme.font.normal, + fontSize: '0.875rem', + minWidth: 'initial', + padding: 0, + }), + })} + /> ); }; diff --git a/packages/manager/src/features/Volumes/VolumesActionMenu.tsx b/packages/manager/src/features/Volumes/VolumesActionMenu.tsx index 4e0c062b541..70229bf43fd 100644 --- a/packages/manager/src/features/Volumes/VolumesActionMenu.tsx +++ b/packages/manager/src/features/Volumes/VolumesActionMenu.tsx @@ -11,6 +11,7 @@ import { useIsResourceRestricted } from 'src/hooks/useIsResourceRestricted'; import type { Volume } from '@linode/api-v4'; import type { Theme } from '@mui/material/styles'; import type { Action } from 'src/components/ActionMenu/ActionMenu'; +import type { VolumeAction } from 'src/routes/volumes'; export interface ActionHandlers { handleAttach: () => void; @@ -43,12 +44,14 @@ export const VolumesActionMenu = (props: Props) => { id: volume.id, }); - const actions: Action[] = [ + const actions: (Action & { action?: VolumeAction })[] = [ { + action: 'details', onClick: handlers.handleDetails, title: 'Show Config', }, { + action: 'edit', disabled: isVolumeReadOnly, onClick: handlers.handleEdit, title: 'Edit', @@ -61,6 +64,7 @@ export const VolumesActionMenu = (props: Props) => { : undefined, }, { + action: 'resize', disabled: isVolumeReadOnly, onClick: handlers.handleResize, title: 'Resize', @@ -73,6 +77,7 @@ export const VolumesActionMenu = (props: Props) => { : undefined, }, { + action: 'clone', disabled: isVolumeReadOnly, onClick: handlers.handleClone, title: 'Clone', @@ -88,6 +93,7 @@ export const VolumesActionMenu = (props: Props) => { if (!attached && isVolumesLanding) { actions.push({ + action: 'attach', disabled: isVolumeReadOnly, onClick: handlers.handleAttach, title: 'Attach', @@ -101,6 +107,7 @@ export const VolumesActionMenu = (props: Props) => { }); } else { actions.push({ + action: 'detach', disabled: isVolumeReadOnly, onClick: handlers.handleDetach, title: 'Detach', @@ -115,6 +122,7 @@ export const VolumesActionMenu = (props: Props) => { } actions.push({ + action: 'delete', disabled: isVolumeReadOnly || attached, onClick: handlers.handleDelete, title: 'Delete', @@ -138,6 +146,15 @@ export const VolumesActionMenu = (props: Props) => { inlineActions.map((action) => { return (