@centreon/ui 25.3.4 → 25.4.0-MON-191119-npm-develop.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (176) hide show
  1. package/package.json +25 -11
  2. package/public/mockServiceWorker.js +8 -31
  3. package/src/Button/Save/index.stories.tsx +1 -0
  4. package/src/Checkbox/Checkbox.tsx +3 -1
  5. package/src/Checkbox/CheckboxGroup/index.tsx +6 -1
  6. package/src/Colors/index.tsx +1 -1
  7. package/src/Dashboard/Dashboard.styles.ts +1 -1
  8. package/src/Dashboard/Layout.tsx +1 -1
  9. package/src/Dialog/UnsavedChanges/index.stories.tsx +1 -0
  10. package/src/Form/CollapsibleGroup.tsx +13 -13
  11. package/src/Form/Form.cypress.spec.tsx +137 -2
  12. package/src/Form/Form.stories.tsx +11 -31
  13. package/src/Form/Form.tsx +2 -0
  14. package/src/Form/Inputs/Checkbox.tsx +3 -2
  15. package/src/Form/Inputs/ConnectedAutocomplete.tsx +6 -1
  16. package/src/Form/Inputs/Grid.tsx +18 -29
  17. package/src/Form/Inputs/SubGroupDivider.tsx +7 -0
  18. package/src/Form/Inputs/Text.tsx +1 -0
  19. package/src/Form/Inputs/index.tsx +31 -24
  20. package/src/Form/Inputs/models.ts +8 -1
  21. package/src/Form/Section/FormSection.tsx +34 -0
  22. package/src/Form/Section/PanelTabs.tsx +13 -0
  23. package/src/Form/Section/navigateToSection.ts +9 -0
  24. package/src/Form/storiesData.tsx +14 -4
  25. package/src/Graph/BarChart/BarChart.cypress.spec.tsx +46 -6
  26. package/src/Graph/BarChart/BarChart.stories.tsx +60 -0
  27. package/src/Graph/BarChart/BarChart.tsx +56 -32
  28. package/src/Graph/BarChart/BarGroup.tsx +22 -32
  29. package/src/Graph/BarChart/MemoizedGroup.tsx +8 -11
  30. package/src/Graph/BarChart/ResponsiveBarChart.tsx +145 -32
  31. package/src/Graph/BarChart/Tooltip/BarChartTooltip.tsx +2 -2
  32. package/src/Graph/Chart/BasicComponents/Lines/StackedLines/index.tsx +7 -1
  33. package/src/Graph/Chart/BasicComponents/Lines/StackedLines/useStackedLines.ts +18 -45
  34. package/src/Graph/Chart/BasicComponents/Lines/index.tsx +42 -28
  35. package/src/Graph/Chart/Chart.cypress.spec.tsx +85 -15
  36. package/src/Graph/Chart/Chart.stories.tsx +84 -1
  37. package/src/Graph/Chart/Chart.tsx +17 -4
  38. package/src/Graph/Chart/InteractiveComponents/AnchorPoint/RegularAnchorPoint.tsx +8 -2
  39. package/src/Graph/Chart/InteractiveComponents/AnchorPoint/StackedAnchorPoint.tsx +10 -3
  40. package/src/Graph/Chart/InteractiveComponents/AnchorPoint/useTickGraph.ts +19 -2
  41. package/src/Graph/Chart/InteractiveComponents/GraphValueTooltip/useGraphValueTooltip.ts +2 -4
  42. package/src/Graph/Chart/InteractiveComponents/ZoomPreview/index.tsx +14 -3
  43. package/src/Graph/Chart/InteractiveComponents/ZoomPreview/models.ts +3 -0
  44. package/src/Graph/Chart/InteractiveComponents/ZoomPreview/useZoomPreview.ts +12 -10
  45. package/src/Graph/Chart/InteractiveComponents/index.tsx +63 -5
  46. package/src/Graph/Chart/Legend/index.tsx +26 -2
  47. package/src/Graph/Chart/index.tsx +45 -45
  48. package/src/Graph/Chart/models.ts +8 -0
  49. package/src/Graph/Chart/useChartData.ts +14 -2
  50. package/src/Graph/Gauge/Gauge.tsx +18 -14
  51. package/src/Graph/Gauge/ResponsiveGauge.tsx +10 -6
  52. package/src/Graph/Gauge/useResizeObserver.ts +68 -0
  53. package/src/Graph/SingleBar/ResponsiveSingleBar.tsx +18 -16
  54. package/src/Graph/SingleBar/ThresholdLine.tsx +4 -4
  55. package/src/Graph/SingleBar/models.ts +1 -0
  56. package/src/Graph/Text/Text.styles.ts +2 -2
  57. package/src/Graph/Text/Text.tsx +23 -10
  58. package/src/Graph/Timeline/ResponsiveTimeline.tsx +4 -0
  59. package/src/Graph/Timeline/Timeline.tsx +21 -4
  60. package/src/Graph/Tree/Links.tsx +2 -2
  61. package/src/Graph/Tree/Tree.tsx +2 -2
  62. package/src/Graph/Tree/constants.ts +1 -1
  63. package/src/Graph/common/BaseChart/BaseChart.tsx +6 -1
  64. package/src/Graph/common/BaseChart/ChartSvgWrapper.tsx +5 -4
  65. package/src/Graph/common/BaseChart/Header/index.tsx +3 -1
  66. package/src/Graph/common/BaseChart/useComputeBaseChartDimensions.ts +13 -9
  67. package/src/Graph/common/timeSeries/index.test.ts +20 -0
  68. package/src/Graph/common/timeSeries/index.ts +225 -44
  69. package/src/Graph/common/timeSeries/models.ts +6 -2
  70. package/src/Graph/common/utils.ts +45 -12
  71. package/src/Graph/index.ts +3 -1
  72. package/src/Graph/mockedData/dataWithMissingPoint.json +74 -0
  73. package/src/Graph/mockedData/pingServiceWithStackedKeys.json +205 -0
  74. package/src/Icon/RegexIcon.tsx +20 -0
  75. package/src/Icon/index.ts +1 -0
  76. package/src/InputField/Select/Autocomplete/Connected/Multi/MultiConnectedAutocompleteField.cypress.spec.tsx +68 -14
  77. package/src/InputField/Select/Autocomplete/Connected/index.tsx +49 -14
  78. package/src/InputField/Select/Autocomplete/Multi/Listbox.tsx +78 -0
  79. package/src/InputField/Select/Autocomplete/Multi/Multi.styles.ts +26 -0
  80. package/src/InputField/Select/Autocomplete/Multi/Multi.tsx +124 -0
  81. package/src/InputField/Select/Autocomplete/Multi/index.tsx +1 -117
  82. package/src/InputField/Select/Autocomplete/index.tsx +28 -17
  83. package/src/InputField/Select/Option.tsx +3 -3
  84. package/src/InputField/Select/index.tsx +4 -0
  85. package/src/InputField/Text/index.tsx +4 -2
  86. package/src/InputField/translatedLabels.ts +4 -0
  87. package/src/Listing/ActionBar/Pagination.tsx +10 -23
  88. package/src/Listing/ActionBar/PaginationActions.tsx +1 -10
  89. package/src/Listing/ActionBar/index.tsx +1 -1
  90. package/src/Listing/Cell/DataCell.tsx +6 -6
  91. package/src/Listing/Cell/EllipsisTypography.tsx +10 -32
  92. package/src/Listing/Cell/index.tsx +37 -76
  93. package/src/Listing/Checkbox.tsx +8 -20
  94. package/src/Listing/Header/Cell/ListingHeaderCell.tsx +17 -14
  95. package/src/Listing/Header/Cell/SelectActionListingHeaderCell.tsx +5 -9
  96. package/src/Listing/Header/ListingHeader.tsx +2 -5
  97. package/src/Listing/Header/_internals/Label.tsx +1 -17
  98. package/src/Listing/Row/EmptyRow.tsx +2 -6
  99. package/src/Listing/Row/Row.tsx +7 -36
  100. package/src/Listing/index.stories.tsx +1 -0
  101. package/src/Listing/index.tsx +26 -26
  102. package/src/Listing/useStyleTable.ts +58 -32
  103. package/src/ListingPage/index.stories.tsx +1 -0
  104. package/src/Module/index.tsx +8 -2
  105. package/src/MultiSelectEntries/index.stories.tsx +1 -0
  106. package/src/MultiSelectEntries/index.tsx +1 -1
  107. package/src/Pagination/Pagination.cypress.spec.tsx +137 -0
  108. package/src/Pagination/Pagination.stories.tsx +46 -0
  109. package/src/Pagination/Pagination.styles.ts +56 -0
  110. package/src/Pagination/Pagination.tsx +146 -0
  111. package/src/Pagination/index.ts +3 -0
  112. package/src/Pagination/utils.ts +7 -0
  113. package/src/SortableItems/index.stories.tsx +2 -2
  114. package/src/StoryBookThemeProvider/index.tsx +3 -1
  115. package/src/ThemeProvider/base.css +49 -0
  116. package/src/ThemeProvider/index.tsx +21 -47
  117. package/src/ThemeProvider/palettes.ts +3 -1
  118. package/src/ThemeProvider/tailwindcss.css +230 -0
  119. package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/PickersStartEndDate.tsx +9 -11
  120. package/src/TimePeriods/CustomTimePeriod/PopoverCustomTimePeriod/models.ts +1 -0
  121. package/src/TimePeriods/DateTimePickerInput.tsx +3 -1
  122. package/src/api/models.ts +9 -0
  123. package/src/api/useGraphQuery/index.ts +108 -12
  124. package/src/components/Avatar/Avatar.stories.tsx +1 -0
  125. package/src/components/Button/Button.module.css +38 -0
  126. package/src/components/Button/Button.stories.tsx +25 -0
  127. package/src/components/Button/Button.tsx +2 -5
  128. package/src/components/CrudPage/CrudPage.stories.tsx +1 -0
  129. package/src/components/CrudPage/CrudPageRoot.tsx +1 -1
  130. package/src/components/DataTable/DataTable.stories.tsx +1 -0
  131. package/src/components/DataTable/EmptyState/DataTableEmptyState.stories.tsx +1 -0
  132. package/src/components/DataTable/EmptyState/DataTableEmptyState.styles.ts +3 -1
  133. package/src/components/DataTable/EmptyState/DataTableEmptyState.tsx +4 -1
  134. package/src/components/DataTable/Item/DataTableItem.stories.tsx +1 -0
  135. package/src/components/Form/AccessRights/AccessRights.stories.tsx +1 -0
  136. package/src/components/Form/AccessRights/ShareInput/ShareInput.tsx +4 -3
  137. package/src/components/Form/AccessRights/ShareInput/useShareInput.tsx +15 -10
  138. package/src/components/Form/FormActions.tsx +21 -12
  139. package/src/components/Layout/AreaIndicator.tsx +4 -6
  140. package/src/components/Layout/PageLayout/PageLayout.stories.tsx +1 -0
  141. package/src/components/Layout/PageLayout/PageLayout.tsx +9 -3
  142. package/src/components/Layout/PageLayout/PageLayoutActions.tsx +5 -3
  143. package/src/components/Layout/PageLayout/PageLayoutBody.tsx +5 -3
  144. package/src/components/Layout/PageLayout/PageLayoutHeader.tsx +5 -3
  145. package/src/components/Layout/PageLayout/PageQuickAccess.tsx +17 -17
  146. package/src/components/Menu/Button/MenuButton.tsx +6 -6
  147. package/src/components/Menu/MenuDivider.tsx +1 -5
  148. package/src/components/Menu/MenuItem.tsx +1 -5
  149. package/src/components/Menu/MenuItems.tsx +5 -4
  150. package/src/components/Modal/ConfirmationModal/ConfirmationModal.stories.tsx +1 -0
  151. package/src/components/Modal/ConfirmationModal/ConfirmationModal.tsx +4 -1
  152. package/src/components/Modal/Modal.stories.tsx +21 -0
  153. package/src/components/Modal/Modal.styles.ts +1 -19
  154. package/src/components/Modal/Modal.tsx +1 -1
  155. package/src/components/Modal/ModalBody.tsx +6 -4
  156. package/src/components/Modal/ModalHeader.tsx +9 -5
  157. package/src/components/Modal/modal.module.css +16 -0
  158. package/src/components/Tabs/Tab.styles.ts +0 -6
  159. package/src/components/Tabs/Tabs.tsx +37 -15
  160. package/src/index.ts +3 -0
  161. package/src/queryParameters/url/index.ts +7 -2
  162. package/src/utils/index.ts +1 -0
  163. package/src/utils/useLocale/index.ts +9 -0
  164. package/src/utils/useLocale/useLocale.cypress.spec.tsx +38 -0
  165. package/src/utils/useLocaleDateTimeFormat/index.ts +4 -2
  166. package/src/utils/usePluralizedTranslation.ts +2 -3
  167. package/src/Listing/Cell/DataCell.styles.ts +0 -27
  168. package/src/Listing/Header/Cell/ListingHeaderCell.styles.ts +0 -71
  169. package/src/Listing/Header/Cell/SelectActionListingHeaderCell.styles.ts +0 -26
  170. package/src/Listing/Header/ListingHeader.styles.ts +0 -16
  171. package/src/Listing/Listing.styles.ts +0 -78
  172. package/src/Listing/Row/EmptyRow.styles.ts +0 -14
  173. package/src/components/Button/Button.styles.ts +0 -44
  174. package/src/components/Layout/AreaIndicator.styles.ts +0 -33
  175. package/src/components/Menu/Button/MenuButton.styles.ts +0 -27
  176. package/src/components/Menu/Menu.styles.ts +0 -68
