agroptima-design-system 0.28.0-beta.9 → 0.28.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.
@@ -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.1",
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,56 @@
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;
7
+ @mixin generate-title-actions($max-actions: 5) {
8
+ @for $actions from 1 through $max-actions {
9
+ .title-actions-#{$actions} {
10
+ width: calc(
11
+ 100% -
12
+ #{$actions} *
13
+ config.$icon-size-5x -
14
+ #{($actions - 1) *
15
+ config.$space-7x} -
16
+ config.$space-3x
17
+ );
18
18
  }
19
19
  }
20
-
21
- td {
22
- width: 100%;
23
- flex: inherit;
24
- padding: 0px;
25
- }
26
20
  }
27
21
 
28
22
  .cards-table-list {
29
- display: flex;
30
- flex-direction: column;
31
- gap: config.$space-3x;
23
+ border-collapse: separate;
24
+ border-spacing: 0 config.$space-2x;
25
+ width: 100%;
32
26
 
33
- tbody {
34
- display: flex;
35
- flex-direction: column;
36
- gap: config.$space-3x;
27
+ th,
28
+ td {
29
+ vertical-align: top;
30
+ padding: config.$space-2x config.$space-3x;
31
+ padding: config.$space-2x config.$space-3x;
32
+ }
37
33
 
34
+ tbody {
38
35
  tr {
39
36
  box-shadow: 0px 0px 3px 0px rgba(0, 0, 0, 0.25);
37
+ cursor: default;
40
38
  }
41
39
  }
42
40
 
43
- tr {
41
+ .cell {
44
42
  display: flex;
45
- flex-grow: 1;
43
+ align-items: flex-start;
44
+ gap: config.$space-2x;
46
45
  }
47
46
 
48
- .container {
49
- display: flex;
50
- flex-direction: row;
51
- justify-content: space-between;
52
- align-items: center;
53
- width: 100%;
47
+ .checkbox {
48
+ margin-top: config.$space-1x;
54
49
  }
55
50
 
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
- }
51
+ .actions > .cell {
52
+ gap: config.$space-7x;
53
+ justify-content: center;
73
54
  }
74
55
 
75
56
  .no-wrap {
@@ -80,13 +61,12 @@
80
61
  justify-content: flex-start;
81
62
  }
82
63
 
83
- .alignment-center {
84
- justify-content: center;
64
+ .alignment-right {
65
+ justify-content: flex-end !important;
85
66
  }
86
67
 
87
- .actions {
88
- display: flex;
89
- gap: config.$space-7x;
68
+ .alignment-center {
69
+ justify-content: center;
90
70
  }
91
71
 
92
72
  &.primary {
@@ -96,37 +76,7 @@
96
76
 
97
77
  th {
98
78
  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
- }
79
+ @include mixins.icon-color(color_alias.$neutral-white);
130
80
  }
131
81
 
132
82
  th:first-child {
@@ -154,131 +104,80 @@
154
104
 
155
105
  tr.disabled {
156
106
  background: color_alias.$neutral-color-50;
157
-
158
107
  td {
159
108
  @include typography.cards-table-list-disabled-text;
160
109
  }
161
110
  }
162
- tr.active {
163
- border-color: color_alias.$primary-color-1000;
164
- box-shadow: none;
165
- }
166
- tr.action {
167
- cursor: default;
168
- }
169
- }
170
-
171
- // Desktop
172
- thead {
173
- display: flex;
174
- }
175
- tr {
176
- flex-direction: row;
177
- }
178
111
 
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;
112
+ tr > td {
113
+ border-top: 1px solid transparent;
114
+ border-bottom: 1px solid transparent;
115
+ &:first-child {
116
+ border-left: 1px solid transparent;
117
+ }
118
+ &:last-child {
119
+ border-right: 1px solid transparent;
120
+ }
188
121
  }
189
- }
190
122
 
191
- td {
192
- padding: config.$space-2x config.$space-3x;
193
- }
194
-
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
- }
207
-
208
- .alignment-right {
209
- justify-content: flex-end !important;
210
- }
211
-
212
- &.vertically {
213
- @include align-data-vertically();
123
+ tr.active {
124
+ box-shadow: none;
125
+ > td {
126
+ border-color: color_alias.$primary-color-1000;
127
+ }
128
+ }
214
129
  }
215
130
 
216
- // Media queries
217
- // Mobile & tablet cases
218
131
  @media only screen and (max-width: breakpoints.$large) {
219
- @include align-data-vertically();
220
-
221
- td:first-child {
222
- order: -2;
223
- }
224
-
225
- .badge:has(.icon) {
226
- margin: 0;
227
- margin-left: config.$space-2x;
132
+ thead {
133
+ display: none;
228
134
  }
229
135
 
230
- &.with-title td:not(.actions):nth-child(2) {
231
- margin-top: config.$space-2x;
136
+ tr {
137
+ display: flex;
138
+ flex-direction: row;
139
+ flex-wrap: wrap;
140
+ position: relative;
141
+ margin-block: config.$space-3x;
142
+ padding: config.$space-2x config.$space-3x;
143
+ gap: config.$space-1x;
232
144
  }
233
145
 
234
- .title-actions-5 {
235
- width: calc(100% - 5 * config.$icon-size-5x - 4 * config.$space-7x - 8px);
236
- }
237
- .title-actions-4 {
238
- width: calc(100% - 4 * config.$icon-size-5x - 3 * config.$space-7x - 8px);
239
- }
240
- .title-actions-3 {
241
- width: calc(100% - 3 * config.$icon-size-5x - 2 * config.$space-7x - 8px);
242
- }
243
- .title-actions-2 {
244
- width: calc(100% - 2 * config.$icon-size-5x - 1 * config.$space-7x - 8px);
245
- }
246
- .title-actions-1 {
247
- width: calc(100% - 1 * config.$icon-size-5x - 8px);
146
+ td {
147
+ width: 100%;
148
+ flex: inherit;
149
+ padding: 0px;
248
150
  }
249
151
 
250
- td.actions {
251
- order: -1;
252
- flex-grow: 1;
253
- align-items: flex-start;
254
- justify-content: flex-end;
255
- flex-basis: content;
152
+ .actions {
153
+ width: auto;
154
+ position: absolute;
155
+ inset: config.$space-3x config.$space-3x auto auto;
256
156
  }
257
157
 
258
- .alignment-right {
259
- justify-content: flex-start;
158
+ .floating-left-mobile {
159
+ width: auto;
160
+ order: 98;
260
161
  }
261
162
 
262
- .badge {
263
- position: absolute;
264
- inset: auto auto config.$space-2x config.$space-2x;
163
+ .floating-right-mobile {
164
+ margin-left: auto;
165
+ width: auto;
166
+ order: 99;
265
167
  }
266
168
 
267
- .badge:has(> .icon) {
268
- position: relative;
269
- inset: inherit;
169
+ tr.active {
170
+ box-shadow: none;
171
+ border: 1px solid color_alias.$primary-color-1000;
172
+ > td {
173
+ border-color: transparent !important;
174
+ }
270
175
  }
271
176
 
272
- td:has(.badge > .icon) {
273
- justify-content: flex-start;
177
+ &.with-title td:not(.actions):nth-child(2) {
178
+ margin-top: config.$space-2x;
274
179
  }
275
180
 
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
- }
181
+ @include generate-title-actions(5);
283
182
  }
284
183
  }
@@ -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}