agroptima-design-system 1.1.1-beta.1 → 1.2.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/atoms/CardsTable/CardsTable.scss +1 -1
- package/src/atoms/Drawer.tsx +11 -9
- package/src/atoms/Icon.scss +3 -0
- package/src/atoms/Icon.tsx +1 -1
- package/src/atoms/Notification/NotificationCenter.scss +161 -0
- package/src/atoms/Notification/NotificationCenter.tsx +43 -0
- package/src/atoms/Notification/NotificationEmptyState.tsx +31 -0
- package/src/atoms/Notification/NotificationHeader.tsx +28 -0
- package/src/atoms/Notification/NotificationLine.tsx +45 -0
- package/src/atoms/Notification/NotificationList.tsx +17 -0
- package/src/atoms/Notification/index.ts +13 -0
- package/src/atoms/Popover/Popover.tsx +4 -2
- package/src/atoms/Popover/index.ts +8 -1
- package/src/atoms/Timeline/LoadMoreMilestonesButton.tsx +47 -0
- package/src/atoms/Timeline/Milestone.tsx +44 -0
- package/src/atoms/Timeline/Timeline.scss +156 -0
- package/src/atoms/Timeline/Timeline.tsx +26 -0
- package/src/atoms/Timeline/index.tsx +5 -0
- package/src/icons/index.tsx +8 -0
- package/src/icons/notification.svg +1 -0
- package/src/icons/timeline-circle-default.svg +1 -0
- package/src/icons/timeline-circle-selected.svg +1 -0
- package/src/icons/traceability.svg +1 -0
- package/src/settings/_depth.scss +4 -1
- package/src/stories/Changelog.mdx +12 -4
- package/src/stories/Header.stories.tsx +1 -2
- package/src/stories/Notification.stories.tsx +169 -0
- package/src/stories/Timeline.stories.tsx +155 -0
- package/tests/Timeline.spec.tsx +53 -0
- package/tests/library.ts +1 -0
package/package.json
CHANGED
package/src/atoms/Drawer.tsx
CHANGED
|
@@ -12,7 +12,7 @@ export interface DrawerProps extends React.ComponentPropsWithoutRef<'div'> {
|
|
|
12
12
|
id: string
|
|
13
13
|
variant?: Variant
|
|
14
14
|
title: string
|
|
15
|
-
buttons
|
|
15
|
+
buttons?: ButtonProps[]
|
|
16
16
|
onClose: () => void
|
|
17
17
|
}
|
|
18
18
|
|
|
@@ -21,7 +21,7 @@ export function Drawer({
|
|
|
21
21
|
className,
|
|
22
22
|
variant = 'primary',
|
|
23
23
|
title,
|
|
24
|
-
buttons,
|
|
24
|
+
buttons = [],
|
|
25
25
|
children,
|
|
26
26
|
onClose,
|
|
27
27
|
...props
|
|
@@ -59,13 +59,15 @@ export function Drawer({
|
|
|
59
59
|
{children}
|
|
60
60
|
</div>
|
|
61
61
|
</div>
|
|
62
|
-
|
|
63
|
-
<
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
62
|
+
{buttons.length > 0 && (
|
|
63
|
+
<div className="footer">
|
|
64
|
+
<Actions>
|
|
65
|
+
{buttons.map(({ ...button }) => (
|
|
66
|
+
<Button key={button.label} {...button} />
|
|
67
|
+
))}
|
|
68
|
+
</Actions>
|
|
69
|
+
</div>
|
|
70
|
+
)}
|
|
69
71
|
</div>
|
|
70
72
|
</div>
|
|
71
73
|
)
|
package/src/atoms/Icon.scss
CHANGED
package/src/atoms/Icon.tsx
CHANGED
|
@@ -5,7 +5,7 @@ import { classNames } from '../utils/classNames'
|
|
|
5
5
|
export type IconType = keyof typeof icons
|
|
6
6
|
|
|
7
7
|
export type IconSize = '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8'
|
|
8
|
-
export type Variant = 'info' | 'success' | 'warning' | 'error'
|
|
8
|
+
export type Variant = 'info' | 'success' | 'warning' | 'error' | 'primary'
|
|
9
9
|
|
|
10
10
|
export interface IconProps extends React.SVGAttributes<HTMLOrSVGElement> {
|
|
11
11
|
name: IconType
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
@use '../../settings/typography/content' as typography;
|
|
2
|
+
@use '../../settings/config';
|
|
3
|
+
@use '../../settings/depth';
|
|
4
|
+
@use '../../settings/breakpoints';
|
|
5
|
+
@use '../../settings/mixins';
|
|
6
|
+
|
|
7
|
+
.notification-center-container {
|
|
8
|
+
.notification-center {
|
|
9
|
+
display: flex;
|
|
10
|
+
flex-direction: column;
|
|
11
|
+
width: 350px;
|
|
12
|
+
box-shadow:
|
|
13
|
+
0 3px 6px -4px rgba(0, 0, 0, 0.12),
|
|
14
|
+
0px 6px 16px 0px rgba(0, 0, 0, 0.08),
|
|
15
|
+
0px 9px 28px 8px rgba(0, 0, 0, 0.05);
|
|
16
|
+
|
|
17
|
+
.notification-header {
|
|
18
|
+
display: flex;
|
|
19
|
+
flex-direction: column;
|
|
20
|
+
width: 100%;
|
|
21
|
+
|
|
22
|
+
.notification-header-title {
|
|
23
|
+
@include typography.body-bold;
|
|
24
|
+
display: flex;
|
|
25
|
+
padding: config.$space-2x config.$space-3x;
|
|
26
|
+
gap: var(--space-1x);
|
|
27
|
+
border-radius: config.$corner-radius-m config.$corner-radius-m 0 0;
|
|
28
|
+
background: var(--neutral-color-900);
|
|
29
|
+
color: var(--neutral-white);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
.notification-header-content {
|
|
33
|
+
display: flex;
|
|
34
|
+
flex-direction: row;
|
|
35
|
+
justify-content: space-between;
|
|
36
|
+
align-items: center;
|
|
37
|
+
padding: config.$space-2x config.$space-3x;
|
|
38
|
+
gap: config.$space-2x;
|
|
39
|
+
background: var(--neutral-white);
|
|
40
|
+
|
|
41
|
+
> .button:last-child {
|
|
42
|
+
@include typography.footnote-primary;
|
|
43
|
+
color: var(--primary-color-600);
|
|
44
|
+
border: 0;
|
|
45
|
+
background-color: transparent;
|
|
46
|
+
padding: 0;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.notification-list {
|
|
52
|
+
max-height: 370px;
|
|
53
|
+
overflow-y: auto;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.notification-line {
|
|
57
|
+
display: flex;
|
|
58
|
+
flex-direction: column;
|
|
59
|
+
width: 100%;
|
|
60
|
+
padding: config.$space-2x config.$space-3x config.$space-2x
|
|
61
|
+
config.$space-3x;
|
|
62
|
+
background-color: var(--neutral-white);
|
|
63
|
+
|
|
64
|
+
&:hover {
|
|
65
|
+
background-color: var(--primary-color-50);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.notification-line-head {
|
|
69
|
+
display: flex;
|
|
70
|
+
gap: config.$space-2x;
|
|
71
|
+
justify-content: space-between;
|
|
72
|
+
align-items: center;
|
|
73
|
+
cursor: default;
|
|
74
|
+
|
|
75
|
+
.notification-line-title {
|
|
76
|
+
white-space: normal;
|
|
77
|
+
display: flex;
|
|
78
|
+
align-items: baseline;
|
|
79
|
+
@include typography.body-bold;
|
|
80
|
+
|
|
81
|
+
&:has(.icon.success) {
|
|
82
|
+
align-items: center;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.icon {
|
|
86
|
+
margin-right: config.$space-1x;
|
|
87
|
+
|
|
88
|
+
&.primary {
|
|
89
|
+
width: config.$icon-size-2x;
|
|
90
|
+
height: config.$icon-size-2x;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
.notification-line-date {
|
|
95
|
+
@include typography.footnote-primary;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.notification-line-description {
|
|
100
|
+
display: flex;
|
|
101
|
+
flex-direction: column;
|
|
102
|
+
gap: config.$space-2x;
|
|
103
|
+
cursor: default;
|
|
104
|
+
|
|
105
|
+
&[open] summary::after {
|
|
106
|
+
content: attr(data-open);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
&:not([open]) summary::after {
|
|
110
|
+
content: attr(data-close);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
> summary {
|
|
114
|
+
list-style: none;
|
|
115
|
+
color: var(--primary-color-600);
|
|
116
|
+
text-decoration-line: underline;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
> summary::-webkit-details-marker {
|
|
120
|
+
display: none;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
> p {
|
|
124
|
+
white-space: normal;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
@media only screen and (max-width: breakpoints.$medium) {
|
|
132
|
+
.popover-container {
|
|
133
|
+
position: relative;
|
|
134
|
+
|
|
135
|
+
.popover-menu-container {
|
|
136
|
+
margin: 0;
|
|
137
|
+
padding: 0;
|
|
138
|
+
width: 100%;
|
|
139
|
+
|
|
140
|
+
.backdrop {
|
|
141
|
+
display: none;
|
|
142
|
+
visibility: hidden;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.notification-center {
|
|
146
|
+
width: 100%;
|
|
147
|
+
height: 96vh;
|
|
148
|
+
|
|
149
|
+
.notification-header {
|
|
150
|
+
.notification-header-title {
|
|
151
|
+
border-radius: 0;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.notification-list {
|
|
156
|
+
max-height: 100vh;
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import './NotificationCenter.scss'
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import { classNames } from '../../utils/classNames'
|
|
5
|
+
import { IconButton } from '../Button'
|
|
6
|
+
import type { Variant } from '../Button/IconButton'
|
|
7
|
+
import { Popover, type Position } from '../Popover'
|
|
8
|
+
|
|
9
|
+
export interface NotificationCenterProps {
|
|
10
|
+
position?: Position
|
|
11
|
+
className?: string
|
|
12
|
+
variant?: Variant
|
|
13
|
+
accessibilityLabel?: string
|
|
14
|
+
children: React.ReactNode
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function NotificationCenter({
|
|
18
|
+
position = 'right',
|
|
19
|
+
className,
|
|
20
|
+
variant = 'secondary',
|
|
21
|
+
accessibilityLabel = 'Open notifications center',
|
|
22
|
+
children,
|
|
23
|
+
}: NotificationCenterProps) {
|
|
24
|
+
return (
|
|
25
|
+
<Popover
|
|
26
|
+
position={position}
|
|
27
|
+
className={classNames('notification-center-container', className)}
|
|
28
|
+
renderButton={({ toggle }) => (
|
|
29
|
+
<IconButton
|
|
30
|
+
icon="Notification"
|
|
31
|
+
variant={variant}
|
|
32
|
+
accessibilityLabel={accessibilityLabel}
|
|
33
|
+
onClick={toggle}
|
|
34
|
+
/>
|
|
35
|
+
)}
|
|
36
|
+
closeOnClick={false}
|
|
37
|
+
>
|
|
38
|
+
<div className="notification-center">{children}</div>
|
|
39
|
+
</Popover>
|
|
40
|
+
)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export { NotificationCenter }
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import './NotificationCenter.scss'
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import { classNames } from '../../utils/classNames'
|
|
5
|
+
import { Icon } from '../Icon'
|
|
6
|
+
|
|
7
|
+
export interface NotificationEmptyStateProps {
|
|
8
|
+
title: string
|
|
9
|
+
date: string
|
|
10
|
+
className?: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function NotificationEmptyState({
|
|
14
|
+
title,
|
|
15
|
+
date,
|
|
16
|
+
className,
|
|
17
|
+
}: NotificationEmptyStateProps) {
|
|
18
|
+
return (
|
|
19
|
+
<div className={classNames('notification-line', className)}>
|
|
20
|
+
<div className="notification-line-head">
|
|
21
|
+
<span className="notification-line-title">
|
|
22
|
+
<Icon variant="success" name="Check" />
|
|
23
|
+
{title}
|
|
24
|
+
</span>
|
|
25
|
+
<span className="notification-line-date">{date}</span>
|
|
26
|
+
</div>
|
|
27
|
+
</div>
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export { NotificationEmptyState }
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import './NotificationCenter.scss'
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import { classNames } from '../../utils/classNames'
|
|
5
|
+
import { IconButton } from '../Button'
|
|
6
|
+
import type { Variant } from '../Button/IconButton'
|
|
7
|
+
import { Popover, type Position } from '../Popover'
|
|
8
|
+
|
|
9
|
+
export interface NotificationHeaderProps {
|
|
10
|
+
title: string
|
|
11
|
+
className?: string
|
|
12
|
+
children: React.ReactNode
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function NotificationHeader({
|
|
16
|
+
title,
|
|
17
|
+
className,
|
|
18
|
+
children,
|
|
19
|
+
}: NotificationHeaderProps) {
|
|
20
|
+
return (
|
|
21
|
+
<div className={classNames('notification-header', className)}>
|
|
22
|
+
<div className="notification-header-title">{title}</div>
|
|
23
|
+
<div className="notification-header-content">{children}</div>
|
|
24
|
+
</div>
|
|
25
|
+
)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export { NotificationHeader }
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import './NotificationCenter.scss'
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import { classNames } from '../../utils/classNames'
|
|
5
|
+
import { Icon } from '../Icon'
|
|
6
|
+
|
|
7
|
+
export interface NotificationLineProps extends React.ComponentPropsWithoutRef<'div'> {
|
|
8
|
+
title: string
|
|
9
|
+
date: string
|
|
10
|
+
isRead?: boolean
|
|
11
|
+
expandLabel?: string
|
|
12
|
+
collapseLabel?: string
|
|
13
|
+
className?: string
|
|
14
|
+
onClick?: () => void
|
|
15
|
+
children: React.ReactNode
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function NotificationLine({
|
|
19
|
+
title,
|
|
20
|
+
date,
|
|
21
|
+
isRead = false,
|
|
22
|
+
expandLabel = 'View more',
|
|
23
|
+
collapseLabel = 'View less',
|
|
24
|
+
className,
|
|
25
|
+
onClick = () => {},
|
|
26
|
+
children,
|
|
27
|
+
}: NotificationLineProps) {
|
|
28
|
+
return (
|
|
29
|
+
<div className={classNames('notification-line', className)}>
|
|
30
|
+
<div className="notification-line-head" onClick={onClick}>
|
|
31
|
+
<span className="notification-line-title">
|
|
32
|
+
{!isRead && <Icon variant="primary" name="TimelineCircleSelected" />}
|
|
33
|
+
{title}
|
|
34
|
+
</span>
|
|
35
|
+
<span className="notification-line-date">{date}</span>
|
|
36
|
+
</div>
|
|
37
|
+
<details className="notification-line-description">
|
|
38
|
+
<summary data-open={collapseLabel} data-close={expandLabel}></summary>
|
|
39
|
+
<p>{children}</p>
|
|
40
|
+
</details>
|
|
41
|
+
</div>
|
|
42
|
+
)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export { NotificationLine }
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
import './NotificationCenter.scss'
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import { classNames } from '../../utils/classNames'
|
|
5
|
+
|
|
6
|
+
export interface NotificationListProps {
|
|
7
|
+
className?: string
|
|
8
|
+
children: React.ReactNode
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function NotificationList({ className, children }: NotificationListProps) {
|
|
12
|
+
return (
|
|
13
|
+
<div className={classNames('notification-list', className)}>{children}</div>
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export { NotificationList }
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { NotificationCenter } from './NotificationCenter'
|
|
2
|
+
import { NotificationEmptyState } from './NotificationEmptyState'
|
|
3
|
+
import { NotificationHeader } from './NotificationHeader'
|
|
4
|
+
import { NotificationLine } from './NotificationLine'
|
|
5
|
+
import { NotificationList } from './NotificationList'
|
|
6
|
+
|
|
7
|
+
export {
|
|
8
|
+
NotificationCenter,
|
|
9
|
+
NotificationEmptyState,
|
|
10
|
+
NotificationHeader,
|
|
11
|
+
NotificationLine,
|
|
12
|
+
NotificationList,
|
|
13
|
+
}
|
|
@@ -14,12 +14,13 @@ type Actions = {
|
|
|
14
14
|
|
|
15
15
|
export type Horizontal = 'left' | 'right' | 'center'
|
|
16
16
|
|
|
17
|
-
type Position = Horizontal | `top-${Horizontal}`
|
|
17
|
+
export type Position = Horizontal | `top-${Horizontal}`
|
|
18
18
|
|
|
19
19
|
export interface PopoverProps {
|
|
20
20
|
renderButton: (props: Actions) => React.ReactNode
|
|
21
21
|
position?: Position
|
|
22
22
|
className?: string
|
|
23
|
+
closeOnClick?: boolean
|
|
23
24
|
children: React.ReactNode
|
|
24
25
|
}
|
|
25
26
|
|
|
@@ -27,6 +28,7 @@ function Popover({
|
|
|
27
28
|
renderButton,
|
|
28
29
|
position = 'left',
|
|
29
30
|
className,
|
|
31
|
+
closeOnClick = true,
|
|
30
32
|
children,
|
|
31
33
|
}: PopoverProps) {
|
|
32
34
|
const { isOpen, close, open, toggle } = useOpen()
|
|
@@ -44,7 +46,7 @@ function Popover({
|
|
|
44
46
|
className={classNames('popover-menu-container', position, {
|
|
45
47
|
hidden: !isOpen,
|
|
46
48
|
})}
|
|
47
|
-
onClick={close}
|
|
49
|
+
onClick={closeOnClick ? close : () => {}}
|
|
48
50
|
aria-hidden={!isOpen}
|
|
49
51
|
>
|
|
50
52
|
<div className="backdrop"></div>
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
import { Popover } from './Popover'
|
|
2
2
|
import { type Horizontal } from './Popover'
|
|
3
|
+
import { type Position } from './Popover'
|
|
3
4
|
import { PopoverMenu } from './PopoverMenu'
|
|
4
5
|
import { PopoverMenuOption } from './PopoverMenuOption'
|
|
5
6
|
|
|
6
|
-
export {
|
|
7
|
+
export {
|
|
8
|
+
type Horizontal,
|
|
9
|
+
Popover,
|
|
10
|
+
PopoverMenu,
|
|
11
|
+
PopoverMenuOption,
|
|
12
|
+
type Position,
|
|
13
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import './Timeline'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import { classNames } from '../../utils/classNames'
|
|
4
|
+
import { BaseButton, type BaseButtonProps } from '../Button'
|
|
5
|
+
import { Icon, type IconType } from '../Icon'
|
|
6
|
+
|
|
7
|
+
export type Variant = 'primary'
|
|
8
|
+
|
|
9
|
+
export interface CustomProps {
|
|
10
|
+
variant?: Variant
|
|
11
|
+
title: string
|
|
12
|
+
disabled?: boolean
|
|
13
|
+
active?: boolean
|
|
14
|
+
leftIcon?: IconType
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type LoadMoreMilestonesButtonProps = CustomProps & BaseButtonProps
|
|
18
|
+
|
|
19
|
+
export function LoadMoreMilestonesButton({
|
|
20
|
+
variant = 'primary',
|
|
21
|
+
className,
|
|
22
|
+
title,
|
|
23
|
+
disabled,
|
|
24
|
+
leftIcon,
|
|
25
|
+
prefetch = false,
|
|
26
|
+
...props
|
|
27
|
+
}: LoadMoreMilestonesButtonProps): React.JSX.Element {
|
|
28
|
+
const cssClasses = classNames(
|
|
29
|
+
'load-more-milestones-button',
|
|
30
|
+
variant,
|
|
31
|
+
className,
|
|
32
|
+
{
|
|
33
|
+
disabled,
|
|
34
|
+
},
|
|
35
|
+
)
|
|
36
|
+
return (
|
|
37
|
+
<BaseButton
|
|
38
|
+
className={cssClasses}
|
|
39
|
+
aria-disabled={disabled}
|
|
40
|
+
disabled={disabled}
|
|
41
|
+
{...props}
|
|
42
|
+
>
|
|
43
|
+
{leftIcon && <Icon name={leftIcon} size="6" />}
|
|
44
|
+
<span className="title">{title}</span>
|
|
45
|
+
</BaseButton>
|
|
46
|
+
)
|
|
47
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import './Timeline.scss'
|
|
2
|
+
import Link from 'next/link'
|
|
3
|
+
import React from 'react'
|
|
4
|
+
import { classNames } from '../../utils/classNames'
|
|
5
|
+
import { Icon } from '../Icon'
|
|
6
|
+
|
|
7
|
+
export interface MilestoneProps extends React.HTMLAttributes<HTMLLIElement> {
|
|
8
|
+
title: string
|
|
9
|
+
description: string
|
|
10
|
+
isSelected?: boolean
|
|
11
|
+
href?: string
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function Milestone({
|
|
15
|
+
title,
|
|
16
|
+
description,
|
|
17
|
+
isSelected = false,
|
|
18
|
+
href = '',
|
|
19
|
+
className,
|
|
20
|
+
...props
|
|
21
|
+
}: MilestoneProps) {
|
|
22
|
+
return (
|
|
23
|
+
<li
|
|
24
|
+
className={classNames('milestone-item', { selected: isSelected })}
|
|
25
|
+
{...props}
|
|
26
|
+
>
|
|
27
|
+
<div className="left-wrapper">
|
|
28
|
+
<Icon
|
|
29
|
+
name={isSelected ? 'TimelineCircleSelected' : 'TimelineCircleDefault'}
|
|
30
|
+
/>
|
|
31
|
+
</div>
|
|
32
|
+
<div className="right-wrapper">
|
|
33
|
+
{href === '' ? (
|
|
34
|
+
<span className="milestone-title">{title}</span>
|
|
35
|
+
) : (
|
|
36
|
+
<Link href={href} className={classNames('milestone-title-link')}>
|
|
37
|
+
<span className="milestone-title">{title}</span>
|
|
38
|
+
</Link>
|
|
39
|
+
)}
|
|
40
|
+
<p className="milestone-description">{description}</p>
|
|
41
|
+
</div>
|
|
42
|
+
</li>
|
|
43
|
+
)
|
|
44
|
+
}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
@use '../../settings/typography/content' as typography;
|
|
2
|
+
@use '../../settings/config';
|
|
3
|
+
@use '../../settings/mixins';
|
|
4
|
+
@use '../../settings/depth';
|
|
5
|
+
|
|
6
|
+
.timeline-container {
|
|
7
|
+
.timeline-rail {
|
|
8
|
+
position: relative;
|
|
9
|
+
|
|
10
|
+
&::after {
|
|
11
|
+
content: '';
|
|
12
|
+
position: absolute;
|
|
13
|
+
width: config.$space-halfx;
|
|
14
|
+
top: 0;
|
|
15
|
+
bottom: 0;
|
|
16
|
+
left: 11px;
|
|
17
|
+
z-index: depth.$z-timeline-rail;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.milestones-list {
|
|
22
|
+
list-style: none;
|
|
23
|
+
padding: 0;
|
|
24
|
+
margin: config.$space-2x 0px config.$space-2x 6px;
|
|
25
|
+
|
|
26
|
+
.milestone-item {
|
|
27
|
+
display: flex;
|
|
28
|
+
justify-content: flex-start;
|
|
29
|
+
align-items: flex-start;
|
|
30
|
+
gap: config.$space-3x;
|
|
31
|
+
|
|
32
|
+
.left-wrapper {
|
|
33
|
+
display: flex;
|
|
34
|
+
flex-direction: column;
|
|
35
|
+
justify-content: center;
|
|
36
|
+
align-items: center;
|
|
37
|
+
margin-top: config.$space-2x;
|
|
38
|
+
|
|
39
|
+
.icon {
|
|
40
|
+
width: config.$icon-size-3x;
|
|
41
|
+
height: config.$icon-size-3x;
|
|
42
|
+
z-index: depth.$z-timeline-circle;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
.milestone-title {
|
|
47
|
+
@include typography.body-regular-primary;
|
|
48
|
+
}
|
|
49
|
+
.milestone-description {
|
|
50
|
+
@include typography.footnote-primary;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
&.selected {
|
|
54
|
+
.milestone-title {
|
|
55
|
+
@include typography.body-bold;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
&.primary {
|
|
62
|
+
.timeline-rail {
|
|
63
|
+
&::after {
|
|
64
|
+
background-color: var(--neutral-color-200);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
.milestone-item {
|
|
68
|
+
.milestone-description {
|
|
69
|
+
color: var(--neutral-color-600);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.milestone-title-link {
|
|
73
|
+
.milestone-title {
|
|
74
|
+
color: var(--primary-color-600);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
&.selected {
|
|
79
|
+
.milestone-description {
|
|
80
|
+
color: var(--neutral-color-1000);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@include mixins.icon-color(var(--primary-color-600));
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.load-more-milestones-button {
|
|
90
|
+
display: flex;
|
|
91
|
+
justify-content: space-between;
|
|
92
|
+
gap: config.$space-2x;
|
|
93
|
+
border: 0;
|
|
94
|
+
background-color: transparent;
|
|
95
|
+
padding: 0;
|
|
96
|
+
|
|
97
|
+
.icon {
|
|
98
|
+
display: flex;
|
|
99
|
+
justify-content: center;
|
|
100
|
+
align-items: center;
|
|
101
|
+
gap: config.$space-2x;
|
|
102
|
+
border-radius: config.$corner-radius-xxs;
|
|
103
|
+
padding: config.$space-1x;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
&.primary {
|
|
107
|
+
&:hover {
|
|
108
|
+
.icon {
|
|
109
|
+
&:not(:disabled) {
|
|
110
|
+
border: 1px solid var(--primary-color-600);
|
|
111
|
+
background: var(--primary-color-50);
|
|
112
|
+
color: var(--primary-color-600);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.title {
|
|
117
|
+
&:not(:disabled) {
|
|
118
|
+
color: var(--primary-color-800);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.icon {
|
|
124
|
+
border: 1px solid var(--neutral-color-600);
|
|
125
|
+
background: var(--neutral-white);
|
|
126
|
+
@include typography.body-regular-primary;
|
|
127
|
+
|
|
128
|
+
> svg {
|
|
129
|
+
fill: var(--primary-color-600);
|
|
130
|
+
path {
|
|
131
|
+
fill: var(--primary-color-600);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
&:disabled,
|
|
136
|
+
&.disabled {
|
|
137
|
+
pointer-events: none;
|
|
138
|
+
border: 1px solid var(--neutral-color-400);
|
|
139
|
+
background: var(--neutral-color-50);
|
|
140
|
+
color: var(--neutral-color-400);
|
|
141
|
+
> .icon {
|
|
142
|
+
> svg {
|
|
143
|
+
fill: var(--neutral-color-400);
|
|
144
|
+
path {
|
|
145
|
+
fill: var(--neutral-color-400);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.title {
|
|
153
|
+
color: var(--primary-color-600);
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import './Timeline.scss'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import { classNames } from '../../utils/classNames'
|
|
4
|
+
|
|
5
|
+
export type Variant = 'primary'
|
|
6
|
+
export interface TimelineProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
7
|
+
variant?: Variant
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export function Timeline({
|
|
11
|
+
className,
|
|
12
|
+
variant = 'primary',
|
|
13
|
+
children,
|
|
14
|
+
...props
|
|
15
|
+
}: TimelineProps) {
|
|
16
|
+
return (
|
|
17
|
+
<div
|
|
18
|
+
className={classNames('timeline-container', variant, className)}
|
|
19
|
+
{...props}
|
|
20
|
+
>
|
|
21
|
+
<div className="timeline-rail">
|
|
22
|
+
<ol className={classNames('milestones-list')}>{children}</ol>
|
|
23
|
+
</div>
|
|
24
|
+
</div>
|
|
25
|
+
)
|
|
26
|
+
}
|
package/src/icons/index.tsx
CHANGED
|
@@ -40,6 +40,7 @@ import Logout from './logout.svg'
|
|
|
40
40
|
import Minus from './minus.svg'
|
|
41
41
|
import More from './more.svg'
|
|
42
42
|
import NewView from './new-view.svg'
|
|
43
|
+
import Notification from './notification.svg'
|
|
43
44
|
import Orders from './orders.svg'
|
|
44
45
|
import PDF from './pdf.svg'
|
|
45
46
|
import Picture from './picture.svg'
|
|
@@ -57,6 +58,9 @@ import Show from './show.svg'
|
|
|
57
58
|
import ShowOff from './show-off.svg'
|
|
58
59
|
import Sorter from './sorter.svg'
|
|
59
60
|
import TaxRule from './tax-rule.svg'
|
|
61
|
+
import TimelineCircleDefault from './timeline-circle-default.svg'
|
|
62
|
+
import TimelineCircleSelected from './timeline-circle-selected.svg'
|
|
63
|
+
import Traceability from './traceability.svg'
|
|
60
64
|
import Upload from './upload.svg'
|
|
61
65
|
import UserMenu from './user-menu.svg'
|
|
62
66
|
import ValidateInvoice from './validate-invoice.svg'
|
|
@@ -105,6 +109,7 @@ export {
|
|
|
105
109
|
Minus,
|
|
106
110
|
More,
|
|
107
111
|
NewView,
|
|
112
|
+
Notification,
|
|
108
113
|
Orders,
|
|
109
114
|
PDF,
|
|
110
115
|
Picture,
|
|
@@ -122,6 +127,9 @@ export {
|
|
|
122
127
|
ShowOff,
|
|
123
128
|
Sorter,
|
|
124
129
|
TaxRule,
|
|
130
|
+
TimelineCircleDefault,
|
|
131
|
+
TimelineCircleSelected,
|
|
132
|
+
Traceability,
|
|
125
133
|
Upload,
|
|
126
134
|
UserMenu,
|
|
127
135
|
ValidateInvoice,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M2 17.025v-1.983h1.983V8.1c0-1.372.414-2.59 1.24-3.657.826-1.066 1.9-1.764 3.223-2.095v-.694c0-.413.144-.764.434-1.053A1.43 1.43 0 0 1 9.933.167c.414 0 .765.144 1.054.434.29.289.434.64.434 1.053v.694a5.725 5.725 0 0 1 3.223 2.095c.826 1.066 1.24 2.285 1.24 3.657v6.942h1.983v1.983H2ZM9.933 20a1.91 1.91 0 0 1-1.4-.583 1.91 1.91 0 0 1-.583-1.4h3.967a1.91 1.91 0 0 1-.583 1.4 1.91 1.91 0 0 1-1.4.583Z" fill="#161C26"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg"><path d="M0 5a5 5 0 1 1 10 0A5 5 0 0 1 0 5Z" fill="var(--neutral-white)"/><path d="M8 5a3 3 0 1 0-3 3v2A5 5 0 1 1 5 0a5 5 0 0 1 0 10V8a3 3 0 0 0 3-3Z" fill="var(--neutral-color-800)"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg viewBox="0 0 10 10" xmlns="http://www.w3.org/2000/svg"><path d="M0 5a5 5 0 1 1 10 0A5 5 0 0 1 0 5Z" fill="#161C26"/></svg>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path d="M17 19c-.65 0-1.233-.188-1.75-.563A2.91 2.91 0 0 1 14.175 17H9c-1.1 0-2.042-.392-2.825-1.175C5.392 15.042 5 14.1 5 13s.392-2.042 1.175-2.825C6.958 9.392 7.9 9 9 9h2c.55 0 1.02-.196 1.412-.588C12.804 8.021 13 7.55 13 7c0-.55-.196-1.02-.588-1.412A1.926 1.926 0 0 0 11 5H5.825a3.09 3.09 0 0 1-1.088 1.438A2.852 2.852 0 0 1 3 7a2.893 2.893 0 0 1-2.125-.875A2.893 2.893 0 0 1 0 4c0-.833.292-1.542.875-2.125A2.893 2.893 0 0 1 3 1c.65 0 1.23.188 1.737.563.509.375.871.854 1.088 1.437H11c1.1 0 2.042.392 2.825 1.175C14.608 4.958 15 5.9 15 7s-.392 2.042-1.175 2.825C13.042 10.608 12.1 11 11 11H9c-.55 0-1.02.196-1.412.588A1.926 1.926 0 0 0 7 13c0 .55.196 1.02.588 1.412.391.392.862.588 1.412.588h5.175a3.09 3.09 0 0 1 1.087-1.438A2.851 2.851 0 0 1 17 13c.833 0 1.542.292 2.125.875S20 15.167 20 16s-.292 1.542-.875 2.125A2.893 2.893 0 0 1 17 19ZM3 5a.97.97 0 0 0 .712-.287A.968.968 0 0 0 4 4a.968.968 0 0 0-.288-.712A.968.968 0 0 0 3 3a.968.968 0 0 0-.712.288A.968.968 0 0 0 2 4c0 .283.096.52.288.713A.968.968 0 0 0 3 5Z" fill="#161C26"/></svg>
|
package/src/settings/_depth.scss
CHANGED
|
@@ -4,17 +4,27 @@ import { Meta } from "@storybook/addon-docs/blocks";
|
|
|
4
4
|
|
|
5
5
|
# Changelog
|
|
6
6
|
|
|
7
|
+
## 1.2.0
|
|
8
|
+
|
|
9
|
+
* Add NotificationCenter components
|
|
10
|
+
|
|
7
11
|
## 1.1.1
|
|
8
12
|
|
|
9
13
|
* Update to Storybook 10
|
|
10
|
-
* Add custom `composeStories` helper workaround because of Storybook 10 breaking changes
|
|
14
|
+
* Add custom `composeStories` helper workaround for a11y tests because of Storybook 10 breaking changes
|
|
11
15
|
* Add missing components to a11y tests
|
|
12
16
|
|
|
17
|
+
## 1.1.0
|
|
18
|
+
|
|
19
|
+
* Add Timeline, Milestone and LoadMoreMilestonesButton components
|
|
20
|
+
* On Drawer component, `buttons` prop is optional
|
|
21
|
+
* Add Traceability icon
|
|
22
|
+
* Fix Checkbox vertical displacement on CardsTable component
|
|
23
|
+
|
|
13
24
|
## 1.0.9
|
|
14
25
|
|
|
15
26
|
* Add TaxRule icon
|
|
16
27
|
|
|
17
|
-
|
|
18
28
|
## 1.0.8
|
|
19
29
|
|
|
20
30
|
* CardMenuOption can be a button or a link
|
|
@@ -24,12 +34,10 @@ import { Meta } from "@storybook/addon-docs/blocks";
|
|
|
24
34
|
|
|
25
35
|
* Add link styles to Alert component
|
|
26
36
|
|
|
27
|
-
|
|
28
37
|
## 1.0.6
|
|
29
38
|
|
|
30
39
|
* Restore select `disabled` styles
|
|
31
40
|
|
|
32
|
-
|
|
33
41
|
## 1.0.5
|
|
34
42
|
|
|
35
43
|
* Rechecking npm security changes
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import type { StoryObj } from '@storybook/nextjs'
|
|
2
2
|
import React from 'react'
|
|
3
|
-
import {
|
|
3
|
+
import { IconButton } from '../atoms/Button'
|
|
4
4
|
import { Header, type HeaderProps } from '../atoms/Header'
|
|
5
|
-
import { Popover, PopoverMenu, PopoverMenuOption } from '../atoms/Popover'
|
|
6
5
|
|
|
7
6
|
const meta = {
|
|
8
7
|
title: 'Design System/Atoms/Header',
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
import type { StoryObj } from '@storybook/nextjs'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import { Button, IconButton } from '../atoms/Button'
|
|
4
|
+
import { CheckableTag, CheckableTagGroup } from '../atoms/CheckableTag'
|
|
5
|
+
import { Header } from '../atoms/Header'
|
|
6
|
+
import {
|
|
7
|
+
NotificationCenter,
|
|
8
|
+
NotificationEmptyState,
|
|
9
|
+
NotificationHeader,
|
|
10
|
+
NotificationLine,
|
|
11
|
+
NotificationList,
|
|
12
|
+
} from '../atoms/Notification'
|
|
13
|
+
import type { NotificationCenterProps } from '../atoms/Notification/NotificationCenter'
|
|
14
|
+
|
|
15
|
+
const meta = {
|
|
16
|
+
title: 'Design System/Atoms/Notification',
|
|
17
|
+
component: NotificationCenter,
|
|
18
|
+
parameters: {
|
|
19
|
+
docs: {
|
|
20
|
+
description: {
|
|
21
|
+
component:
|
|
22
|
+
'<h2>Usage guidelines</h2>' +
|
|
23
|
+
'<p>The <code>Header</code> component is used to provide consistent branding and global navigation across the application.</p>' +
|
|
24
|
+
'<ul>' +
|
|
25
|
+
' <li>Use it at the top of every page to display the logo, user menu, and language selector</li>' +
|
|
26
|
+
' <li>Keep the header content minimal and focused on global actions only</li>' +
|
|
27
|
+
' <li>Position utility items (language selector, user menu) on the right side for better accessibility</li>' +
|
|
28
|
+
' <li>Maintain consistent height and styling across all pages</li>' +
|
|
29
|
+
'</ul>',
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
tags: ['autodocs', 'Feedback components', 'Layout components'],
|
|
34
|
+
argTypes: {
|
|
35
|
+
children: {
|
|
36
|
+
description: 'Header elements are passed as children',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export default meta
|
|
42
|
+
type Story = StoryObj<typeof meta>
|
|
43
|
+
|
|
44
|
+
export const Primary: Story = {
|
|
45
|
+
render: (props: NotificationCenterProps) => (
|
|
46
|
+
<Header {...props}>
|
|
47
|
+
<h1>Header Title</h1>
|
|
48
|
+
|
|
49
|
+
<div style={{ display: 'flex', gap: '10px', marginRight: '30px' }}>
|
|
50
|
+
<NotificationCenter {...props}>
|
|
51
|
+
<NotificationHeader title="Notifications">
|
|
52
|
+
<CheckableTagGroup>
|
|
53
|
+
<CheckableTag
|
|
54
|
+
variant="primary"
|
|
55
|
+
label="All"
|
|
56
|
+
aria-label="All notifications"
|
|
57
|
+
onSelect={() => alert('click')}
|
|
58
|
+
isChecked={true}
|
|
59
|
+
/>
|
|
60
|
+
<CheckableTag
|
|
61
|
+
variant="primary"
|
|
62
|
+
label="Errors"
|
|
63
|
+
aria-label="Notification errors"
|
|
64
|
+
onSelect={() => alert('click')}
|
|
65
|
+
isChecked={false}
|
|
66
|
+
/>
|
|
67
|
+
<CheckableTag
|
|
68
|
+
variant="primary"
|
|
69
|
+
label="Updates"
|
|
70
|
+
aria-label="Notification updates"
|
|
71
|
+
onSelect={() => alert('click')}
|
|
72
|
+
isChecked={false}
|
|
73
|
+
/>
|
|
74
|
+
</CheckableTagGroup>
|
|
75
|
+
<Button
|
|
76
|
+
onClick={() => alert('mark all as read')}
|
|
77
|
+
label="Mark all as read"
|
|
78
|
+
/>
|
|
79
|
+
</NotificationHeader>
|
|
80
|
+
<NotificationList>
|
|
81
|
+
<NotificationLine
|
|
82
|
+
title="Trophy: Parting on Good Terms"
|
|
83
|
+
date="Jan 04"
|
|
84
|
+
onClick={() => alert('Notification clicked')}
|
|
85
|
+
>
|
|
86
|
+
Good terms? No. I'm here to burn bridges.
|
|
87
|
+
</NotificationLine>
|
|
88
|
+
<NotificationLine title="New operating system update" date="Jan 02">
|
|
89
|
+
Enjoy the new UI and performance improvements. <br /> Contact{' '}
|
|
90
|
+
<a href="support@fakemail.com">support@fakemail.com</a> for help.
|
|
91
|
+
</NotificationLine>
|
|
92
|
+
<NotificationLine title="Trophy: Shell of the Past" date="Dec 30">
|
|
93
|
+
What exactly have we learned?
|
|
94
|
+
</NotificationLine>
|
|
95
|
+
<NotificationLine
|
|
96
|
+
title="New SHf game patch update"
|
|
97
|
+
date="Dec 29"
|
|
98
|
+
isRead={true}
|
|
99
|
+
>
|
|
100
|
+
Fixes a bug when saving the game in certain conditions.
|
|
101
|
+
</NotificationLine>
|
|
102
|
+
<NotificationLine
|
|
103
|
+
title="Trophy: On the Way to School"
|
|
104
|
+
date="Dec 28"
|
|
105
|
+
isRead={true}
|
|
106
|
+
onClick={() => alert('Notification clicked')}
|
|
107
|
+
>
|
|
108
|
+
The little sparrow escapes with its friends, wings flapping
|
|
109
|
+
nervously...
|
|
110
|
+
</NotificationLine>
|
|
111
|
+
</NotificationList>
|
|
112
|
+
</NotificationCenter>
|
|
113
|
+
<IconButton
|
|
114
|
+
icon="UserMenu"
|
|
115
|
+
accessibilityLabel="User menu button"
|
|
116
|
+
variant="secondary"
|
|
117
|
+
/>
|
|
118
|
+
</div>
|
|
119
|
+
</Header>
|
|
120
|
+
),
|
|
121
|
+
} as unknown as Story
|
|
122
|
+
|
|
123
|
+
export const EmptyState: Story = {
|
|
124
|
+
render: (props: NotificationCenterProps) => (
|
|
125
|
+
<Header {...props}>
|
|
126
|
+
<h1>Header Title</h1>
|
|
127
|
+
|
|
128
|
+
<div style={{ display: 'flex', gap: '10px', marginRight: '30px' }}>
|
|
129
|
+
<NotificationCenter {...props}>
|
|
130
|
+
<NotificationHeader title="Notifications">
|
|
131
|
+
<CheckableTagGroup>
|
|
132
|
+
<CheckableTag
|
|
133
|
+
variant="primary"
|
|
134
|
+
label="All"
|
|
135
|
+
aria-label="All notifications"
|
|
136
|
+
onSelect={() => alert('click')}
|
|
137
|
+
isChecked={true}
|
|
138
|
+
/>
|
|
139
|
+
<CheckableTag
|
|
140
|
+
variant="primary"
|
|
141
|
+
label="Errors"
|
|
142
|
+
aria-label="Notification errors"
|
|
143
|
+
onSelect={() => alert('click')}
|
|
144
|
+
isChecked={false}
|
|
145
|
+
/>
|
|
146
|
+
<CheckableTag
|
|
147
|
+
variant="primary"
|
|
148
|
+
label="Updates"
|
|
149
|
+
aria-label="Notification updates"
|
|
150
|
+
onSelect={() => alert('click')}
|
|
151
|
+
isChecked={false}
|
|
152
|
+
/>
|
|
153
|
+
</CheckableTagGroup>
|
|
154
|
+
<Button
|
|
155
|
+
onClick={() => alert('mark all as read')}
|
|
156
|
+
label="Mark all as read"
|
|
157
|
+
/>
|
|
158
|
+
</NotificationHeader>
|
|
159
|
+
<NotificationEmptyState title="No new notifications" date="Jan 21" />
|
|
160
|
+
</NotificationCenter>
|
|
161
|
+
<IconButton
|
|
162
|
+
icon="UserMenu"
|
|
163
|
+
accessibilityLabel="User menu button"
|
|
164
|
+
variant="secondary"
|
|
165
|
+
/>
|
|
166
|
+
</div>
|
|
167
|
+
</Header>
|
|
168
|
+
),
|
|
169
|
+
} as unknown as Story
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import type { StoryObj } from '@storybook/nextjs'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import { Drawer } from '../atoms/Drawer'
|
|
4
|
+
import { Milestone, Timeline } from '../atoms/Timeline'
|
|
5
|
+
import { LoadMoreMilestonesButton } from '../atoms/Timeline/LoadMoreMilestonesButton'
|
|
6
|
+
|
|
7
|
+
const figmaPrimaryDesign = {
|
|
8
|
+
design: {
|
|
9
|
+
type: 'figma',
|
|
10
|
+
url: 'https://www.figma.com/design/DN2ova21vWqCRvPspBXgI1/Design-System?node-id=4786-71&m=dev',
|
|
11
|
+
},
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const meta = {
|
|
15
|
+
title: 'Design System/Atoms/Timeline',
|
|
16
|
+
component: Timeline,
|
|
17
|
+
tags: ['autodocs', 'Data display components'],
|
|
18
|
+
argTypes: {
|
|
19
|
+
variant: {
|
|
20
|
+
description: 'Component variant used',
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
parameters: {
|
|
24
|
+
docs: {
|
|
25
|
+
description: {
|
|
26
|
+
component:
|
|
27
|
+
'<h2>Usage guidelines</h2>' +
|
|
28
|
+
'<p>The vertical display Timeline component shows progress through a workflow or chronological events in a linear order.</p>' +
|
|
29
|
+
'<ul>' +
|
|
30
|
+
' <li>Use it when a series of information needs to be ordered by time (ascending or descending).</li>' +
|
|
31
|
+
' <li>Use it when you need a timeline to make a visual connection.</li>' +
|
|
32
|
+
' <li>The milestone title can either be a button or a link.</li>' +
|
|
33
|
+
'</ul>',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
figmaPrimaryDesign,
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export default meta
|
|
41
|
+
type Story = StoryObj<typeof meta>
|
|
42
|
+
|
|
43
|
+
export const TimelineDrawer: Story = {
|
|
44
|
+
render: () => (
|
|
45
|
+
<Drawer id="timeline-drawer" title="1986" onClose={() => alert('close')}>
|
|
46
|
+
<div style={{ marginTop: '20px' }}>
|
|
47
|
+
<LoadMoreMilestonesButton
|
|
48
|
+
onClick={() => alert('more milestones')}
|
|
49
|
+
variant="primary"
|
|
50
|
+
title="View previous"
|
|
51
|
+
leftIcon="AngleUp"
|
|
52
|
+
/>
|
|
53
|
+
<Timeline>
|
|
54
|
+
<Milestone
|
|
55
|
+
title="1985"
|
|
56
|
+
description="Nintendo
|
|
57
|
+
NES launches with breakout hits like Super
|
|
58
|
+
Mario Bros.
|
|
59
|
+
Sega launches its Master System."
|
|
60
|
+
/>
|
|
61
|
+
<Milestone
|
|
62
|
+
isSelected
|
|
63
|
+
title="1986"
|
|
64
|
+
description="Legend of Zelda comes out, spawning a long series of popular games."
|
|
65
|
+
/>
|
|
66
|
+
<Milestone
|
|
67
|
+
title="1988"
|
|
68
|
+
description="Sega's 16-bit
|
|
69
|
+
Mega Drive is introduced, becoming the company's most successful system."
|
|
70
|
+
/>
|
|
71
|
+
<Milestone
|
|
72
|
+
title="1989"
|
|
73
|
+
description="Nintendo's handheld
|
|
74
|
+
Game Boy hits the market."
|
|
75
|
+
/>
|
|
76
|
+
<Milestone
|
|
77
|
+
title="1991"
|
|
78
|
+
description="Sega's hit Sonic the Hedgehog and the 16-bit
|
|
79
|
+
Super Nintendo come out."
|
|
80
|
+
/>
|
|
81
|
+
<Milestone
|
|
82
|
+
title="1994"
|
|
83
|
+
description="32-bit consoles like the Sega Saturn, Sony PlayStation, and NEC PC-FX launch."
|
|
84
|
+
/>
|
|
85
|
+
</Timeline>
|
|
86
|
+
<LoadMoreMilestonesButton
|
|
87
|
+
onClick={() => alert('more milestones')}
|
|
88
|
+
variant="primary"
|
|
89
|
+
title="View next"
|
|
90
|
+
leftIcon="AngleDown"
|
|
91
|
+
/>
|
|
92
|
+
</div>
|
|
93
|
+
</Drawer>
|
|
94
|
+
),
|
|
95
|
+
} as unknown as Story
|
|
96
|
+
|
|
97
|
+
export const TimelineWithLinksDrawer: Story = {
|
|
98
|
+
render: () => (
|
|
99
|
+
<Drawer id="timeline-drawer" title="1986" onClose={() => alert('close')}>
|
|
100
|
+
<div style={{ marginTop: '20px' }}>
|
|
101
|
+
<LoadMoreMilestonesButton
|
|
102
|
+
onClick={() => alert('more milestones')}
|
|
103
|
+
variant="primary"
|
|
104
|
+
title="View previous"
|
|
105
|
+
leftIcon="AngleUp"
|
|
106
|
+
/>
|
|
107
|
+
<Timeline>
|
|
108
|
+
<Milestone
|
|
109
|
+
title="1985"
|
|
110
|
+
description="Nintendo
|
|
111
|
+
NES launches with breakout hits like Super
|
|
112
|
+
Mario Bros.
|
|
113
|
+
Sega launches its Master System."
|
|
114
|
+
href="link.com"
|
|
115
|
+
/>
|
|
116
|
+
<Milestone
|
|
117
|
+
isSelected
|
|
118
|
+
title="1986"
|
|
119
|
+
description="Legend of Zelda comes out, spawning a long series of popular games."
|
|
120
|
+
href="link.com"
|
|
121
|
+
/>
|
|
122
|
+
<Milestone
|
|
123
|
+
title="1988"
|
|
124
|
+
description="Sega's 16-bit
|
|
125
|
+
Mega Drive is introduced, becoming the company's most successful system."
|
|
126
|
+
href="link.com"
|
|
127
|
+
/>
|
|
128
|
+
<Milestone
|
|
129
|
+
title="1989"
|
|
130
|
+
description="Nintendo's handheld
|
|
131
|
+
Game Boy hits the market."
|
|
132
|
+
href="link.com"
|
|
133
|
+
/>
|
|
134
|
+
<Milestone
|
|
135
|
+
title="1991"
|
|
136
|
+
description="Sega's hit Sonic the Hedgehog and the 16-bit
|
|
137
|
+
Super Nintendo come out."
|
|
138
|
+
href="link.com"
|
|
139
|
+
/>
|
|
140
|
+
<Milestone
|
|
141
|
+
title="1994"
|
|
142
|
+
description="32-bit consoles like the Sega Saturn, Sony PlayStation, and NEC PC-FX launch."
|
|
143
|
+
href="link.com"
|
|
144
|
+
/>
|
|
145
|
+
</Timeline>
|
|
146
|
+
<LoadMoreMilestonesButton
|
|
147
|
+
onClick={() => alert('more milestones')}
|
|
148
|
+
variant="primary"
|
|
149
|
+
title="View next"
|
|
150
|
+
leftIcon="AngleDown"
|
|
151
|
+
/>
|
|
152
|
+
</div>
|
|
153
|
+
</Drawer>
|
|
154
|
+
),
|
|
155
|
+
} as unknown as Story
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { render } from '@testing-library/react'
|
|
2
|
+
import React from 'react'
|
|
3
|
+
import { Milestone, Timeline } from '../src/atoms/Timeline'
|
|
4
|
+
import { LoadMoreMilestonesButton } from '../src/atoms/Timeline/LoadMoreMilestonesButton'
|
|
5
|
+
|
|
6
|
+
describe('Timeline', () => {
|
|
7
|
+
it('renders with expected content and buttons', () => {
|
|
8
|
+
const { getByText, getAllByRole } = render(
|
|
9
|
+
<>
|
|
10
|
+
<LoadMoreMilestonesButton
|
|
11
|
+
onClick={() => jest.fn()}
|
|
12
|
+
variant="primary"
|
|
13
|
+
title="View previous"
|
|
14
|
+
leftIcon="AngleUp"
|
|
15
|
+
/>
|
|
16
|
+
<Timeline>
|
|
17
|
+
<Milestone
|
|
18
|
+
title="1985"
|
|
19
|
+
description="Nintendo
|
|
20
|
+
NES launches with breakout hits like Super
|
|
21
|
+
Mario Bros.
|
|
22
|
+
Sega launches its Master System."
|
|
23
|
+
/>
|
|
24
|
+
<Milestone
|
|
25
|
+
isSelected
|
|
26
|
+
title="1986"
|
|
27
|
+
description="Legend of Zelda comes out, spawning a long series of popular games."
|
|
28
|
+
/>
|
|
29
|
+
</Timeline>
|
|
30
|
+
<LoadMoreMilestonesButton
|
|
31
|
+
onClick={() => jest.fn()}
|
|
32
|
+
variant="primary"
|
|
33
|
+
title="View next"
|
|
34
|
+
leftIcon="AngleDown"
|
|
35
|
+
/>
|
|
36
|
+
</>,
|
|
37
|
+
)
|
|
38
|
+
expect(getByText('1985')).toBeInTheDocument()
|
|
39
|
+
expect(getByText(/Nintendo NES launches with/i)).toBeInTheDocument()
|
|
40
|
+
expect(getByText('1986')).toBeInTheDocument()
|
|
41
|
+
expect(getByText(/Legend of Zelda comes out/i)).toBeInTheDocument()
|
|
42
|
+
expect(getAllByRole('listitem')[0]).toHaveClass('milestone-item')
|
|
43
|
+
expect(getAllByRole('listitem')[1]).toHaveClass('milestone-item selected')
|
|
44
|
+
expect(getAllByRole('button')[0]).toBeInTheDocument()
|
|
45
|
+
expect(getAllByRole('button')[1]).toBeInTheDocument()
|
|
46
|
+
expect(getAllByRole('button')[0]).toHaveClass(
|
|
47
|
+
'load-more-milestones-button primary',
|
|
48
|
+
)
|
|
49
|
+
expect(getAllByRole('button')[1]).toHaveClass(
|
|
50
|
+
'load-more-milestones-button primary',
|
|
51
|
+
)
|
|
52
|
+
})
|
|
53
|
+
})
|
package/tests/library.ts
CHANGED
|
@@ -36,3 +36,4 @@ export * as Select from '../src/stories/Select.stories'
|
|
|
36
36
|
export * as Switch from '../src/stories/Switch.stories'
|
|
37
37
|
export * as TabMenu from '../src/stories/TabMenu.stories'
|
|
38
38
|
export * as TextArea from '../src/stories/TextArea.stories'
|
|
39
|
+
export * as Timeline from '../src/stories/Timeline.stories'
|