@altinn/altinn-components 0.5.0 → 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.
Files changed (32) 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/lib/components/Button/ButtonLabel.tsx +4 -2
  6. package/lib/components/Dialog/Dialog.stories.ts +12 -5
  7. package/lib/components/Dropdown/DropdownBase.tsx +14 -2
  8. package/lib/components/Dropdown/dropdownBase.module.css +5 -1
  9. package/lib/components/GlobalMenu/AccountButton.tsx +30 -0
  10. package/lib/components/GlobalMenu/AccountMenu.stories.tsx +65 -0
  11. package/lib/components/GlobalMenu/AccountMenu.tsx +82 -0
  12. package/lib/components/GlobalMenu/BackButton.tsx +10 -0
  13. package/lib/components/GlobalMenu/GlobalMenu.stories.tsx +110 -119
  14. package/lib/components/GlobalMenu/GlobalMenu.tsx +50 -91
  15. package/lib/components/GlobalMenu/GlobalMenuBase.tsx +22 -0
  16. package/lib/components/GlobalMenu/LogoutButton.tsx +19 -0
  17. package/lib/components/GlobalMenu/globalMenuBase.module.css +39 -0
  18. package/lib/components/GlobalMenu/index.tsx +1 -1
  19. package/lib/components/GlobalMenu/logoutButton.module.css +9 -0
  20. package/lib/components/Header/Header.stories.tsx +24 -8
  21. package/lib/components/Header/Header.tsx +12 -10
  22. package/lib/components/Layout/Layout.stories.tsx +7 -2
  23. package/lib/components/Menu/MenuItem.tsx +2 -0
  24. package/lib/components/Menu/MenuItemBase.tsx +8 -2
  25. package/lib/components/Menu/menuItemBase.module.css +6 -1
  26. package/lib/components/Menu/menuItemLabel.module.css +11 -1
  27. package/lib/components/Menu/menuSearch.module.css +1 -0
  28. package/lib/stories/Inbox/InboxLayout.tsx +1 -0
  29. package/lib/stories/Inbox/InboxProvider.tsx +0 -1
  30. package/package.json +16 -14
  31. package/lib/components/Menu/__MenuGroup.tsx +0 -18
  32. package/lib/components/Menu/__menuItem.module.css +0 -130
@@ -1,122 +1,81 @@
1
1
  'use client';
2
2
  import { type MouseEventHandler, useState } from 'react';
