@arbor-education/design-system.components 0.4.0 → 0.4.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 (134) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/CLAUDE.md +9 -0
  3. package/dist/components/avatar/Avatar.d.ts +11 -0
  4. package/dist/components/avatar/Avatar.d.ts.map +1 -0
  5. package/dist/components/avatar/Avatar.js +17 -0
  6. package/dist/components/avatar/Avatar.js.map +1 -0
  7. package/dist/components/avatar/Avatar.stories.d.ts +14 -0
  8. package/dist/components/avatar/Avatar.stories.d.ts.map +1 -0
  9. package/dist/components/avatar/Avatar.stories.js +66 -0
  10. package/dist/components/avatar/Avatar.stories.js.map +1 -0
  11. package/dist/components/avatar/Avatar.test.d.ts +2 -0
  12. package/dist/components/avatar/Avatar.test.d.ts.map +1 -0
  13. package/dist/components/avatar/Avatar.test.js +51 -0
  14. package/dist/components/avatar/Avatar.test.js.map +1 -0
  15. package/dist/components/dropdown/Dropdown.d.ts +2 -0
  16. package/dist/components/dropdown/Dropdown.d.ts.map +1 -1
  17. package/dist/components/dropdown/Dropdown.js +5 -1
  18. package/dist/components/dropdown/Dropdown.js.map +1 -1
  19. package/dist/components/dropdown/items/DropdownGroup.d.ts +3 -0
  20. package/dist/components/dropdown/items/DropdownGroup.d.ts.map +1 -0
  21. package/dist/components/dropdown/items/DropdownGroup.js +8 -0
  22. package/dist/components/dropdown/items/DropdownGroup.js.map +1 -0
  23. package/dist/components/dropdown/items/DropdownSeparator.d.ts +3 -0
  24. package/dist/components/dropdown/items/DropdownSeparator.d.ts.map +1 -0
  25. package/dist/components/dropdown/items/DropdownSeparator.js +8 -0
  26. package/dist/components/dropdown/items/DropdownSeparator.js.map +1 -0
  27. package/dist/components/formField/inputs/selectDropdown/SelectDropdown.d.ts +2 -0
  28. package/dist/components/formField/inputs/selectDropdown/SelectDropdown.d.ts.map +1 -1
  29. package/dist/components/formField/inputs/selectDropdown/SelectDropdown.js +2 -2
  30. package/dist/components/formField/inputs/selectDropdown/SelectDropdown.js.map +1 -1
  31. package/dist/components/formField/inputs/selectDropdown/SelectDropdown.stories.d.ts +12 -0
  32. package/dist/components/formField/inputs/selectDropdown/SelectDropdown.stories.d.ts.map +1 -1
  33. package/dist/components/formField/inputs/selectDropdown/SelectDropdown.stories.js +13 -0
  34. package/dist/components/formField/inputs/selectDropdown/SelectDropdown.stories.js.map +1 -1
  35. package/dist/components/table/Table.d.ts.map +1 -1
  36. package/dist/components/table/Table.js +0 -2
  37. package/dist/components/table/Table.js.map +1 -1
  38. package/dist/components/table/Table.stories.d.ts.map +1 -1
  39. package/dist/components/table/Table.stories.js +2 -10
  40. package/dist/components/table/Table.stories.js.map +1 -1
  41. package/dist/components/table/Table.test.js +2 -40
  42. package/dist/components/table/Table.test.js.map +1 -1
  43. package/dist/components/table/cellRenderers/SelectDropdownCellRenderer.d.ts.map +1 -1
  44. package/dist/components/table/cellRenderers/SelectDropdownCellRenderer.js +22 -12
  45. package/dist/components/table/cellRenderers/SelectDropdownCellRenderer.js.map +1 -1
  46. package/dist/components/userDropdown/UserDropdown.d.ts +47 -0
  47. package/dist/components/userDropdown/UserDropdown.d.ts.map +1 -0
  48. package/dist/components/userDropdown/UserDropdown.js +13 -0
  49. package/dist/components/userDropdown/UserDropdown.js.map +1 -0
  50. package/dist/components/userDropdown/UserDropdown.stories.d.ts +12 -0
  51. package/dist/components/userDropdown/UserDropdown.stories.d.ts.map +1 -0
  52. package/dist/components/userDropdown/UserDropdown.stories.js +222 -0
  53. package/dist/components/userDropdown/UserDropdown.stories.js.map +1 -0
  54. package/dist/components/userDropdown/UserDropdown.test.d.ts +2 -0
  55. package/dist/components/userDropdown/UserDropdown.test.d.ts.map +1 -0
  56. package/dist/components/userDropdown/UserDropdown.test.js +197 -0
  57. package/dist/components/userDropdown/UserDropdown.test.js.map +1 -0
  58. package/dist/components/userDropdown/assets/arbor.png +0 -0
  59. package/dist/components/userDropdown/assets/govhub.png +0 -0
  60. package/dist/components/userDropdown/assets/key.png +0 -0
  61. package/dist/components/userDropdown/assets/logos.d.ts +7 -0
  62. package/dist/components/userDropdown/assets/logos.d.ts.map +1 -0
  63. package/dist/components/userDropdown/assets/logos.js +13 -0
  64. package/dist/components/userDropdown/assets/logos.js.map +1 -0
  65. package/dist/components/userDropdown/assets/robin.png +0 -0
  66. package/dist/components/userDropdown/assets/sampeople.png +0 -0
  67. package/dist/components/userDropdown/assets/timetabler.png +0 -0
  68. package/dist/components/userDropdown/internal/UserDropdownAppItem.d.ts +3 -0
  69. package/dist/components/userDropdown/internal/UserDropdownAppItem.d.ts.map +1 -0
  70. package/dist/components/userDropdown/internal/UserDropdownAppItem.js +9 -0
  71. package/dist/components/userDropdown/internal/UserDropdownAppItem.js.map +1 -0
  72. package/dist/components/userDropdown/internal/UserDropdownCollapsibleSection.d.ts +9 -0
  73. package/dist/components/userDropdown/internal/UserDropdownCollapsibleSection.d.ts.map +1 -0
  74. package/dist/components/userDropdown/internal/UserDropdownCollapsibleSection.js +11 -0
  75. package/dist/components/userDropdown/internal/UserDropdownCollapsibleSection.js.map +1 -0
  76. package/dist/components/userDropdown/internal/UserDropdownSignOut.d.ts +7 -0
  77. package/dist/components/userDropdown/internal/UserDropdownSignOut.d.ts.map +1 -0
  78. package/dist/components/userDropdown/internal/UserDropdownSignOut.js +9 -0
  79. package/dist/components/userDropdown/internal/UserDropdownSignOut.js.map +1 -0
  80. package/dist/components/userDropdown/internal/UserDropdownTrigger.d.ts +11 -0
  81. package/dist/components/userDropdown/internal/UserDropdownTrigger.d.ts.map +1 -0
  82. package/dist/components/userDropdown/internal/UserDropdownTrigger.js +10 -0
  83. package/dist/components/userDropdown/internal/UserDropdownTrigger.js.map +1 -0
  84. package/dist/components/userDropdown/internal/UserDropdownUserInfo.d.ts +8 -0
  85. package/dist/components/userDropdown/internal/UserDropdownUserInfo.d.ts.map +1 -0
  86. package/dist/components/userDropdown/internal/UserDropdownUserInfo.js +17 -0
  87. package/dist/components/userDropdown/internal/UserDropdownUserInfo.js.map +1 -0
  88. package/dist/index.css +401 -1
  89. package/dist/index.css.map +1 -1
  90. package/dist/index.d.ts +4 -0
  91. package/dist/index.d.ts.map +1 -1
  92. package/dist/index.js +3 -0
  93. package/dist/index.js.map +1 -1
  94. package/package.json +2 -2
  95. package/src/components/avatar/Avatar.stories.tsx +84 -0
  96. package/src/components/avatar/Avatar.test.tsx +60 -0
  97. package/src/components/avatar/Avatar.tsx +68 -0
  98. package/src/components/avatar/avatar.scss +71 -0
  99. package/src/components/dropdown/Dropdown.tsx +5 -1
  100. package/src/components/dropdown/dropdown.scss +4 -1
  101. package/src/components/dropdown/items/DropdownGroup.tsx +11 -0
  102. package/src/components/dropdown/items/DropdownSeparator.tsx +9 -0
  103. package/src/components/formField/inputs/selectDropdown/SelectDropdown.stories.tsx +15 -0
  104. package/src/components/formField/inputs/selectDropdown/SelectDropdown.tsx +5 -1
  105. package/src/components/table/Table.stories.tsx +2 -10
  106. package/src/components/table/Table.test.tsx +2 -49
  107. package/src/components/table/Table.tsx +0 -2
  108. package/src/components/table/cellRenderers/SelectDropdownCellRenderer.tsx +34 -19
  109. package/src/components/table/table.scss +4 -2
  110. package/src/components/userDropdown/UserDropdown.stories.tsx +237 -0
  111. package/src/components/userDropdown/UserDropdown.test.tsx +349 -0
  112. package/src/components/userDropdown/UserDropdown.tsx +110 -0
  113. package/src/components/userDropdown/assets/arbor.png +0 -0
  114. package/src/components/userDropdown/assets/govhub.png +0 -0
  115. package/src/components/userDropdown/assets/key.png +0 -0
  116. package/src/components/userDropdown/assets/logos.ts +13 -0
  117. package/src/components/userDropdown/assets/robin.png +0 -0
  118. package/src/components/userDropdown/assets/sampeople.png +0 -0
  119. package/src/components/userDropdown/assets/timetabler.png +0 -0
  120. package/src/components/userDropdown/internal/UserDropdownAppItem.tsx +21 -0
  121. package/src/components/userDropdown/internal/UserDropdownCollapsibleSection.tsx +38 -0
  122. package/src/components/userDropdown/internal/UserDropdownSignOut.tsx +19 -0
  123. package/src/components/userDropdown/internal/UserDropdownTrigger.tsx +42 -0
  124. package/src/components/userDropdown/internal/UserDropdownUserInfo.tsx +60 -0
  125. package/src/components/userDropdown/userDropdown.scss +377 -0
  126. package/src/index.scss +2 -0
  127. package/src/index.ts +4 -0
  128. package/tsconfig.json +1 -1
  129. package/vite-env.d.ts +31 -0
  130. package/dist/components/table/cellRenderers/SelectDropdownCellEditor.d.ts +0 -8
  131. package/dist/components/table/cellRenderers/SelectDropdownCellEditor.d.ts.map +0 -1
  132. package/dist/components/table/cellRenderers/SelectDropdownCellEditor.js +0 -19
  133. package/dist/components/table/cellRenderers/SelectDropdownCellEditor.js.map +0 -1
  134. package/src/components/table/cellRenderers/SelectDropdownCellEditor.tsx +0 -43
