agroptima-design-system 1.0.7 → 1.1.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agroptima-design-system",
3
- "version": "1.0.7",
3
+ "version": "1.1.0-beta.1",
4
4
  "scripts": {
5
5
  "dev": "npm run storybook",
6
6
  "storybook": "storybook dev -p 6006 --ci",
@@ -47,7 +47,7 @@
47
47
  cursor: default;
48
48
  }
49
49
 
50
- .checkbox {
50
+ .checkbox-group {
51
51
  margin-top: config.$space-1x;
52
52
  }
53
53
 
@@ -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: ButtonProps[]
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
- <div className="footer">
63
- <Actions>
64
- {buttons.map(({ ...button }) => (
65
- <Button key={button.label} {...button} />
66
- ))}
67
- </Actions>
68
- </div>
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
  )
@@ -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
+ }
@@ -0,0 +1,5 @@
1
+ import { Timeline } from './Timeline'
2
+ export type { TimelineProps } from './Timeline'
3
+ import { Milestone } from './Milestone'
4
+
5
+ export { Milestone, Timeline }
@@ -56,6 +56,9 @@ import Settings from './settings.svg'
56
56
  import Show from './show.svg'
57
57
  import ShowOff from './show-off.svg'
58
58
  import Sorter from './sorter.svg'
59
+ import TimelineCircleDefault from './timeline-circle-default.svg'
60
+ import TimelineCircleSelected from './timeline-circle-selected.svg'
61
+ import Traceability from './traceability.svg'
59
62
  import Upload from './upload.svg'
60
63
  import UserMenu from './user-menu.svg'
61
64
  import ValidateInvoice from './validate-invoice.svg'
@@ -120,6 +123,9 @@ export {
120
123
  Show,
121
124
  ShowOff,
122
125
  Sorter,
126
+ TimelineCircleDefault,
127
+ TimelineCircleSelected,
128
+ Traceability,
123
129
  Upload,
124
130
  UserMenu,
125
131
  ValidateInvoice,
@@ -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>
@@ -13,4 +13,7 @@ $z-modal: $z-alert-container + $above;
13
13
  $z-aside-desktop: $base + $above;
14
14
  $z-aside-mobile: $z-modal + $above;
15
15
 
16
- $z-header: $base + $above;
16
+ $z-header: $base + $above;
17
+
18
+ $z-timeline-rail: $base;
19
+ $z-timeline-circle: $base + $above;
@@ -4,16 +4,21 @@ import { Meta } from "@storybook/addon-docs/blocks";
4
4
 
5
5
  # Changelog
6
6
 
7
+ ## 1.1.0
8
+
9
+ * Add Timeline, Milestone and LoadMoreMilestonesButton components
10
+ * On Drawer component, `buttons` prop is optional
11
+ * Add Traceability icon
12
+ * Fix Checkbox vertical displacement on CardsTable component
13
+
7
14
  ## 1.0.7
8
15
 
9
16
  * Add link styles to Alert component
10
17
 
11
-
12
18
  ## 1.0.6
13
19
 
14
20
  * Restore select `disabled` styles
15
21
 
16
-
17
22
  ## 1.0.5
18
23
 
19
24
  * Rechecking npm security changes
@@ -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
+ })