refactor: update icons and improve action visibility in row and bulk action menus
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { Fragment, memo } from 'react';
|
||||
import { Group, ActionIcon, Tooltip, Menu, Divider, Box, Button } from '@mantine/core';
|
||||
import { Group, ActionIcon, Tooltip, Menu, Divider, Box, Button, MantineSpacing } from '@mantine/core';
|
||||
import { RowActionProps } from './types';
|
||||
import { getIntentColor } from './utils';
|
||||
import { MoreVertical } from 'lucide-react';
|
||||
@@ -9,6 +9,8 @@ export interface RowActionsProps {
|
||||
actions: RowActionProps[];
|
||||
showLabels?: boolean;
|
||||
responsiveView?: boolean;
|
||||
gapActionDesktop?: MantineSpacing;
|
||||
gapActionMobile?: MantineSpacing;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -17,11 +19,9 @@ export interface RowActionsProps {
|
||||
*
|
||||
* @performance Wrapped in React.memo to guarantee zero overhead inside large lists/grids.
|
||||
*/
|
||||
export const RowActions = memo(function RowActions({
|
||||
actions = [],
|
||||
showLabels = false,
|
||||
responsiveView = true,
|
||||
}: RowActionsProps) {
|
||||
export const RowActions = memo(function RowActions(props: RowActionsProps) {
|
||||
const { actions = [], showLabels = false, responsiveView = true, gapActionDesktop = 0, gapActionMobile = 0 } = props;
|
||||
|
||||
/**
|
||||
* Helper function to render a standalone item.
|
||||
*/
|
||||
@@ -114,14 +114,14 @@ export const RowActions = memo(function RowActions({
|
||||
return (
|
||||
<Box style={{ display: 'inline-flex' }}>
|
||||
{/* --- DESKTOP VIEW (hidden on mobile devices) --- */}
|
||||
<Group gap={0} wrap="nowrap" visibleFrom={responsiveView ? 'sm' : undefined}>
|
||||
<Group gap={gapActionDesktop} wrap="nowrap" visibleFrom={responsiveView ? 'sm' : undefined}>
|
||||
{renderFlatActions()}
|
||||
</Group>
|
||||
|
||||
{/* --- MOBILE VIEW (hidden on desktop devices) --- */}
|
||||
|
||||
{responsiveView && (
|
||||
<Group gap={0} wrap="nowrap" hiddenFrom="sm">
|
||||
<Group gap={gapActionMobile} wrap="nowrap" hiddenFrom="sm">
|
||||
<Menu position="bottom-end" withArrow withinPortal zIndex={9999}>
|
||||
<Menu.Target>
|
||||
<ActionIcon variant="transparent" size="md">
|
||||
|
||||
+25
-17
@@ -4,7 +4,7 @@ import {
|
||||
useEnterpriseModuleTranslationContext,
|
||||
useEnterpriseModuleConfigContext,
|
||||
} from '../../../hooks/use-module.context';
|
||||
import { Trash2, CheckCircle, XCircle, PauseCircle, RotateCcw, X, Check } from 'lucide-react';
|
||||
import { Trash, Unlock, Lock, PauseCircle, RotateCcw, X, Check } from 'lucide-react';
|
||||
import { PageActions, PageActionProps } from '../../../../../components';
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
@@ -29,7 +29,7 @@ export interface BulkActionMenuProps {
|
||||
* privilege checks, and the status of selected rows — mirroring the
|
||||
* row-level action logic in `RowActionMenu`.
|
||||
*
|
||||
* All actions have `showLabel: false` so they render as icon-only
|
||||
* All actions have `showLabel: t so they render as icon-only
|
||||
* `ActionIcon` buttons via the `PageActions` component.
|
||||
*
|
||||
* @performance
|
||||
@@ -74,9 +74,9 @@ export function BulkActionMenu({
|
||||
defaultActions.push({
|
||||
key: ModuleAction.DEACTIVATE,
|
||||
label: t('common:actions.deactivate'),
|
||||
icon: <XCircle size={16} />,
|
||||
icon: <Lock size={14} />,
|
||||
variant: 'default',
|
||||
showLabel: false,
|
||||
showLabel: true,
|
||||
onClick: handleClick(ModuleAction.DEACTIVATE),
|
||||
});
|
||||
}
|
||||
@@ -85,9 +85,9 @@ export function BulkActionMenu({
|
||||
defaultActions.push({
|
||||
key: ModuleAction.ACTIVATE,
|
||||
label: t('common:actions.activate'),
|
||||
icon: <CheckCircle size={16} />,
|
||||
icon: <Unlock size={14} />,
|
||||
variant: 'default',
|
||||
showLabel: false,
|
||||
showLabel: true,
|
||||
onClick: handleClick(ModuleAction.ACTIVATE),
|
||||
});
|
||||
}
|
||||
@@ -99,9 +99,9 @@ export function BulkActionMenu({
|
||||
defaultActions.push({
|
||||
key: ModuleAction.HOLD,
|
||||
label: t('common:actions.hold'),
|
||||
icon: <PauseCircle size={16} />,
|
||||
icon: <PauseCircle size={14} />,
|
||||
variant: 'default',
|
||||
showLabel: false,
|
||||
showLabel: true,
|
||||
onClick: handleClick(ModuleAction.HOLD),
|
||||
});
|
||||
}
|
||||
@@ -110,9 +110,9 @@ export function BulkActionMenu({
|
||||
defaultActions.push({
|
||||
key: ModuleAction.ROLLBACK,
|
||||
label: t('common:actions.rollback'),
|
||||
icon: <RotateCcw size={16} />,
|
||||
icon: <RotateCcw size={14} />,
|
||||
variant: 'default',
|
||||
showLabel: false,
|
||||
showLabel: true,
|
||||
onClick: handleClick(ModuleAction.ROLLBACK),
|
||||
});
|
||||
}
|
||||
@@ -121,9 +121,9 @@ export function BulkActionMenu({
|
||||
defaultActions.push({
|
||||
key: ModuleAction.CANCEL,
|
||||
label: t('common:actions.cancel'),
|
||||
icon: <X size={16} />,
|
||||
icon: <X size={14} />,
|
||||
variant: 'default',
|
||||
showLabel: false,
|
||||
showLabel: true,
|
||||
onClick: handleClick(ModuleAction.CANCEL),
|
||||
});
|
||||
}
|
||||
@@ -132,9 +132,9 @@ export function BulkActionMenu({
|
||||
defaultActions.push({
|
||||
key: ModuleAction.CONFIRM,
|
||||
label: t('common:actions.confirm'),
|
||||
icon: <Check size={16} />,
|
||||
icon: <Check size={14} />,
|
||||
variant: 'default',
|
||||
showLabel: false,
|
||||
showLabel: true,
|
||||
onClick: handleClick(ModuleAction.CONFIRM),
|
||||
});
|
||||
}
|
||||
@@ -145,10 +145,10 @@ export function BulkActionMenu({
|
||||
defaultActions.push({
|
||||
key: ModuleAction.DELETE,
|
||||
label: t('common:actions.delete'),
|
||||
icon: <Trash2 size={16} />,
|
||||
icon: <Trash size={14} />,
|
||||
variant: 'outline',
|
||||
intent: 'destructive',
|
||||
showLabel: false,
|
||||
showLabel: true,
|
||||
onClick: handleClick(ModuleAction.DELETE),
|
||||
});
|
||||
}
|
||||
@@ -158,5 +158,13 @@ export function BulkActionMenu({
|
||||
|
||||
if (actions.length === 0) return null;
|
||||
|
||||
return <PageActions actions={actions} />;
|
||||
return (
|
||||
<PageActions
|
||||
actions={actions}
|
||||
gapActionDesktop={'sm'}
|
||||
customButtonProps={() => {
|
||||
return { size: 'xs' };
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
+11
-11
@@ -1,5 +1,5 @@
|
||||
import { useMemo } from 'react';
|
||||
import { Eye, Trash2, CheckCircle, XCircle, Edit2, Copy, PauseCircle, RotateCcw, X, Check } from 'lucide-react';
|
||||
import { FileSearchCorner, Trash, Unlock, Lock, SquarePen, Copy, PauseCircle, RotateCcw, X, Check } from 'lucide-react';
|
||||
import { ModuleAction, ModuleActionType } from '../../../entities/entity';
|
||||
import {
|
||||
useEnterpriseModuleTranslationContext,
|
||||
@@ -47,7 +47,7 @@ export function RowActionMenu({ data, onActionClick, statusKey = 'status', custo
|
||||
key: 'VIEW',
|
||||
label: t('common:actions.detail'),
|
||||
tooltip: t('common:actions.detail'),
|
||||
icon: <Eye size={14} />,
|
||||
icon: <FileSearchCorner size={15} />,
|
||||
onClick: () => onActionClick('VIEW' as any, data),
|
||||
});
|
||||
|
||||
@@ -56,7 +56,7 @@ export function RowActionMenu({ data, onActionClick, statusKey = 'status', custo
|
||||
key: ModuleAction.EDIT,
|
||||
label: t('common:actions.edit'),
|
||||
tooltip: t('common:actions.edit'),
|
||||
icon: <Edit2 size={14} />,
|
||||
icon: <SquarePen size={15} />,
|
||||
onClick: () => onActionClick(ModuleAction.EDIT, data),
|
||||
});
|
||||
}
|
||||
@@ -66,7 +66,7 @@ export function RowActionMenu({ data, onActionClick, statusKey = 'status', custo
|
||||
key: ModuleAction.DUPLICATE,
|
||||
label: t('common:actions.duplicate'),
|
||||
tooltip: t('common:actions.duplicate'),
|
||||
icon: <Copy size={14} />,
|
||||
icon: <Copy size={15} />,
|
||||
onClick: () => onActionClick(ModuleAction.DUPLICATE, data),
|
||||
});
|
||||
}
|
||||
@@ -77,7 +77,7 @@ export function RowActionMenu({ data, onActionClick, statusKey = 'status', custo
|
||||
key: ModuleAction.DEACTIVATE,
|
||||
label: t('common:actions.deactivate'),
|
||||
tooltip: t('common:actions.deactivate'),
|
||||
icon: <XCircle size={14} />,
|
||||
icon: <Lock size={15} />,
|
||||
onClick: () => onActionClick(ModuleAction.DEACTIVATE, data),
|
||||
});
|
||||
}
|
||||
@@ -86,7 +86,7 @@ export function RowActionMenu({ data, onActionClick, statusKey = 'status', custo
|
||||
key: ModuleAction.ACTIVATE,
|
||||
label: t('common:actions.activate'),
|
||||
tooltip: t('common:actions.activate'),
|
||||
icon: <CheckCircle size={14} />,
|
||||
icon: <Unlock size={15} />,
|
||||
onClick: () => onActionClick(ModuleAction.ACTIVATE, data),
|
||||
});
|
||||
}
|
||||
@@ -98,7 +98,7 @@ export function RowActionMenu({ data, onActionClick, statusKey = 'status', custo
|
||||
key: ModuleAction.HOLD,
|
||||
label: t('common:actions.hold'),
|
||||
tooltip: t('common:actions.hold'),
|
||||
icon: <PauseCircle size={14} />,
|
||||
icon: <PauseCircle size={15} />,
|
||||
onClick: () => onActionClick(ModuleAction.HOLD, data),
|
||||
});
|
||||
}
|
||||
@@ -107,7 +107,7 @@ export function RowActionMenu({ data, onActionClick, statusKey = 'status', custo
|
||||
key: ModuleAction.ROLLBACK,
|
||||
label: t('common:actions.rollback'),
|
||||
tooltip: t('common:actions.rollback'),
|
||||
icon: <RotateCcw size={14} />,
|
||||
icon: <RotateCcw size={15} />,
|
||||
onClick: () => onActionClick(ModuleAction.ROLLBACK, data),
|
||||
});
|
||||
}
|
||||
@@ -116,7 +116,7 @@ export function RowActionMenu({ data, onActionClick, statusKey = 'status', custo
|
||||
key: ModuleAction.CANCEL,
|
||||
label: t('common:actions.cancel'),
|
||||
tooltip: t('common:actions.cancel'),
|
||||
icon: <X size={14} />,
|
||||
icon: <X size={15} />,
|
||||
onClick: () => onActionClick(ModuleAction.CANCEL, data),
|
||||
});
|
||||
}
|
||||
@@ -125,7 +125,7 @@ export function RowActionMenu({ data, onActionClick, statusKey = 'status', custo
|
||||
key: ModuleAction.CONFIRM,
|
||||
label: t('common:actions.confirm'),
|
||||
tooltip: t('common:actions.confirm'),
|
||||
icon: <Check size={14} />,
|
||||
icon: <Check size={15} />,
|
||||
onClick: () => onActionClick(ModuleAction.CONFIRM, data),
|
||||
});
|
||||
}
|
||||
@@ -136,7 +136,7 @@ export function RowActionMenu({ data, onActionClick, statusKey = 'status', custo
|
||||
key: ModuleAction.DELETE,
|
||||
label: t('common:actions.delete'),
|
||||
tooltip: t('common:actions.delete'),
|
||||
icon: <Trash2 size={14} />,
|
||||
icon: <Trash size={15} />,
|
||||
intent: 'destructive',
|
||||
onClick: () => onActionClick(ModuleAction.DELETE, data),
|
||||
});
|
||||
|
||||
@@ -824,7 +824,7 @@ export function EnterpriseDataTable<E extends BaseEntity>(props: EnterpriseDataT
|
||||
{
|
||||
key: 'filter',
|
||||
icon: (
|
||||
<Indicator disabled={activeFilterCount === 0} size={8} offset={2}>
|
||||
<Indicator disabled={activeFilterCount === 0} size={8} offset={2} color="yellow">
|
||||
<Filter size={16} />
|
||||
</Indicator>
|
||||
),
|
||||
@@ -881,7 +881,7 @@ export function EnterpriseDataTable<E extends BaseEntity>(props: EnterpriseDataT
|
||||
statusBar={statusBar}
|
||||
domLayout={domLayout}
|
||||
overlayLoadingTemplate={`<span style="padding:10px">${loadingMessage}</span>`}
|
||||
overlayNoRowsTemplate={`<span style="padding:10px;color:var(--ag-foreground-color,#868e96)">${noRowsMessage}</span>`}
|
||||
overlayNoRowsTemplate={`<span style="padding:10px;color:var(--ag-foreground-color,#868e96);">${noRowsMessage}</span>`}
|
||||
{...restAgGridProps}
|
||||
/>
|
||||
</Box>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { BaseEntity } from '@repo/core-api/data-services';
|
||||
import { Check, CheckCircle, Copy, Edit2, PauseCircle, Plus, RotateCcw, Trash2, X, XCircle } from 'lucide-react';
|
||||
import { Check, Unlock, Copy, SquarePen, PauseCircle, Plus, RotateCcw, Trash, X, Lock } from 'lucide-react';
|
||||
|
||||
import { DetailPageContext } from '../hooks/use-detail-page.context';
|
||||
import { EnterpriseDetailPageConfig, ModuleAction, ModuleActionType, ActionModalState } from '../entities/entity';
|
||||
@@ -421,7 +421,7 @@ export function EnterpriseDetailPageProvider<E extends BaseEntity = BaseEntity>(
|
||||
ALLOW_DELETE && {
|
||||
key: ModuleAction.DELETE,
|
||||
label: t('common:actions.delete'),
|
||||
icon: <Trash2 size={16} />,
|
||||
icon: <Trash size={16} />,
|
||||
intent: 'destructive',
|
||||
variant: 'subtle',
|
||||
onClick: (key: ModuleActionType) => handleActionClick(key),
|
||||
@@ -432,7 +432,7 @@ export function EnterpriseDetailPageProvider<E extends BaseEntity = BaseEntity>(
|
||||
isDataActive && {
|
||||
key: ModuleAction.DEACTIVATE,
|
||||
label: t('common:actions.deactivate'),
|
||||
icon: <XCircle size={16} />,
|
||||
icon: <Lock size={16} />,
|
||||
intent: 'default',
|
||||
variant: 'subtle',
|
||||
onClick: (key: ModuleActionType) => handleActionClick(key),
|
||||
@@ -443,7 +443,7 @@ export function EnterpriseDetailPageProvider<E extends BaseEntity = BaseEntity>(
|
||||
key: ModuleAction.ACTIVATE,
|
||||
label: t('common:actions.activate'),
|
||||
tooltipLabel: t('common:actions.activate'),
|
||||
icon: <CheckCircle size={16} />,
|
||||
icon: <Unlock size={16} />,
|
||||
intent: 'default',
|
||||
variant: 'subtle',
|
||||
onClick: (key: ModuleActionType) => handleActionClick(key),
|
||||
@@ -460,7 +460,7 @@ export function EnterpriseDetailPageProvider<E extends BaseEntity = BaseEntity>(
|
||||
ALLOW_EDIT && {
|
||||
key: ModuleAction.EDIT,
|
||||
label: t('common:actions.edit'),
|
||||
icon: <Edit2 size={16} />,
|
||||
icon: <SquarePen size={16} />,
|
||||
intent: 'default',
|
||||
variant: 'subtle',
|
||||
onClick: (key: ModuleActionType) => handleActionClick(key),
|
||||
|
||||
Reference in New Issue
Block a user