@@ -0,0 +1,13 @@
1
+ import arborPng from './arbor.png';
2
+ import govhubPng from './govhub.png';
3
+ import keyPng from './key.png';
4
+ import robinPng from './robin.png';
5
+ import sampeoplePng from './sampeople.png';
6
+ import timetablerPng from './timetabler.png';
7
+
8
+ export const ArborLogo = arborPng;
9
+ export const GovhubLogo = govhubPng;
10
+ export const KeyLogo = keyPng;
11
+ export const RobinLogo = robinPng;
12
+ export const SampeopleLogo = sampeoplePng;
13
+ export const TimetablerLogo = timetablerPng;
@@ -0,0 +1,21 @@
1
+ import React from 'react';
2
+ import { Dropdown } from 'Components/dropdown/Dropdown';
3
+ import { Icon } from 'Components/icon/Icon';
4
+ import type { UserDropdownApp } from '../UserDropdown';
5
+
6
+ export const UserDropdownAppItem = (props: UserDropdownApp) => {
7
+ const { logo, name, description, onClick } = props;
8
+
9
+ return (
10
+ <Dropdown.Item className="ds-user-dropdown__app-item" onClick={onClick}>
11
+ {logo && <div className="ds-user-dropdown__app-item-logo">{logo}</div>}
12
+ <div className="ds-user-dropdown__app-item-text">
13
+ <div className="ds-user-dropdown__app-item-name">{name}</div>
14
+ {description && <div className="ds-user-dropdown__app-item-description">{description}</div>}
15
+ </div>
16
+ <div className="ds-user-dropdown__app-item-arrow" aria-hidden="true">
17
+ <Icon name="arrow-up-right" size={16} />
18
+ </div>
19
+ </Dropdown.Item>
20
+ );
21
+ };
@@ -0,0 +1,38 @@
1
+ import React, { useState } from 'react';
2
+ import { Icon } from 'Components/icon/Icon';
3
+ import { Dropdown } from 'Components/dropdown/Dropdown';
4
+ import type { UserDropdownApp } from '../UserDropdown';
5
+ import { UserDropdownAppItem } from './UserDropdownAppItem';
6
+
7
+ type UserDropdownCollapsibleSectionProps = {
8
+ label: string;
9
+ apps: UserDropdownApp[];
10
+ defaultOpen?: boolean;
11
+ };
12
+
13
+ export const UserDropdownCollapsibleSection = (props: UserDropdownCollapsibleSectionProps) => {
14
+ const { label, apps, defaultOpen = false } = props;
15
+ const [isOpen, setIsOpen] = useState(defaultOpen);
16
+
17
+ return (
18
+ <div className="ds-user-dropdown__collapsible-section">
19
+ <div
20
+ className="ds-user-dropdown__collapsible-section-header"
21
+ onClick={() => { setIsOpen(!isOpen); }}
22
+ role="button"
23
+ tabIndex={0}
24
+ aria-expanded={isOpen}
25
+ >
26
+ <span className="ds-user-dropdown__collapsible-section-label">{label}</span>
27
+ <Icon name={isOpen ? 'chevron-up' : 'chevron-down'} size={16} className="ds-user-dropdown__collapsible-section-icon" />
28
+ </div>
29
+ {isOpen && (
30
+ <Dropdown.Group className="ds-user-dropdown__collapsible-section-content">
31
+ {apps.map((app, index) => (
32
+ <UserDropdownAppItem key={index} {...app} />
33
+ ))}
34
+ </Dropdown.Group>
35
+ )}
36
+ </div>
37
+ );
38
+ };
@@ -0,0 +1,19 @@
1
+ import React from 'react';
2
+ import { Icon } from 'Components/icon/Icon';
3
+ import { Dropdown } from 'Components/dropdown/Dropdown';
4
+
5
+ type UserDropdownSignOutProps = {
6
+ onClick: () => void;
7
+ label?: string;
8
+ };
9
+
10
+ export const UserDropdownSignOut = (props: UserDropdownSignOutProps) => {
11
+ const { onClick, label = 'Sign out' } = props;
12
+
13
+ return (
14
+ <Dropdown.Item className="ds-user-dropdown__sign-out" onClick={onClick}>
15
+ <Icon name="log-out" size={24} />
16
+ <span className="ds-user-dropdown__sign-out-label">{label}</span>
17
+ </Dropdown.Item>
18
+ );
19
+ };
@@ -0,0 +1,42 @@
1
+ import React from 'react';
2
+ import { Dropdown } from 'Components/dropdown/Dropdown';
3
+ import { Avatar } from 'Components/avatar/Avatar';
4
+ import { Button } from 'Components/button/Button';
5
+
6
+ type UserDropdownTriggerProps = {
7
+ avatarSrc?: string;
8
+ avatarAlt?: string;
9
+ avatarInitials?: string;
10
+ logoSrc?: string;
11
+ logoAlt?: string;
12
+ variant?: 'dark' | 'light';
13
+ };
14
+
15
+ export const UserDropdownTrigger = (props: UserDropdownTriggerProps) => {
16
+ const { avatarSrc, avatarAlt, avatarInitials, logoSrc, logoAlt = 'Logo', variant = 'dark' } = props;
17
+
18
+ return (
19
+ <div
20
+ className={`ds-user-dropdown__trigger-container ds-user-dropdown__trigger-container--${variant}${
21
+ logoSrc ? ' ds-user-dropdown__trigger-container--with-logo' : ''
22
+ }`}
23
+ >
24
+ <Dropdown.Trigger>
25
+ <Button
26
+ variant="secondary"
27
+ borderless={true}
28
+ iconRightName="chevron-down"
29
+ className="ds-user-dropdown__trigger"
30
+ >
31
+ <Avatar size="medium" src={avatarSrc} alt={avatarAlt} initials={avatarInitials} />
32
+ </Button>
33
+ </Dropdown.Trigger>
34
+ {logoSrc && (
35
+ <>
36
+ <div className="ds-user-dropdown__trigger-divider" />
37
+ <img src={logoSrc} alt={logoAlt} className="ds-user-dropdown__trigger-logo" />
38
+ </>
39
+ )}
40
+ </div>
41
+ );
42
+ };
@@ -0,0 +1,60 @@
1
+ import React, { useContext } from 'react';
2
+ import { DropdownMenu } from 'radix-ui';
3
+ import { Avatar } from 'Components/avatar/Avatar';
4
+ import { Icon } from 'Components/icon/Icon';
5
+ import { Dropdown } from 'Components/dropdown/Dropdown';
6
+ import { PopupParentContext } from 'Utils/PopupParentContext';
7
+ import type { UserDropdownUser, UserDropdownUserInfoAction } from '../UserDropdown';
8
+
9
+ type UserDropdownUserInfoProps = {
10
+ user: UserDropdownUser;
11
+ action?: UserDropdownUserInfoAction;
12
+ };
13
+
14
+ export const UserDropdownUserInfo = (props: UserDropdownUserInfoProps) => {
15
+ const { user, action } = props;
16
+ const popupParentRef = useContext(PopupParentContext);
17
+
18
+ const content = (
19
+ <>
20
+ <Avatar size="medium" src={user.avatarSrc} alt={user.avatarAlt} initials={user.avatarInitials} />
21
+ <div className="ds-user-dropdown__user-info-text">
22
+ <div className="ds-user-dropdown__user-info-name">{user.name}</div>
23
+ {user.subtitle && <div className="ds-user-dropdown__user-info-role">{user.subtitle}</div>}
24
+ </div>
25
+ {action && <Icon name="chevron-right" size={16} className="ds-user-dropdown__user-info-chevron" />}
26
+ </>
27
+ );
28
+
29
+ if (action?.type === 'menu') {
30
+ return (
31
+ <DropdownMenu.Sub>
32
+ <DropdownMenu.SubTrigger className="ds-user-dropdown__user-info">
33
+ {content}
34
+ </DropdownMenu.SubTrigger>
35
+ <DropdownMenu.Portal container={popupParentRef.current}>
36
+ <DropdownMenu.SubContent className="ds-user-dropdown__sub-content">
37
+ {action.items.map((item, index) => (
38
+ <DropdownMenu.Item
39
+ key={index}
40
+ className="ds-user-dropdown__sub-item"
41
+ onSelect={item.onClick}
42
+ >
43
+ {item.label}
44
+ </DropdownMenu.Item>
45
+ ))}
46
+ </DropdownMenu.SubContent>
47
+ </DropdownMenu.Portal>
48
+ </DropdownMenu.Sub>
49
+ );
50
+ }
51
+
52
+ return (
53
+ <Dropdown.Item
54
+ className="ds-user-dropdown__user-info"
55
+ onClick={action?.type === 'link' ? action.onClick : undefined}
56
+ >
57
+ {content}
58
+ </Dropdown.Item>
59
+ );
60
+ };
@@ -0,0 +1,377 @@
1
+ // ========== Trigger Divider ==========
2
+ .ds-user-dropdown__trigger-divider {
3
+ width: 1px;
4
+ height: 24px;
5
+ }
6
+
7
+ // ========== Trigger Container ==========
8
+ .ds-user-dropdown__trigger-container {
9
+ display: inline-flex;
10
+ align-items: center;
11
+ gap: var(--spacing-xsmall);
12
+ padding: var(--spacing-xsmall);
13
+ border: 1px solid;
14
+ border-radius: var(--border-radius-round);
15
+
16
+ &--with-logo {
17
+ padding-right: var(--spacing-medium);
18
+ }
19
+
20
+ // Dark variant (default)
21
+ &--dark {
22
+ background-color: var(--color-grey-900);
23
+ border-color: var(--color-grey-700);
24
+
25
+ .ds-avatar {
26
+ border-color: var(--color-grey-700);
27
+ }
28
+
29
+ .ds-user-dropdown__trigger-divider {
30
+ background-color: var(--color-grey-700);
31
+ }
32
+
33
+ .ds-user-dropdown__trigger:hover,
34
+ .ds-user-dropdown__trigger:focus-visible,
35
+ .ds-user-dropdown__trigger[data-state="open"] {
36
+ background-color: var(--color-grey-800);
37
+ }
38
+
39
+ .ds-icon {
40
+ color: var(--color-mono-white);
41
+ }
42
+ }
43
+
44
+ // Light variant
45
+ &--light {
46
+ background-color: var(--color-mono-white);
47
+ border-color: var(--color-grey-100);
48
+
49
+ .ds-avatar {
50
+ border-color: var(--color-grey-100);
51
+ }
52
+
53
+ .ds-user-dropdown__trigger-divider {
54
+ background-color: var(--color-grey-100);
55
+ }
56
+
57
+ .ds-user-dropdown__trigger:hover,
58
+ .ds-user-dropdown__trigger:focus-visible,
59
+ .ds-user-dropdown__trigger[data-state="open"] {
60
+ background-color: var(--color-grey-050);
61
+ }
62
+
63
+ .ds-icon {
64
+ color: var(--color-grey-700);
65
+ }
66
+ }
67
+ }
68
+
69
+ // ========== Trigger Button ==========
70
+ // Higher specificity (0,3,0) to override Button component defaults without !important
71
+ .ds-user-dropdown__trigger-container .ds-button.ds-user-dropdown__trigger {
72
+ background-color: transparent;
73
+ border-radius: var(--border-radius-round);
74
+ padding-right: var(--spacing-xsmall);
75
+ padding-left: 0;
76
+ border: none;
77
+
78
+ &:focus-visible,
79
+ &[data-state="open"] {
80
+ outline: var(--focus-border) solid var(--color-brand-500);
81
+ outline-offset: 0;
82
+ border: none;
83
+ }
84
+ }
85
+
86
+ .ds-user-dropdown__trigger-logo {
87
+ max-height: 32px;
88
+ max-width: 54px;
89
+ height: auto;
90
+ width: auto;
91
+ border-radius: var(--border-radius-small);
92
+ }
93
+
94
+ // ========== Content ==========
95
+ .ds-user-dropdown__content {
96
+ width: 304px;
97
+ padding: var(--spacing-large);
98
+ display: flex;
99
+ flex-direction: column;
100
+ align-items: stretch;
101
+ gap: var(--spacing-small);
102
+ }
103
+
104
+ // ========== User Info ==========
105
+ .ds-user-dropdown__user-info {
106
+ display: flex;
107
+ align-items: center;
108
+ gap: var(--spacing-small);
109
+ padding: var(--spacing-small);
110
+ border-radius: var(--border-radius-small);
111
+ cursor: pointer;
112
+ transition: background-color 0.2s ease;
113
+
114
+ &:hover,
115
+ &[data-highlighted] {
116
+ background-color: var(--color-grey-050);
117
+ outline: none;
118
+ }
119
+
120
+ &:focus-visible:not(:hover) {
121
+ outline: var(--focus-border) solid var(--color-brand-500);
122
+ outline-offset: -2px;
123
+ }
124
+ }
125
+
126
+ .ds-user-dropdown__user-info-text {
127
+ flex: 1;
128
+ min-width: 0;
129
+ display: flex;
130
+ flex-direction: column;
131
+ gap: 2px;
132
+ }
133
+
134
+ .ds-user-dropdown__user-info-name {
135
+ font-family: var(--type-body-bold-family);
136
+ font-size: var(--type-body-bold-size);
137
+ font-weight: var(--type-body-bold-weight);
138
+ color: var(--color-grey-900);
139
+ line-height: 1.5;
140
+ overflow: hidden;
141
+ text-overflow: ellipsis;
142
+ white-space: nowrap;
143
+ }
144
+
145
+ .ds-user-dropdown__user-info-role {
146
+ font-family: var(--type-body-p-family);
147
+ font-size: var(--type-body-p-size);
148
+ font-weight: var(--type-body-p-weight);
149
+ color: var(--color-grey-700);
150
+ line-height: 1.5;
151
+ overflow: hidden;
152
+ text-overflow: ellipsis;
153
+ white-space: nowrap;
154
+ }
155
+
156
+ .ds-user-dropdown__user-info-chevron {
157
+ color: var(--color-grey-700);
158
+ flex-shrink: 0;
159
+ }
160
+
161
+ // ========== User Info Sub-menu ==========
162
+ .ds-user-dropdown__sub-content {
163
+ min-width: 180px;
164
+ padding: var(--spacing-small);
165
+ display: flex;
166
+ flex-direction: column;
167
+ gap: 2px;
168
+ background-color: var(--color-mono-white);
169
+ border: 1px solid var(--color-grey-200);
170
+ border-radius: var(--border-radius-small);
171
+ box-shadow: 0 4px 12px 0 rgb(32 32 32 / 8%);
172
+ }
173
+
174
+ .ds-user-dropdown__sub-item {
175
+ padding: var(--spacing-small);
176
+ border-radius: var(--border-radius-small);
177
+ font-family: var(--type-body-p-family);
178
+ font-size: var(--type-body-p-size);
179
+ font-weight: var(--type-body-p-weight);
180
+ color: var(--color-grey-900);
181
+ line-height: 1.5;
182
+ cursor: pointer;
183
+
184
+ &:hover,
185
+ &[data-highlighted] {
186
+ background-color: var(--color-grey-050);
187
+ outline: none;
188
+ }
189
+
190
+ &:focus-visible:not(:hover) {
191
+ outline: var(--focus-border) solid var(--color-brand-500);
192
+ outline-offset: -2px;
193
+ }
194
+ }
195
+
196
+ // ========== Divider ==========
197
+ .ds-user-dropdown__divider {
198
+ height: 1px;
199
+ flex-shrink: 0;
200
+ background-color: var(--color-grey-200);
201
+ }
202
+
203
+ // ========== Section ==========
204
+ .ds-user-dropdown__section {
205
+ display: flex;
206
+ flex-direction: column;
207
+ gap: var(--spacing-small);
208
+ }
209
+
210
+ .ds-user-dropdown__section-label {
211
+ padding: var(--spacing-small);
212
+ font-family: var(--type-body-p-family);
213
+ font-size: var(--type-body-p-size);
214
+ font-weight: var(--type-body-p-weight);
215
+ color: var(--color-grey-700);
216
+ line-height: 1.5;
217
+ }
218
+
219
+ // ========== App Item ==========
220
+ .ds-user-dropdown__app-item {
221
+ display: flex;
222
+ align-items: center;
223
+ gap: var(--spacing-small);
224
+ padding: var(--spacing-small);
225
+ border-radius: var(--border-radius-small);
226
+ cursor: pointer;
227
+ transition: background-color 0.2s ease;
228
+
229
+ &:hover,
230
+ &[data-highlighted] {
231
+ background-color: var(--color-grey-050);
232
+ }
233
+
234
+ &:focus-visible:not(:hover) {
235
+ outline: var(--focus-border) solid var(--color-brand-500);
236
+ outline-offset: -2px;
237
+ }
238
+ }
239
+
240
+ .ds-user-dropdown__app-item-logo {
241
+ width: 24px;
242
+ height: 24px;
243
+ flex-shrink: 0;
244
+ display: flex;
245
+ align-items: center;
246
+ justify-content: center;
247
+ overflow: hidden;
248
+ border-radius: var(--border-radius-xsmall);
249
+
250
+ img {
251
+ width: 100%;
252
+ height: 100%;
253
+ object-fit: contain;
254
+ }
255
+ }
256
+
257
+ .ds-user-dropdown__app-item-text {
258
+ flex: 1;
259
+ min-width: 0;
260
+ display: flex;
261
+ flex-direction: column;
262
+ gap: 2px;
263
+ }
264
+
265
+ .ds-user-dropdown__app-item-arrow {
266
+ display: none;
267
+ align-items: center;
268
+ justify-content: center;
269
+ flex-shrink: 0;
270
+ padding: var(--spacing-xsmall);
271
+ border-radius: 99px;
272
+ background-color: var(--color-brand-050);
273
+ color: var(--color-brand-500);
274
+
275
+ .ds-user-dropdown__collapsible-section-content .ds-user-dropdown__app-item:hover &,
276
+ .ds-user-dropdown__collapsible-section-content .ds-user-dropdown__app-item[data-highlighted] & {
277
+ display: flex;
278
+ }
279
+ }
280
+
281
+ .ds-user-dropdown__app-item-name {
282
+ font-family: var(--type-body-bold-family);
283
+ font-size: var(--type-body-bold-size);
284
+ font-weight: var(--type-body-bold-weight);
285
+ color: var(--color-grey-900);
286
+ line-height: 1.5;
287
+ overflow: hidden;
288
+ text-overflow: ellipsis;
289
+ white-space: nowrap;
290
+ }
291
+
292
+ .ds-user-dropdown__app-item-description {
293
+ font-family: var(--type-body-p-family);
294
+ font-size: var(--type-body-p-size);
295
+ font-weight: var(--type-body-p-weight);
296
+ color: var(--color-grey-700);
297
+ line-height: 1.5;
298
+ overflow: hidden;
299
+ text-overflow: ellipsis;
300
+ white-space: nowrap;
301
+ }
302
+
303
+ // ========== Collapsible Section ==========
304
+ .ds-user-dropdown__collapsible-section {
305
+ display: flex;
306
+ flex-direction: column;
307
+ gap: var(--spacing-small);
308
+ }
309
+
310
+ .ds-user-dropdown__collapsible-section-header {
311
+ display: flex;
312
+ align-items: center;
313
+ justify-content: space-between;
314
+ gap: var(--spacing-small);
315
+ padding: var(--spacing-small);
316
+ border-radius: var(--border-radius-small);
317
+ cursor: pointer;
318
+ transition: background-color 0.2s ease;
319
+
320
+ &:hover {
321
+ background-color: var(--color-grey-050);
322
+ }
323
+
324
+ &:focus-visible:not(:hover) {
325
+ outline: var(--focus-border) solid var(--color-brand-500);
326
+ outline-offset: -2px;
327
+ }
328
+ }
329
+
330
+ .ds-user-dropdown__collapsible-section-label {
331
+ flex: 1;
332
+ font-family: var(--type-body-p-family);
333
+ font-size: var(--type-body-p-size);
334
+ font-weight: var(--type-body-p-weight);
335
+ color: var(--color-grey-700);
336
+ line-height: 1.5;
337
+ }
338
+
339
+ .ds-user-dropdown__collapsible-section-icon {
340
+ color: var(--color-grey-700);
341
+ flex-shrink: 0;
342
+ }
343
+
344
+ .ds-user-dropdown__collapsible-section-content {
345
+ display: flex;
346
+ flex-direction: column;
347
+ gap: var(--spacing-small);
348
+ }
349
+
350
+ // ========== Sign Out ==========
351
+ .ds-user-dropdown__sign-out {
352
+ display: flex;
353
+ align-items: center;
354
+ gap: var(--spacing-small);
355
+ padding: var(--spacing-small);
356
+ border-radius: var(--border-radius-small);
357
+ cursor: pointer;
358
+ transition: background-color 0.2s ease;
359
+
360
+ &:hover,
361
+ &[data-highlighted] {
362
+ background-color: var(--color-grey-050);
363
+ }
364
+
365
+ &:focus-visible:not(:hover) {
366
+ outline: var(--focus-border) solid var(--color-brand-500);
367
+ outline-offset: -2px;
368
+ }
369
+ }
370
+
371
+ .ds-user-dropdown__sign-out-label {
372
+ font-family: var(--type-body-bold-family);
373
+ font-size: var(--type-body-bold-size);
374
+ font-weight: var(--type-body-bold-weight);
375
+ color: var(--color-grey-900);
376
+ line-height: 1.5;
377
+ }
package/src/index.scss CHANGED
@@ -32,4 +32,6 @@
32
32
  @use "components/editableText/editableText.scss";
