diff --git a/components/DrawerHeader.tsx b/components/DrawerHeader.tsx index 4adf32cce8e..1c64f34fb59 100644 --- a/components/DrawerHeader.tsx +++ b/components/DrawerHeader.tsx @@ -10,6 +10,7 @@ import { DropdownActionItem } from './table/RowActionsMenu'; import { Button } from './ui/Button'; import { DropdownMenu, DropdownMenuContent, DropdownMenuSeparator, DropdownMenuTrigger } from './ui/DropdownMenu'; import { SheetClose } from './ui/Sheet'; +import Link from './Link'; type DrawerHeaderProps = { actions?: { @@ -68,6 +69,7 @@ export default function DrawerHeader({ {primary?.map(action => ( ))} diff --git a/components/ExchangeRate.tsx b/components/ExchangeRate.tsx index 61a0554871e..7929b1ab559 100644 --- a/components/ExchangeRate.tsx +++ b/components/ExchangeRate.tsx @@ -7,7 +7,7 @@ import type { CurrencyExchangeRate, CurrencyExchangeRateInput } from '../lib/gra import { cn } from '../lib/utils'; import { Input } from './ui/Input'; -import { Tooltip, TooltipContent, TooltipPortal, TooltipTrigger } from './ui/Tooltip'; +import { Tooltip, TooltipContent, TooltipTrigger } from './ui/Tooltip'; import { formatFxRateInfo } from './AmountWithExchangeRateInfo'; import Spinner from './Spinner'; @@ -98,11 +98,9 @@ export const ExchangeRate = ({ )} - - - {formatFxRateInfo(intl, exchangeRate, { approximateCustomMessage, warning, error })} - - + + {formatFxRateInfo(intl, exchangeRate, { approximateCustomMessage, warning, error })} + ); }; diff --git a/components/dashboard/sections/contributions/actions.tsx b/components/dashboard/sections/contributions/actions.tsx index 3e041884ae2..f5bce9d9030 100644 --- a/components/dashboard/sections/contributions/actions.tsx +++ b/components/dashboard/sections/contributions/actions.tsx @@ -8,13 +8,12 @@ import type { ContributionDrawerQuery, ManagedOrderFieldsFragment } from '../../ import { ContributionFrequency, OrderStatus, PaymentMethodType } from '../../../../lib/graphql/types/v2/graphql'; import useLoggedInUser from '../../../../lib/hooks/useLoggedInUser'; import { getWebsiteUrl } from '../../../../lib/utils'; +import useClipboard from '@/lib/hooks/useClipboard'; import ContributionConfirmationModal from '../../../ContributionConfirmationModal'; import { getTransactionsUrl } from '../../../contributions/ContributionTimeline'; -import { CopyID } from '../../../CopyId'; import type { EditOrderActions } from '../../../EditOrderModal'; import EditOrderModal from '../../../EditOrderModal'; -import Link from '../../../Link'; import { useModal } from '../../../ModalContext'; import { useToast } from '../../../ui/useToast'; @@ -54,6 +53,7 @@ export function useContributionActions - - - - ), + Icon: ArrowLeftRightIcon, + href: transactionsUrl.toString(), + label: intl.formatMessage({ defaultMessage: 'View transactions', id: 'DfQJQ6' }), onClick: () => {}, }); } @@ -157,8 +154,9 @@ export function useContributionActions { showModal( CreatePendingContributionModal, @@ -252,12 +250,8 @@ export function useContributionActions - - {intl.formatMessage({ defaultMessage: 'Edit funds', id: 'Kbjd3f' })} - - ), + Icon: Pencil, + label: intl.formatMessage({ defaultMessage: 'Edit funds', id: 'Kbjd3f' }), onClick: () => showEditOrderModal('editAddedFunds'), }); } @@ -268,20 +262,17 @@ export function useContributionActions} - className="" - > -
- - -
- - ), - onClick: () => {}, + Icon: LinkIcon, + label: intl.formatMessage({ defaultMessage: 'Copy link', id: 'CopyLink' }), + onClick: e => { + e.preventDefault(); // Prevent dropdown from closing when copying + + copy(orderUrl); + toast({ + message: , + variant: 'success', + }); + }, }); return actions; diff --git a/components/dashboard/sections/exports/index.tsx b/components/dashboard/sections/exports/index.tsx index 7b110d58fe6..5ff0473af03 100644 --- a/components/dashboard/sections/exports/index.tsx +++ b/components/dashboard/sections/exports/index.tsx @@ -5,6 +5,7 @@ import { useRouter } from 'next/router'; import { defineMessage, FormattedMessage, useIntl } from 'react-intl'; import { z } from 'zod'; +import type { Action, GetActions } from '@/lib/actions/types'; import { i18nGraphqlException } from '@/lib/errors'; import { formatFileSize } from '@/lib/file-utils'; import type { FilterComponentConfigs, Views } from '@/lib/filters/filter-types'; @@ -341,19 +342,18 @@ const Exports = ({ accountSlug, subpath }: DashboardSectionProps) => { [intl, removeExportRequest, showConfirmationModal, toast], ); - const getActions = React.useCallback( - (exportRequest: ExportRequestNode) => { - const primary = []; - const secondary = []; + const getActions = React.useCallback>( + exportRequest => { + const primary: Action[] = []; + const secondary: Action[] = []; if (exportRequest?.status === ExportRequestStatus.COMPLETED && exportRequest.file) { primary.push({ key: 'download', label: intl.formatMessage({ defaultMessage: 'Download', id: 'Download' }), Icon: Download, - onClick: () => { - window.open(exportRequest.file.url, '_blank'); - }, + href: exportRequest.file.url, + target: '_blank', }); } @@ -361,7 +361,6 @@ const Exports = ({ accountSlug, subpath }: DashboardSectionProps) => { key: 'delete', label: intl.formatMessage({ defaultMessage: 'Delete', id: 'actions.delete' }), Icon: Trash2, - variant: 'danger', onClick: () => handleRemove(exportRequest), }); @@ -398,6 +397,7 @@ const Exports = ({ accountSlug, subpath }: DashboardSectionProps) => { getActions={getActions} onClickRow={row => pushSubpath(row.original.id)} mobileTableView + showQuickActions /> diff --git a/components/dashboard/sections/transactions-imports/lib/actions.tsx b/components/dashboard/sections/transactions-imports/lib/actions.tsx index b9ddfce6202..900a4cbbf36 100644 --- a/components/dashboard/sections/transactions-imports/lib/actions.tsx +++ b/components/dashboard/sections/transactions-imports/lib/actions.tsx @@ -2,7 +2,7 @@ import React from 'react'; import { useMutation } from '@apollo/client'; import { cloneDeep, pick, uniq, update } from 'lodash'; import { ArchiveRestore, Banknote, Merge, PauseCircle, Receipt, SquareSlashIcon, Unlink } from 'lucide-react'; -import { FormattedMessage, useIntl } from 'react-intl'; +import { useIntl } from 'react-intl'; import type { GetActions } from '../../../../../lib/actions/types'; import { i18nGraphqlException } from '../../../../../lib/errors'; @@ -13,7 +13,6 @@ import type { import { TransactionsImportRowStatus } from '../../../../../lib/graphql/types/v2/graphql'; import { useModal } from '../../../../ModalContext'; -import Spinner from '../../../../Spinner'; import { useToast } from '../../../../ui/useToast'; import { HostCreateExpenseModal } from '../../expenses/HostCreateExpenseModal'; import { AddFundsModalFromImportRow } from '../AddFundsModalFromTransactionsImportRow'; @@ -176,7 +175,7 @@ export const useTransactionsImportActions = ({ actions.primary.push({ key: 'revert', Icon: Unlink, - label: , + label: intl.formatMessage({ defaultMessage: 'Unlink', id: 'Transaction.Unlink' }), disabled: isUpdatingRow, onClick: () => { showModal( @@ -195,7 +194,7 @@ export const useTransactionsImportActions = ({ actions.primary.push({ key: 'match', Icon: Merge, - label: , + label: intl.formatMessage({ defaultMessage: 'Match', id: 'Qr9R5O' }), disabled: isUpdatingRow, onClick: () => showModal( @@ -217,7 +216,7 @@ export const useTransactionsImportActions = ({ actions.primary.push({ key: 'add-funds', Icon: Banknote, - label: , + label: intl.formatMessage({ defaultMessage: 'Add funds', id: 'sx0aSl' }), disabled: isUpdatingRow, onClick: showAddFundsModal, }); @@ -225,7 +224,7 @@ export const useTransactionsImportActions = ({ actions.primary.push({ key: 'match', Icon: Merge, - label: , + label: intl.formatMessage({ defaultMessage: 'Match', id: 'Qr9R5O' }), disabled: isUpdatingRow, onClick: () => { showModal( @@ -238,7 +237,7 @@ export const useTransactionsImportActions = ({ actions.primary.push({ key: 'create-expense', Icon: Receipt, - label: , + label: intl.formatMessage({ defaultMessage: 'Create expense', id: 'YUK+rq' }), disabled: isUpdatingRow, onClick: () => { showModal( @@ -257,12 +256,8 @@ export const useTransactionsImportActions = ({ Icon: PauseCircle, onClick: () => setRowsStatus([row.id], TransactionsImportRowStatus.ON_HOLD), disabled: isUpdatingRow, - label: ( -
- - {isUpdatingRow && } -
- ), + isLoading: isUpdatingRow, + label: intl.formatMessage({ defaultMessage: 'Put on Hold', id: '+pCc8I' }), }); } else { actions.primary.push({ @@ -270,12 +265,8 @@ export const useTransactionsImportActions = ({ Icon: ArchiveRestore, onClick: () => setRowsStatus([row.id], TransactionsImportRowStatus.PENDING), disabled: isUpdatingRow, - label: ( -
- - {isUpdatingRow && } -
- ), + isLoading: isUpdatingRow, + label: intl.formatMessage({ defaultMessage: 'Restore', id: 'zz6ObK' }), }); } @@ -285,13 +276,8 @@ export const useTransactionsImportActions = ({ Icon: SquareSlashIcon, onClick: () => setRowsStatus([row.id], TransactionsImportRowStatus.IGNORED), disabled: isUpdatingRow, - label: ( -
- - - {isUpdatingRow && } -
- ), + isLoading: isUpdatingRow, + label: intl.formatMessage({ defaultMessage: 'No action', id: 'zue9QR' }), }); } diff --git a/components/table/DataTable.tsx b/components/table/DataTable.tsx index 48608cd2c64..3e04b3e0ce3 100644 --- a/components/table/DataTable.tsx +++ b/components/table/DataTable.tsx @@ -60,6 +60,7 @@ interface DataTableProps { rowSelection?: Record; setRowSelection?: OnChangeFn; enableMultiRowSelection?: boolean; + showQuickActions?: boolean; } const defaultGetRowId = (data: any) => data.id; @@ -90,6 +91,7 @@ export function DataTable({ rowSelection: rowSelectionFromProps, setRowSelection: setRowSelectionFromProps, enableMultiRowSelection, + showQuickActions, meta, // TODO: Possibly remove this prop once the getActions pattern is implemented fully ...tableProps }: DataTableProps) { @@ -125,6 +127,7 @@ export function DataTable({ hasDefaultColumnVisibility, setColumnVisibility, defaultColumnVisibility, + showQuickActions, ...meta, }, }); @@ -277,7 +280,7 @@ export const stickyColumnVariants = cva( select: 'left-0 z-1 w-10 max-w-10 min-w-10 [filter:drop-shadow(2px_0px_6px_rgba(0,0,0,var(--scroll-shadow-left,0)))] [clip-path:inset(0px_-20px_0px_0px)]', actions: - 'right-0 w-12 max-w-12 min-w-12 !pr-2 [filter:drop-shadow(-2px_0px_6px_rgba(0,0,0,var(--scroll-shadow-right,0)))] [clip-path:inset(0px_0px_0px_-20px)]', + 'right-0 w-12 max-w-12 min-w-12 !pr-2 [filter:drop-shadow(-2px_0px_6px_rgba(0,0,0,var(--scroll-shadow-right,0)))]', //[clip-path:inset(0px_0px_0px_-20px)] }, }, }, diff --git a/components/table/RowActionsMenu.tsx b/components/table/RowActionsMenu.tsx index 98ded00c014..a2d8c5dc463 100644 --- a/components/table/RowActionsMenu.tsx +++ b/components/table/RowActionsMenu.tsx @@ -4,9 +4,13 @@ import { MoreHorizontal, PanelRightOpen } from 'lucide-react'; import { FormattedMessage } from 'react-intl'; import type { Action } from '@/lib/actions/types'; +import useLoggedInUser from '@/lib/hooks/useLoggedInUser'; +import { PREVIEW_FEATURE_KEYS } from '@/lib/preview-features'; +import Link from '../Link'; import Spinner from '../Spinner'; import { Button } from '../ui/Button'; +import { ButtonGroup } from '../ui/ButtonGroup'; import { DropdownMenu, DropdownMenuContent, @@ -16,17 +20,31 @@ import { } from '../ui/DropdownMenu'; import { Tooltip, TooltipContent, TooltipTrigger } from '../ui/Tooltip'; +function DropdownActionItemContent({ action }: { action: Action }) { + return ( + + {action.Icon && } + {action.label} + {action.isLoading && } + + ); +} + export function DropdownActionItem({ action }: { action: Action }) { - const item = ( + const item = action.href ? ( + + + + + + ) : ( - {action.Icon && } - {action.label} - {action.isLoading && } + ); @@ -48,10 +66,16 @@ interface RowActionsMenuProps { } export function RowActionsMenu({ row, actionsMenuTriggerRef, table }: RowActionsMenuProps) { + const { LoggedInUser } = useLoggedInUser(); + const hasQuickActionsPreviewEnabled = LoggedInUser?.hasPreviewFeatureEnabled( + PREVIEW_FEATURE_KEYS.TABLE_QUICK_ACTIONS, + ); + if (!row.original) { return null; } - const { getActions, openDrawer } = table.options.meta; + const { getActions, openDrawer, showQuickActions } = table.options.meta; + const hasQuickActionsEnabled = showQuickActions || hasQuickActionsPreviewEnabled; if (!getActions) { return null; @@ -60,19 +84,55 @@ export function RowActionsMenu({ row, actionsMenuTriggerRef, table }: Row const { primary, secondary } = getActions(row.original, actionsMenuTriggerRef) ?? {}; const hasNoActions = !primary?.length && !secondary?.length && !openDrawer; + if (hasNoActions) { + return null; + } + + const quickActions = + hasQuickActionsEnabled && primary + ? primary + .filter(a => a.Icon && !a.disabled) // only actions with Icons can be rendered as quick-actions, and should not be disabled + .slice(0, 2) // only show the first 2 primary actions + : []; + return ( - - - + + {quickActions.map(action => ( + + + + + {action.label} + + ))} + + + + + {openDrawer && ( diff --git a/components/table/data-table.d.ts b/components/table/data-table.d.ts index 758d7a03029..42e78851da9 100644 --- a/components/table/data-table.d.ts +++ b/components/table/data-table.d.ts @@ -22,6 +22,7 @@ declare module '@tanstack/react-table' { hasDefaultColumnVisibility?: boolean; openDrawer?: (row: Row, actionsMenuTriggerRef?: RefObject) => void; getActions?: GetActions; + showQuickActions?: boolean; // TODO: remove types below when all tables use getActions // Hosted Collectives table diff --git a/components/ui/ButtonGroup.tsx b/components/ui/ButtonGroup.tsx new file mode 100644 index 00000000000..6f42c626d93 --- /dev/null +++ b/components/ui/ButtonGroup.tsx @@ -0,0 +1,81 @@ +import React from 'react'; +import { Slot } from '@radix-ui/react-slot'; +import { cva, type VariantProps } from 'class-variance-authority'; + +import { cn } from '@/lib/utils'; + +import { Separator } from '@/components/ui/Separator'; + +const buttonGroupVariants = cva( + "flex w-fit items-stretch *:focus-visible:relative *:focus-visible:z-10 has-[>[data-slot=button-group]]:gap-2 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-lg [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1", + { + variants: { + orientation: { + horizontal: + '[&>*:not(:first-child)]:rounded-l-none [&>*:not(:first-child)]:border-l-0 [&>*:not(:last-child)]:rounded-r-none [&>[data-slot]:not(:has(~[data-slot]))]:rounded-r-lg!', + vertical: + 'flex-col [&>*:not(:first-child)]:rounded-t-none [&>*:not(:first-child)]:border-t-0 [&>*:not(:last-child)]:rounded-b-none [&>[data-slot]:not(:has(~[data-slot]))]:rounded-b-lg!', + }, + }, + defaultVariants: { + orientation: 'horizontal', + }, + }, +); + +function ButtonGroup({ + className, + orientation, + ...props +}: React.ComponentProps<'div'> & VariantProps) { + return ( +
+ ); +} + +function ButtonGroupText({ + className, + asChild = false, + ...props +}: React.ComponentProps<'div'> & { + asChild?: boolean; +}) { + const Comp = asChild ? Slot : 'div'; + + return ( + + ); +} + +function ButtonGroupSeparator({ + className, + orientation = 'vertical', + ...props +}: React.ComponentProps) { + return ( + + ); +} + +// ts-unused-exports:disable-next-line +export { ButtonGroup, ButtonGroupSeparator, ButtonGroupText, buttonGroupVariants }; diff --git a/components/ui/Tooltip.tsx b/components/ui/Tooltip.tsx index c71cec811bf..4c72144abe1 100644 --- a/components/ui/Tooltip.tsx +++ b/components/ui/Tooltip.tsx @@ -3,30 +3,42 @@ import * as TooltipPrimitive from '@radix-ui/react-tooltip'; import { cn } from '../../lib/utils'; -const TooltipProvider = TooltipPrimitive.Provider; +function TooltipProvider({ delayDuration = 0, ...props }: React.ComponentProps) { + return ; +} -const Tooltip = TooltipPrimitive.Root; +function Tooltip({ ...props }: React.ComponentProps) { + return ; +} -const TooltipTrigger = (props: React.ComponentProps) => ( - -); +function TooltipTrigger({ ...props }: React.ComponentProps) { + return ; +} const TooltipPortal = TooltipPrimitive.Portal; -const TooltipContent = React.forwardRef< - React.ElementRef, - React.ComponentPropsWithoutRef ->(({ className, sideOffset = 4, ...props }, ref) => ( - -)); -TooltipContent.displayName = TooltipPrimitive.Content.displayName; +function TooltipContent({ + className, + sideOffset = 4, + children, + ...props +}: React.ComponentProps) { + return ( + + + {children} + + + ); +} +// ts-unused-exports:disable-next-line export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider, TooltipPortal }; diff --git a/lang/ca.json b/lang/ca.json index 52b6ce71e1f..8be9df82b17 100644 --- a/lang/ca.json +++ b/lang/ca.json @@ -3405,6 +3405,8 @@ "PreviewFeatures.searchCommandDescription": "Discover a new way to search for collectives, transactions, expenses, and more through an intuitive command menu interface. Access information faster with powerful search capabilities.", "PreviewFeatures.searchCommandTitle": "Search Command Menu", "PreviewFeatures.searchResultsPage": "Search Results Page", + "PreviewFeatures.tableQuickActionsDescription": "Enable quick action buttons that appear on table rows when you hover over them. Perform common actions faster without opening the dropdown menu.", + "PreviewFeatures.tableQuickActionsTitle": "Table Quick Actions", "Pricing-Crowdfunding": "Crowdfunding contributions", "Pricing-Crowdfunding-Price": "Free with Platform Tips activated", "Pricing-forOrganizations": "Pricing for Organizations", diff --git a/lang/cs.json b/lang/cs.json index b06ded6ac76..e3357063e9f 100644 --- a/lang/cs.json +++ b/lang/cs.json @@ -3405,6 +3405,8 @@ "PreviewFeatures.searchCommandDescription": "Discover a new way to search for collectives, transactions, expenses, and more through an intuitive command menu interface. Access information faster with powerful search capabilities.", "PreviewFeatures.searchCommandTitle": "Search Command Menu", "PreviewFeatures.searchResultsPage": "Search Results Page", + "PreviewFeatures.tableQuickActionsDescription": "Enable quick action buttons that appear on table rows when you hover over them. Perform common actions faster without opening the dropdown menu.", + "PreviewFeatures.tableQuickActionsTitle": "Table Quick Actions", "Pricing-Crowdfunding": "Crowdfunding contributions", "Pricing-Crowdfunding-Price": "Free with Platform Tips activated", "Pricing-forOrganizations": "Pricing for Organizations", diff --git a/lang/de.json b/lang/de.json index 18b5f308869..2e47728d794 100644 --- a/lang/de.json +++ b/lang/de.json @@ -3405,6 +3405,8 @@ "PreviewFeatures.searchCommandDescription": "Discover a new way to search for collectives, transactions, expenses, and more through an intuitive command menu interface. Access information faster with powerful search capabilities.", "PreviewFeatures.searchCommandTitle": "Search Command Menu", "PreviewFeatures.searchResultsPage": "Search Results Page", + "PreviewFeatures.tableQuickActionsDescription": "Enable quick action buttons that appear on table rows when you hover over them. Perform common actions faster without opening the dropdown menu.", + "PreviewFeatures.tableQuickActionsTitle": "Table Quick Actions", "Pricing-Crowdfunding": "Crowdfunding contributions", "Pricing-Crowdfunding-Price": "Free with Platform Tips activated", "Pricing-forOrganizations": "Pricing for Organizations", diff --git a/lang/en.json b/lang/en.json index 5098cd3d983..a79efe3e249 100644 --- a/lang/en.json +++ b/lang/en.json @@ -3405,6 +3405,8 @@ "PreviewFeatures.searchCommandDescription": "Discover a new way to search for collectives, transactions, expenses, and more through an intuitive command menu interface. Access information faster with powerful search capabilities.", "PreviewFeatures.searchCommandTitle": "Search Command Menu", "PreviewFeatures.searchResultsPage": "Search Results Page", + "PreviewFeatures.tableQuickActionsDescription": "Enable quick action buttons that appear on table rows when you hover over them. Perform common actions faster without opening the dropdown menu.", + "PreviewFeatures.tableQuickActionsTitle": "Table Quick Actions", "Pricing-Crowdfunding": "Crowdfunding contributions", "Pricing-Crowdfunding-Price": "Free with Platform Tips activated", "Pricing-forOrganizations": "Pricing for Organizations", diff --git a/lang/es.json b/lang/es.json index cd67a31515b..4443a6ffac0 100644 --- a/lang/es.json +++ b/lang/es.json @@ -3405,6 +3405,8 @@ "PreviewFeatures.searchCommandDescription": "Descubre una nueva forma de buscar colectivos, transacciones, gastos y mucho más a través de un intuitivo menú de comandos. Accede a la información más rápidamente con potentes funciones de búsqueda.", "PreviewFeatures.searchCommandTitle": "Menú de comandos de búsqueda", "PreviewFeatures.searchResultsPage": "Search Results Page", + "PreviewFeatures.tableQuickActionsDescription": "Enable quick action buttons that appear on table rows when you hover over them. Perform common actions faster without opening the dropdown menu.", + "PreviewFeatures.tableQuickActionsTitle": "Table Quick Actions", "Pricing-Crowdfunding": "Crowdfunding contributions", "Pricing-Crowdfunding-Price": "Free with Platform Tips activated", "Pricing-forOrganizations": "Pricing for Organizations", diff --git a/lang/fr.json b/lang/fr.json index 64f7543aa4a..7aa34d438de 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -3405,6 +3405,8 @@ "PreviewFeatures.searchCommandDescription": "Découvrez une nouvelle façon de rechercher des Collectifs, des transactions, des dépenses, et plus encore grâce à une interface intuitive dans le menu de commandes. Accédez plus rapidement aux informations grâce à de puissantes capacités de recherche.", "PreviewFeatures.searchCommandTitle": "Rechercher le menu de commande", "PreviewFeatures.searchResultsPage": "Page de résultats de recherche", + "PreviewFeatures.tableQuickActionsDescription": "Enable quick action buttons that appear on table rows when you hover over them. Perform common actions faster without opening the dropdown menu.", + "PreviewFeatures.tableQuickActionsTitle": "Table Quick Actions", "Pricing-Crowdfunding": "Contributions via le financement participatif", "Pricing-Crowdfunding-Price": "Gratuit avec les Pourboires de la plateforme activés", "Pricing-forOrganizations": "Tarif pour les Organisations", diff --git a/lang/he.json b/lang/he.json index b3cda50998a..c20b076dd18 100644 --- a/lang/he.json +++ b/lang/he.json @@ -3405,6 +3405,8 @@ "PreviewFeatures.searchCommandDescription": "Discover a new way to search for collectives, transactions, expenses, and more through an intuitive command menu interface. Access information faster with powerful search capabilities.", "PreviewFeatures.searchCommandTitle": "Search Command Menu", "PreviewFeatures.searchResultsPage": "Search Results Page", + "PreviewFeatures.tableQuickActionsDescription": "Enable quick action buttons that appear on table rows when you hover over them. Perform common actions faster without opening the dropdown menu.", + "PreviewFeatures.tableQuickActionsTitle": "Table Quick Actions", "Pricing-Crowdfunding": "Crowdfunding contributions", "Pricing-Crowdfunding-Price": "Free with Platform Tips activated", "Pricing-forOrganizations": "Pricing for Organizations", diff --git a/lang/it.json b/lang/it.json index 3d00a8e7899..2747cb9474f 100644 --- a/lang/it.json +++ b/lang/it.json @@ -3405,6 +3405,8 @@ "PreviewFeatures.searchCommandDescription": "Discover a new way to search for collectives, transactions, expenses, and more through an intuitive command menu interface. Access information faster with powerful search capabilities.", "PreviewFeatures.searchCommandTitle": "Search Command Menu", "PreviewFeatures.searchResultsPage": "Search Results Page", + "PreviewFeatures.tableQuickActionsDescription": "Enable quick action buttons that appear on table rows when you hover over them. Perform common actions faster without opening the dropdown menu.", + "PreviewFeatures.tableQuickActionsTitle": "Table Quick Actions", "Pricing-Crowdfunding": "Crowdfunding contributions", "Pricing-Crowdfunding-Price": "Free with Platform Tips activated", "Pricing-forOrganizations": "Pricing for Organizations", diff --git a/lang/ja.json b/lang/ja.json index cd35164a335..c860816d705 100644 --- a/lang/ja.json +++ b/lang/ja.json @@ -3405,6 +3405,8 @@ "PreviewFeatures.searchCommandDescription": "Discover a new way to search for collectives, transactions, expenses, and more through an intuitive command menu interface. Access information faster with powerful search capabilities.", "PreviewFeatures.searchCommandTitle": "Search Command Menu", "PreviewFeatures.searchResultsPage": "Search Results Page", + "PreviewFeatures.tableQuickActionsDescription": "Enable quick action buttons that appear on table rows when you hover over them. Perform common actions faster without opening the dropdown menu.", + "PreviewFeatures.tableQuickActionsTitle": "Table Quick Actions", "Pricing-Crowdfunding": "Crowdfunding contributions", "Pricing-Crowdfunding-Price": "Free with Platform Tips activated", "Pricing-forOrganizations": "Pricing for Organizations", diff --git a/lang/ko.json b/lang/ko.json index 57cf858b039..3dbb862d08a 100644 --- a/lang/ko.json +++ b/lang/ko.json @@ -3405,6 +3405,8 @@ "PreviewFeatures.searchCommandDescription": "Discover a new way to search for collectives, transactions, expenses, and more through an intuitive command menu interface. Access information faster with powerful search capabilities.", "PreviewFeatures.searchCommandTitle": "Search Command Menu", "PreviewFeatures.searchResultsPage": "Search Results Page", + "PreviewFeatures.tableQuickActionsDescription": "Enable quick action buttons that appear on table rows when you hover over them. Perform common actions faster without opening the dropdown menu.", + "PreviewFeatures.tableQuickActionsTitle": "Table Quick Actions", "Pricing-Crowdfunding": "Crowdfunding contributions", "Pricing-Crowdfunding-Price": "Free with Platform Tips activated", "Pricing-forOrganizations": "Pricing for Organizations", diff --git a/lang/nl.json b/lang/nl.json index 89f2825a908..d6bc17fab6a 100644 --- a/lang/nl.json +++ b/lang/nl.json @@ -3405,6 +3405,8 @@ "PreviewFeatures.searchCommandDescription": "Discover a new way to search for collectives, transactions, expenses, and more through an intuitive command menu interface. Access information faster with powerful search capabilities.", "PreviewFeatures.searchCommandTitle": "Search Command Menu", "PreviewFeatures.searchResultsPage": "Search Results Page", + "PreviewFeatures.tableQuickActionsDescription": "Enable quick action buttons that appear on table rows when you hover over them. Perform common actions faster without opening the dropdown menu.", + "PreviewFeatures.tableQuickActionsTitle": "Table Quick Actions", "Pricing-Crowdfunding": "Crowdfunding contributions", "Pricing-Crowdfunding-Price": "Free with Platform Tips activated", "Pricing-forOrganizations": "Pricing for Organizations", diff --git a/lang/pl.json b/lang/pl.json index f4f21fc73a2..9a446f87090 100644 --- a/lang/pl.json +++ b/lang/pl.json @@ -3405,6 +3405,8 @@ "PreviewFeatures.searchCommandDescription": "Discover a new way to search for collectives, transactions, expenses, and more through an intuitive command menu interface. Access information faster with powerful search capabilities.", "PreviewFeatures.searchCommandTitle": "Search Command Menu", "PreviewFeatures.searchResultsPage": "Search Results Page", + "PreviewFeatures.tableQuickActionsDescription": "Enable quick action buttons that appear on table rows when you hover over them. Perform common actions faster without opening the dropdown menu.", + "PreviewFeatures.tableQuickActionsTitle": "Table Quick Actions", "Pricing-Crowdfunding": "Crowdfunding contributions", "Pricing-Crowdfunding-Price": "Free with Platform Tips activated", "Pricing-forOrganizations": "Pricing for Organizations", diff --git a/lang/pt-BR.json b/lang/pt-BR.json index d6c2c9ca691..4dca6f5a895 100644 --- a/lang/pt-BR.json +++ b/lang/pt-BR.json @@ -3405,6 +3405,8 @@ "PreviewFeatures.searchCommandDescription": "Discover a new way to search for collectives, transactions, expenses, and more through an intuitive command menu interface. Access information faster with powerful search capabilities.", "PreviewFeatures.searchCommandTitle": "Search Command Menu", "PreviewFeatures.searchResultsPage": "Search Results Page", + "PreviewFeatures.tableQuickActionsDescription": "Enable quick action buttons that appear on table rows when you hover over them. Perform common actions faster without opening the dropdown menu.", + "PreviewFeatures.tableQuickActionsTitle": "Table Quick Actions", "Pricing-Crowdfunding": "Crowdfunding contributions", "Pricing-Crowdfunding-Price": "Free with Platform Tips activated", "Pricing-forOrganizations": "Pricing for Organizations", diff --git a/lang/pt.json b/lang/pt.json index 40ac151e778..2f4d032cdd1 100644 --- a/lang/pt.json +++ b/lang/pt.json @@ -3405,6 +3405,8 @@ "PreviewFeatures.searchCommandDescription": "Discover a new way to search for collectives, transactions, expenses, and more through an intuitive command menu interface. Access information faster with powerful search capabilities.", "PreviewFeatures.searchCommandTitle": "Search Command Menu", "PreviewFeatures.searchResultsPage": "Search Results Page", + "PreviewFeatures.tableQuickActionsDescription": "Enable quick action buttons that appear on table rows when you hover over them. Perform common actions faster without opening the dropdown menu.", + "PreviewFeatures.tableQuickActionsTitle": "Table Quick Actions", "Pricing-Crowdfunding": "Crowdfunding contributions", "Pricing-Crowdfunding-Price": "Free with Platform Tips activated", "Pricing-forOrganizations": "Pricing for Organizations", diff --git a/lang/ru.json b/lang/ru.json index cf6254d9b41..0a10271b150 100644 --- a/lang/ru.json +++ b/lang/ru.json @@ -3405,6 +3405,8 @@ "PreviewFeatures.searchCommandDescription": "Discover a new way to search for collectives, transactions, expenses, and more through an intuitive command menu interface. Access information faster with powerful search capabilities.", "PreviewFeatures.searchCommandTitle": "Search Command Menu", "PreviewFeatures.searchResultsPage": "Search Results Page", + "PreviewFeatures.tableQuickActionsDescription": "Enable quick action buttons that appear on table rows when you hover over them. Perform common actions faster without opening the dropdown menu.", + "PreviewFeatures.tableQuickActionsTitle": "Table Quick Actions", "Pricing-Crowdfunding": "Crowdfunding contributions", "Pricing-Crowdfunding-Price": "Free with Platform Tips activated", "Pricing-forOrganizations": "Pricing for Organizations", diff --git a/lang/sk-SK.json b/lang/sk-SK.json index 5f56efbb737..13c8e043678 100644 --- a/lang/sk-SK.json +++ b/lang/sk-SK.json @@ -3405,6 +3405,8 @@ "PreviewFeatures.searchCommandDescription": "Discover a new way to search for collectives, transactions, expenses, and more through an intuitive command menu interface. Access information faster with powerful search capabilities.", "PreviewFeatures.searchCommandTitle": "Search Command Menu", "PreviewFeatures.searchResultsPage": "Search Results Page", + "PreviewFeatures.tableQuickActionsDescription": "Enable quick action buttons that appear on table rows when you hover over them. Perform common actions faster without opening the dropdown menu.", + "PreviewFeatures.tableQuickActionsTitle": "Table Quick Actions", "Pricing-Crowdfunding": "Crowdfunding contributions", "Pricing-Crowdfunding-Price": "Free with Platform Tips activated", "Pricing-forOrganizations": "Pricing for Organizations", diff --git a/lang/sv-SE.json b/lang/sv-SE.json index 39ac1728bbf..d37707b7d60 100644 --- a/lang/sv-SE.json +++ b/lang/sv-SE.json @@ -3405,6 +3405,8 @@ "PreviewFeatures.searchCommandDescription": "Discover a new way to search for collectives, transactions, expenses, and more through an intuitive command menu interface. Access information faster with powerful search capabilities.", "PreviewFeatures.searchCommandTitle": "Search Command Menu", "PreviewFeatures.searchResultsPage": "Search Results Page", + "PreviewFeatures.tableQuickActionsDescription": "Enable quick action buttons that appear on table rows when you hover over them. Perform common actions faster without opening the dropdown menu.", + "PreviewFeatures.tableQuickActionsTitle": "Table Quick Actions", "Pricing-Crowdfunding": "Crowdfunding contributions", "Pricing-Crowdfunding-Price": "Free with Platform Tips activated", "Pricing-forOrganizations": "Pricing for Organizations", diff --git a/lang/uk.json b/lang/uk.json index 4d56c8e202c..5e459e5e7c2 100644 --- a/lang/uk.json +++ b/lang/uk.json @@ -3405,6 +3405,8 @@ "PreviewFeatures.searchCommandDescription": "Discover a new way to search for collectives, transactions, expenses, and more through an intuitive command menu interface. Access information faster with powerful search capabilities.", "PreviewFeatures.searchCommandTitle": "Search Command Menu", "PreviewFeatures.searchResultsPage": "Search Results Page", + "PreviewFeatures.tableQuickActionsDescription": "Enable quick action buttons that appear on table rows when you hover over them. Perform common actions faster without opening the dropdown menu.", + "PreviewFeatures.tableQuickActionsTitle": "Table Quick Actions", "Pricing-Crowdfunding": "Crowdfunding contributions", "Pricing-Crowdfunding-Price": "Free with Platform Tips activated", "Pricing-forOrganizations": "Pricing for Organizations", diff --git a/lang/zh.json b/lang/zh.json index 740df72b1be..7026e9a1e73 100644 --- a/lang/zh.json +++ b/lang/zh.json @@ -3405,6 +3405,8 @@ "PreviewFeatures.searchCommandDescription": "Discover a new way to search for collectives, transactions, expenses, and more through an intuitive command menu interface. Access information faster with powerful search capabilities.", "PreviewFeatures.searchCommandTitle": "Search Command Menu", "PreviewFeatures.searchResultsPage": "Search Results Page", + "PreviewFeatures.tableQuickActionsDescription": "Enable quick action buttons that appear on table rows when you hover over them. Perform common actions faster without opening the dropdown menu.", + "PreviewFeatures.tableQuickActionsTitle": "Table Quick Actions", "Pricing-Crowdfunding": "Crowdfunding contributions", "Pricing-Crowdfunding-Price": "Free with Platform Tips activated", "Pricing-forOrganizations": "Pricing for Organizations", diff --git a/lib/actions/types.ts b/lib/actions/types.ts index b91ce40c0a7..2d7b68a8d7f 100644 --- a/lib/actions/types.ts +++ b/lib/actions/types.ts @@ -2,8 +2,10 @@ import type { LucideIcon } from 'lucide-react'; import type React from 'react'; export type Action = { - label: React.ReactNode; - onClick: () => void; + label: string; + onClick?: (e: React.MouseEvent) => void; + href?: string; // used for links + target?: string; // used for links Icon?: LucideIcon; isLoading?: boolean; disabled?: boolean; diff --git a/lib/preview-features.tsx b/lib/preview-features.tsx index dd5cdcfa244..f910d0ea548 100644 --- a/lib/preview-features.tsx +++ b/lib/preview-features.tsx @@ -22,6 +22,7 @@ export enum PREVIEW_FEATURE_KEYS { PLATFORM_BILLING = 'PLATFORM_BILLING', SIDEBAR_REORG_DISBURSEMENTS = 'SIDEBAR_REORG_DISBURSEMENTS', ASYNC_EXPORTS = 'ASYNC_EXPORTS', + TABLE_QUICK_ACTIONS = 'TABLE_QUICK_ACTIONS', } enum Categories { @@ -312,4 +313,17 @@ export const previewFeatures: PreviewFeature[] = [ closedBetaAccessFor: [...PLATFORM_ACCOUNTS, ...OFICO_MEMBER_ORGANIZATIONS], category: Categories.HOSTING, }, + { + key: PREVIEW_FEATURE_KEYS.TABLE_QUICK_ACTIONS, + title: , + description: ( + + ), + publicBeta: true, + alwaysEnableInDev: true, + category: Categories.GENERAL, + }, ];