3
- import type { AvatarType } from '../Avatar';
4
- import { Menu, MenuItem, type MenuItemGroups, type MenuItemProps, type MenuSearchProps } from '../Menu';
5
-
6
- export type Account = {
7
- type: AvatarType;
8
- name: string;
9
- selected?: boolean;
10
- group?: string;
11
- };
12
-
13
- export interface AccountSearch extends MenuSearchProps {
14
- getResultsLabel?: (hits: number) => string;
15
- hidden?: boolean;
16
- }
17
-
18
- export type MobileMenuType = 'dropdown' | 'drawer';
19
-
20
- export interface GlobalMenuProps {
21
- variant: MobileMenuType;
3
+ import { Menu, type MenuItemGroups, type MenuItemProps } from '../Menu';
4
+ import { type Account, 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 GlobalMenuProps extends AccountMenuProps {
22
11
  expanded: boolean;
23
12
  onToggle: MouseEventHandler;
24
13
  items: MenuItemProps[];
25
14
  groups?: MenuItemGroups;
26
- accounts?: Account[];
27
- accountGroups?: MenuItemGroups;
28
- accountSearch?: AccountSearch;
29
15
  menuLabel?: string;
30
16
  backLabel?: string;
17
+ changeLabel?: string;
18
+ logoutLabel?: string;
31
19
  className?: string;
20
+ currentAccount?: Account;
21
+ changeCurrentAccount?: (id: string) => void;
32
22
  }
33
23
 
34
- const defaultResultLabel = (hits: number) => `${hits} hits`;
35
-
36
24
  export const GlobalMenu = ({
37
25
  accounts = [],
38
26
  accountGroups = {},
39
27
  accountSearch,
40
28
  items = [],
41
29
  groups,
30
+ changeLabel = 'Change',
31
+ logoutLabel = 'Logout',
42
32
  backLabel = 'Back',
33
+ currentAccount,
34
+ changeCurrentAccount,
43
35
  }: 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
- const [selectAccount, setSelectAccount] = useState<boolean>(false);
57
- const [filterString, setFilterString] = useState<string>('');
36
+ const [selectingAccount, setSelectingAccount] = useState<boolean>(false);
58
37
 
59
38
  const onToggleAccounts = () => {
60
- setSelectAccount((prevState) => !prevState);
61
- };
62
-
63
- const accountMenuItem: MenuItemProps = {
64
- ...selectedAccount,
65
- id: 'account',
66
- selected: false,
67
- size: 'lg',
68
- onClick: onToggleAccounts,
39
+ setSelectingAccount((prevState) => !prevState);
69
40
  };
70
41
 
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
- groupId: '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),
42
+ const onSelectAccount = (id: string) => {
43
+ onToggleAccounts();
44
+ changeCurrentAccount?.(id);
99
45
  };
100
46
 
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', groupId: 'search', hidden: true }]),
110
- ];
47
+ if (selectingAccount) {
48
+ return (
49
+ <GlobalMenuBase>
50
+ <BackButton onClick={onToggleAccounts} label={backLabel} />
51
+ <AccountMenu
52
+ currentAccount={currentAccount}
53
+ accounts={accounts}
54
+ accountGroups={accountGroups}
55
+ accountSearch={accountSearch}
56
+ onSelectAccount={onSelectAccount}
57
+ />
58
+ </GlobalMenuBase>
59
+ );
60
+ }
111
61
 
112
- if (selectAccount) {
62
+ if (currentAccount) {
113
63
  return (
114
- <>
115
- <MenuItem {...backItem} />
116
- <Menu theme="global" search={accountSearchItem} groups={filterAccountGroups} items={accountSwitcher} />
117
- </>
64
+ <GlobalMenuBase>
65
+ <GlobalMenuHeader>
66
+ <AccountButton account={currentAccount} linkText={changeLabel} onClick={onToggleAccounts} />
67
+ </GlobalMenuHeader>
68
+ <Menu groups={groups} items={items} />
69
+ <GlobalMenuFooter>
70
+ <LogoutButton label={logoutLabel} />
71
+ </GlobalMenuFooter>
72
+ </GlobalMenuBase>
118
73
  );
119
74
  }
120
75
 
121
- return <Menu theme="global" groups={groups} items={MobileMenu} />;
76
+ return (
77
+ <GlobalMenuBase>
78
+ <Menu groups={groups} items={items} />
79
+ </GlobalMenuBase>
80
+ );
122
81
  };
@@ -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
+ }
@@ -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
- <DropdownBase placement="right" expanded={currentId === 'menu'} className={styles.dropdown}>
52
- <GlobalMenu {...menu} variant="dropdown" />
53
+ <DropdownBase padding={false} placement="right" expanded={currentId === 'menu'} className={styles.dropdown}>
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} variant="drawer" 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: {
@@ -31,6 +31,8 @@ export interface MenuItemProps {
31
31
  avatarGroup?: AvatarGroupProps;
32
32
  children?: ReactNode;
33
33
  items?: MenuItemProps[];
34
+ linkIcon?: IconName;
35
+ linkText?: string;
34
36
  className?: string;
35
37
  }
36
38
 
@@ -1,5 +1,5 @@
1
1
  import cx from 'classnames';
2
- import type { ElementType, ReactNode } from 'react';
2
+ import type { ElementType, MouseEventHandler, ReactNode } from 'react';
3
3
  import { Badge, type BadgeProps } from '../Badge';
4
4
  import { Icon, type IconName } from '../Icon';
5
5
  import styles from './menuItemBase.module.css';
@@ -9,11 +9,13 @@ export type MenuItemSize = 'sm' | 'md' | 'lg';
9
9
 
10
10
  export interface MenuItemBaseProps {
11
11
  as?: ElementType;
12
+ onClick?: MouseEventHandler;
12
13
  color?: MenuItemColor;
13
14
  children?: ReactNode;
14
15
  tabIndex?: number;
15
16
  size?: MenuItemSize;
16
17
  linkIcon?: IconName;
18
+ linkText?: string;
17
19
  badge?: BadgeProps;
18
20
  collapsible?: boolean;
19
21
  active?: boolean;
@@ -25,9 +27,11 @@ export interface MenuItemBaseProps {
25
27
 
26
28
  export const MenuItemBase = ({
27
29
  as,
30
+ onClick,
28
31
  size,
29
32
  color,
30
33
  linkIcon,
34
+ linkText,
31
35
  badge,
32
36
  tabIndex = 0,
33
37
  active = false,
@@ -54,6 +58,7 @@ export const MenuItemBase = ({
54
58
  aria-expanded={expanded}
55
59
  aria-disabled={disabled}
56
60
  aria-selected={selected}
61
+ onClick={onClick}
57
62
  className={cx(styles.item, className)}
58
63
  {...rest}
59
64
  >
@@ -63,7 +68,8 @@ export const MenuItemBase = ({
63
68
  </div>
64
69
  {applicableIcon && (
65
70
  <div className={styles.action}>
66
- {applicableIcon && <Icon name={applicableIcon} className={styles.actionIcon} />}
71
+ <span className={styles.linkText}>{linkText}</span>
72
+ {applicableIcon && <Icon name={applicableIcon} className={styles.linkIcon} />}
67
73
  </div>
68
74
  )}
69
75
  </Component>
@@ -36,7 +36,12 @@
36
36
  padding: 10px;
37
37
  }
38
38
 
39
- .actionIcon {
39
+ .linkText {
40
+ font-size: 0.875rem;
41
+ white-space: nowrap;
42
+ }
43
+
44
+ .linkIcon {
40
45
  font-size: 1.5rem;
41
46
  }
42
47
 
@@ -4,12 +4,22 @@
4
4
  padding: 0 0.25rem;
5
5
  }
6
6
 
7
+ .title {
8
+ color: var(--theme-text-default);
9
+ }
10
+
7
11
  .title[data-size="lg"] {
8
12
  font-size: 1.125rem;
9
13
  line-height: 1.25;
10
14
  font-weight: 500;
11
15
  }
12
16
 
17
+ .title[data-size="md"] {
18
+ font-size: 1rem;
19
+ line-height: 1.25;
20
+ font-weight: 500;
21
+ }
22
+
13
23
  .title[data-size="sm"] {
14
24
  font-size: 1rem;
15
25
  line-height: 1.25;
@@ -17,6 +27,6 @@
17
27
  }
18
28
 
19
29
  .description {
20
- font-size: 14px;
30
+ font-size: 0.875rem;
21
31
  color: var(--theme-text-subtle);
22
32
  }
@@ -1,5 +1,6 @@
1
1
  .input {
2
2
  width: 100%;
3
+ height: 2.75rem;
3
4
  font-size: 0.875rem;
4
5
  line-height: 1rem;
5
6
  font-weight: normal;
@@ -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.0",
3
+ "version": "0.5.2",
4
4
  "main": "lib/index.ts",
5
5
  "description": "Reusable react components",
6
6
  "publishConfig": {
@@ -15,24 +15,26 @@
15
15
  "react": "^18.3.1"
16
16
  },
17
17
  "devDependencies": {
18
- "@biomejs/biome": "1.9.3",
19
- "@chromatic-com/storybook": "^1.9.0",
20
- "@storybook/addon-essentials": "^8.3.5",
21
- "@storybook/addon-interactions": "^8.3.5",
22
- "@storybook/addon-links": "^8.3.5",
23
- "@storybook/addon-onboarding": "^8.3.5",
24
- "@storybook/addon-themes": "^8.3.5",
25
- "@storybook/blocks": "^8.3.5",
26
- "@storybook/react": "^8.3.5",
27
- "@storybook/react-vite": "^8.3.5",
28
- "@storybook/test": "^8.3.5",
18
+ "@biomejs/biome": "1.9.4",
19
+ "@chromatic-com/storybook": "^3.2.2",
20
+ "@storybook/addon-a11y": "^8.4.4",
21
+ "@storybook/addon-essentials": "^8.4.4",
22
+ "@storybook/addon-interactions": "^8.4.4",
23
+ "@storybook/addon-links": "^8.4.4",
24
+ "@storybook/addon-onboarding": "^8.4.4",
25
+ "@storybook/addon-themes": "^8.4.4",
26
+ "@storybook/blocks": "^8.4.4",
27
+ "@storybook/react": "^8.4.4",
28
+ "@storybook/react-vite": "^8.4.4",
29
+ "@storybook/test": "^8.4.4",
29
30
  "@types/react": "^18.3.11",
30
31
  "@types/react-dom": "^18.3.1",
31
32
  "@vitejs/plugin-react-swc": "^3.7.1",
33
+ "axe-core": "^4.10.2",
32
34
  "lint-staged": "^15.2.10",
33
35
  "prop-types": "^15.8.1",
34
- "storybook": "^8.3.5",
35
- "storybook-addon-theme-provider": "^0.2.6",
36
+ "storybook": "^8.4.4",
37
+ "storybook-addon-theme-provider": "^0.2.8",
36
38
  "typescript": "^5.6.3",
37
39
  "vite": "^5.4.9"
38
40
  },
@@ -1,18 +0,0 @@
1
- import type { ElementType, ReactNode } from 'react';
2
- import styles from './menu.module.css';
3
-
4
- export interface MenuGroupProps {
5
- as?: ElementType;
6
- expanded?: boolean;
7
- divider?: boolean;
8
- children?: ReactNode;
9
- }
10
-
11
- export const MenuGroup = ({ as = 'div', expanded, divider = true, children }: MenuGroupProps) => {
12
- const Component = as;
13
- return (
14
- <Component aria-expanded={expanded} data-divider={divider} className={styles.group}>
15
- {children}
16
- </Component>
17
- );
18
- };