-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: added `ActionBar`, `SelectableList` and `DocumentList` refactor: moved action bar from `ThumbnailGrid` into `ActionBar` refactor: updated `SearchPage`
- Loading branch information
1 parent
a0aa52b
commit 0e819ee
Showing
23 changed files
with
1,887 additions
and
182 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
--- | ||
'@smile/react-front-kit': minor | ||
'storybook-pages': minor | ||
--- | ||
|
||
Extracted action bar from `ThumbnailGrid` into new component. | ||
Added `ActionBar`, `SelectableList` and `DocumentList` components. | ||
Updated `SearchPage` example page. |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
58 changes: 58 additions & 0 deletions
58
packages/react-front-kit/src/Components/ActionBar/ActionBar.mock.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
import type { IActionBarProps } from './ActionBar'; | ||
import type { IThumbnail, IThumbnailAction } from '../../types'; | ||
|
||
import { Trash } from '@phosphor-icons/react'; | ||
import { FolderMove } from '@smile/react-front-kit-shared'; | ||
import { action } from '@storybook/addon-actions'; | ||
|
||
export const actionBarActionsMock: IThumbnailAction[] = [ | ||
{ | ||
icon: <FolderMove size={16} />, | ||
id: 'move', | ||
isItemAction: false, | ||
isMassAction: true, | ||
label: 'Move in tree', | ||
onAction: action('Move selected in tree'), | ||
}, | ||
{ | ||
color: 'red', | ||
confirmModalProps: { | ||
cancelLabel: 'Abort', | ||
children: <p>Are you sure ?</p>, | ||
confirmColor: 'red', | ||
confirmLabel: 'Remove', | ||
title: 'remove files ?', | ||
}, | ||
confirmation: true, | ||
icon: <Trash size={16} />, | ||
id: 'delete', | ||
isItemAction: false, | ||
isMassAction: true, | ||
label: 'Delete', | ||
onAction: action('Delete selected'), | ||
}, | ||
]; | ||
|
||
export const actionBarSelectedMock: IThumbnail[] = [ | ||
{ | ||
id: '1', | ||
label: 'Label A', | ||
}, | ||
{ | ||
id: '2', | ||
label: 'Label B', | ||
}, | ||
{ | ||
id: '3', | ||
label: 'Label C', | ||
}, | ||
]; | ||
|
||
export const actionBarLabelMock = (elements: number): string => | ||
`${elements} selected`; | ||
|
||
export const actionBarMock: IActionBarProps<IThumbnail> = { | ||
actions: actionBarActionsMock, | ||
selectedElements: actionBarSelectedMock, | ||
selectedElementsLabel: actionBarLabelMock, | ||
}; |
28 changes: 28 additions & 0 deletions
28
packages/react-front-kit/src/Components/ActionBar/ActionBar.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import type { IActionBarAction } from './ActionBar'; | ||
import type { Meta, StoryObj } from '@storybook/react'; | ||
|
||
import { ActionBar as Cmp } from './ActionBar'; | ||
import { | ||
actionBarActionsMock, | ||
actionBarLabelMock, | ||
actionBarSelectedMock, | ||
} from './ActionBar.mock'; | ||
|
||
const meta = { | ||
component: Cmp, | ||
tags: ['autodocs'], | ||
title: '3-custom/Components/ActionBar', | ||
} satisfies Meta<typeof Cmp>; | ||
|
||
export default meta; | ||
type IStory = StoryObj<typeof meta>; | ||
|
||
export const ActionBar: IStory = { | ||
args: { | ||
actions: actionBarActionsMock as IActionBarAction< | ||
Record<string, unknown> | ||
>[], | ||
selectedElements: actionBarSelectedMock, | ||
selectedElementsLabel: actionBarLabelMock, | ||
}, | ||
}; |
11 changes: 11 additions & 0 deletions
11
packages/react-front-kit/src/Components/ActionBar/ActionBar.test.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { renderWithProviders } from '@smile/react-front-kit-shared/test-utils'; | ||
|
||
import { ActionBar } from './ActionBar'; | ||
import { actionBarMock } from './ActionBar.mock'; | ||
|
||
describe('ActionBar', () => { | ||
it('matches snapshot', () => { | ||
const { container } = renderWithProviders(<ActionBar {...actionBarMock} />); | ||
expect(container).toMatchSnapshot(); | ||
}); | ||
}); |
129 changes: 129 additions & 0 deletions
129
packages/react-front-kit/src/Components/ActionBar/ActionBar.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
import type { GroupProps, ModalProps } from '@mantine/core'; | ||
import type { Record } from '@phosphor-icons/react'; | ||
import type { | ||
IAction, | ||
IActionConfirmModalProps, | ||
} from '@smile/react-front-kit-shared'; | ||
import type { ReactElement } from 'react'; | ||
|
||
import { Button, Group } from '@mantine/core'; | ||
import { createStyles } from '@mantine/styles'; | ||
import { useState } from 'react'; | ||
|
||
import { ConfirmModal } from '../ConfirmModal/ConfirmModal'; | ||
|
||
const useStyles = createStyles((theme) => ({ | ||
actionBar: { | ||
alignItems: 'center', | ||
background: theme.fn.primaryColor(), | ||
borderRadius: 4, | ||
color: 'white', | ||
display: 'inline-flex', | ||
justifyContent: 'space-between', | ||
padding: '16px 24px', | ||
width: '100%', | ||
}, | ||
})); | ||
|
||
export type IActionBarAction<Data extends Record<string, unknown>> = IAction< | ||
Data | Data[] | ||
>; | ||
|
||
export interface IActionBarProps<Data extends Record<string, unknown>> | ||
extends GroupProps { | ||
actions?: IActionBarAction<Data>[]; | ||
modalProps?: Omit<ModalProps, 'title'>; | ||
selectedElements: Data[]; | ||
selectedElementsLabel?: (selectedElements: number) => string; | ||
} | ||
|
||
export function ActionBar<Data extends Record<string, unknown>>( | ||
props: IActionBarProps<Data>, | ||
): ReactElement { | ||
const { | ||
actions, | ||
modalProps, | ||
selectedElements, | ||
selectedElementsLabel = (selectedElements: number) => | ||
`${selectedElements} file(s) selected`, | ||
...groupProps | ||
} = props; | ||
const [confirmAction, setConfirmAction] = useState<IActionConfirmModalProps< | ||
Data | Data[] | ||
> | null>(null); | ||
const numberOfSelectedElements = selectedElements.length; | ||
|
||
const { classes } = useStyles(); | ||
|
||
function setModal(action: IAction<Data>): void { | ||
setConfirmAction({ | ||
cancelColor: action.confirmModalProps?.cancelColor, | ||
cancelLabel: action.confirmModalProps?.cancelLabel, | ||
children: action.confirmModalProps?.children, | ||
confirmColor: action.confirmModalProps?.confirmColor, | ||
confirmLabel: action.confirmModalProps?.confirmLabel, | ||
onConfirm: () => action.onAction?.(selectedElements), | ||
title: action.confirmModalProps?.title, | ||
}); | ||
} | ||
|
||
function clearConfirmAction(): void { | ||
setConfirmAction(null); | ||
} | ||
|
||
function handleClose(): void { | ||
clearConfirmAction(); | ||
} | ||
|
||
function handleModalButton(onAction?: (item: Data[]) => void): void { | ||
onAction?.(selectedElements); | ||
handleClose(); | ||
} | ||
|
||
function handleGridAction(action: IAction<Data>): void { | ||
if (action.confirmation) { | ||
setModal(action); | ||
} else { | ||
action.onAction?.(selectedElements); | ||
} | ||
} | ||
|
||
return ( | ||
<> | ||
<div className={classes.actionBar}> | ||
<span>{selectedElementsLabel(numberOfSelectedElements)}</span> | ||
{actions && actions.length > 0 ? ( | ||
<Group {...groupProps}> | ||
{actions.map((action) => ( | ||
<Button | ||
key={action.id} | ||
color={action.color} | ||
leftIcon={ | ||
typeof action.icon === 'function' | ||
? action.icon(selectedElements) | ||
: action.icon | ||
} | ||
onClick={() => handleGridAction(action)} | ||
variant={action.color ? 'filled' : 'default'} | ||
> | ||
{typeof action.label === 'function' | ||
? action.label(selectedElements) | ||
: action.label} | ||
</Button> | ||
))} | ||
</Group> | ||
) : null} | ||
</div> | ||
<ConfirmModal | ||
{...confirmAction} | ||
onCancel={() => handleModalButton(confirmAction?.onCancel)} | ||
onClose={handleClose} | ||
onConfirm={() => handleModalButton(confirmAction?.onConfirm)} | ||
opened={Boolean(confirmAction)} | ||
{...modalProps} | ||
> | ||
{confirmAction?.children} | ||
</ConfirmModal> | ||
</> | ||
); | ||
} |
90 changes: 90 additions & 0 deletions
90
packages/react-front-kit/src/Components/ActionBar/__snapshots__/ActionBar.test.tsx.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`ActionBar matches snapshot 1`] = ` | ||
<div> | ||
<div | ||
class="mantine-zzdfuz" | ||
> | ||
<span> | ||
3 selected | ||
</span> | ||
<div | ||
class="mantine-Group-root mantine-k3ov3c" | ||
> | ||
<button | ||
class="mantine-UnstyledButton-root mantine-Button-root mantine-1q6w75n" | ||
data-button="true" | ||
type="button" | ||
> | ||
<div | ||
class="mantine-1wpc1xj mantine-Button-inner" | ||
> | ||
<span | ||
class="mantine-Button-icon mantine-Button-leftIcon mantine-1jbrfp" | ||
> | ||
<svg | ||
fill="none" | ||
height="16" | ||
stroke="currentColor" | ||
viewBox="0 0 12 12" | ||
width="16" | ||
xmlns="http://www.w3.org/2000/svg" | ||
> | ||
<path | ||
d="M3.58333 10H1.41667C1.30616 10 1.20018 9.95564 1.12204 9.87668C1.0439 9.79771 1 9.69062 1 9.57895V2.42105C1 2.30938 1.0439 2.20229 1.12204 2.12332C1.20018 2.04436 1.30616 2 1.41667 2H4.19271C4.2828 2.00037 4.37041 2.02988 4.44271 2.08421L5.89062 3.17895C5.96292 3.23327 6.05053 3.26278 6.14062 3.26316H10.5833C10.6938 3.26316 10.7998 3.30752 10.878 3.38648C10.9561 3.46544 11 3.57254 11 3.68421V5.36842" | ||
stroke-linecap="round" | ||
stroke-linejoin="round" | ||
/> | ||
<path | ||
d="M6 9H11" | ||
stroke-linecap="round" | ||
stroke-linejoin="round" | ||
/> | ||
<path | ||
d="M9 7L11 9L9 11" | ||
stroke-linecap="round" | ||
stroke-linejoin="round" | ||
/> | ||
</svg> | ||
</span> | ||
<span | ||
class="mantine-1ryt1ht mantine-Button-label" | ||
> | ||
Move in tree | ||
</span> | ||
</div> | ||
</button> | ||
<button | ||
class="mantine-UnstyledButton-root mantine-Button-root mantine-3agwv" | ||
data-button="true" | ||
type="button" | ||
> | ||
<div | ||
class="mantine-1wpc1xj mantine-Button-inner" | ||
> | ||
<span | ||
class="mantine-Button-icon mantine-Button-leftIcon mantine-1jbrfp" | ||
> | ||
<svg | ||
fill="currentColor" | ||
height="16" | ||
viewBox="0 0 256 256" | ||
width="16" | ||
xmlns="http://www.w3.org/2000/svg" | ||
> | ||
<path | ||
d="M216,48H176V40a24,24,0,0,0-24-24H104A24,24,0,0,0,80,40v8H40a8,8,0,0,0,0,16h8V208a16,16,0,0,0,16,16H192a16,16,0,0,0,16-16V64h8a8,8,0,0,0,0-16ZM96,40a8,8,0,0,1,8-8h48a8,8,0,0,1,8,8v8H96Zm96,168H64V64H192ZM112,104v64a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Zm48,0v64a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Z" | ||
/> | ||
</svg> | ||
</span> | ||
<span | ||
class="mantine-1ryt1ht mantine-Button-label" | ||
> | ||
Delete | ||
</span> | ||
</div> | ||
</button> | ||
</div> | ||
</div> | ||
</div> | ||
`; |
Oops, something went wrong.