@altinn/altinn-components 0.4.1 → 0.5.1

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/StoryDecorator.tsx +1 -1
  2. package/.storybook/main.ts +3 -4
  3. package/.storybook/preview.tsx +28 -0
  4. package/CHANGELOG.md +14 -0
  5. package/biome.jsonc +1 -1
  6. package/lib/components/Attachment/AttachmentLink.stories.ts +1 -1
  7. package/lib/components/Attachment/AttachmentList.stories.ts +1 -1
  8. package/lib/components/Button/Button.tsx +13 -10
  9. package/lib/components/Button/ButtonBase.tsx +1 -1
  10. package/lib/components/Button/ButtonIcon.tsx +16 -0
  11. package/lib/components/Button/ButtonLabel.tsx +18 -0
  12. package/lib/components/Button/Buttons.stories.tsx +64 -0
  13. package/lib/components/Button/ComboButton.tsx +9 -7
  14. package/lib/components/Button/IconButton.stories.tsx +47 -0
  15. package/lib/components/Button/IconButton.tsx +15 -5
  16. package/lib/components/Button/button.module.css +5 -46
  17. package/lib/components/Button/buttonBase.module.css +55 -23
  18. package/lib/components/Button/buttonIcon.module.css +17 -0
  19. package/lib/components/Button/buttonLabel.module.css +17 -0
  20. package/lib/components/Button/comboButton.module.css +15 -65
  21. package/lib/components/Button/iconButton.module.css +21 -4
  22. package/lib/components/Button/index.ts +2 -0
  23. package/lib/components/ContextMenu/ContextMenu.stories.ts +49 -0
  24. package/lib/components/ContextMenu/ContextMenu.tsx +12 -20
  25. package/lib/components/ContextMenu/ContextMenuBase.tsx +33 -0
  26. package/lib/components/Dialog/Dialog.stories.ts +12 -5
  27. package/lib/components/Dialog/Dialog.tsx +2 -0
  28. package/lib/components/Dialog/DialogGroup.tsx +24 -0
  29. package/lib/components/Dialog/DialogList.stories.ts +14 -10
  30. package/lib/components/Dialog/DialogList.tsx +26 -11
  31. package/lib/components/Dialog/DialogListItem.tsx +12 -2
  32. package/lib/components/Dialog/DialogListItemBase.tsx +4 -2
  33. package/lib/components/Dialog/DialogNav.stories.ts +5 -5
  34. package/lib/components/Dialog/DialogNav.tsx +2 -6
  35. package/lib/components/Dialog/DialogSelect.tsx +1 -1
  36. package/lib/components/Dialog/dialogGroup.module.css +35 -0
  37. package/lib/components/Dropdown/Backdrop.tsx +4 -3
  38. package/lib/components/Dropdown/DrawerBase.tsx +5 -2
  39. package/lib/components/Dropdown/DrawerBody.tsx +12 -0
  40. package/lib/components/Dropdown/DrawerButton.tsx +17 -0
  41. package/lib/components/Dropdown/DrawerFooter.tsx +12 -0
  42. package/lib/components/Dropdown/DrawerHeader.tsx +19 -0
  43. package/lib/components/Dropdown/DrawerOrDropdown.tsx +29 -0
  44. package/lib/components/Dropdown/DropdownBase.tsx +17 -2
  45. package/lib/components/Dropdown/backdrop.module.css +3 -0
  46. package/lib/components/Dropdown/drawerBase.module.css +9 -0
  47. package/lib/components/Dropdown/drawerBody.module.css +5 -0
  48. package/lib/components/Dropdown/drawerButton.module.css +6 -0
  49. package/lib/components/Dropdown/drawerFooter.module.css +13 -0
  50. package/lib/components/Dropdown/drawerHeader.module.css +17 -0
  51. package/lib/components/Dropdown/drawerOrDropdown.module.css +19 -0
  52. package/lib/components/Dropdown/dropdownBase.module.css +20 -4
  53. package/lib/components/Dropdown/index.ts +7 -1
  54. package/lib/components/Footer/footerMenu.module.css +5 -0
  55. package/lib/components/GlobalMenu/AccountButton.tsx +29 -0
  56. package/lib/components/GlobalMenu/AccountMenu.stories.tsx +65 -0
  57. package/lib/components/GlobalMenu/AccountMenu.tsx +73 -0
  58. package/lib/components/GlobalMenu/BackButton.tsx +10 -0
  59. package/lib/components/GlobalMenu/GlobalMenu.stories.tsx +112 -121
  60. package/lib/components/GlobalMenu/GlobalMenu.tsx +41 -89
  61. package/lib/components/GlobalMenu/GlobalMenuBase.tsx +22 -0
  62. package/lib/components/GlobalMenu/LogoutButton.tsx +19 -0
  63. package/lib/components/GlobalMenu/globalMenuBase.module.css +39 -0
  64. package/lib/components/GlobalMenu/index.tsx +1 -1
  65. package/lib/components/GlobalMenu/logoutButton.module.css +9 -0
  66. package/lib/components/Header/{Header.stories.ts → Header.stories.tsx} +79 -20
  67. package/lib/components/Header/Header.tsx +25 -38
  68. package/lib/components/Header/HeaderBase.tsx +7 -3
  69. package/lib/components/Header/header.module.css +10 -42
  70. package/lib/components/Header/headerBase.module.css +43 -0
  71. package/lib/components/Header/headerButton.module.css +1 -0
  72. package/lib/components/Layout/Layout.stories.tsx +77 -38
  73. package/lib/components/Layout/Layout.tsx +5 -3
  74. package/lib/components/Layout/LayoutBase.tsx +3 -2
  75. package/lib/components/Layout/layoutBase.module.css +11 -0
  76. package/lib/components/Layout/layoutBody.module.css +1 -0
  77. package/lib/components/LayoutAction/ActionHeader.tsx +1 -1
  78. package/lib/components/LayoutAction/ActionMenu.tsx +2 -4
  79. package/lib/components/LayoutAction/actionMenu.module.css +3 -0
  80. package/lib/components/List/List.stories.tsx +43 -0
  81. package/lib/components/List/List.tsx +6 -6
  82. package/lib/components/List/ListBase.tsx +6 -6
  83. package/lib/components/List/ListItem.tsx +4 -1
  84. package/lib/components/List/ListItemBase.tsx +20 -4
  85. package/lib/components/List/listBase.module.css +3 -3
  86. package/lib/components/List/listItemBase.module.css +4 -0
  87. package/lib/components/Menu/Menu.stories.ts +46 -46
  88. package/lib/components/Menu/Menu.tsx +3 -102
  89. package/lib/components/Menu/MenuBase.tsx +47 -3
  90. package/lib/components/Menu/MenuItem.tsx +8 -4
  91. package/lib/components/Menu/MenuItemBase.tsx +15 -2
  92. package/lib/components/Menu/MenuItems.stories.ts +438 -0
  93. package/lib/components/Menu/MenuItems.tsx +96 -0
  94. package/lib/components/Menu/MenuOption.tsx +4 -1
  95. package/lib/components/Menu/index.ts +1 -1
  96. package/lib/components/Menu/menu.module.css +2 -3
  97. package/lib/components/Menu/menuBase.module.css +25 -0
  98. package/lib/components/Menu/menuItemBase.module.css +11 -5
  99. package/lib/components/Menu/menuItemLabel.module.css +11 -1
  100. package/lib/components/Menu/menuSearch.module.css +1 -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/hooks/index.ts +3 -0
  152. package/lib/{components/Menu → hooks}/useEscapeKey.ts +2 -2
  153. package/lib/hooks/useMenu.tsx +80 -0
  154. package/lib/index.ts +1 -0
  155. package/lib/stories/Color/MenuItem.stories.tsx +43 -0
  156. package/lib/stories/Color/Swatches.stories.tsx +19 -0
  157. package/lib/stories/Color/Swatches.tsx +42 -0
  158. package/lib/stories/Color/colors.json +62 -0
  159. package/lib/stories/Color/swatches.module.css +14 -0
  160. package/lib/stories/Inbox/BookmarksPage.tsx +52 -0
  161. package/lib/stories/Inbox/DialogPage.tsx +15 -0
  162. package/lib/stories/Inbox/Inbox.stories.tsx +55 -0
  163. package/lib/stories/Inbox/Inbox.tsx +12 -0
  164. package/lib/stories/Inbox/InboxLayout.tsx +50 -0
  165. package/lib/stories/Inbox/InboxPage.tsx +50 -0
  166. package/lib/stories/Inbox/InboxProvider.tsx +136 -0
  167. package/lib/stories/Inbox/InboxSection.tsx +39 -0
  168. package/lib/stories/Inbox/InboxToolbar.tsx +94 -0
  169. package/lib/stories/Inbox/ProfilePage.tsx +35 -0
  170. package/lib/stories/Inbox/SettingsPage.tsx +19 -0
  171. package/lib/stories/Inbox/accounts/accounts.ts +24 -0
  172. package/lib/stories/Inbox/accounts/index.ts +1 -0
  173. package/lib/stories/Inbox/actionMenu.ts +24 -0
  174. package/lib/stories/Inbox/dialogs/brreg-completed.json +35 -0
  175. package/lib/stories/Inbox/dialogs/brreg-draft.json +45 -0
  176. package/lib/stories/Inbox/dialogs/index.ts +10 -0
  177. package/lib/stories/Inbox/dialogs/skatt-2023.json +33 -0
  178. package/lib/stories/Inbox/groupBy.ts +19 -0
  179. package/lib/stories/Inbox/inboxSection.module.css +19 -0
  180. package/lib/stories/Inbox/index.ts +15 -0
  181. package/lib/stories/Inbox/layout/footer.ts +27 -0
  182. package/lib/stories/Inbox/layout/header.ts +11 -0
  183. package/lib/stories/Inbox/layout/index.ts +3 -0
  184. package/lib/stories/Inbox/layout/menu.ts +64 -0
  185. package/package.json +15 -13
  186. package/tsconfig.json +7 -2
  187. package/lib/components/Header/HeaderSearch.stories.ts +0 -20
  188. package/lib/components/Header/HeaderSearch.tsx +0 -44
  189. package/lib/components/Header/headerSearch.module.css +0 -30
  190. package/lib/components/Menu/MenuGroup.tsx +0 -18
  191. package/lib/components/Menu/__menuItem.module.css +0 -130
  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