33
33
  @use "components/progress/progress.scss";
34
34
  @use "components/toast/toast.scss";
35
+ @use "components/avatar/avatar.scss";
36
+ @use "components/userDropdown/userDropdown.scss";
35
37
  @import "https://fonts.googleapis.com/css2?family=Inter:ital,opsz,wght@0,14..32,100..900;1,14..32,100..900&display=swap";
package/src/index.ts CHANGED
@@ -30,3 +30,7 @@ export { Banner, type BannerProps, BANNER_LEVEL } from 'Components/banner/Banner
30
30
  export { EditableText } from 'Components/editableText/EditableText';
31
31
  export { Progress } from 'Components/progress/Progress';
32
32
  export { Toast } from 'Components/toast/Toast';
33
+ export { Avatar } from 'Components/avatar/Avatar';
34
+ export { UserDropdown } from 'Components/userDropdown/UserDropdown';
35
+ export type { UserDropdownUserInfoAction } from 'Components/userDropdown/UserDropdown';
36
+ export { ArborLogo, GovhubLogo, KeyLogo, SampeopleLogo, RobinLogo, TimetablerLogo } from 'Components/userDropdown/assets/logos';
package/tsconfig.json CHANGED
@@ -48,6 +48,6 @@
48
48
  "Utils/*": ["./src/utils/*"]