@@ -7,8 +7,7 @@ import {
7
7
 
8
8
  import { AriaLabelingAttributes } from '../../@types/aria-attributes';
9
9
  import { DataTestAttributes } from '../../@types/data-attributes';
10
-
11
- import { useStyles } from './Button.styles';
10
+ import { button } from './Button.module.css';
12
11
 
13
12
  const muiVariantMap: Record<
14
13
  Required<ButtonProps>['variant'],
@@ -48,8 +47,6 @@ const Button = ({
48
47
  className = '',
49
48
  ...attr
50
49
  }: ButtonProps): ReactElement => {
51
- const { classes, cx } = useStyles();
52
-
53
50
  const MuiOverrideProps = useMemo(
54
51
  () => ({
55
52
  color: 'primary' as const,
@@ -61,7 +58,7 @@ const Button = ({
61
58
 
62
59
  return (
63
60
  <MuiButton
64
- className={cx(classes.button, className)}
61
+ className={`${button} ${className}`}
65
62
  data-icon-variant={iconVariant}
66
63
  data-is-danger={isDanger}
67
64
  data-size={size}
@@ -7,6 +7,7 @@ import { ChangeEvent, useEffect } from 'react';
7
7
  import { CrudPage } from '.';
8
8
  import { SnackbarProvider } from '../../';
9
9
  import { Column, ColumnType } from '../../Listing/models';
10
+ import '../../ThemeProvider/tailwindcss.css';
10
11
 
11
12
  interface Item {
12
13
  id: number;
@@ -97,7 +97,7 @@ export const CrudPageRoot = <
97
97
  {isDataEmpty && !isLoading ? (
98
98
  <DataTable.EmptyState
99
99
  aria-label="create"
100
- data-testid="create-agent-configuration"
100
+ buttonCreateTestId="create-crudpage"
101
101
  labels={{
102
102
  title: labels.welcome.title,
103
103
  description: labels.welcome.description,
@@ -5,6 +5,7 @@ import { Box } from '@mui/material';
5
5
  import { ColumnType } from '../../Listing/models';
6
6
 
7
7
  import { DataTable } from './index';
8
+ import '../../ThemeProvider/tailwindcss.css';
8
9
 
9
10
  const meta: Meta<typeof DataTable> = {
10
11
  component: DataTable
@@ -1,6 +1,7 @@
1
1
  import { Meta, StoryObj } from '@storybook/react';
2
2
 
3
3
  import { DataTableEmptyState } from './DataTableEmptyState';
4
+ import '../../../ThemeProvider/tailwindcss.css';
4
5
 
5
6
  const meta: Meta<typeof DataTableEmptyState> = {
6
7
  component: DataTableEmptyState
@@ -6,6 +6,7 @@ const useStyles = makeStyles()((theme) => ({
6
6
  flexDirection: 'row'
7
7
  },
8
8
  dataTableEmptyState: {
9
+ marginTop: theme.spacing(3),
9
10
  alignItems: 'center',
10
11
  display: 'flex',
11
12
  flexDirection: 'column',
@@ -21,7 +22,8 @@ const useStyles = makeStyles()((theme) => ({
21
22
  width: '100%'
22
23
  },
23
24
  description: {
24
- maxWidth: '65%'
25
+ maxWidth: '65%',
26
+ textAlign: 'center'
25
27
  }
26
28
  }));
27
29
 
@@ -19,12 +19,14 @@ type ListEmptyStateProps = {
19
19
  description?: string;
20
20
  };
21
21
  onCreate?: () => void;
22
+ buttonCreateTestId?: string;
22
23
  };
23
24
 
24
25
  const DataTableEmptyState = ({
25
26
  labels,
26
27
  onCreate,
27
- canCreate = true
28
+ canCreate = true,
29
+ buttonCreateTestId
28
30
  }: ListEmptyStateProps): ReactElement => {
29
31
  const { classes } = useStyles();
30
32
  const { t } = useTranslation();
@@ -47,6 +49,7 @@ const DataTableEmptyState = ({
47
49
  icon={<AddIcon />}
48
50
  iconVariant="start"
49
51
  onClick={() => onCreate?.()}
52
+ data-testid={buttonCreateTestId}
50
53
  >
51
54
  {t(labels.actions?.create || '')}
52
55
  </Button>
@@ -1,6 +1,7 @@
1
1
  import { Meta, StoryObj } from '@storybook/react';
2
2
 
3
3
  import { DataTableItem } from './DataTableItem';
4
+ import '../../../ThemeProvider/tailwindcss.css';
4
5
 
5
6
  const meta: Meta<typeof DataTableItem> = {
6
7
  component: DataTableItem
@@ -12,6 +12,7 @@ import {
12
12
  labels,
13
13
  roles
14
14
  } from './storiesData';
15
+ import '../../../ThemeProvider/tailwindcss.css';
15
16
 
16
17
  const meta: Meta<typeof AccessRights> = {
17
18
  component: AccessRights,
@@ -8,6 +8,7 @@ import { SelectEntry, SingleConnectedAutocompleteField } from '../../../..';
8
8
  import RoleSelectField from '../common/RoleSelectField';
9
9
  import { Endpoints, Labels } from '../models';
10
10
 
11
+ import { ReactElement } from 'react';
11
12
  import ContactSwitch from './ContactSwitch';
12
13
  import { useShareInputStyles } from './ShareInput.styles';
13
14
  import useShareInput from './useShareInput';
@@ -18,18 +19,18 @@ interface Props {
18
19
  roles: Array<SelectEntry>;
19
20
  }
20
21
 
21
- const ShareInput = ({ labels, endpoints, roles }: Props): JSX.Element => {
22
+ const ShareInput = ({ labels, endpoints, roles }: Props): ReactElement => {
22
23
  const { t } = useTranslation();
23
24
  const { classes } = useShareInputStyles();
24
25
 
25
26
  const {
26
- renderOption,
27
27
  selectedContact,
28
28
  getOptionDisabled,
29
29
  getEndpoint,
30
30
  selectContact,
31
31
  isContactGroup,
32
32
  selectedRole,
33
+ getRenderedOptionText,
33
34
  setSelectedRole,
34
35
  add,
35
36
  changeIdValue
@@ -46,6 +47,7 @@ const ShareInput = ({ labels, endpoints, roles }: Props): JSX.Element => {
46
47
  disableClearable={false}
47
48
  field="name"
48
49
  getEndpoint={getEndpoint}
50
+ getRenderedOptionText={getRenderedOptionText}
49
51
  getOptionDisabled={getOptionDisabled}
50
52
  label={t(
51
53
  isContactGroup
@@ -53,7 +55,6 @@ const ShareInput = ({ labels, endpoints, roles }: Props): JSX.Element => {
53
55
  : t(labels.autocompleteContact)
54
56
  )}
55
57
  queryKey={isContactGroup ? labels.contactGroup : labels.contact}
56
- renderOption={renderOption}
57
58
  value={selectedContact}
58
59
  onChange={selectContact}
59
60
  />
@@ -1,10 +1,15 @@
1
- import { Dispatch, SetStateAction, useEffect, useState } from 'react';
1
+ import {
2
+ Dispatch,
3
+ ReactElement,
4
+ SetStateAction,
5
+ useEffect,
6
+ useState
7
+ } from 'react';
2
8
 
3
9
  import { useAtomValue, useSetAtom } from 'jotai';
4
10
  import { equals, includes, isNil } from 'ramda';
5
11
 
6
12
  import CheckCircleIcon from '@mui/icons-material/CheckCircle';
7
- import { ListItemText, MenuItem } from '@mui/material';
8
13
 
9
14
  import { SelectEntry, buildListingEndpoint } from '../../../..';
10
15
  import {
@@ -20,7 +25,7 @@ interface UseShareInputState {
20
25
  getEndpoint: (parameters) => string;
21
26
  getOptionDisabled: (option) => boolean;
22
27
  isContactGroup: boolean;
23
- renderOption: (attr, option) => JSX.Element;
28
+ getRenderedOptionText: (option: unknown) => ReactElement | string;
24
29
  selectContact: (_, entry) => void;
25
30
  selectedContact: AccessRightInitialValues | null;
26
31
  selectedRole: string;
@@ -40,7 +45,7 @@ const useShareInput = (endpoints: Endpoints): UseShareInputState => {
40
45
 
41
46
  const selectContact = (_, entry): void => {
42
47
  setSelectedContact(entry);
43
- if (equals('editor', entry.most_permissive_role)) {
48
+ if (equals('editor', entry?.most_permissive_role)) {
44
49
  return;
45
50
  }
46
51
  setSelectedRole('viewer');
@@ -71,14 +76,14 @@ const useShareInput = (endpoints: Endpoints): UseShareInputState => {
71
76
  }
72
77
  });
73
78
 
74
- const renderOption = (attr, option): JSX.Element => {
79
+ const getRenderedOptionText = (option): ReactElement => {
75
80
  return (
76
- <MenuItem {...attr}>
77
- <ListItemText>{option.name}</ListItemText>
78
- {includes(option.id, accessRightIds) && (
81
+ <>
82
+ {option?.name}
83
+ {includes(option?.id, accessRightIds) && (
79
84
  <CheckCircleIcon color="success" />
80
85
  )}
81
- </MenuItem>
86
+ </>
82
87
  );
83
88
  };
84
89
 
@@ -102,7 +107,7 @@ const useShareInput = (endpoints: Endpoints): UseShareInputState => {
102
107
  getEndpoint,
103
108
  getOptionDisabled,
104
109
  isContactGroup,
105
- renderOption,
110
+ getRenderedOptionText,
106
111
  selectContact,
107
112
  selectedContact,
108
113
  selectedRole,
@@ -12,6 +12,8 @@ export type FormActionsProps = {
12
12
  labels: FormActionsLabels;
13
13
  onCancel: () => void;
14
14
  variant: FormVariant;
15
+ isCancelButtonVisible?: boolean;
16
+ disableSubmit?: boolean;
15
17
  };
16
18
 
17
19
  export type FormActionsLabels = {
@@ -23,27 +25,34 @@ const FormActions = <TResource extends object>({
23
25
  labels,
24
26
  onCancel,
25
27
  variant,
26
- enableSubmitWhenNotDirty
28
+ enableSubmitWhenNotDirty,
29
+ isCancelButtonVisible = true,
30
+ disableSubmit = false
27
31
  }: FormActionsProps): ReactElement => {
28
32
  const { classes } = useStyles();
29
33
  const { isSubmitting, dirty, isValid, submitForm } =
30
34
  useFormikContext<TResource>();
31
35
 
32
36
  const isSubmitDisabled =
33
- isSubmitting || (!dirty && !enableSubmitWhenNotDirty) || !isValid;
37
+ disableSubmit ||
38
+ isSubmitting ||
39
+ (!dirty && !enableSubmitWhenNotDirty) ||
40
+ !isValid;
34
41
 
35
42
  return (
36
43
  <div className={classes.actions}>
37
- <Button
38
- aria-label={labels.cancel}
39
- data-testid="cancel"
40
- disabled={isSubmitting}
41
- size="medium"
42
- variant="secondary"
43
- onClick={() => onCancel?.()}
44
- >
45
- {labels.cancel}
46
- </Button>
44
+ {isCancelButtonVisible && (
45
+ <Button
46
+ aria-label={labels.cancel}
47
+ data-testid="cancel"
48
+ disabled={isSubmitting}
49
+ size="medium"
50
+ variant="secondary"
51
+ onClick={() => onCancel?.()}
52
+ >
53
+ {labels.cancel}
54
+ </Button>
55
+ )}
47
56
  <Button
48
57
  aria-label={labels.submit[variant]}
49
58
  data-testid="submit"
@@ -1,7 +1,5 @@
1
1
  import { ReactElement, ReactNode } from 'react';
2
2
 
3
- import { useStyles } from './AreaIndicator.styles';
4
-
5
3
  type AreaIndicatorProps = {
6
4
  children?: ReactNode | Array<ReactNode>;
7
5
  depth?: number;
@@ -17,16 +15,16 @@ const AreaIndicator = ({
17
15
  height = '100%',
18
16
  depth = 0
19
17
  }: AreaIndicatorProps): ReactElement => {
20
- const { classes } = useStyles();
21
-
22
18
  return (
23
19
  <div
24
- className={classes.areaIndicator}
20
+ className={'bg-secondary-main/25 min-h-8 grid grid-cols-[3fr_1fr]'}
25
21
  data-depth={depth}
26
22
  style={{ height, width }}
27
23
  >
28
24
  {/* biome-ignore lint/a11y: */}
29
- <label>{name}</label>
25
+ <label className="left-2 rounded-sm border border-[#9747FF7F] border-dashed text-[#9747FF] text-[0.75rem] font-medium left-2 top-1.5 px-2 py-0.5">
26
+ {name}
27
+ </label>
30
28
  {children}
31
29
  </div>
32
30
  );
@@ -4,6 +4,7 @@ import { Default as DefaultPageHeaderStory } from '../../Header/PageHeader/PageH
4
4
  import { AreaIndicator } from '../AreaIndicator';
5
5
 
6
6
  import { PageLayout } from './index';
7
+ import '../../../ThemeProvider/tailwindcss.css';
7
8
 
8
9
  const meta: Meta<typeof PageLayout> = {
9
10
  argTypes: {
@@ -5,16 +5,22 @@ import { useStyles } from './PageLayout.styles';
5
5
  type PageLayoutProps = {
6
6
  children: Array<ReactNode> | ReactNode;
7
7
  variant?: 'default' | 'fixed-header';
8
+ className?: string;
8
9
  };
9
10
 
10
11
  export const PageLayout = ({
11
12
  children,
12
- variant = 'default'
13
+ variant = 'default',
14
+ className
13
15
  }: PageLayoutProps): ReactElement => {
14
- const { classes } = useStyles();
16
+ const { classes, cx } = useStyles();
15
17
 
16
18
  return (
17
- <section className={classes.pageLayout} data-variant={variant} id="page">
19
+ <section
20
+ className={cx(classes.pageLayout, className)}
21
+ data-variant={variant}
22
+ id="page"
23
+ >
18
24
  {children}
19
25
  </section>
20
26
  );
@@ -5,17 +5,19 @@ import { useStyles } from './PageLayout.styles';
5
5
  interface PageLayoutActionsProps {
6
6
  children: Array<ReactNode> | ReactNode;
7
7
  rowReverse?: boolean;
8
+ className?: string;
8
9
  }
9
10
 
10
11
  export const PageLayoutActions = ({
11
12
  children,
12
- rowReverse
13
+ rowReverse,
14
+ className
13
15
  }: PageLayoutActionsProps): ReactElement => {
14
- const { classes } = useStyles();
16
+ const { classes, cx } = useStyles();
15
17
 
16
18
  return (
17
19
  <section
18
- className={classes.pageLayoutActions}
20
+ className={cx(classes.pageLayoutActions, className)}
19
21
  data-row-reverse={rowReverse}
20
22
  id="actions"
21
23
  >
@@ -5,17 +5,19 @@ import { useStyles } from './PageLayout.styles';
5
5
  type PageLayoutBodyProps = {
6
6
  children: Array<ReactNode> | ReactNode;
7
7
  hasBackground?: boolean;
8
+ className?: string;
8
9
  };
9
10
 
10
11
  export const PageLayoutBody = ({
11
12
  children,
12
- hasBackground = false
13
+ hasBackground = false,
14
+ className
13
15
  }: PageLayoutBodyProps): ReactElement => {
14
- const { classes } = useStyles();
16
+ const { classes, cx } = useStyles();
15
17
 
16
18
  return (
17
19
  <section
18
- className={classes.pageLayoutBody}
20
+ className={cx(classes.pageLayoutBody, className)}
19
21
  data-has-background={hasBackground}
20
22
  data-has-actions={!!children?.length}
21
23
  id="page-body"
@@ -4,15 +4,17 @@ import { useStyles } from './PageLayout.styles';
4
4
 
5
5
  type PageLayoutHeaderProps = {
6
6
  children: Array<ReactNode> | ReactNode;
7
+ className?: string;
7
8
  };
8
9
 
9
10
  export const PageLayoutHeader = ({
10
- children
11
+ children,
12
+ className
11
13
  }: PageLayoutHeaderProps): JSX.Element => {
12
- const { classes } = useStyles();
14
+ const { classes, cx } = useStyles();
13
15
 
14
16
  return (
15
- <header className={classes.pageLayoutHeader} id="header">
17
+ <header className={cx(classes.pageLayoutHeader, className)} id="header">
16
18
  {children}
17
19
  </header>
18
20
  );
@@ -11,10 +11,11 @@ interface NamedEntity {
11
11
  }
12
12
 
13
13
  type Props = {
14
- create: () => void;
14
+ create?: () => void;
15
15
  elements: Array<NamedEntity>;
16
16
  goBack: () => void;
17
17
  isActive: (id: number | string) => boolean;
18
+ isDisabled?: (id: number | string) => boolean;
18
19
  labels: {
19
20
  create: string;
20
21
  goBack: string;
@@ -25,6 +26,7 @@ type Props = {
25
26
  export const PageQuickAccess = ({
26
27
  elements,
27
28
  isActive,
29
+ isDisabled,
28
30
  navigateToElement,
29
31
  goBack,
30
32
  create,
@@ -40,25 +42,23 @@ export const PageQuickAccess = ({
40
42
  <Menu.Item
41
43
  key={`${element.id}`}
42
44
  onClick={navigateToElement(element.id)}
43
- {...(isActive(element.id) && {
44
- isActive: true,
45
- isDisabled: true
46
- })}
45
+ isActive={isActive(element.id)}
46
+ isDisabled={isDisabled?.(element.id)}
47
47
  >
48
48
  {element.name}
49
49
  </Menu.Item>
50
50
  ))}
51
51
  <Menu.Divider key="divider" />
52
- <Menu.Item key="create">
53
- <>
54
- <Button
55
- icon={<ArrowBackIcon />}
56
- iconVariant="start"
57
- variant="ghost"
58
- onClick={goBack}
59
- >
60
- {t(labels.goBack)}
61
- </Button>
52
+ <div className="px-2 pb-2 flex gap-4">
53
+ <Button
54
+ icon={<ArrowBackIcon />}
55
+ iconVariant="start"
56
+ variant="ghost"
57
+ onClick={goBack}
58
+ >
59
+ {t(labels.goBack)}
60
+ </Button>
61
+ {create && (
62
62
  <Button
63
63
  icon={<AddIcon />}
64
64
  iconVariant="start"
@@ -67,8 +67,8 @@ export const PageQuickAccess = ({
67
67
  >
68
68
  {t(labels.create)}
69
69
  </Button>
70
- </>
71
- </Menu.Item>
70
+ )}
71
+ </div>
72
72
  </Menu.Items>
73
73
  </Menu>
74
74
  );
@@ -10,8 +10,6 @@ import { DataTestAttributes } from '../../../@types/data-attributes';
10
10
  import { Button, ButtonProps } from '../../Button';
11
11
  import { useMenu } from '../useMenu';
12
12
 
13
- import { useStyles } from './MenuButton.styles';
14
-
15
13
  type MenuButtonProps = {
16
14
  ariaLabel?: string;
17
15
  children?: ReactNode;
@@ -33,8 +31,6 @@ const MenuButton = ({
33
31
  className,
34
32
  ...attr
35
33
  }: MenuButtonProps): ReactElement => {
36
- const { cx, classes } = useStyles();
37
-
38
34
  const { isMenuOpen, setIsMenuOpen, setAnchorEl, onOpen } = useMenu();
39
35
 
40
36
  const onToggle = useCallback(
@@ -52,14 +48,18 @@ const MenuButton = ({
52
48
  <Button
53
49
  {...attr}
54
50
  aria-label={ariaLabel}
55
- className={cx(classes.menuButton, className)}
51
+ className={`${isMenuOpen ? 'bg-primary-main/8 text-text-primary-main' : 'text-text-secondary'} ${className}`}
56
52
  data-is-active={isMenuOpen}
57
53
  size={size}
58
54
  variant={variant}
59
55
  onClick={onToggle}
60
56
  >
61
57
  {children || <MenuIcon />}
62
- {hasArrow && <ArrowDropDownIcon className={classes.buttonIcon} />}
58
+ {hasArrow && (
59
+ <ArrowDropDownIcon
60
+ className={`transform-gpu transition-[rotate] ${isMenuOpen ? 'rotate-180' : 'rotate-0'}`}
61
+ />
62
+ )}
63
63
  </Button>
64
64
  );
65
65
  };
@@ -2,12 +2,8 @@ import { ReactElement } from 'react';
2
2
 
3
3
  import { Divider as MuiDivider } from '@mui/material';
4
4
 
5
- import { useStyles } from './Menu.styles';
6
-
7
5
  const MenuDivider = (): ReactElement => {
8
- const { classes } = useStyles();
9
-
10
- return <MuiDivider className={classes.menuDivider} />;
6
+ return <MuiDivider />;
11
7
  };
12
8
 
13
9
  export { MenuDivider };
@@ -2,8 +2,6 @@ import { ReactElement, ReactNode } from 'react';
2
2
 
3
3
  import { MenuItem as MuiMenuItem } from '@mui/material';
4
4
 
5
- import { useStyles } from './Menu.styles';
6
-
7
5
  type MenuItemProps = {
8
6
  children?: ReactNode;
9
7
  className?: string;
@@ -19,11 +17,9 @@ const MenuItem = ({
19
17
  isDisabled = false,
20
18
  className
21
19
  }: MenuItemProps): ReactElement => {
22
- const { cx, classes } = useStyles();
23
-
24
20
  return (
25
21
  <MuiMenuItem
26
- className={cx(classes.menuItem, className)}
22
+ className={className}
27
23
  data-is-active={isActive}
28
24
  data-is-disabled={isDisabled}
29
25
  disabled={isDisabled}
@@ -2,7 +2,6 @@ import { ReactElement, ReactNode } from 'react';
2
2
 
3
3
  import { Menu as MuiMenu } from '@mui/material';
4
4
 
5
- import { useStyles } from './Menu.styles';
6
5
  import { useMenu } from './useMenu';
7
6
 
8
7
  type MenuItemsProps = {
@@ -10,8 +9,6 @@ type MenuItemsProps = {
10
9
  className?: string;
11
10
  };
12
11
  const MenuItems = ({ children, className }: MenuItemsProps): ReactElement => {
13
- const { cx, classes } = useStyles();
14
-
15
12
  const { isMenuOpen, setIsMenuOpen, anchorEl, onClose } = useMenu();
16
13
 
17
14
  const onCloseMenu = (): void => {
@@ -22,7 +19,11 @@ const MenuItems = ({ children, className }: MenuItemsProps): ReactElement => {
22
19
  return (
23
20
  <MuiMenu
24
21
  anchorEl={anchorEl}
25
- className={cx(classes.menuItems, className)}
22
+ className={className}
23
+ classes={{
24
+ paper:
25
+ 'rounded-sm shadow-lg min-w-[240px] bg-background-paper border-1 border-divider'
26
+ }}
26
27
  open={isMenuOpen}
27
28
  variant="menu"
28
29
  onClick={onCloseMenu}
@@ -4,6 +4,7 @@ import { Provider, atom, createStore, useSetAtom } from 'jotai';
4
4
  import { Button } from '../../Button';
5
5
 
6
6
  import { ConfirmationModal } from './ConfirmationModal';
7
+ import '../../../ThemeProvider/tailwindcss.css';
7
8
 
8
9
  const meta: Meta<typeof ConfirmationModal> = {
9
10
  component: ConfirmationModal
@@ -19,6 +19,7 @@ export interface ConfirmationModalProps<TAtom> {
19
19
  onCancel?: (atomData: Awaited<TAtom> | null) => void;
20
20
  onClose?: (atomData: Awaited<TAtom> | null) => void;
21
21
  onConfirm?: (atomData: Awaited<TAtom> | null) => void;
22
+ size?: 'small' | 'medium' | 'large' | 'xlarge' | 'fullscreen';
22
23
  }
23
24
 
24
25
  interface GetLabelProps<TAtom> {
@@ -39,7 +40,8 @@ export const ConfirmationModal = <TAtom,>({
39
40
  onClose,
40
41
  hasCloseButton = true,
41
42
  isDanger,
42
- disabled
43
+ disabled,
44
+ size
43
45
  }: ConfirmationModalProps<TAtom>): JSX.Element => {
44
46
  const [atomData, setAtomData] = useAtom<TAtom | null>(atom);
45
47
 
@@ -72,6 +74,7 @@ export const ConfirmationModal = <TAtom,>({
72
74
  hasCloseButton={hasCloseButton}
73
75
  open={Boolean(atomData)}
74
76
  onClose={closeModal}
77
+ size={size}
75
78
  >
76
79
  <Modal.Header>{formattedLabels.title}</Modal.Header>
77
80
  <Modal.Body>{formattedLabels.description}</Modal.Body>
@@ -3,6 +3,8 @@ import { Meta, StoryObj } from '@storybook/react';
3
3
  import { Button } from '../Button';
4
4
 
5
5
  import { Modal } from '.';
6
+ import '../../ThemeProvider/tailwindcss.css';
7
+ import { basicFormWithCollapsibleGroups } from '../../Form/Form.stories';
6
8
 
7
9
  const meta: Meta<typeof Modal> = {
8
10
  argTypes: {
@@ -44,6 +46,25 @@ export const Default: Story = {
44
46
  )
45
47
  };
46
48
 
49
+ export const WithForm: Story = {
50
+ args: {
51
+ ...Default.args
52
+ },
53
+
54
+ render: (args) => (
55
+ <Modal {...args}>
56
+ <Modal.Header>Modal title</Modal.Header>
57
+ <Modal.Body>{basicFormWithCollapsibleGroups()}</Modal.Body>
58
+ <Modal.Actions
59
+ labels={{
60
+ cancel: 'Cancel',
61
+ confirm: 'Confirm'
62
+ }}
63
+ />
64
+ </Modal>
65
+ )
66
+ };
67
+
47
68
  export const AsDangerAction: Story = {
48
69
  args: {
49
70
  ...Default.args