@altinn/altinn-components 0.5.1 → 0.5.2

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.5.2](https://github.com/Altinn/altinn-components/compare/v0.5.1...v0.5.2) (2024-11-18)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * fixing selecting current account and simplify API for Header ([#58](https://github.com/Altinn/altinn-components/issues/58)) ([b39a14a](https://github.com/Altinn/altinn-components/commit/b39a14a14014ff78209d636f3edc93507b443fd2))
9
+
3
10
  ## [0.5.1](https://github.com/Altinn/altinn-components/compare/v0.5.0...v0.5.1) (2024-11-16)
4
11
 
5
12
 
@@ -1,6 +1,7 @@
1
1
  import { MenuItemBase, MenuItemLabel, MenuItemMedia } from '../Menu';
2
2
 
3
- type Account = {
3
+ export type Account = {
4
+ id: string;
4
5
  type: 'person' | 'company';
5
6
  name: string;
6
7
  description?: string;
@@ -10,7 +10,7 @@ export interface AccountSearch extends MenuSearchProps {
10
10
  export interface AccountMenuItem {
11
11
  type: 'person' | 'company';
12
12
  name: string;
13
- id?: string;
13
+ id: string;
14
14
  groupId?: string;
15
15
  selected?: boolean;
16
16
  }
@@ -19,20 +19,29 @@ export interface AccountMenuProps {
19
19
  accounts?: AccountMenuItem[];
20
20
  accountGroups?: MenuItemGroups;
21
21
  accountSearch?: AccountSearch;
22
+ currentAccount?: AccountMenuItem;
23
+ onSelectAccount?: (id: string) => void;
22
24
  }
23
25
 
24
26
  const defaultResultLabel = (hits: number) => `${hits} hits`;
25
27
 
26
- export const AccountMenu = ({ accounts = [], accountGroups = {}, accountSearch }: AccountMenuProps) => {
28
+ export const AccountMenu = ({
29
+ accounts = [],
30
+ accountGroups = {},
31
+ accountSearch,
32
+ onSelectAccount,
33
+ currentAccount,
34
+ }: AccountMenuProps) => {
27
35
  const accountMenu: MenuItemProps[] = accounts.map((account) => ({
28
- id: account.name,
36
+ id: account.id || account.name,
29
37
  groupId: account.groupId || 'search',
30
- selected: account.selected,
38
+ selected: account.selected ?? currentAccount?.id === account.id,
31
39
  title: account.name,
32
40
  avatar: {
33
41
  type: account.type,
34
42
  name: account.name,
35
43
  },
44
+ onClick: () => onSelectAccount?.(account.id || account.name),
36
45
  }));
37
46
 
38
47
  const [filterString, setFilterString] = useState<string>('');
@@ -23,40 +23,40 @@ const meta = {
23
23
  },
24
24
  accounts: [
25
25
  {
26
+ id: 'party:mathias',
26
27
  groupId: 'primary',
27
28
  type: 'person',
28
29
  name: 'Mathias Dyngeland',
29
- selected: true,
30
30
  },
31
31
  {
32
+ id: 'party:bergerbar',
32
33
  groupId: 'favourites',
33
34
  type: 'company',
34
35
  name: 'Bergen bar',
35
- selected: false,
36
36
  },
37
37
  {
38
+ id: 'party:keeperhansker',
38
39
  groupId: 'secondary',
39
40
  type: 'company',
40
41
  name: 'Keeperhansker AS',
41
- selected: false,
42
42
  },
43
43
  {
44
+ id: 'party:stadiondrift',
44
45
  groupId: 'secondary',
45
46
  type: 'company',
46
47
  name: 'Stadion drift AS',
47
- selected: false,
48
48
  },
49
49
  {
50
+ id: 'party:brann',
50
51
  groupId: 'favourites',
51
52
  type: 'company',
52
53
  name: 'Sportsklubben Brann',
53
- selected: false,
54
54
  },
55
55
  {
56
+ id: 'party:landslaget',
56
57
  groupId: 'secondary',
57
58
  type: 'company',
58
59
  name: 'Landslaget',
59
- selected: false,
60
60
  },
61
61
  ],
62
62
  groups: {
@@ -1,20 +1,13 @@
1
1
  'use client';
2
2
  import { type MouseEventHandler, useState } from 'react';
3
3
  import { Menu, type MenuItemGroups, type MenuItemProps } from '../Menu';
4
- import { AccountButton } from './AccountButton';
4
+ import { type Account, AccountButton } from './AccountButton';
5
5
  import { AccountMenu, type AccountMenuProps } from './AccountMenu';
6
6
  import { BackButton } from './BackButton';
7
7
  import { GlobalMenuBase, GlobalMenuFooter, GlobalMenuHeader } from './GlobalMenuBase';
8
8
  import { LogoutButton } from './LogoutButton';
9
9
 
10
- export interface CurrentAccount {
11
- type: 'person' | 'company';
12
- name: string;
13
- description?: string;
14
- }
15
-
16
10
  export interface GlobalMenuProps extends AccountMenuProps {
17
- currentEndUser?: CurrentAccount;
18
11
  expanded: boolean;
19
12
  onToggle: MouseEventHandler;
20
13
  items: MenuItemProps[];
@@ -24,10 +17,11 @@ export interface GlobalMenuProps extends AccountMenuProps {
24
17
  changeLabel?: string;
25
18
  logoutLabel?: string;
26
19
  className?: string;
20
+ currentAccount?: Account;
21
+ changeCurrentAccount?: (id: string) => void;
27
22
  }
28
23
 
29
24
  export const GlobalMenu = ({
30
- currentEndUser,
31
25
  accounts = [],
32
26
  accountGroups = {},
33
27
  accountSearch,
@@ -36,27 +30,40 @@ export const GlobalMenu = ({
36
30
  changeLabel = 'Change',
37
31
  logoutLabel = 'Logout',
38
32
  backLabel = 'Back',
33
+ currentAccount,
34
+ changeCurrentAccount,
39
35
  }: GlobalMenuProps) => {
40
- const [selectAccount, setSelectAccount] = useState<boolean>(false);
36
+ const [selectingAccount, setSelectingAccount] = useState<boolean>(false);
41
37
 
42
38
  const onToggleAccounts = () => {
43
- setSelectAccount((prevState) => !prevState);
39
+ setSelectingAccount((prevState) => !prevState);
40
+ };
41
+
42
+ const onSelectAccount = (id: string) => {
43
+ onToggleAccounts();
44
+ changeCurrentAccount?.(id);
44
45
  };
45
46
 
46
- if (selectAccount) {
47
+ if (selectingAccount) {
47
48
  return (
48
49
  <GlobalMenuBase>
49
50
  <BackButton onClick={onToggleAccounts} label={backLabel} />
50
- <AccountMenu accounts={accounts} accountGroups={accountGroups} accountSearch={accountSearch} />
51
+ <AccountMenu
52
+ currentAccount={currentAccount}
53
+ accounts={accounts}
54
+ accountGroups={accountGroups}
55
+ accountSearch={accountSearch}
56
+ onSelectAccount={onSelectAccount}
57
+ />
51
58
  </GlobalMenuBase>
52
59
  );
53
60
  }
54
61
 
55
- if (currentEndUser) {
62
+ if (currentAccount) {
56
63
  return (
57
64
  <GlobalMenuBase>
58
65
  <GlobalMenuHeader>
59
- <AccountButton account={currentEndUser} linkText={changeLabel} onClick={onToggleAccounts} />
66
+ <AccountButton account={currentAccount} linkText={changeLabel} onClick={onToggleAccounts} />
60
67
  </GlobalMenuHeader>
61
68
  <Menu groups={groups} items={items} />
62
69
  <GlobalMenuFooter>
@@ -25,46 +25,46 @@ const meta = {
25
25
  },
26
26
  accounts: [
27
27
  {
28
+ id: 'party:aurora',
28
29
  groupId: 'primary',
29
30
  type: 'person',
30
31
  name: 'Aurora Mikalsen',
31
- selected: true,
32
32
  },
33
33
  {
34
+ id: 'party:rakel',
34
35
  groupId: 'favourites',
35
36
  type: 'person',
36
37
  name: 'Rakel Engelsvik',
37
- selected: false,
38
38
  },
39
39
  {
40
+ id: 'party:auroraskeeperskole',
40
41
  groupId: 'favourites',
41
42
  type: 'company',
42
43
  name: 'Auroras keeperskole',
43
- selected: false,
44
44
  },
45
45
  {
46
+ id: 'party:aurorashandsker',
46
47
  groupId: 'secondary',
47
48
  type: 'company',
48
49
  name: 'Keeperhansker AS',
49
- selected: false,
50
50
  },
51
51
  {
52
+ id: 'party:aurorasfotballskole',
52
53
  groupId: 'secondary',
53
54
  type: 'company',
54
55
  name: 'Stadion drift AS',
55
- selected: false,
56
56
  },
57
57
  {
58
+ id: 'party:aurorasfotballskole',
58
59
  groupId: 'secondary',
59
60
  type: 'company',
60
61
  name: 'Sportsklubben Brann',
61
- selected: false,
62
62
  },
63
63
  {
64
+ id: 'party:aurorasfotballskole',
64
65
  groupId: 'secondary',
65
66
  type: 'company',
66
67
  name: 'Landslaget',
67
- selected: false,
68
68
  },
69
69
  ],
70
70
  items: [
@@ -94,10 +94,20 @@ const meta = {
94
94
  export default meta;
95
95
  type Story = StoryObj<typeof meta>;
96
96
 
97
- export const Default: Story = {};
97
+ export const Default: Story = {
98
+ args: {
99
+ currentAccount: {
100
+ id: 'party:aurora',
101
+ type: 'person',
102
+ name: 'Aurora Mikalsen',
103
+ },
104
+ },
105
+ };
98
106
 
99
107
  export const ControlledState = (args) => {
100
108
  const [q, setQ] = useState<string>('');
109
+ const currentEndUserId = 'party:aurora';
110
+ const [selectedAccountId, setSelectedAccountId] = useState<string>(currentEndUserId);
101
111
  const onChange = (event) => {
102
112
  setQ(event.target.value);
103
113
  };
@@ -160,6 +170,12 @@ export const ControlledState = (args) => {
160
170
  return (
161
171
  <Header
162
172
  {...args}
173
+ currentAccount={args.menu.accounts.find((account) => account.id === selectedAccountId)}
174
+ menu={{
175
+ ...args.menu,
176
+ ...args.menu.accounts,
177
+ changeCurrentAccount: setSelectedAccountId,
178
+ }}
163
179
  search={{
164
180
  ...args.search,
165
181
  value: q,
@@ -2,6 +2,7 @@
2
2
  import { useEscapeKey } from '../../hooks';
3
3
  import { DrawerBase, DropdownBase } from '../Dropdown';
4
4
  import { GlobalMenu, type GlobalMenuProps } from '../GlobalMenu';
5
+ import type { Account } from '../GlobalMenu/AccountButton.tsx';
5
6
  import { useRootContext } from '../RootProvider';
6
7
  import { Searchbar, type SearchbarProps } from '../Searchbar';
7
8
  import { HeaderBase } from './HeaderBase';
@@ -13,15 +14,11 @@ import styles from './header.module.css';
13
14
  export interface HeaderProps {
14
15
  menu: GlobalMenuProps;
15
16
  search?: SearchbarProps;
17
+ currentAccount?: Account;
16
18
  }
17
19
 
18
- export const Header = ({ search, menu }: HeaderProps) => {
20
+ export const Header = ({ search, menu, currentAccount }: HeaderProps) => {
19
21
  const { currentId, toggleId, openId, closeAll } = useRootContext();
20
- const selectedAccount = menu.accounts?.find((account) => account.selected);
21
- const selectedAvatar = selectedAccount && {
22
- type: selectedAccount.type,
23
- name: selectedAccount.name,
24
- };
25
22
 
26
23
  useEscapeKey(closeAll);
27
24
 
@@ -42,14 +39,19 @@ export const Header = ({ search, menu }: HeaderProps) => {
42
39
  <HeaderLogo className={styles.logo} />
43
40
  <HeaderMenu className={styles.menu}>
44
41
  <HeaderButton
45
- avatar={selectedAvatar}
42
+ avatar={
43
+ currentAccount && {
44
+ type: currentAccount.type,
45
+ name: currentAccount.name,
46
+ }
47
+ }
46
48
  onClick={onToggleMenu}
47
49
  expanded={currentId === 'menu'}
48
50
  label={menu?.menuLabel}
49
51
  />
50
52
  {menu && (
51
53
  <DropdownBase padding={false} placement="right" expanded={currentId === 'menu'} className={styles.dropdown}>
52
- <GlobalMenu {...menu} currentEndUser={selectedAccount} />
54
+ <GlobalMenu {...menu} currentAccount={currentAccount} />
53
55
  </DropdownBase>
54
56
  )}
55
57
  </HeaderMenu>
@@ -64,7 +66,7 @@ export const Header = ({ search, menu }: HeaderProps) => {
64
66
  )}
65
67
  {menu && (
66
68
  <DrawerBase expanded={currentId === 'menu'} className={styles.drawer}>
67
- <GlobalMenu {...menu} currentEndUser={selectedAccount} expanded={currentId === 'menu'} />
69
+ <GlobalMenu {...menu} expanded={currentId === 'menu'} currentAccount={currentAccount} />
68
70
  </DrawerBase>
69
71
  )}
70
72
  </HeaderBase>
@@ -9,12 +9,17 @@ const header: HeaderProps = {
9
9
  name: 'search',
10
10
  placeholder: 'Søk i Altinn',
11
11
  },
12
+ currentAccount: {
13
+ id: 'party:aurora',
14
+ type: 'person',
15
+ name: 'Aurora Mikalsen',
16
+ },
12
17
  menu: {
13
18
  accounts: [
14
19
  {
20
+ id: 'party:aurora',
15
21
  type: 'person',
16
22
  name: 'Aurora Mikalsen',
17
- selected: true,
18
23
  },
19
24
  ],
20
25
  },
@@ -197,7 +202,7 @@ export const ControlledStateSearch = (args) => {
197
202
  };
198
203
 
199
204
  export const InboxBulkMode = (args) => {
200
- const [snackbars, setSnacbars] = useState([]);
205
+ const [snackbars, setSnackbars] = useState([]);
201
206
 
202
207
  const [itemsById, setItemsById] = useState({
203
208
  1: {
@@ -19,6 +19,7 @@ export const InboxLayout = ({ children }: InboxLayoutProps) => {
19
19
  footer={footer}
20
20
  header={{
21
21
  ...header,
22
+ currentAccount: accounts?.[0],
22
23
  menu: {
23
24
  accounts,
24
25
  },
@@ -5,7 +5,6 @@ interface AccountProps {
5
5
  id?: string;
6
6
  type?: string;
7
7
  name?: string;
8
- selected?: boolean;
9
8
  }
10
9
 
11
10
  export interface InboxDefaultValue {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@altinn/altinn-components",
3
- "version": "0.5.1",
3
+ "version": "0.5.2",
4
4
  "main": "lib/index.ts",
5
5
  "description": "Reusable react components",
6
6
  "publishConfig": {
@@ -15,7 +15,7 @@
15
15
  "react": "^18.3.1"
16
16
  },
17
17
  "devDependencies": {
18
- "@biomejs/biome": "1.9.3",
18
+ "@biomejs/biome": "1.9.4",
19
19
  "@chromatic-com/storybook": "^3.2.2",
20
20
  "@storybook/addon-a11y": "^8.4.4",
21
21
  "@storybook/addon-essentials": "^8.4.4",