@@ -3,11 +3,62 @@ import { useState } from 'react';
3
3
  import { GlobalMenu } from './GlobalMenu';
4
4
 
5
5
  const meta = {
6
- title: 'Header/GlobalMenu',
6
+ title: 'GlobalMenu/GlobalMenu',
7
7
  component: GlobalMenu,
8
8
  tags: ['autodocs'],
9
9
  parameters: {},
10
10
  args: {
11
+ accountGroups: {
12
+ primary: {
13
+ title: 'Deg selv og favoritter',
14
+ },
15
+ secondary: {
16
+ title: 'Andre kontoer',
17
+ },
18
+ },
19
+ currentAccount: {
20
+ type: 'person',
21
+ name: 'Mathias Dyngeland',
22
+ description: 'Fødselsnr. 07101995 XXXXXX',
23
+ },
24
+ accounts: [
25
+ {
26
+ groupId: 'primary',
27
+ type: 'person',
28
+ name: 'Mathias Dyngeland',
29
+ selected: true,
30
+ },
31
+ {
32
+ groupId: 'favourites',
33
+ type: 'company',
34
+ name: 'Bergen bar',
35
+ selected: false,
36
+ },
37
+ {
38
+ groupId: 'secondary',
39
+ type: 'company',
40
+ name: 'Keeperhansker AS',
41
+ selected: false,
42
+ },
43
+ {
44
+ groupId: 'secondary',
45
+ type: 'company',
46
+ name: 'Stadion drift AS',
47
+ selected: false,
48
+ },
49
+ {
50
+ groupId: 'favourites',
51
+ type: 'company',
52
+ name: 'Sportsklubben Brann',
53
+ selected: false,
54
+ },
55
+ {
56
+ groupId: 'secondary',
57
+ type: 'company',
58
+ name: 'Landslaget',
59
+ selected: false,
60
+ },
61
+ ],
11
62
  groups: {
12
63
  apps: {
13
64
  divider: true,
@@ -16,17 +67,48 @@ const meta = {
16
67
  items: [
17
68
  {
18
69
  id: 'inbox',
19
- group: 'apps',
70
+ groupId: 'apps',
20
71
  size: 'lg',
21
72
  icon: 'inbox',
22
- label: 'Innboks',
73
+ title: 'Innboks',
74
+ badge: {
75
+ color: 'alert',
76
+ label: '4',
77
+ },
78
+ },
79
+ {
80
+ id: 'access',
81
+ groupId: 'apps',
82
+ size: 'lg',
83
+ icon: 'bookmark',
84
+ title: 'Tilganger',
85
+ badge: {
86
+ color: 'alert',
87
+ label: '2',
88
+ },
23
89
  },
24
90
  {
25
- id: 'settings',
26
- group: 'apps',
91
+ id: 'access',
92
+ groupId: 'apps',
27
93
  size: 'lg',
28
- icon: 'cog',
29
- label: 'Settings',
94
+ icon: 'menu-grid',
95
+ title: 'Alle skjema',
96
+ },
97
+ {
98
+ id: 'startup',
99
+ groupId: 'help',
100
+ color: 'neutral',
101
+ size: 'sm',
102
+ icon: 'buildings2',
103
+ title: 'Starte og drive bedrift',
104
+ },
105
+ {
106
+ id: 'help',
107
+ groupId: 'help',
108
+ size: 'sm',
109
+ color: 'neutral',
110
+ icon: 'chat-exclamationmark',
111
+ title: 'Trenger du hjelp?',
30
112
  },
31
113
  ],
32
114
  },
@@ -39,43 +121,31 @@ export const Default: Story = {};
39
121
 
40
122
  export const Login: Story = {
41
123
  args: {
42
- expanded: true,
124
+ currentAccount: undefined,
43
125
  items: [
44
126
  {
45
127
  id: 'login',
128
+ groupId: 'login',
46
129
  size: 'lg',
130
+ color: 'strong',
47
131
  icon: 'padlock-locked',
48
132
  title: 'Logg inn',
49
133
  },
50
134
  {
51
- id: 'help',
52
- size: 'lg',
53
- icon: 'chat-exclamationmark',
54
- title: 'Hjelp',
135
+ id: 'startup',
136
+ groupId: 'help',
137
+ color: 'neutral',
138
+ size: 'sm',
139
+ icon: 'buildings2',
140
+ title: 'Starte og drive bedrift',
55
141
  },
56
- ],
57
- },
58
- };
59
-
60
- export const ControlledStateLogin = () => {
61
- const [expanded, setExpanded] = useState<boolean>(false);
62
- return (
63
- <GlobalMenu
64
- {...Login.args}
65
- expanded={expanded}
66
- onToggle={() => setExpanded((prevState) => !prevState)}
67
- items={Login.args.items ?? []}
68
- />
69
- );
70
- };
71
-
72
- export const Person: Story = {
73
- args: {
74
- accounts: [
75
142
  {
76
- type: 'person',
77
- name: 'Aurora Mikalsen',
78
- selected: true,
143
+ id: 'help',
144
+ groupId: 'help',
145
+ color: 'neutral',
146
+ size: 'sm',
147
+ icon: 'chat-exclamationmark',
148
+ title: 'Trenger du hjelp?',
79
149
  },
80
150
  ],
81
151
  },
@@ -83,46 +153,20 @@ export const Person: Story = {
83
153
 
84
154
  export const Company: Story = {
85
155
  args: {
86
- accounts: [
87
- {
88
- type: 'company',
89
- name: 'Bergen bar',
90
- selected: true,
91
- },
92
- ],
93
- },
94
- };
95
-
96
- export const Expanded: Story = {
97
- args: {
98
- expanded: true,
99
- accounts: [
100
- {
101
- type: 'company',
102
- name: 'Bergen bar',
103
- selected: true,
104
- },
105
- ],
106
- },
107
- };
108
-
109
- export const CustomLabel: Story = {
110
- args: {
111
- menuLabel: 'Meny',
112
- accounts: [
113
- {
114
- type: 'person',
115
- name: 'Aurora Mikalsen',
116
- selected: true,
117
- },
118
- ],
156
+ currentAccount: {
157
+ type: 'company',
158
+ name: 'Sportsklubben Brann',
159
+ description: 'Org. nr. 934908988',
160
+ },
119
161
  },
120
162
  };
121
163
 
122
- export const Accounts: Story = {
164
+ export const CustomLabels: Story = {
123
165
  args: {
166
+ logoutLabel: 'Logg ut',
124
167
  menuLabel: 'Meny',
125
168
  backLabel: 'Tilbake',
169
+ changeLabel: 'Endre konto',
126
170
  accountSearch: {
127
171
  placeholder: 'Søk etter konto',
128
172
  getResultsLabel: (hits = 0) => {
@@ -133,58 +177,5 @@ export const Accounts: Story = {
133
177
  },
134
178
  hidden: false,
135
179
  },
136
- expanded: true,
137
- accountGroups: {
138
- primary: {
139
- title: 'Deg selv og favoritter',
140
- },
141
- secondary: {
142
- title: 'Andre kontoer',
143
- },
144
- },
145
- accounts: [
146
- {
147
- group: 'primary',
148
- type: 'person',
149
- name: 'Aurora Mikalsen',
150
- selected: true,
151
- },
152
- {
153
- group: 'favourites',
154
- type: 'person',
155
- name: 'Rakel Engelsvik',
156
- selected: false,
157
- },
158
- {
159
- group: 'favourites',
160
- type: 'company',
161
- name: 'Auroras keeperskole',
162
- selected: false,
163
- },
164
- {
165
- group: 'secondary',
166
- type: 'company',
167
- name: 'Keeperhansker AS',
168
- selected: false,
169
- },
170
- {
171
- group: 'secondary',
172
- type: 'company',
173
- name: 'Stadion drift AS',
174
- selected: false,
175
- },
176
- {
177
- group: 'secondary',
178
- type: 'company',
179
- name: 'Sportsklubben Brann',
180
- selected: false,
181
- },
182
- {
183
- group: 'secondary',
184
- type: 'company',
185
- name: 'Landslaget',
186
- selected: false,
187
- },
188
- ],
189
180
  },
190
181
  };
@@ -1,122 +1,74 @@
1
1
  'use client';
2
2
  import { type MouseEventHandler, useState } from 'react';
3
- import type { AvatarType } from '../Avatar';
4
- import { Menu, type MenuGroups, MenuItem, type MenuItemProps, type MenuSearchProps } from '../Menu';
5
-
6
- export type Account = {
7
- type: AvatarType;
3
+ import { Menu, type MenuItemGroups, type MenuItemProps } from '../Menu';
4
+ import { AccountButton } from './AccountButton';
5
+ import { AccountMenu, type AccountMenuProps } from './AccountMenu';
6
+ import { BackButton } from './BackButton';
7
+ import { GlobalMenuBase, GlobalMenuFooter, GlobalMenuHeader } from './GlobalMenuBase';
8
+ import { LogoutButton } from './LogoutButton';
9
+
10
+ export interface CurrentAccount {
11
+ type: 'person' | 'company';
8
12
  name: string;
9
- selected?: boolean;
10
- group?: string;
11
- };
12
-
13
- export interface AccountSearch extends MenuSearchProps {
14
- getResultsLabel?: (hits: number) => string;
15
- hidden?: boolean;
13
+ description?: string;
16
14
  }
17
15
 
18
- export type MobileMenuType = 'dropdown' | 'drawer';
19
-
20
- export interface GlobalMenuProps {
21
- variant: MobileMenuType;
16
+ export interface GlobalMenuProps extends AccountMenuProps {
17
+ currentEndUser?: CurrentAccount;
22
18
  expanded: boolean;
23
19
  onToggle: MouseEventHandler;
24
20
  items: MenuItemProps[];
25
- groups?: MenuGroups;
26
- accounts?: Account[];
27
- accountGroups?: MenuGroups;
28
- accountSearch?: AccountSearch;
21
+ groups?: MenuItemGroups;
29
22
  menuLabel?: string;
30
23
  backLabel?: string;
24
+ changeLabel?: string;
25
+ logoutLabel?: string;
31
26
  className?: string;
32
27
  }
33
28
 
34
- const defaultResultLabel = (hits: number) => `${hits} hits`;
35
-
36
29
  export const GlobalMenu = ({
30
+ currentEndUser,
37
31
  accounts = [],
38
32
  accountGroups = {},
39
33
  accountSearch,
40
34
  items = [],
41
35
  groups,
36
+ changeLabel = 'Change',
37
+ logoutLabel = 'Logout',
42
38
  backLabel = 'Back',
43
39
  }: GlobalMenuProps) => {
44
- const accountMenu: MenuItemProps[] = accounts.map((account) => ({
45
- id: account.name,
46
- group: account.group || 'search',
47
- selected: account.selected,
48
- title: account.name,
49
- avatar: {
50
- type: account.type,
51
- name: account.name,
52
- },
53
- }));
54
-
55
- const selectedAccount = accountMenu.find((account) => account.selected);
56
40
  const [selectAccount, setSelectAccount] = useState<boolean>(false);
57
- const [filterString, setFilterString] = useState<string>('');
58
41
 
59
42
  const onToggleAccounts = () => {
60
43
  setSelectAccount((prevState) => !prevState);
61
44
  };
62
45
 
63
- const accountMenuItem: MenuItemProps = {
64
- ...selectedAccount,
65
- id: 'account',
66
- selected: false,
67
- size: 'lg',
68
- onClick: onToggleAccounts,
69
- };
70
-
71
- const MobileMenu = selectedAccount ? [accountMenuItem, ...items] : items;
72
-
73
- const filteredAccountMenu = filterString
74
- ? accountMenu
75
- .filter((item) => item?.title?.toLowerCase().includes(filterString.toLowerCase()))
76
- .map((item) => {
77
- return {
78
- ...item,
79
- group: 'search',
80
- };
81
- })
82
- : accountMenu;
83
-
84
- const filterAccountGroups = filterString
85
- ? {
86
- search: {
87
- title:
88
- accountSearch?.getResultsLabel?.(filteredAccountMenu.length) ??
89
- defaultResultLabel(filteredAccountMenu.length),
90
- },
91
- }
92
- : accountGroups;
93
-
94
- const accountSearchItem: MenuSearchProps = {
95
- name: 'account-search',
96
- value: filterString,
97
- placeholder: accountSearch?.placeholder ?? 'Find account',
98
- onChange: (event: React.ChangeEvent<HTMLInputElement>) => setFilterString(event.target.value),
99
- };
100
-
101
- const backItem: MenuItemProps = {
102
- id: 'back',
103
- title: backLabel ?? 'Back',
104
- icon: 'arrow-left',
105
- onClick: onToggleAccounts,
106
- };
107
-
108
- const accountSwitcher: MenuItemProps[] = [
109
- ...(filteredAccountMenu.length > 0 ? filteredAccountMenu : [{ id: 'search', group: 'search', hidden: true }]),
110
- ];
111
-
112
46
  if (selectAccount) {
113
47
  return (
114
- <>
115
- <MenuItem {...backItem} />
116
- <Menu theme="global" search={accountSearchItem} groups={filterAccountGroups} items={accountSwitcher} />
117
- </>
48
+ <GlobalMenuBase>
49
+ <BackButton onClick={onToggleAccounts} label={backLabel} />
50
+ <AccountMenu accounts={accounts} accountGroups={accountGroups} accountSearch={accountSearch} />
51
+ </GlobalMenuBase>
52
+ );
53
+ }
54
+
55
+ if (currentEndUser) {
56
+ return (
57
+ <GlobalMenuBase>
58
+ <GlobalMenuHeader>
59
+ <AccountButton account={currentEndUser} linkText={changeLabel} onClick={onToggleAccounts} />
60
+ </GlobalMenuHeader>
61
+ <Menu groups={groups} items={items} />
62
+ <GlobalMenuFooter>
63
+ <LogoutButton label={logoutLabel} />
64
+ </GlobalMenuFooter>
65
+ </GlobalMenuBase>
118
66
  );
119
67
  }
120
68
 
121
- return <Menu theme="global" groups={groups} items={MobileMenu} />;
69
+ return (
70
+ <GlobalMenuBase>
71
+ <Menu groups={groups} items={items} />
72
+ </GlobalMenuBase>
73
+ );
122
74
  };
@@ -0,0 +1,22 @@
1
+ import type { ReactNode } from 'react';
2
+ import styles from './globalMenuBase.module.css';
3
+
4
+ export interface GlobalMenuBaseProps {
5
+ children: ReactNode;
6
+ }
7
+
8
+ export const GlobalMenuBase = ({ children }: GlobalMenuBaseProps) => {
9
+ return (
10
+ <nav className={styles.nav} data-theme="global">
11
+ {children}
12
+ </nav>
13
+ );
14
+ };
15
+
16
+ export const GlobalMenuHeader = ({ children }: GlobalMenuBaseProps) => {
17
+ return <header className={styles.header}>{children}</header>;
18
+ };
19
+
20
+ export const GlobalMenuFooter = ({ children }: GlobalMenuBaseProps) => {
21
+ return <footer className={styles.footer}>{children}</footer>;
22
+ };
@@ -0,0 +1,19 @@
1
+ import type { MouseEventHandler, ReactNode } from 'react';
2
+ import { ButtonBase, ButtonLabel } from '../Button';
3
+ import styles from './logoutButton.module.css';
4
+
5
+ export interface LogoutButtonProps {
6
+ label?: string;
7
+ children?: ReactNode;
8
+ onClick?: MouseEventHandler;
9
+ }
10
+
11
+ export const LogoutButton = ({ label = 'Logout', children, onClick }: LogoutButtonProps) => {
12
+ return (
13
+ <ButtonBase className={styles.button} variant="outline" size="lg" onClick={onClick}>
14
+ <ButtonLabel className={styles.label} size="lg">
15
+ {children || label}
16
+ </ButtonLabel>
17
+ </ButtonBase>
18
+ );
19
+ };
@@ -0,0 +1,39 @@
1
+ .nav {
2
+ background-color: #fff;
3
+ display: flex;
4
+ flex-direction: column;
5
+ padding: 0 0.5rem;
6
+ }
7
+
8
+ .header {
9
+ border-bottom: 1px solid var(--theme-border-subtle);
10
+ }
11
+
12
+ .footer {
13
+ border-top: 1px solid var(--theme-border-subtle);
14
+ padding: 1rem 0.5rem;
15
+ display: flex;
16
+ flex-direction: column;
17
+ align-items: stretch;
18
+ }
19
+
20
+ .drawer[aria-expanded="true"] {
21
+ display: block;
22
+ padding: 0.5rem;
23
+ z-index: 2;
24
+ }
25
+
26
+ .dropdown[aria-expanded="true"] {
27
+ display: none;
28
+ }
29
+
30
+ @media (min-width: 1024px) {
31
+ .drawer[aria-expanded="true"] {
32
+ display: none;
33
+ }
34
+
35
+ .dropdown[aria-expanded="true"] {
36
+ display: block;
37
+ z-index: 2;
38
+ }
39
+ }
@@ -1 +1 @@
1
- export * from './GlobalMenu.tsx';
1
+ export * from './GlobalMenu';
@@ -0,0 +1,9 @@
1
+ .button {
2
+ justify-content: center;
3
+ }
4
+
5
+ .label {
6
+ display: block;
7
+ width: 100%;
8
+ text-align: center;
9
+ }
@@ -1,11 +1,14 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react';
2
+ import { useState } from 'react';
2
3
  import { Header } from './Header';
3
4
 
4
5
  const meta = {
5
6
  title: 'Header/Header',
6
7
  component: Header,
7
8
  tags: ['autodocs'],
8
- parameters: {},
9
+ parameters: {
10
+ layout: 'fullscreen',
11
+ },
9
12
  args: {
10
13
  expanded: true,
11
14
  search: {
@@ -22,43 +25,43 @@ const meta = {
22
25
  },
23
26
  accounts: [
24
27
  {
25
- group: 'primary',
28
+ groupId: 'primary',
26
29
  type: 'person',
27
30
  name: 'Aurora Mikalsen',
28
31
  selected: true,
29
32
  },
30
33
  {
31
- group: 'favourites',
34
+ groupId: 'favourites',
32
35
  type: 'person',
33
36
  name: 'Rakel Engelsvik',
34
37
  selected: false,
35
38
  },
36
39
  {
37
- group: 'favourites',
40
+ groupId: 'favourites',
38
41
  type: 'company',
39
42
  name: 'Auroras keeperskole',
40
43
  selected: false,
41
44
  },
42
45
  {
43
- group: 'secondary',
46
+ groupId: 'secondary',
44
47
  type: 'company',
45
48
  name: 'Keeperhansker AS',
46
49
  selected: false,
47
50
  },
48
51
  {
49
- group: 'secondary',
52
+ groupId: 'secondary',
50
53
  type: 'company',
51
54
  name: 'Stadion drift AS',
52
55
  selected: false,
53
56
  },
54
57
  {
55
- group: 'secondary',
58
+ groupId: 'secondary',
56
59
  type: 'company',
57
60
  name: 'Sportsklubben Brann',
58
61
  selected: false,
59
62
  },
60
63
  {
61
- group: 'secondary',
64
+ groupId: 'secondary',
62
65
  type: 'company',
63
66
  name: 'Landslaget',
64
67
  selected: false,
@@ -93,21 +96,77 @@ type Story = StoryObj<typeof meta>;
93
96
 
94
97
  export const Default: Story = {};
95
98
 
96
- export const Company: Story = {
97
- args: {
98
- menu: {
99
- ...meta.args?.menu,
100
- accounts: [
99
+ export const ControlledState = (args) => {
100
+ const [q, setQ] = useState<string>('');
101
+ const onChange = (event) => {
102
+ setQ(event.target.value);
103
+ };
104
+
105
+ const scopes = [
106
+ {
107
+ groupId: '1',
108
+ id: 'inbox',
109
+ href: '#',
110
+ label: q
111
+ ? () => {
112
+ return (
113
+ <span>
114
+ <mark>{q}</mark> i innboksen
115
+ </span>
116
+ );
117
+ }
118
+ : 'Alt i innboksen',
119
+ },
120
+ {
121
+ groupId: '1',
122
+ id: 'global',
123
+ href: '#',
124
+ label: q
125
+ ? () => {
126
+ return (
127
+ <span>
128
+ <mark>{q}</mark> i hele Altinn
129
+ </span>
130
+ );
131
+ }
132
+ : 'Alt i hele Altinn',
133
+ },
134
+ ];
135
+
136
+ const suggestions = q
137
+ ? [
101
138
  {
102
- type: 'company',
103
- name: 'Bergen bar',
104
- selected: true,
139
+ groupId: '2',
140
+ href: 'http://www.altinn.no',
141
+ label: 'Skattemelding 2024',
105
142
  },
106
143
  {
107
- type: 'person',
108
- name: 'Aurora Mikalsen',
144
+ groupId: '2',
145
+ href: 'http://www.altinn.no',
146
+ label: 'Skattemelding 2025',
109
147
  },
110
- ],
148
+ ].filter((item) => item.label.toLowerCase().includes((q ?? '').toLowerCase()))
149
+ : [];
150
+
151
+ const autocomplete = {
152
+ groups: {
153
+ 2: {
154
+ title: `${suggestions.length} treff i innboksen`,
155
+ },
111
156
  },
112
- },
157
+ items: [...scopes, ...suggestions],
158
+ };
159
+
160
+ return (
161
+ <Header
162
+ {...args}
163
+ search={{
164
+ ...args.search,
165
+ value: q,
166
+ onChange,
167
+ onClear: () => setQ(''),
168
+ autocomplete,
169
+ }}
170
+ />
171
+ );
113
172
  };