agroptima-design-system 0.28.0-beta.9 → 0.28.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.
@@ -15,6 +15,7 @@ jobs:
15
15
  with:
16
16
  node-version: '20.x'
17
17
  registry-url: 'https://registry.npmjs.org'
18
+ - run: npm config set legacy-peer-deps true
18
19
  - run: npm ci --force
19
20
  - run: npm publish
20
21
  env:
@@ -0,0 +1,5 @@
1
+ {
2
+ "onlyChanged": true,
3
+ "projectId": "Project:653ba0ccdf919d51bb667622",
4
+ "zip": true
5
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agroptima-design-system",
3
- "version": "0.28.0-beta.9",
3
+ "version": "0.28.0",
4
4
  "scripts": {
5
5
  "dev": "npm run storybook",
6
6
  "storybook": "storybook dev -p 6006 --ci",
@@ -22,19 +22,19 @@
22
22
  "sass": "^1.83.1"
23
23
  },
24
24
  "devDependencies": {
25
- "@chromatic-com/storybook": "^3.2.3",
25
+ "@chromatic-com/storybook": "^3.2.4",
26
26
  "@eslint/eslintrc": "^3.2.0",
27
27
  "@eslint/js": "^9.16.0",
28
- "@storybook/addon-a11y": "^8.4.7",
28
+ "@storybook/addon-a11y": "^8.5.1",
29
29
  "@storybook/addon-designs": "^8.0.4",
30
- "@storybook/addon-essentials": "^8.4.7",
31
- "@storybook/addon-interactions": "^8.4.7",
32
- "@storybook/addon-links": "^8.4.7",
33
- "@storybook/addon-viewport": "^8.4.7",
34
- "@storybook/blocks": "^8.4.7",
35
- "@storybook/nextjs": "^8.4.7",
36
- "@storybook/react": "^8.4.7",
37
- "@storybook/test": "^8.4.7",
30
+ "@storybook/addon-essentials": "^8.5.1",
31
+ "@storybook/addon-interactions": "^8.5.1",
32
+ "@storybook/addon-links": "^8.5.1",
33
+ "@storybook/addon-viewport": "^8.5.1",
34
+ "@storybook/blocks": "^8.5.1",
35
+ "@storybook/nextjs": "^8.5.1",
36
+ "@storybook/react": "^8.5.1",
37
+ "@storybook/test": "^8.5.1",
38
38
  "@svgr/webpack": "^8.1.0",
39
39
  "@testing-library/jest-dom": "^6.6.3",
40
40
  "@testing-library/react": "^16.1.0",
@@ -55,7 +55,7 @@
55
55
  "jest-axe": "^9.0.0",
56
56
  "jest-environment-jsdom": "^29.7.0",
57
57
  "prettier": "^3.4.2",
58
- "storybook": "^8.4.7",
58
+ "storybook": "^8.5.1",
59
59
  "ts-node": "^10.9.2",
60
60
  "typescript": "^5.7.2"
61
61
  },
@@ -13,7 +13,7 @@ a.card {
13
13
  .card {
14
14
  display: flex;
15
15
  flex-direction: column;
16
- gap: config.$space-1x;
16
+ gap: config.$space-2x;
17
17
  padding: config.$space-3x;
18
18
  width: 100%;
19
19
  p {
@@ -27,17 +27,12 @@ a.card {
27
27
  .icon {
28
28
  width: config.$icon-size-4x;
29
29
  height: config.$icon-size-4x;
30
- > svg {
31
- width: 100%;
32
- height: 100%;
33
- }
34
30
  }
35
31
 
36
32
  .header {
37
33
  display: flex;
38
34
  flex-direction: row;
39
35
  justify-content: space-between;
40
- margin-bottom: config.$space-1x;
41
36
  gap: config.$space-1x;
42
37
  .title {
43
38
  overflow: hidden;
@@ -52,7 +47,7 @@ a.card {
52
47
  }
53
48
 
54
49
  .content {
55
- margin-bottom: config.$space-2x;
50
+ margin-bottom: config.$space-1x;
56
51
  }
57
52
 
58
53
  .footer {
@@ -13,6 +13,8 @@ export interface CardProps {
13
13
  isActive?: boolean
14
14
  error?: boolean
15
15
  href?: string
16
+ onClick?: () => void
17
+ role?: string
16
18
  children: React.ReactNode
17
19
  }
18
20
 
@@ -33,6 +35,7 @@ export function Card({
33
35
  disabled: isDisabled,
34
36
  active: isActive,
35
37
  error: error,
38
+ clickable: Boolean(props.onClick),
36
39
  })
37
40
 
38
41
  if (href && !isDisabled) {
@@ -4,7 +4,7 @@ import { classNames } from '../../utils/classNames'
4
4
 
5
5
  export interface CardHeaderProps extends React.ComponentPropsWithoutRef<'div'> {
6
6
  title: string
7
- isBold: boolean
7
+ isBold?: boolean
8
8
  }
9
9
 
10
10
  export function CardHeader({
@@ -1,75 +1,36 @@
1
+ @use '../../settings/mixins';
1
2
  @use '../../settings/color_alias';
2
3
  @use '../../settings/typography/cards_table' as typography;
3
4
  @use '../../settings/config';
4
5
  @use '../../settings/breakpoints';
5
6
 
6
- @mixin align-data-vertically() {
7
- thead {
8
- display: none;
9
- }
10
-
11
- tbody {
12
- tr {
13
- flex-direction: row;
14
- flex-wrap: wrap;
15
- position: relative;
16
- gap: config.$space-1x;
17
- padding: config.$space-2x config.$space-3x;
18
- }
19
- }
7
+ .cards-table-list {
8
+ border-collapse: separate;
9
+ border-spacing: 0 config.$space-2x;
10
+ width: 100%;
20
11
 
12
+ th,
21
13
  td {
22
- width: 100%;
23
- flex: inherit;
24
- padding: 0px;
14
+ padding: config.$space-2x config.$space-3x;
15
+ padding: config.$space-2x config.$space-3x;
25
16
  }
26
- }
27
-
28
- .cards-table-list {
29
- display: flex;
30
- flex-direction: column;
31
- gap: config.$space-3x;
32
17
 
33
18
  tbody {
34
- display: flex;
35
- flex-direction: column;
36
- gap: config.$space-3x;
37
-
38
19
  tr {
39
20
  box-shadow: 0px 0px 3px 0px rgba(0, 0, 0, 0.25);
21
+ cursor: default;
40
22
  }
41
23
  }
42
24
 
43
- tr {
25
+ .cell {
44
26
  display: flex;
45
- flex-grow: 1;
46
- }
47
-
48
- .container {
49
- display: flex;
50
- flex-direction: row;
51
- justify-content: space-between;
52
27
  align-items: center;
53
- width: 100%;
28
+ gap: config.$space-2x;
54
29
  }
55
30
 
56
- th {
57
- padding: config.$space-2x config.$space-3x;
58
- text-align: left;
59
-
60
- &.sortable {
61
- cursor: pointer;
62
- }
63
-
64
- .icon {
65
- width: config.$icon-size-3x;
66
- height: config.$icon-size-3x;
67
- margin-left: config.$space-1x;
68
- > svg {
69
- width: 100%;
70
- height: 100%;
71
- }
72
- }
31
+ .actions > .cell {
32
+ gap: config.$space-7x;
33
+ justify-content: center;
73
34
  }
74
35
 
75
36
  .no-wrap {
@@ -80,13 +41,12 @@
80
41
  justify-content: flex-start;
81
42
  }
82
43
 
83
- .alignment-center {
84
- justify-content: center;
44
+ .alignment-right {
45
+ justify-content: flex-end !important;
85
46
  }
86
47
 
87
- .actions {
88
- display: flex;
89
- gap: config.$space-7x;
48
+ .alignment-center {
49
+ justify-content: center;
90
50
  }
91
51
 
92
52
  &.primary {
@@ -96,37 +56,7 @@
96
56
 
97
57
  th {
98
58
  background: color_alias.$neutral-color-900;
99
-
100
- .icon {
101
- > svg {
102
- fill: color_alias.$neutral-white;
103
- path {
104
- fill: color_alias.$neutral-white;
105
- }
106
- }
107
-
108
- &.ascending {
109
- > svg {
110
- .sorter_svg__up {
111
- fill: color_alias.$primary-color-600;
112
- }
113
- .sorter_svg__down {
114
- fill: color_alias.$neutral-white;
115
- }
116
- }
117
- }
118
-
119
- &.descending {
120
- > svg {
121
- .sorter_svg__up {
122
- fill: color_alias.$neutral-white;
123
- }
124
- .sorter_svg__down {
125
- fill: color_alias.$primary-color-600;
126
- }
127
- }
128
- }
129
- }
59
+ @include mixins.icon-color(color_alias.$neutral-white);
130
60
  }
131
61
 
132
62
  th:first-child {
@@ -154,77 +84,74 @@
154
84
 
155
85
  tr.disabled {
156
86
  background: color_alias.$neutral-color-50;
157
-
158
87
  td {
159
88
  @include typography.cards-table-list-disabled-text;
160
89
  }
161
90
  }
91
+
92
+ tr > td {
93
+ border-top: 1px solid transparent;
94
+ border-bottom: 1px solid transparent;
95
+ &:first-child {
96
+ border-left: 1px solid transparent;
97
+ }
98
+ &:last-child {
99
+ border-right: 1px solid transparent;
100
+ }
101
+ }
102
+
162
103
  tr.active {
163
- border-color: color_alias.$primary-color-1000;
164
104
  box-shadow: none;
105
+ > td {
106
+ border-color: color_alias.$primary-color-1000;
107
+ }
165
108
  }
166
- tr.action {
167
- cursor: default;
168
- }
169
- }
170
-
171
- // Desktop
172
- thead {
173
- display: flex;
174
- }
175
- tr {
176
- flex-direction: row;
177
109
  }
178
110
 
179
- th,
180
- td {
181
- display: flex;
182
- justify-content: flex-start;
183
- align-items: center;
184
- flex: 2;
185
-
186
- .checkbox-group {
187
- margin-right: config.$space-1x;
111
+ @media only screen and (max-width: breakpoints.$large) {
112
+ thead {
113
+ display: none;
188
114
  }
189
- }
190
-
191
- td {
192
- padding: config.$space-2x config.$space-3x;
193
- }
194
115
 
195
- th.actions {
196
- justify-content: center;
197
- }
198
-
199
- td.actions {
200
- order: 0;
201
- justify-content: center;
202
- }
203
-
204
- .badge:has(.icon) {
205
- margin: auto;
206
- }
116
+ tr {
117
+ display: flex;
118
+ flex-direction: row;
119
+ flex-wrap: wrap;
120
+ position: relative;
121
+ margin-block: config.$space-3x;
122
+ padding: config.$space-2x config.$space-3x;
123
+ gap: config.$space-1x;
124
+ }
207
125
 
208
- .alignment-right {
209
- justify-content: flex-end !important;
210
- }
126
+ td {
127
+ width: 100%;
128
+ flex: inherit;
129
+ padding: 0px;
130
+ }
211
131
 
212
- &.vertically {
213
- @include align-data-vertically();
214
- }
132
+ .actions {
133
+ width: auto;
134
+ position: absolute;
135
+ inset: config.$space-3x config.$space-3x auto auto;
136
+ }
215
137
 
216
- // Media queries
217
- // Mobile & tablet cases
218
- @media only screen and (max-width: breakpoints.$large) {
219
- @include align-data-vertically();
138
+ .floating-left-mobile {
139
+ width: auto;
140
+ order: 98;
141
+ }
220
142
 
221
- td:first-child {
222
- order: -2;
143
+ .floating-right-mobile {
144
+ margin-left: auto;
145
+ width: auto;
146
+ order: 99;
223
147
  }
224
148
 
225
- .badge:has(.icon) {
226
- margin: 0;
227
- margin-left: config.$space-2x;
149
+ tr.active {
150
+ box-shadow: none;
151
+ border: 1px solid color_alias.$primary-color-1000;
152
+ > td {
153
+ border-color: transparent !important;
154
+ }
228
155
  }
229
156
 
230
157
  &.with-title td:not(.actions):nth-child(2) {
@@ -246,39 +173,5 @@
246
173
  .title-actions-1 {
247
174
  width: calc(100% - 1 * config.$icon-size-5x - 8px);
248
175
  }
249
-
250
- td.actions {
251
- order: -1;
252
- flex-grow: 1;
253
- align-items: flex-start;
254
- justify-content: flex-end;
255
- flex-basis: content;
256
- }
257
-
258
- .alignment-right {
259
- justify-content: flex-start;
260
- }
261
-
262
- .badge {
263
- position: absolute;
264
- inset: auto auto config.$space-2x config.$space-2x;
265
- }
266
-
267
- .badge:has(> .icon) {
268
- position: relative;
269
- inset: inherit;
270
- }
271
-
272
- td:has(.badge > .icon) {
273
- justify-content: flex-start;
274
- }
275
-
276
- // Specify Badge vertical position depending on having a right aligned item or not
277
- tr:not(.alignment-right) {
278
- padding-bottom: config.$space-10x;
279
- }
280
- tr:has(.alignment-right) {
281
- padding-bottom: config.$space-2x;
282
- }
283
176
  }
284
177
  }
@@ -7,7 +7,6 @@ export interface CardsTableProps
7
7
  extends React.ComponentPropsWithoutRef<'table'> {
8
8
  variant?: Variant
9
9
  withTitle?: boolean
10
- vertically?: boolean
11
10
  }
12
11
 
13
12
  export function CardsTable({
@@ -15,13 +14,11 @@ export function CardsTable({
15
14
  summary,
16
15
  variant = 'primary',
17
16
  withTitle = false,
18
- vertically = false,
19
17
  children,
20
18
  ...props
21
19
  }: CardsTableProps): React.JSX.Element {
22
20
  const cssClasses = classNames('cards-table-list', variant, className, {
23
21
  'with-title': withTitle,
24
- vertically: vertically,
25
22
  })
26
23
  return (
27
24
  <table summary={summary} role="table" className={cssClasses} {...props}>
@@ -13,6 +13,8 @@ export interface CardsTableCellProps
13
13
  noWrap?: boolean
14
14
  align?: Alignment
15
15
  actions?: boolean
16
+ floatingLeftMobile?: boolean
17
+ floatingRightMobile?: boolean
16
18
  titleWithActions?: number
17
19
  }
18
20
 
@@ -21,6 +23,8 @@ export function CardsTableCell({
21
23
  actions = false,
22
24
  titleWithActions = 0,
23
25
  align = Alignment.Left,
26
+ floatingLeftMobile = false,
27
+ floatingRightMobile = false,
24
28
  children,
25
29
  className,
26
30
  ...props
@@ -34,12 +38,25 @@ export function CardsTableCell({
34
38
  className,
35
39
  {
36
40
  'no-wrap': noWrap,
37
- actions,
38
41
  },
39
42
  )
43
+
44
+ const actionsStopPropagation = actions
45
+ ? { onClick: (e: React.MouseEvent) => e.stopPropagation() }
46
+ : {}
47
+
40
48
  return (
41
- <td role="cell" className={cssClasses} {...props}>
42
- {children}
49
+ <td
50
+ role="cell"
51
+ className={classNames({
52
+ actions,
53
+ 'floating-left-mobile': floatingLeftMobile,
54
+ 'floating-right-mobile': floatingRightMobile,
55
+ })}
56
+ {...actionsStopPropagation}
57
+ {...props}
58
+ >
59
+ <div className={cssClasses}>{children}</div>
43
60
  </td>
44
61
  )
45
62
  }
@@ -14,12 +14,18 @@ export function CardsTableHeader({
14
14
  actions = false,
15
15
  ...props
16
16
  }: CardsTableHeaderProps) {
17
- const cssClasses = classNames('header', `alignment-${align}`, className, {
18
- actions,
19
- })
17
+ const cssClasses = classNames(
18
+ 'header',
19
+ 'cell',
20
+ `alignment-${align}`,
21
+ className,
22
+ {
23
+ actions,
24
+ },
25
+ )
20
26
  return (
21
- <th scope="col" role="columnheader" className={cssClasses} {...props}>
22
- {children}
27
+ <th role="columnheader" {...props}>
28
+ <div className={cssClasses}>{children}</div>
23
29
  </th>
24
30
  )
25
31
  }
@@ -20,7 +20,6 @@ export function CardsTableRow({
20
20
  className={classNames('row', {
21
21
  disabled,
22
22
  active,
23
- action: Boolean(props.onClick),
24
23
  })}
25
24
  {...props}
26
25
  >
@@ -42,7 +42,12 @@ export function Checkbox({
42
42
  aria-label={accessibilityLabel || label}
43
43
  {...props}
44
44
  />
45
- {!hideLabel && <label htmlFor={identifier}>{label}</label>}
45
+ <label
46
+ htmlFor={identifier}
47
+ className={classNames({ 'visually-hidden': hideLabel })}
48
+ >
49
+ {label}
50
+ </label>
46
51
  </div>
47
52
  )
48
53
  }
@@ -4,10 +4,12 @@
4
4
  @use '../settings/depth';
5
5
  @use '../settings/breakpoints';
6
6
 
7
+ // Interpolation applied: https://sass-lang.com/documentation/breaking-changes/css-vars/
8
+
7
9
  .date-picker {
8
10
  .rdp-root {
9
11
  width: 309px;
10
- --rdp-accent-color: #eb004dff; // color_alias.$primary-color-600;
11
- --rdp-accent-background-color: #ffedeeff; // color_alias.$primary-color-50;
12
+ --rdp-accent-color: #{color_alias.$primary-color-600};
13
+ --rdp-accent-background-color: #{color_alias.$primary-color-50};
12
14
  }
13
15
  }
@@ -1,23 +1,32 @@
1
1
  import 'react-day-picker/style.css'
2
2
  import './DatePicker.scss'
3
3
  import { useEffect, useState } from 'react'
4
- import { type DateRange, DayPicker } from 'react-day-picker'
4
+ import { type DateRange, DayPicker, type Locale } from 'react-day-picker'
5
5
  import { enGB, es } from 'react-day-picker/locale'
6
6
  import { classNames } from '../utils/classNames'
7
7
 
8
8
  export type Variant = 'primary'
9
9
 
10
- type DivPropsWithoutOnChange = Omit<
10
+ type DivPropsWithoutOnSelect = Omit<
11
11
  React.ComponentPropsWithoutRef<'div'>,
12
12
  'onSelect'
13
13
  >
14
14
 
15
- export interface CalendarProps extends DivPropsWithoutOnChange {
15
+ interface AvailableLocale {
16
+ [index: string]: Locale
17
+ }
18
+
19
+ const availableLocales: AvailableLocale = {
20
+ es: es,
21
+ en: enGB,
22
+ }
23
+
24
+ export interface DatePickerProps extends DivPropsWithoutOnSelect {
16
25
  variant?: Variant
17
26
  onSelect: (dateRange: DateRange | undefined) => void
18
27
  footer: string
19
28
  selected?: DateRange
20
- locale?: string
29
+ lng: keyof typeof availableLocales
21
30
  }
22
31
 
23
32
  export function DatePicker({
@@ -26,13 +35,12 @@ export function DatePicker({
26
35
  onSelect = () => {},
27
36
  footer = 'Pick a day',
28
37
  selected: preselected,
29
- locale = 'es',
30
- }: CalendarProps): React.JSX.Element {
38
+ lng,
39
+ }: DatePickerProps): React.JSX.Element {
31
40
  useEffect(() => {
32
41
  setSelected(preselected)
33
42
  }, [preselected])
34
43
 
35
- console.log('preselected: ', preselected)
36
44
  const cssClasses = classNames('date-picker', variant, className)
37
45
 
38
46
  const [selected, setSelected] = useState<DateRange | undefined>(preselected)
@@ -45,7 +53,7 @@ export function DatePicker({
45
53
  return (
46
54
  <div className={cssClasses}>
47
55
  <DayPicker
48
- locale={locale === 'es' ? es : enGB}
56
+ locale={availableLocales[lng]}
49
57
  mode="range"
50
58
  min={1}
51
59
  selected={selected}
@@ -1,6 +1,15 @@
1
1
  @use '../settings/color_alias';
2
2
  @use '../settings/config';
3
3
 
4
+ @mixin icon-color($color) {
5
+ .icon > svg {
6
+ fill: $color;
7
+ path {
8
+ fill: $color;
9
+ }
10
+ }
11
+ }
12
+
4
13
  .icon {
5
14
  display: inline-flex;
6
15
  justify-content: center;