49
49
  }
50
50
  },
51
- "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.test.tsx"],
51
+ "include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.test.tsx", "vite-env.d.ts"],
52
52
  "exclude": ["src/**/*.story.tsx"]
53
53
  }
package/vite-env.d.ts ADDED
@@ -0,0 +1,31 @@
1
+ /// <reference types="vite/client" />
2
+
3
+ declare module '*.png' {
4
+ const value: string;
5
+ export default value;
6
+ }
7
+
8
+ declare module '*.jpg' {
9
+ const value: string;
10
+ export default value;
11
+ }
12
+
13
+ declare module '*.jpeg' {
14
+ const value: string;
15
+ export default value;
16
+ }
17
+
18
+ declare module '*.gif' {
19
+ const value: string;
20
+ export default value;
21
+ }
22
+
23
+ declare module '*.svg' {
24
+ const value: string;
25
+ export default value;
26
+ }
27
+
28
+ declare module '*.webp' {
29
+ const value: string;
30
+ export default value;
31
+ }
@@ -1,8 +0,0 @@
1
- import type { CustomCellEditorProps } from 'ag-grid-react';
2
- import type { SelectDropdownItemProps } from '../../formField/inputs/selectDropdown/items/item/SelectDropdownItem';
3
- export type SelectDropdownCellEditorParams = {
4
- options: SelectDropdownItemProps[];
5
- placeholder?: string;
6
- };
7
- export declare const SelectDropdownCellEditor: import("react").MemoExoticComponent<(props: CustomCellEditorProps & SelectDropdownCellEditorParams) => import("react/jsx-runtime").JSX.Element>;
8
- //# sourceMappingURL=SelectDropdownCellEditor.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SelectDropdownCellEditor.d.ts","sourceRoot":"","sources":["../../../../src/components/table/cellRenderers/SelectDropdownCellEditor.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAE3D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,0EAA0E,CAAC;AAGxH,MAAM,MAAM,8BAA8B,GAAG;IAC3C,OAAO,EAAE,uBAAuB,EAAE,CAAC;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,eAAO,MAAM,wBAAwB,8CAAgB,qBAAqB,GAAG,8BAA8B,6CA6BzG,CAAC"}
@@ -1,19 +0,0 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { memo, useCallback, useRef } from 'react';
3
- import { SelectDropdown } from '../../formField/inputs/selectDropdown/SelectDropdown';
4
- import { PopupParentContext } from '../../../utils/PopupParentContext';
5
- export const SelectDropdownCellEditor = memo((props) => {
6
- const { value, onValueChange, stopEditing } = props;
7
- const options = props.options ?? [];
8
- const placeholder = props.placeholder ?? 'Select';
9
- const wrapperRef = useRef(null);
10
- const initialSelectedValues = value != null && value !== '' ? [String(value)] : [];
11
- const handleSelectionChange = useCallback((selected) => {
12
- const newValue = selected.length > 0 ? selected[0] : '';
13
- onValueChange(newValue);
14
- stopEditing();
15
- }, [onValueChange, stopEditing]);
16
- return (_jsx(PopupParentContext.Provider, { value: wrapperRef, children: _jsx("div", { ref: wrapperRef, className: "ds-table__select-dropdown-editor", children: _jsx(SelectDropdown, { options: options, placeholder: placeholder, initialSelectedValues: initialSelectedValues, onSelectionChange: handleSelectionChange }) }) }));
17
- });
18
- SelectDropdownCellEditor.displayName = 'SelectDropdownCellEditor';
19
- //# sourceMappingURL=SelectDropdownCellEditor.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"SelectDropdownCellEditor.js","sourceRoot":"","sources":["../../../../src/components/table/cellRenderers/SelectDropdownCellEditor.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AAElD,OAAO,EAAE,cAAc,EAAE,MAAM,2DAA2D,CAAC;AAE3F,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAO9D,MAAM,CAAC,MAAM,wBAAwB,GAAG,IAAI,CAAC,CAAC,KAA6D,EAAE,EAAE;IAC7G,MAAM,EAAE,KAAK,EAAE,aAAa,EAAE,WAAW,EAAE,GAAG,KAAK,CAAC;IACpD,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC;IACpC,MAAM,WAAW,GAAG,KAAK,CAAC,WAAW,IAAI,QAAQ,CAAC;IAClD,MAAM,UAAU,GAAG,MAAM,CAAiB,IAAI,CAAC,CAAC;IAEhD,MAAM,qBAAqB,GAAG,KAAK,IAAI,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAEnF,MAAM,qBAAqB,GAAG,WAAW,CACvC,CAAC,QAAkB,EAAE,EAAE;QACrB,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACxD,aAAa,CAAC,QAAQ,CAAC,CAAC;QACxB,WAAW,EAAE,CAAC;IAChB,CAAC,EACD,CAAC,aAAa,EAAE,WAAW,CAAC,CAC7B,CAAC;IAEF,OAAO,CACL,KAAC,kBAAkB,CAAC,QAAQ,IAAC,KAAK,EAAE,UAAU,YAC5C,cAAK,GAAG,EAAE,UAAU,EAAE,SAAS,EAAC,kCAAkC,YAChE,KAAC,cAAc,IACb,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,WAAW,EACxB,qBAAqB,EAAE,qBAAqB,EAC5C,iBAAiB,EAAE,qBAAqB,GACxC,GACE,GACsB,CAC/B,CAAC;AACJ,CAAC,CAAC,CAAC;AAEH,wBAAwB,CAAC,WAAW,GAAG,0BAA0B,CAAC"}