@altinn/altinn-components 0.4.0 → 0.5.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 (194) hide show
  1. package/.storybook/main.ts +1 -1
  2. package/CHANGELOG.md +14 -0
  3. package/biome.jsonc +1 -1
  4. package/lib/components/Attachment/AttachmentLink.stories.ts +1 -1
  5. package/lib/components/Attachment/AttachmentList.stories.ts +1 -1
  6. package/lib/components/Button/Button.tsx +13 -10
  7. package/lib/components/Button/ButtonBase.tsx +1 -1
  8. package/lib/components/Button/ButtonIcon.tsx +16 -0
  9. package/lib/components/Button/ButtonLabel.tsx +16 -0
  10. package/lib/components/Button/Buttons.stories.tsx +64 -0
  11. package/lib/components/Button/ComboButton.tsx +9 -7
  12. package/lib/components/Button/IconButton.stories.tsx +47 -0
  13. package/lib/components/Button/IconButton.tsx +15 -5
  14. package/lib/components/Button/button.module.css +5 -46
  15. package/lib/components/Button/buttonBase.module.css +55 -23
  16. package/lib/components/Button/buttonIcon.module.css +17 -0
  17. package/lib/components/Button/buttonLabel.module.css +17 -0
  18. package/lib/components/Button/comboButton.module.css +15 -65
  19. package/lib/components/Button/iconButton.module.css +21 -4
  20. package/lib/components/Button/index.ts +2 -0
  21. package/lib/components/ContextMenu/ContextMenu.stories.ts +49 -0
  22. package/lib/components/ContextMenu/ContextMenu.tsx +12 -20
  23. package/lib/components/ContextMenu/ContextMenuBase.tsx +33 -0
  24. package/lib/components/Dialog/Dialog.tsx +2 -0
  25. package/lib/components/Dialog/DialogGroup.tsx +24 -0
  26. package/lib/components/Dialog/DialogList.stories.ts +14 -10
  27. package/lib/components/Dialog/DialogList.tsx +26 -11
  28. package/lib/components/Dialog/DialogListItem.tsx +12 -3
  29. package/lib/components/Dialog/DialogListItemBase.tsx +4 -2
  30. package/lib/components/Dialog/DialogNav.stories.ts +5 -5
  31. package/lib/components/Dialog/DialogNav.tsx +3 -7
  32. package/lib/components/Dialog/DialogSelect.tsx +1 -1
  33. package/lib/components/Dialog/dialogGroup.module.css +35 -0
  34. package/lib/components/Dialog/dialogNav.module.css +12 -0
  35. package/lib/components/Dropdown/Backdrop.tsx +4 -3
  36. package/lib/components/Dropdown/DrawerBase.tsx +5 -2
  37. package/lib/components/Dropdown/DrawerBody.tsx +12 -0
  38. package/lib/components/Dropdown/DrawerButton.tsx +17 -0
  39. package/lib/components/Dropdown/DrawerFooter.tsx +12 -0
  40. package/lib/components/Dropdown/DrawerHeader.tsx +19 -0
  41. package/lib/components/Dropdown/DrawerOrDropdown.tsx +29 -0
  42. package/lib/components/Dropdown/DropdownBase.tsx +5 -2
  43. package/lib/components/Dropdown/backdrop.module.css +3 -0
  44. package/lib/components/Dropdown/drawerBase.module.css +9 -0
  45. package/lib/components/Dropdown/drawerBody.module.css +5 -0
  46. package/lib/components/Dropdown/drawerButton.module.css +6 -0
  47. package/lib/components/Dropdown/drawerFooter.module.css +13 -0
  48. package/lib/components/Dropdown/drawerHeader.module.css +17 -0
  49. package/lib/components/Dropdown/drawerOrDropdown.module.css +19 -0
  50. package/lib/components/Dropdown/dropdownBase.module.css +15 -3
  51. package/lib/components/Dropdown/index.ts +7 -1
  52. package/lib/components/Footer/footerMenu.module.css +5 -0
  53. package/lib/components/GlobalMenu/GlobalMenu.stories.tsx +9 -9
  54. package/lib/components/GlobalMenu/GlobalMenu.tsx +5 -5
  55. package/lib/components/Header/{Header.stories.ts → Header.stories.tsx} +79 -20
  56. package/lib/components/Header/Header.tsx +24 -42
  57. package/lib/components/Header/HeaderBase.tsx +7 -3
  58. package/lib/components/Header/header.module.css +10 -42
  59. package/lib/components/Header/headerBase.module.css +43 -0
  60. package/lib/components/Header/headerButton.module.css +1 -0
  61. package/lib/components/History/HistoryAttachments.tsx +22 -0
  62. package/lib/components/History/HistoryItem.stories.ts +27 -18
  63. package/lib/components/History/HistoryItem.tsx +7 -15
  64. package/lib/components/History/HistoryList.stories.ts +34 -22
  65. package/lib/components/Layout/Layout.stories.tsx +77 -38
  66. package/lib/components/Layout/Layout.tsx +5 -3
  67. package/lib/components/Layout/LayoutBase.tsx +4 -3
  68. package/lib/components/Layout/index.tsx +1 -0
  69. package/lib/components/Layout/layoutBase.module.css +9 -10
  70. package/lib/components/Layout/layoutBody.module.css +1 -0
  71. package/lib/components/Layout/layoutContent.module.css +6 -1
  72. package/lib/components/Layout/layoutSidebar.module.css +1 -0
  73. package/lib/components/LayoutAction/ActionFooter.stories.tsx +1 -1
  74. package/lib/components/LayoutAction/ActionHeader.tsx +2 -2
  75. package/lib/components/LayoutAction/ActionMenu.stories.tsx +1 -0
  76. package/lib/components/LayoutAction/ActionMenu.tsx +4 -3
  77. package/lib/components/LayoutAction/actionMenu.module.css +11 -6
  78. package/lib/components/List/List.stories.tsx +43 -0
  79. package/lib/components/List/List.tsx +6 -6
  80. package/lib/components/List/ListBase.tsx +6 -6
  81. package/lib/components/List/ListItem.tsx +4 -1
  82. package/lib/components/List/ListItemBase.tsx +20 -4
  83. package/lib/components/List/listBase.module.css +3 -3
  84. package/lib/components/List/listItemBase.module.css +4 -0
  85. package/lib/components/Menu/Menu.stories.ts +46 -46
  86. package/lib/components/Menu/Menu.tsx +3 -102
  87. package/lib/components/Menu/MenuBase.tsx +47 -3
  88. package/lib/components/Menu/{MenuItem.stories.ts → MenuItem.stories.tsx} +32 -0
  89. package/lib/components/Menu/MenuItem.tsx +6 -4
  90. package/lib/components/Menu/MenuItemBase.tsx +8 -1
  91. package/lib/components/Menu/MenuItems.stories.ts +438 -0
  92. package/lib/components/Menu/MenuItems.tsx +96 -0
  93. package/lib/components/Menu/MenuOption.tsx +4 -1
  94. package/lib/components/Menu/{MenuGroup.tsx → __MenuGroup.tsx} +1 -1
  95. package/lib/components/Menu/{menuItem.module.css → __menuItem.module.css} +0 -6
  96. package/lib/components/Menu/index.ts +1 -1
  97. package/lib/components/Menu/menu.module.css +2 -3
  98. package/lib/components/Menu/menuBase.module.css +25 -0
  99. package/lib/components/Menu/menuItemBase.module.css +12 -17
  100. package/lib/components/Menu/menuItemMedia.module.css +2 -0
  101. package/lib/components/Meta/MetaItemBase.tsx +1 -1
  102. package/lib/components/Meta/MetaItemLabel.tsx +1 -1
  103. package/lib/components/Meta/MetaItemMedia.tsx +1 -1
  104. package/lib/components/Page/PageBase.tsx +14 -0
  105. package/lib/components/Page/PageHeader.tsx +21 -0
  106. package/lib/components/Page/PageHeaderMedia.tsx +25 -0
  107. package/lib/components/Page/SectionBase.tsx +52 -0
  108. package/lib/components/Page/SectionFooter.tsx +15 -0
  109. package/lib/components/Page/SectionHeader.tsx +16 -0
  110. package/lib/components/Page/index.ts +5 -0
  111. package/lib/components/Page/pageHeader.module.css +5 -0
  112. package/lib/components/Page/sectionBase.module.css +82 -0
  113. package/lib/components/Page/sectionFooter.module.css +8 -0
  114. package/lib/components/Page/sectionHeader.module.css +9 -0
  115. package/lib/components/RootProvider/RootProvider.tsx +43 -7
  116. package/lib/components/Searchbar/Autocomplete.stories.tsx +77 -0
  117. package/lib/components/Searchbar/Autocomplete.tsx +44 -0
  118. package/lib/components/Searchbar/AutocompleteBase.tsx +16 -0
  119. package/lib/components/Searchbar/AutocompleteGroup.tsx +17 -0
  120. package/lib/components/Searchbar/AutocompleteItem.tsx +23 -0
  121. package/lib/components/Searchbar/SearchField.tsx +78 -0
  122. package/lib/components/Searchbar/Searchbar.stories.tsx +151 -0
  123. package/lib/components/Searchbar/Searchbar.tsx +18 -0
  124. package/lib/components/Searchbar/SearchbarBase.tsx +23 -0
  125. package/lib/components/Searchbar/autocompleteBase.module.css +17 -0
  126. package/lib/components/Searchbar/autocompleteGroup.module.css +3 -0
  127. package/lib/components/Searchbar/autocompleteItem.module.css +19 -0
  128. package/lib/components/Searchbar/index.ts +1 -0
  129. package/lib/components/Searchbar/searchField.module.css +54 -0
  130. package/lib/components/Searchbar/searchbarBase.module.css +20 -0
  131. package/lib/components/Toolbar/Toolbar.stories.tsx +10 -10
  132. package/lib/components/Toolbar/Toolbar.tsx +28 -10
  133. package/lib/components/Toolbar/ToolbarAdd.tsx +6 -5
  134. package/lib/components/Toolbar/ToolbarBase.tsx +5 -20
  135. package/lib/components/Toolbar/ToolbarButton.tsx +1 -1
  136. package/lib/components/Toolbar/ToolbarFilter.tsx +11 -6
  137. package/lib/components/Toolbar/ToolbarMenu.tsx +8 -7
  138. package/lib/components/Toolbar/ToolbarOptions.stories.ts +5 -5
  139. package/lib/components/Toolbar/ToolbarOptions.tsx +34 -21
  140. package/lib/components/Toolbar/toolbarAdd.module.css +7 -0
  141. package/lib/components/Toolbar/toolbarBase.module.css +19 -0
  142. package/lib/components/Toolbar/toolbarButton.module.css +1 -1
  143. package/lib/components/Toolbar/toolbarFilter.module.css +25 -0
  144. package/lib/components/Toolbar/toolbarMenu.module.css +7 -0
  145. package/lib/components/Typography/Heading.tsx +23 -0
  146. package/lib/components/Typography/Typography.tsx +8 -5
  147. package/lib/components/Typography/heading.module.css +21 -0
  148. package/lib/components/Typography/index.ts +1 -0
  149. package/lib/components/Typography/typography.module.css +8 -0
  150. package/lib/components/index.ts +2 -0
  151. package/lib/css/global.css +1 -0
  152. package/lib/css/theme-global-dark.css +19 -0
  153. package/lib/hooks/index.ts +3 -0
  154. package/lib/{components/Menu → hooks}/useEscapeKey.ts +2 -2
  155. package/lib/hooks/useMenu.tsx +80 -0
  156. package/lib/index.ts +1 -0
  157. package/lib/stories/Color/MenuItem.stories.tsx +43 -0
  158. package/lib/stories/Color/Swatches.stories.tsx +19 -0
  159. package/lib/stories/Color/Swatches.tsx +42 -0
  160. package/lib/stories/Color/colors.json +62 -0
  161. package/lib/stories/Color/swatches.module.css +14 -0
  162. package/lib/stories/Inbox/BookmarksPage.tsx +52 -0
  163. package/lib/stories/Inbox/DialogPage.tsx +15 -0
  164. package/lib/stories/Inbox/Inbox.stories.tsx +55 -0
  165. package/lib/stories/Inbox/Inbox.tsx +12 -0
  166. package/lib/stories/Inbox/InboxLayout.tsx +50 -0
  167. package/lib/stories/Inbox/InboxPage.tsx +50 -0
  168. package/lib/stories/Inbox/InboxProvider.tsx +136 -0
  169. package/lib/stories/Inbox/InboxSection.tsx +39 -0
  170. package/lib/stories/Inbox/InboxToolbar.tsx +94 -0
  171. package/lib/stories/Inbox/ProfilePage.tsx +35 -0
  172. package/lib/stories/Inbox/SettingsPage.tsx +19 -0
  173. package/lib/stories/Inbox/accounts/accounts.ts +24 -0
  174. package/lib/stories/Inbox/accounts/index.ts +1 -0
  175. package/lib/stories/Inbox/actionMenu.ts +24 -0
  176. package/lib/stories/Inbox/dialogs/brreg-completed.json +35 -0
  177. package/lib/stories/Inbox/dialogs/brreg-draft.json +45 -0
  178. package/lib/stories/Inbox/dialogs/index.ts +10 -0
  179. package/lib/stories/Inbox/dialogs/skatt-2023.json +33 -0
  180. package/lib/stories/Inbox/groupBy.ts +19 -0
  181. package/lib/stories/Inbox/inboxSection.module.css +19 -0
  182. package/lib/stories/Inbox/index.ts +15 -0
  183. package/lib/stories/Inbox/layout/footer.ts +27 -0
  184. package/lib/stories/Inbox/layout/header.ts +11 -0
  185. package/lib/stories/Inbox/layout/index.ts +3 -0
  186. package/lib/stories/Inbox/layout/menu.ts +64 -0
  187. package/package.json +1 -1
  188. package/tsconfig.json +7 -2
  189. package/lib/components/Header/HeaderSearch.stories.ts +0 -20
  190. package/lib/components/Header/HeaderSearch.tsx +0 -44
  191. package/lib/components/Header/headerSearch.module.css +0 -30
  192. package/lib/components/Toolbar/toolbar.module.css +0 -43
  193. /package/lib/components/ContextMenu/{contextMenu.module.css → contextMenuBase.module.css} +0 -0
  194. /package/lib/{components/Menu → hooks}/useClickOutside.ts +0 -0
@@ -1,18 +1,18 @@
1
1
  import type { ReactNode } from 'react';
2
2
  import styles from './listBase.module.css';
3
3
 
4
- import type { LayoutTheme } from '../Layout';
5
- import type { ListItemSize } from './ListItemBase';
4
+ export type ListTheme = 'inherit' | 'global' | 'neutral' | 'person' | 'company';
5
+ export type ListSpacing = 'none' | 'sm' | 'md' | 'lg';
6
6
 
7
7
  export interface ListBaseProps {
8
- size?: ListItemSize;
9
- theme?: LayoutTheme;
8
+ theme?: ListTheme;
9
+ spacing?: ListSpacing;
10
10
  children?: ReactNode;
11
11
  }
12
12
 
13
- export const ListBase = ({ size = 'md', theme, children }: ListBaseProps) => {
13
+ export const ListBase = ({ theme = 'inherit', spacing = 'md', children }: ListBaseProps) => {
14
14
  return (
15
- <div className={styles.list} data-theme={theme} data-size={size}>
15
+ <div className={styles.list} data-theme={theme} data-spacing={spacing}>
16
16
  {children}
17
17
  </div>
18
18
  );
@@ -13,7 +13,10 @@ export interface ListItemProps {
13
13
  as?: ElementType;
14
14
  color?: ListItemColor;
15
15
  href?: string;
16
- onClick?: () => void;
16
+ onClick?(): void;
17
+ /** Item is active */
18
+ active?: boolean;
19
+ /** Item should be hidden from view */
17
20
  hidden?: boolean;
18
21
  /** Collapsible item, sets linkIcon to "chevron down" */
19
22
  collapsible?: boolean;
@@ -1,5 +1,5 @@
1
1
  import cx from 'classnames';
2
- import type { ElementType, ReactNode } from 'react';
2
+ import type { ElementType, KeyboardEvent, KeyboardEventHandler, ReactNode } from 'react';
3
3
  import { Badge, type BadgeProps } from '../Badge';
4
4
  import { Icon, type IconName } from '../Icon';
5
5
  import styles from './listItemBase.module.css';
@@ -15,10 +15,15 @@ interface ListItemBaseProps {
15
15
  badge?: BadgeProps;
16
16
  href?: string;
17
17
  className?: string;
18
+ active?: boolean;
19
+ hidden?: boolean;
18
20
  collapsible?: boolean;
19
21
  selected?: boolean;
20
22
  expanded?: boolean;
23
+ onClick?: () => void;
24
+ onKeyPress?: KeyboardEventHandler;
21
25
  children?: ReactNode;
26
+ style?: React.CSSProperties;
22
27
  }
23
28
 
24
29
  export const ListItemBase = ({
@@ -28,27 +33,38 @@ export const ListItemBase = ({
28
33
  href,
29
34
  size,
30
35
  color,
36
+ active = false,
37
+ hidden = false,
31
38
  collapsible,
32
39
  selected,
33
40
  expanded,
34
41
  linkIcon,
35
42
  badge,
36
- ...rest
43
+ onClick,
44
+ onKeyPress,
45
+ style,
37
46
  }: ListItemBaseProps) => {
38
47
  const Component = as || 'a';
39
48
 
40
49
  const applicableIcon =
41
50
  collapsible && expanded ? 'chevron-up' : collapsible ? 'chevron-down' : href ? 'chevron-right' : linkIcon;
42
-
43
51
  return (
44
52
  <Component
45
53
  className={cx(styles.item, className)}
46
54
  data-color={color}
47
55
  data-size={size}
56
+ data-active={active}
57
+ aria-hidden={hidden}
48
58
  aria-selected={selected}
49
59
  aria-expanded={expanded}
50
60
  href={href}
51
- {...rest}
61
+ onKeyPress={(e: KeyboardEvent) => {
62
+ e.key === 'Enter' && onClick?.();
63
+ onKeyPress?.(e);
64
+ }}
65
+ onClick={onClick}
66
+ tabIndex={-1}
67
+ style={style}
52
68
  >
53
69
  <div className={styles.content} data-size={size}>
54
70
  {children}
@@ -3,14 +3,14 @@
3
3
  flex-direction: column;
4
4
  }
5
5
 
6
- .list[data-size="sm"] {
6
+ .list[data-spacing="sm"] {
7
7
  row-gap: 4px;
8
8
  }
9
9
 
10
- .list[data-size="md"] {
10
+ .list[data-spacing="md"] {
11
11
  row-gap: 8px;
12
12
  }
13
13
 
14
- .list[data-size="lg"] {
14
+ .list[data-spacing="lg"] {
15
15
  row-gap: 16px;
16
16
  }
@@ -77,6 +77,10 @@
77
77
  box-shadow: var(--ds-shadow-xs);
78
78
  }
79
79
 
80
+ .item[data-active="true"] {
81
+ background-color: var(--theme-surface-default);
82
+ }
83
+
80
84
  .item[data-color="accent"] {
81
85
  background-color: var(--theme-surface-default);
82
86
  }
@@ -22,7 +22,7 @@ export const GlobalMenu: Story = {
22
22
  items: [
23
23
  {
24
24
  id: 'account',
25
- group: 'account',
25
+ groupId: 'account',
26
26
  size: 'lg',
27
27
  avatar: {
28
28
  type: 'person',
@@ -33,7 +33,7 @@ export const GlobalMenu: Story = {
33
33
  },
34
34
  {
35
35
  id: 'inbox',
36
- group: 'apps',
36
+ groupId: 'apps',
37
37
  size: 'lg',
38
38
  icon: 'inbox',
39
39
  title: 'Innboks',
@@ -44,7 +44,7 @@ export const GlobalMenu: Story = {
44
44
  },
45
45
  {
46
46
  id: 'access',
47
- group: 'apps',
47
+ groupId: 'apps',
48
48
  size: 'lg',
49
49
  icon: 'bookmark',
50
50
  title: 'Tilganger',
@@ -55,14 +55,14 @@ export const GlobalMenu: Story = {
55
55
  },
56
56
  {
57
57
  id: 'access',
58
- group: 'apps',
58
+ groupId: 'apps',
59
59
  size: 'lg',
60
60
  icon: 'menu-grid',
61
61
  title: 'Alle skjema',
62
62
  },
63
63
  {
64
64
  id: 'settings',
65
- group: 'settings',
65
+ groupId: 'settings',
66
66
  icon: 'cog',
67
67
  title: 'Innstillinger',
68
68
  },
@@ -80,7 +80,7 @@ export const CollapsibleGlobalMenu: Story = {
80
80
  items: [
81
81
  {
82
82
  id: 'account',
83
- group: 'account',
83
+ groupId: 'account',
84
84
  size: 'lg',
85
85
  avatar: {
86
86
  type: 'person',
@@ -91,7 +91,7 @@ export const CollapsibleGlobalMenu: Story = {
91
91
  },
92
92
  {
93
93
  id: 'innboks',
94
- group: 'apps',
94
+ groupId: 'apps',
95
95
  size: 'lg',
96
96
  icon: 'inbox',
97
97
  title: 'Innboks',
@@ -99,32 +99,32 @@ export const CollapsibleGlobalMenu: Story = {
99
99
  items: [
100
100
  {
101
101
  id: 'utkast',
102
- group: '1',
102
+ groupId: '1',
103
103
  icon: 'doc-pencil',
104
104
  title: 'Utkast',
105
105
  },
106
106
  {
107
107
  id: 'sent',
108
- group: '1',
108
+ groupId: '1',
109
109
  icon: 'file-checkmark',
110
110
  selected: true,
111
111
  title: 'Sendt',
112
112
  },
113
113
  {
114
114
  id: 'bookmarks',
115
- group: '3',
115
+ groupId: '3',
116
116
  icon: 'bookmark',
117
117
  title: 'Lagrede søk',
118
118
  },
119
119
  {
120
120
  id: 'arkiv',
121
- group: '4',
121
+ groupId: '4',
122
122
  icon: 'archive',
123
123
  title: 'Arkivert',
124
124
  },
125
125
  {
126
126
  id: 'trash',
127
- group: '4',
127
+ groupId: '4',
128
128
  icon: 'trash',
129
129
  title: 'Papirkurv',
130
130
  },
@@ -132,21 +132,21 @@ export const CollapsibleGlobalMenu: Story = {
132
132
  },
133
133
  {
134
134
  id: 'tilganger',
135
- group: 'apps',
135
+ groupId: 'apps',
136
136
  size: 'lg',
137
137
  icon: 'bookmark',
138
138
  title: 'Tilganger',
139
139
  },
140
140
  {
141
141
  id: 'skjema',
142
- group: 'apps',
142
+ groupId: 'apps',
143
143
  size: 'lg',
144
144
  icon: 'menu-grid',
145
145
  title: 'Alle skjema',
146
146
  },
147
147
  {
148
148
  id: 'settings',
149
- group: 'settings',
149
+ groupId: 'settings',
150
150
  icon: 'cog',
151
151
  title: 'Innstillinger',
152
152
  },
@@ -184,14 +184,14 @@ export const DrilldownMenu: Story = {
184
184
  items: [
185
185
  {
186
186
  id: 'people',
187
- group: 'level-1',
187
+ groupId: 'level-1',
188
188
  size: 'lg',
189
189
  icon: 'menu-grid',
190
190
  title: 'Alle skjema',
191
191
  expanded: true,
192
192
  items: [
193
193
  {
194
- group: 'level-2',
194
+ groupId: 'level-2',
195
195
  name: 'tema',
196
196
  icon: 'teddy-bear',
197
197
  title: 'Tema',
@@ -199,16 +199,16 @@ export const DrilldownMenu: Story = {
199
199
  items: [
200
200
  {
201
201
  id: 'c1',
202
- group: 'level-3',
202
+ groupId: 'level-3',
203
203
  title: 'Kategori 1',
204
204
  },
205
205
  {
206
- group: 'level-3',
206
+ groupId: 'level-3',
207
207
  id: 'c2',
208
208
  title: 'Kategori 2',
209
209
  },
210
210
  {
211
- group: 'level-3',
211
+ groupId: 'level-3',
212
212
  id: 'c3',
213
213
  title: 'Kategori 3',
214
214
  },
@@ -226,7 +226,7 @@ export const InboxMenu: Story = {
226
226
  items: [
227
227
  {
228
228
  id: 'innboks',
229
- group: '1',
229
+ groupId: '1',
230
230
  size: 'lg',
231
231
  icon: 'inbox',
232
232
  title: 'Innboks',
@@ -235,7 +235,7 @@ export const InboxMenu: Story = {
235
235
  },
236
236
  {
237
237
  id: 'utkast',
238
- group: '2',
238
+ groupId: '2',
239
239
  icon: 'doc-pencil',
240
240
  title: 'Utkast',
241
241
  badge: {
@@ -244,7 +244,7 @@ export const InboxMenu: Story = {
244
244
  },
245
245
  {
246
246
  id: 'sendt',
247
- group: '2',
247
+ groupId: '2',
248
248
  icon: 'file-checkmark',
249
249
  selected: true,
250
250
  title: 'Sendt',
@@ -254,7 +254,7 @@ export const InboxMenu: Story = {
254
254
  },
255
255
  {
256
256
  id: 'lagret',
257
- group: '3',
257
+ groupId: '3',
258
258
  icon: 'bookmark',
259
259
  title: 'Lagrede søk',
260
260
  badge: {
@@ -263,7 +263,7 @@ export const InboxMenu: Story = {
263
263
  },
264
264
  {
265
265
  id: 'arkivert',
266
- group: '4',
266
+ groupId: '4',
267
267
  icon: 'archive',
268
268
  title: 'Arkivert',
269
269
  badge: {
@@ -272,7 +272,7 @@ export const InboxMenu: Story = {
272
272
  },
273
273
  {
274
274
  id: 'papirkurv',
275
- group: '4',
275
+ groupId: '4',
276
276
  disabled: true,
277
277
  icon: 'trash',
278
278
  title: 'Papirkurv',
@@ -299,13 +299,13 @@ export const InboxMenuWithShortcuts = {
299
299
  ...(InboxMenu?.args?.items ?? []),
300
300
  {
301
301
  id: 'users',
302
- group: 'shortcuts',
302
+ groupId: 'shortcuts',
303
303
  icon: 'person-group',
304
304
  title: 'Brukere',
305
305
  },
306
306
  {
307
307
  id: 'settings',
308
- group: 'shortcuts',
308
+ groupId: 'shortcuts',
309
309
  icon: 'cog',
310
310
  title: 'Innstillinger',
311
311
  },
@@ -319,7 +319,7 @@ export const PersonMenu: Story = {
319
319
  items: [
320
320
  {
321
321
  id: 'person',
322
- group: '1',
322
+ groupId: '1',
323
323
  size: 'lg',
324
324
  avatar: {
325
325
  type: 'person',
@@ -329,31 +329,31 @@ export const PersonMenu: Story = {
329
329
  },
330
330
  {
331
331
  id: 'profil',
332
- group: '2',
332
+ groupId: '2',
333
333
  icon: 'person-circle',
334
334
  title: 'Kontaktinformasjon',
335
335
  },
336
336
  {
337
337
  id: 'varslinger',
338
- group: '2',
338
+ groupId: '2',
339
339
  icon: 'bell',
340
340
  title: 'Varslingsinnstillinger',
341
341
  },
342
342
  {
343
343
  id: 'bookmarks',
344
- group: '3',
344
+ groupId: '3',
345
345
  icon: 'bookmark',
346
346
  title: 'Favoritter',
347
347
  },
348
348
  {
349
349
  id: 'grupper',
350
- group: '3',
350
+ groupId: '3',
351
351
  icon: 'hexagon-grid',
352
352
  title: 'Grupper',
353
353
  },
354
354
  {
355
355
  id: 'logg',
356
- group: '4',
356
+ groupId: '4',
357
357
  icon: 'clock-dashed',
358
358
  title: 'Aktivitetslogg',
359
359
  },
@@ -367,7 +367,7 @@ export const CompanyMenu: Story = {
367
367
  items: [
368
368
  {
369
369
  id: 'company',
370
- group: '1',
370
+ groupId: '1',
371
371
  size: 'lg',
372
372
  avatar: {
373
373
  type: 'company',
@@ -377,25 +377,25 @@ export const CompanyMenu: Story = {
377
377
  },
378
378
  {
379
379
  id: 'profil',
380
- group: '2',
380
+ groupId: '2',
381
381
  icon: 'buildings2',
382
382
  title: 'Firmaprofil',
383
383
  },
384
384
  {
385
385
  id: 'brukere',
386
- group: '3',
386
+ groupId: '3',
387
387
  icon: 'person-group',
388
388
  title: 'Brukere',
389
389
  },
390
390
  {
391
391
  id: 'grupper',
392
- group: '3',
392
+ groupId: '3',
393
393
  icon: 'hexagon-grid',
394
394
  title: 'Grupper',
395
395
  },
396
396
  {
397
397
  id: 'logg',
398
- group: '4',
398
+ groupId: '4',
399
399
  icon: 'clock-dashed',
400
400
  title: 'Aktivitetslogg',
401
401
  },
@@ -417,7 +417,7 @@ export const AccountMenu: Story = {
417
417
  items: [
418
418
  {
419
419
  id: '1',
420
- group: 'a1',
420
+ groupId: 'a1',
421
421
  avatar: {
422
422
  type: 'person',
423
423
  name: 'Dolly Duck',
@@ -429,7 +429,7 @@ export const AccountMenu: Story = {
429
429
  },
430
430
  {
431
431
  id: '2',
432
- group: 'a2',
432
+ groupId: 'a2',
433
433
  avatar: {
434
434
  type: 'company',
435
435
  name: 'Bergen Bar',
@@ -441,7 +441,7 @@ export const AccountMenu: Story = {
441
441
  },
442
442
  {
443
443
  id: '3',
444
- group: 'a2',
444
+ groupId: 'a2',
445
445
  avatar: {
446
446
  type: 'company',
447
447
  name: 'Sportsklubben Brann',
@@ -453,7 +453,7 @@ export const AccountMenu: Story = {
453
453
  },
454
454
  {
455
455
  id: '4',
456
- group: 'a3',
456
+ groupId: 'a3',
457
457
  avatarGroup: {
458
458
  type: 'company',
459
459
  items: [
@@ -472,7 +472,7 @@ export const AccountMenu: Story = {
472
472
  },
473
473
  {
474
474
  id: '5',
475
- group: 'b1',
475
+ groupId: 'b1',
476
476
  avatar: {
477
477
  type: 'company',
478
478
  name: 'Jensens Laks',
@@ -481,7 +481,7 @@ export const AccountMenu: Story = {
481
481
  },
482
482
  {
483
483
  id: '6',
484
- group: 'b1',
484
+ groupId: 'b1',
485
485
  avatar: {
486
486
  type: 'company',
487
487
  name: 'Haralds gym',
@@ -493,7 +493,7 @@ export const AccountMenu: Story = {
493
493
  },
494
494
  {
495
495
  id: '7',
496
- group: 'b1',
496
+ groupId: 'b1',
497
497
  avatar: {
498
498
  type: 'company',
499
499
  name: 'Trim og tran',
@@ -1,111 +1,12 @@
1
- import { MenuBase } from './MenuBase';
2
- import { MenuGroup } from './MenuGroup';
3
- import { MenuHeader } from './MenuHeader';
1
+ import { MenuBase, type MenuTheme } from './MenuBase';
2
+ import { MenuItems, type MenuItemsProps } from './MenuItems';
4
3
  import { MenuSearch, type MenuSearchProps } from './MenuSearch';
5
4
 
6
- import type { MenuItemColor, MenuItemSize } from './MenuItemBase';
7
-
8
- import { MenuItem, type MenuItemProps } from './MenuItem';
9
- import styles from './menu.module.css';
10
-
11
- export type MenuTheme = 'inherit' | 'global' | 'neutral' | 'company' | 'person';
12
-
13
- interface MenuItemsGroupProps {
14
- title?: string;
15
- divider?: boolean;
16
- defaultItemColor?: MenuItemColor;
17
- defaultItemSize?: MenuItemSize;
18
- }
19
-
20
- export type MenuGroups = Record<string, MenuItemsGroupProps>;
21
-
22
- export interface MenuProps {
23
- items: MenuItemProps[];
5
+ export interface MenuProps extends MenuItemsProps {
24
6
  theme?: MenuTheme;
25
- defaultItemColor?: MenuItemColor;
26
- defaultItemSize?: MenuItemSize;
27
- groups?: MenuGroups;
28
7
  search?: MenuSearchProps;
29
8
  }
30
9
 
31
- const groupMenuItems = (items: MenuItemProps[]) => {
32
- const groups: Record<string, MenuItemProps[]> = items?.reduce(
33
- (acc: Record<string, MenuItemProps[]>, item: MenuItemProps) => {
34
- const group = item?.group || '';
35
- if (!acc[group]) {
36
- acc[group] = [];
37
- }
38
- acc[group].push(item);
39
- return acc;
40
- },
41
- {} as Record<string, MenuItemProps[]>,
42
- );
43
-
44
- return groups;
45
- };
46
-
47
- export const MenuItems = ({
48
- defaultItemColor,
49
- defaultItemSize,
50
- groups = {},
51
- items = [],
52
- }: {
53
- defaultItemColor: MenuItemColor;
54
- defaultItemSize: MenuItemSize;
55
- groups?: MenuGroups;
56
- items: MenuItemProps[];
57
- }) => {
58
- const sections = groupMenuItems(items);
59
-
60
- return Object.entries(sections)?.map(([key, options]) => {
61
- const groupProps = groups?.[key];
62
- return (
63
- <MenuGroup as="ul" divider={groupProps?.divider} key={key}>
64
- {groupProps?.title && (
65
- <li className={styles.item}>
66
- <MenuHeader title={groupProps.title} />
67
- </li>
68
- )}
69
- {(options ?? [])
70
- .filter((option) => !option.hidden)
71
- .map((option, index) => {
72
- if (option.expanded && option.items) {
73
- return (
74
- <li className={styles.item} aria-expanded="true" key={'item' + index}>
75
- <MenuItem
76
- {...option}
77
- className={styles.menuItem}
78
- color={option?.color || groupProps?.defaultItemColor || defaultItemColor}
79
- size={option?.size || groupProps?.defaultItemSize || defaultItemSize}
80
- key={'menu-item' + index}
81
- />
82
- <MenuItems
83
- groups={groups}
84
- items={option?.items}
85
- defaultItemColor={defaultItemColor}
86
- defaultItemSize={defaultItemSize}
87
- />
88
- </li>
89
- );
90
- }
91
-
92
- return (
93
- <li className={styles.item} key={'item' + index}>
94
- <MenuItem
95
- {...option}
96
- className={styles.menuItem}
97
- color={option?.color || groupProps?.defaultItemColor || defaultItemColor}
98
- size={option?.size || groupProps?.defaultItemSize || defaultItemSize}
99
- key={'menu-item' + index}
100
- />
101
- </li>
102
- );
103
- })}
104
- </MenuGroup>
105
- );
106
- });
107
- };
108
-
109
10
  export const Menu = ({
110
11
  theme = 'inherit',
111
12
  defaultItemColor = 'subtle',
@@ -1,10 +1,30 @@
1
1
  import cx from 'classnames';
2
2
  import type { ElementType, ReactNode } from 'react';
3
- import styles from './menu.module.css';
3
+ import styles from './menuBase.module.css';
4
+
5
+ export type MenuTheme = 'inherit' | 'global' | 'neutral' | 'company' | 'person' | 'global-dark';
6
+ export type MenuListRole = 'presentation' | 'group';
7
+ export type MenuListItemRole = 'presentation' | 'group' | 'separator';
4
8
 
5
9
  export interface MenuBaseProps {
6
10
  as?: ElementType;
7
- theme?: string;
11
+ theme?: MenuTheme;
12
+ className?: string;
13
+ children?: ReactNode;
14
+ }
15
+
16
+ export interface MenuListProps {
17
+ as?: ElementType;
18
+ role?: MenuListRole;
19
+ expanded?: boolean;
20
+ className?: string;
21
+ children?: ReactNode;
22
+ }
23
+
24
+ export interface MenuListItemProps {
25
+ as?: ElementType;
26
+ role?: MenuListItemRole;
27
+ expanded?: boolean;
8
28
  className?: string;
9
29
  children?: ReactNode;
10
30
  }
@@ -12,7 +32,31 @@ export interface MenuBaseProps {
12
32
  export const MenuBase = ({ as = 'nav', theme, className, children }: MenuBaseProps) => {
13
33
  const Component = as;
14
34
  return (
15
- <Component className={cx(styles.menu, className)} data-theme={theme}>
35
+ <Component className={cx(styles.menu, className)} data-theme={theme} role="menu">
36
+ {children}
37
+ </Component>
38
+ );
39
+ };
40
+
41
+ export const MenuList = ({ as = 'ul', role = 'group', expanded, className, children }: MenuListProps) => {
42
+ const Component = as;
43
+ return (
44
+ <Component className={cx(styles.list, className)} role={role} aria-expanded={expanded}>
45
+ {children}
46
+ </Component>
47
+ );
48
+ };
49
+
50
+ export const MenuListItem = ({
51
+ as = 'li',
52
+ role = 'presentation',
53
+ expanded,
54
+ className,
55
+ children,
56
+ }: MenuListItemProps) => {
57
+ const Component = as;
58
+ return (
59
+ <Component className={cx(styles.item, className)} role={role} aria-expanded={expanded}>
16
60
  {children}
17
61
  </Component>
18
62
  );