@licklist/design 0.78.5-dev.62 → 0.78.5-dev.64

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/index.js +1 -1
  2. package/dist/provider/location-input/LocationInput.js +1 -1
  3. package/dist/v2/components/ActionMenu/ActionMenu.d.ts.map +1 -1
  4. package/dist/v2/components/ActionMenu/ActionMenu.js +6 -16
  5. package/dist/v2/components/ActionMenu/ActionMenu.scss.js +1 -1
  6. package/dist/v2/components/Badge/Badge.scss.js +1 -1
  7. package/dist/v2/components/FormField/FormField.scss.js +1 -1
  8. package/dist/v2/components/NewPageHeader/NewPageHeader.scss.js +1 -1
  9. package/dist/v2/components/QuickFilter/QuickFilter.scss.js +1 -1
  10. package/dist/v2/components/TableSortIcon/TableSortIcon.d.ts.map +1 -1
  11. package/dist/v2/components/TableSortIcon/TableSortIcon.js +5 -3
  12. package/dist/v2/components/ZoneCard/ResourceRow.d.ts +11 -0
  13. package/dist/v2/components/ZoneCard/ResourceRow.d.ts.map +1 -1
  14. package/dist/v2/components/ZoneCard/ResourceRow.js +61 -9
  15. package/dist/v2/components/ZoneCard/ZoneCard.d.ts +0 -1
  16. package/dist/v2/components/ZoneCard/ZoneCard.d.ts.map +1 -1
  17. package/dist/v2/components/ZoneCard/ZoneCard.js +1 -2
  18. package/dist/v2/components/ZoneCard/ZoneCard.scss.js +1 -1
  19. package/dist/v2/components/ZoneCard/ZoneHeader.d.ts +6 -1
  20. package/dist/v2/components/ZoneCard/ZoneHeader.d.ts.map +1 -1
  21. package/dist/v2/components/ZoneCard/ZoneHeader.js +30 -13
  22. package/dist/v2/components/ZoneCard/index.d.ts +1 -1
  23. package/dist/v2/components/ZoneCard/index.d.ts.map +1 -1
  24. package/dist/v2/components/index.d.ts +1 -1
  25. package/dist/v2/components/index.d.ts.map +1 -1
  26. package/dist/v2/icons/index.d.ts +10 -2
  27. package/dist/v2/icons/index.d.ts.map +1 -1
  28. package/dist/v2/icons/index.js +41 -29
  29. package/dist/v2/index.d.ts +1 -1
  30. package/dist/v2/index.d.ts.map +1 -1
  31. package/dist/v2/pages/ZonesResources/ZonesResourcesPage.d.ts.map +1 -1
  32. package/dist/v2/pages/ZonesResources/ZonesResourcesPage.js +20 -16
  33. package/dist/v2/pages/ZonesResources/ZonesResourcesPage.scss.js +1 -1
  34. package/package.json +3 -3
  35. package/src/provider/location-input/LocationInput.tsx +1 -1
  36. package/src/v2/components/ActionMenu/ActionMenu.scss +7 -20
  37. package/src/v2/components/ActionMenu/ActionMenu.tsx +2 -5
  38. package/src/v2/components/Badge/Badge.scss +25 -23
  39. package/src/v2/components/Customer/CustomersList.scss +60 -9
  40. package/src/v2/components/FormField/FormField.scss +1 -1
  41. package/src/v2/components/NewPageHeader/NewPageHeader.scss +1 -5
  42. package/src/v2/components/QuickFilter/QuickFilter.scss +14 -3
  43. package/src/v2/components/TableSortIcon/TableSortIcon.tsx +3 -5
  44. package/src/v2/components/ZoneCard/ResourceRow.tsx +56 -9
  45. package/src/v2/components/ZoneCard/ZoneCard.scss +74 -10
  46. package/src/v2/components/ZoneCard/ZoneCard.stories.tsx +2 -5
  47. package/src/v2/components/ZoneCard/ZoneCard.tsx +0 -3
  48. package/src/v2/components/ZoneCard/ZoneHeader.tsx +34 -11
  49. package/src/v2/components/ZoneCard/index.ts +1 -1
  50. package/src/v2/components/index.ts +2 -0
  51. package/src/v2/icons/index.tsx +24 -14
  52. package/src/v2/index.ts +1 -1
  53. package/src/v2/pages/ZonesResources/ZonesResourcesPage.scss +25 -0
  54. package/src/v2/pages/ZonesResources/ZonesResourcesPage.tsx +10 -7
@@ -54,6 +54,7 @@
54
54
  width: 30px;
55
55
  height: 30px;
56
56
  flex-shrink: 0;
57
+ fill: var(--shade-lighter);
57
58
  }
58
59
  }
59
60
 
@@ -111,6 +112,10 @@
111
112
 
112
113
  .search-input-wrapper {
113
114
  width: 70%;
115
+
116
+ .new-form-input__icon {
117
+ color: var(--shade-lighter);
118
+ }
114
119
  }
115
120
 
116
121
  .search-helper-text {
@@ -125,13 +130,21 @@
125
130
 
126
131
  .filters-actions-row {
127
132
  display: flex;
128
- justify-content: space-between;
129
- align-items: center;
130
- gap: 24px;
133
+ flex-direction: column;
134
+ align-items: flex-start;
135
+ gap: 16px;
131
136
  width: 100%;
137
+
138
+ @media (min-width: 1024px) {
139
+ flex-direction: row;
140
+ justify-content: space-between;
141
+ align-items: center;
142
+ gap: 24px;
143
+ }
132
144
  }
133
145
 
134
146
  .quick-filters-wrapper {
147
+ width: 100%;
135
148
  flex: 1;
136
149
  }
137
150
 
@@ -139,6 +152,12 @@
139
152
  display: flex;
140
153
  gap: 12px;
141
154
  align-items: center;
155
+
156
+ .ghost-button {
157
+ &__icon svg {
158
+ fill: var(--shade-lighter);
159
+ }
160
+ }
142
161
  }
143
162
 
144
163
  &__row {
@@ -165,19 +184,46 @@
165
184
  &__sub {
166
185
  font-size: 13px;
167
186
  color: #9399B3;
187
+ display: block !important;
168
188
  }
169
189
  &__id {
170
190
  font-size: 13px;
171
191
  color: #9399B3;
172
- display: none;
192
+ display: none !important;
173
193
  }
174
194
 
175
195
  &:hover {
176
196
  .entity-cell__id {
177
- display: block;
197
+ display: block !important;
178
198
  }
179
199
  .entity-cell__sub {
180
- display: none;
200
+ display: none !important;
201
+ }
202
+ }
203
+
204
+ // Ensure hover state on the row also triggers the same behavior
205
+ // This addresses potential flickering when moving between cells
206
+ :is(.new-table__row:hover) & {
207
+ .entity-cell__id {
208
+ display: block !important;
209
+ }
210
+ .entity-cell__sub {
211
+ display: none !important;
212
+ }
213
+ }
214
+
215
+ // When entity-cell__sub is missing (like in template list),
216
+ // showing entity-cell__id on hover causes height jump.
217
+ // We only want to swap if both exist, or ensure height is stable.
218
+ &:not(:has(.entity-cell__sub)) {
219
+ .entity-cell__id {
220
+ display: block !important;
221
+ }
222
+ }
223
+
224
+ :is(.new-table__row:hover) &:not(:has(.entity-cell__sub)) {
225
+ .entity-cell__id {
226
+ display: block !important;
181
227
  }
182
228
  }
183
229
  }
@@ -542,6 +588,7 @@
542
588
  "customer bookings"
543
589
  "divider divider"
544
590
  "next last"
591
+ "status status"
545
592
  "actions actions";
546
593
  grid-template-columns: 1fr auto;
547
594
  border: 1px solid var(--border-primary, #E8E9EF);
@@ -604,6 +651,10 @@
604
651
  grid-area: last; // Reuse 'last' area for waiver in waiver list
605
652
  text-align: right;
606
653
  }
654
+ &.waiver-col-mb {
655
+ grid-area: status;
656
+ text-align: left;
657
+ }
607
658
  }
608
659
  }
609
660
  }
@@ -679,7 +730,7 @@
679
730
  .waiver-cell {
680
731
  display: flex;
681
732
  flex-direction: column;
682
- align-items: flex-end;
733
+ align-items: flex-start;
683
734
  min-width: 0;
684
735
  overflow: hidden;
685
736
 
@@ -688,7 +739,7 @@
688
739
  color: #626A90;
689
740
  font-weight: 500;
690
741
  margin-bottom: 4px;
691
- text-align: right;
742
+ text-align: left;
692
743
  white-space: nowrap;
693
744
  overflow: hidden;
694
745
  text-overflow: ellipsis;
@@ -697,7 +748,7 @@
697
748
 
698
749
  .v2-badge {
699
750
  display: inline-flex;
700
- margin-left: auto;
751
+ margin-right: auto;
701
752
  }
702
753
  }
703
754
 
@@ -33,7 +33,7 @@
33
33
  padding: 8px 10px;
34
34
  height: 40px;
35
35
  font-family: var(--font-family-sans, 'Geist', sans-serif);
36
- font-size: var(--text-regular-size, 15px);
36
+ font-size: var(--text-regular-size, 16px);
37
37
  line-height: var(--text-regular-line, 20px);
38
38
  color: var(--label-primary, #121e52);
39
39
  background-color: var(--surface-secondary, #f8f8fa);
@@ -7,13 +7,9 @@
7
7
  padding: 32px 32px 0px 32px;
8
8
 
9
9
  @media (max-width: 768px) {
10
- padding: 16px 16px 0px 16px;
10
+ padding: 16px 0 0 0;
11
11
  gap: 0;
12
12
  }
13
-
14
- @media (max-width: 480px) {
15
- padding: 16px 12px 0px 12px;
16
- }
17
13
  }
18
14
 
19
15
  .new-page-header {
@@ -12,11 +12,21 @@
12
12
 
13
13
  &__options {
14
14
  display: flex;
15
- flex-wrap: wrap;
15
+ flex-wrap: nowrap;
16
+ overflow-x: auto;
16
17
  gap: 8px;
18
+ -ms-overflow-style: none; /* IE and Edge */
19
+ scrollbar-width: none; /* Firefox */
20
+ padding-bottom: 2px; /* Prevent button shadows/borders from being cut off during scroll if any */
21
+
22
+ &::-webkit-scrollbar {
23
+ display: none; /* Chrome, Safari and Opera */
24
+ }
17
25
 
18
26
  .ghost-button {
19
27
  border-radius: 100px;
28
+ font-family: var(--font-family-mono, 'Geist Mono', monospace);
29
+ flex-shrink: 0;
20
30
  }
21
31
  }
22
32
  }
@@ -26,7 +36,7 @@
26
36
  .quick-filter {
27
37
  display: flex;
28
38
  flex-direction: row;
29
- align-items: flex-start;
39
+ align-items: center;
30
40
  gap: 12px;
31
41
  width: 100%;
32
42
 
@@ -37,7 +47,8 @@
37
47
  &__options {
38
48
  flex: 1;
39
49
  display: flex;
40
- flex-wrap: wrap;
50
+ flex-wrap: nowrap;
51
+ overflow-x: auto;
41
52
  gap: 6px;
42
53
  padding: 0;
43
54
  margin: 0;
@@ -1,5 +1,5 @@
1
1
  import React from 'react'
2
- import { ArrowUpIcon, ArrowDownIcon } from '../../icons'
2
+ import { TableHeaderArrowUpIcon, TableHeaderArrowDownIcon} from '../../icons'
3
3
 
4
4
  export type SortDirection = 'asc' | 'desc' | null
5
5
 
@@ -10,11 +10,9 @@ export interface TableSortIconProps {
10
10
  }
11
11
 
12
12
  export const TableSortIcon: React.FC<TableSortIconProps> = ({ active = false, direction, className = '' }) => {
13
- if (!active || !direction) return null
14
-
15
13
  return (
16
- <span className={className}>
17
- {direction === 'asc' ? <ArrowUpIcon /> : <ArrowDownIcon />}
14
+ <span className={className} style={{ visibility: active && direction ? 'visible' : 'hidden' }}>
15
+ {direction === 'asc' ? <TableHeaderArrowUpIcon /> : <TableHeaderArrowDownIcon />}
18
16
  </span>
19
17
  )
20
18
  }
@@ -1,57 +1,104 @@
1
1
  import React from 'react'
2
2
  import { ActionMenu, ActionMenuItem } from '../ActionMenu'
3
- import { GripVerticalIcon } from '../../icons'
3
+ import { GripVerticalIcon, ArrowUpIcon, ArrowDownIcon } from '../../icons'
4
4
  import { DragHandleProps } from './ZoneContainer'
5
5
  import './ZoneCard.scss'
6
6
 
7
+ export interface ResourceRowLabels {
8
+ quantity?: string
9
+ capacity?: string
10
+ total?: string
11
+ }
12
+
7
13
  export interface ResourceRowProps {
8
14
  name: string
9
15
  quantity: number
10
16
  capacity: number
17
+ labels?: ResourceRowLabels
11
18
  menuItems?: ActionMenuItem[]
12
19
  draggable?: boolean
13
20
  dragHandleProps?: DragHandleProps
14
21
  onClick?: () => void
15
22
  className?: string
16
23
  style?: React.CSSProperties
24
+ isMobile?: boolean
25
+ isFirst?: boolean
26
+ isLast?: boolean
27
+ onMoveUp?: () => void
28
+ onMoveDown?: () => void
17
29
  }
18
30
 
19
31
  export const ResourceRow = React.forwardRef<HTMLDivElement, ResourceRowProps>(({
20
32
  name,
21
33
  quantity,
22
34
  capacity,
35
+ labels = {},
23
36
  menuItems = [],
24
37
  draggable = true,
25
38
  dragHandleProps,
26
39
  onClick,
27
40
  className = '',
28
41
  style,
42
+ isMobile = false,
43
+ isFirst = false,
44
+ isLast = false,
45
+ onMoveUp,
46
+ onMoveDown,
29
47
  }, ref) => {
48
+ const qtyLabel = labels.quantity ?? 'Qty'
49
+ const capLabel = labels.capacity ?? 'Cap'
50
+ const totalLabel = labels.total ?? 'Total'
30
51
  const classes = [
31
52
  'zone-card__resource',
32
53
  onClick ? 'zone-card__resource--clickable' : '',
54
+ isMobile ? 'zone-card__resource--mobile' : '',
33
55
  className,
34
56
  ].filter(Boolean).join(' ')
35
57
 
36
58
  return (
37
59
  <div ref={ref} className={classes} style={style} onClick={onClick}>
38
- {draggable && (
60
+ {draggable && !isMobile && (
39
61
  <div
40
62
  className="zone-card__drag-handle zone-card__drag-handle--resource"
41
63
  {...dragHandleProps}
42
64
  onClick={(e) => e.stopPropagation()}
43
65
  >
44
- {GripVerticalIcon({ width: 14, height: 14 })}
66
+ {GripVerticalIcon({ width: 16, height: 16 })}
67
+ </div>
68
+ )}
69
+ {draggable && isMobile && (
70
+ <div className="zone-card__reorder-arrows zone-card__reorder-arrows--resource" onClick={(e) => e.stopPropagation()}>
71
+ <button
72
+ className="zone-card__arrow-btn"
73
+ disabled={isFirst}
74
+ onClick={(e) => { e.stopPropagation(); onMoveUp?.() }}
75
+ >
76
+ <ArrowUpIcon />
77
+ </button>
78
+ <button
79
+ className="zone-card__arrow-btn"
80
+ disabled={isLast}
81
+ onClick={(e) => { e.stopPropagation(); onMoveDown?.() }}
82
+ >
83
+ <ArrowDownIcon />
84
+ </button>
45
85
  </div>
46
86
  )}
47
87
  <span className="zone-card__resource-name">{name}</span>
48
- <div className="zone-card__resource-stats">
49
- <span className="zone-card__resource-stat">Qty: {quantity}</span>
50
- <span className="zone-card__resource-stat">Cap: {capacity}</span>
51
- <span className="zone-card__resource-stat zone-card__resource-stat--total">
52
- Total: {quantity * capacity}
88
+ {!isMobile && (
89
+ <div className="zone-card__resource-stats">
90
+ <span className="zone-card__resource-stat">{qtyLabel}: {quantity}</span>
91
+ <span className="zone-card__resource-stat">{capLabel}: {capacity}</span>
92
+ <span className="zone-card__resource-stat zone-card__resource-stat--total">
93
+ {totalLabel}: {quantity * capacity}
94
+ </span>
95
+ </div>
96
+ )}
97
+ {isMobile && (
98
+ <span className="zone-card__resource-stats-mobile">
99
+ {qtyLabel}: {quantity} &middot; {capLabel}: {capacity} &middot; {totalLabel}: {quantity * capacity}
53
100
  </span>
54
- </div>
101
+ )}
55
102
  {menuItems.length > 0 && (
56
103
  <div className="zone-card__resource-actions" onClick={(e) => e.stopPropagation()}>
57
104
  <ActionMenu items={menuItems} />
@@ -7,7 +7,7 @@
7
7
  &__header {
8
8
  display: flex;
9
9
  align-items: center;
10
- gap: 12px;
10
+ gap: 16px;
11
11
  padding: 12px 16px;
12
12
  background: var(--surface-secondary);
13
13
  }
@@ -15,14 +15,15 @@
15
15
  &__drag-handle {
16
16
  display: flex;
17
17
  align-items: center;
18
- padding: 4px;
19
- border-radius: 4px;
18
+ padding: 6px;
19
+ border-radius: 6px;
20
20
  cursor: grab;
21
- color: var(--label-secondary);
21
+ color: var(--label-tertiary, var(--label-secondary));
22
22
  transition: all 0.2s ease;
23
+ flex-shrink: 0;
23
24
 
24
25
  &:hover {
25
- color: var(--label-primary);
26
+ color: var(--label-secondary);
26
27
  background: var(--surface-primary);
27
28
  }
28
29
 
@@ -31,7 +32,44 @@
31
32
  }
32
33
 
33
34
  &--resource {
35
+ color: var(--label-tertiary, var(--label-secondary));
36
+ }
37
+ }
38
+
39
+ // Mobile reorder arrows (replaces drag handles)
40
+ &__reorder-arrows {
41
+ display: flex;
42
+ flex-direction: column;
43
+ gap: 2px;
44
+ flex-shrink: 0;
45
+
46
+ &--resource {
47
+ margin-right: 0;
48
+ }
49
+ }
50
+
51
+ &__arrow-btn {
52
+ display: flex;
53
+ align-items: center;
54
+ justify-content: center;
55
+ width: 28px;
56
+ height: 28px;
57
+ border: none;
58
+ border-radius: 4px;
59
+ background: transparent;
60
+ color: var(--label-tertiary, var(--label-secondary));
61
+ cursor: pointer;
62
+ transition: all 0.2s ease;
63
+ padding: 0;
64
+
65
+ &:hover:not(:disabled) {
34
66
  color: var(--label-secondary);
67
+ background: var(--surface-primary);
68
+ }
69
+
70
+ &:disabled {
71
+ opacity: 0.25;
72
+ pointer-events: none;
35
73
  }
36
74
  }
37
75
 
@@ -48,7 +86,7 @@
48
86
  &__header-right {
49
87
  display: flex;
50
88
  align-items: center;
51
- gap: 12px;
89
+ gap: 16px;
52
90
  flex-shrink: 0;
53
91
  }
54
92
 
@@ -59,13 +97,15 @@
59
97
  line-height: 16px;
60
98
  color: var(--label-secondary);
61
99
  white-space: nowrap;
100
+ min-width: 72px;
101
+ text-align: right;
62
102
  }
63
103
 
64
104
  // Resource rows
65
105
  &__resource {
66
106
  display: flex;
67
107
  align-items: center;
68
- gap: 12px;
108
+ gap: 16px;
69
109
  padding: 10px 16px 10px 32px;
70
110
  border-top: 1px solid var(--border-primary);
71
111
  transition: background 0.2s ease;
@@ -77,6 +117,11 @@
77
117
  background: var(--surface-secondary);
78
118
  }
79
119
  }
120
+
121
+ &--mobile {
122
+ flex-wrap: wrap;
123
+ padding-left: 16px;
124
+ }
80
125
  }
81
126
 
82
127
  &__resource-name {
@@ -103,14 +148,24 @@
103
148
  line-height: 16px;
104
149
  color: var(--label-secondary);
105
150
  white-space: nowrap;
106
- min-width: 56px;
151
+ min-width: 72px;
107
152
 
108
153
  &--total {
109
- min-width: 56px;
154
+ min-width: 72px;
110
155
  text-align: right;
111
156
  }
112
157
  }
113
158
 
159
+ // Mobile-only compact stats line
160
+ &__resource-stats-mobile {
161
+ font-family: var(--font-family-sans, 'Geist', sans-serif);
162
+ font-size: 12px;
163
+ font-weight: 400;
164
+ line-height: 16px;
165
+ color: var(--label-secondary);
166
+ white-space: nowrap;
167
+ }
168
+
114
169
  &__resource-actions {
115
170
  flex-shrink: 0;
116
171
  width: 32px;
@@ -127,8 +182,13 @@
127
182
 
128
183
  @media (max-width: 768px) {
129
184
  .zone-card {
185
+ &__header {
186
+ padding: 10px 12px;
187
+ }
188
+
130
189
  &__resource {
131
- padding-left: 16px;
190
+ padding: 10px 12px 10px 12px;
191
+ gap: 12px;
132
192
  }
133
193
 
134
194
  &__resource-stats {
@@ -138,5 +198,9 @@
138
198
  &__resource-stat {
139
199
  min-width: auto;
140
200
  }
201
+
202
+ &__add-resource-wrapper {
203
+ padding: 10px 12px;
204
+ }
141
205
  }
142
206
  }
@@ -30,7 +30,7 @@ const resourceMenuItems = [
30
30
  export const Default: Story = {
31
31
  args: {
32
32
  name: 'Bowling',
33
- status: 'active',
33
+
34
34
  totalCapacity: 2,
35
35
  menuItems: zoneMenuItems,
36
36
  onAddResource: () => alert('Add Resource'),
@@ -41,10 +41,9 @@ export const Default: Story = {
41
41
  },
42
42
  }
43
43
 
44
- export const DisabledZone: Story = {
44
+ export const EmptyZone: Story = {
45
45
  args: {
46
46
  name: 'VIP Lounge',
47
- status: 'disabled',
48
47
  totalCapacity: 0,
49
48
  menuItems: zoneMenuItems,
50
49
  onAddResource: () => alert('Add Resource'),
@@ -58,7 +57,6 @@ export const ComposedManually: Story = {
58
57
  <ZoneContainer>
59
58
  <ZoneHeader
60
59
  name="Bowling"
61
- status="active"
62
60
  totalCapacity={2}
63
61
  menuItems={zoneMenuItems}
64
62
  />
@@ -87,7 +85,6 @@ export const StandaloneHeader: Story = {
87
85
  <ZoneContainer>
88
86
  <ZoneHeader
89
87
  name="Main Floor"
90
- status="active"
91
88
  totalCapacity={50}
92
89
  menuItems={zoneMenuItems}
93
90
  />
@@ -17,7 +17,6 @@ export interface ZoneResource {
17
17
 
18
18
  export interface ZoneCardProps {
19
19
  name: string
20
- status?: 'active' | 'disabled'
21
20
  totalCapacity: number
22
21
  resources?: ZoneResource[]
23
22
  menuItems?: ActionMenuItem[]
@@ -31,7 +30,6 @@ export interface ZoneCardProps {
31
30
 
32
31
  export const ZoneCard = React.forwardRef<HTMLDivElement, ZoneCardProps>(({
33
32
  name,
34
- status = 'active',
35
33
  totalCapacity,
36
34
  resources = [],
37
35
  menuItems = [],
@@ -46,7 +44,6 @@ export const ZoneCard = React.forwardRef<HTMLDivElement, ZoneCardProps>(({
46
44
  <ZoneContainer ref={ref} className={className} style={style}>
47
45
  <ZoneHeader
48
46
  name={name}
49
- status={status}
50
47
  totalCapacity={totalCapacity}
51
48
  menuItems={menuItems}
52
49
  draggable={draggable}
@@ -1,43 +1,66 @@
1
1
  import React from 'react'
2
- import { Badge } from '../Badge'
3
2
  import { ActionMenu, ActionMenuItem } from '../ActionMenu'
4
- import { GripVerticalIcon } from '../../icons'
3
+ import { GripVerticalIcon, ArrowUpIcon, ArrowDownIcon } from '../../icons'
5
4
  import { DragHandleProps } from './ZoneContainer'
6
5
  import './ZoneCard.scss'
7
6
 
8
7
  export interface ZoneHeaderProps {
9
8
  name: string
10
- status?: 'active' | 'disabled'
11
9
  totalCapacity: number
10
+ totalLabel?: string
12
11
  menuItems?: ActionMenuItem[]
13
12
  draggable?: boolean
14
13
  dragHandleProps?: DragHandleProps
15
14
  className?: string
15
+ isMobile?: boolean
16
+ isFirst?: boolean
17
+ isLast?: boolean
18
+ onMoveUp?: () => void
19
+ onMoveDown?: () => void
16
20
  }
17
21
 
18
22
  export const ZoneHeader: React.FC<ZoneHeaderProps> = ({
19
23
  name,
20
- status = 'active',
21
24
  totalCapacity,
25
+ totalLabel = 'Total',
22
26
  menuItems = [],
23
27
  draggable = true,
24
28
  dragHandleProps,
25
29
  className = '',
30
+ isMobile = false,
31
+ isFirst = false,
32
+ isLast = false,
33
+ onMoveUp,
34
+ onMoveDown,
26
35
  }) => {
27
- const statusVariant = status === 'active' ? 'success' : 'neutral'
28
- const statusLabel = status.charAt(0).toUpperCase() + status.slice(1)
29
-
30
36
  return (
31
37
  <div className={`zone-card__header ${className}`}>
32
- {draggable && (
38
+ {draggable && !isMobile && (
33
39
  <div className="zone-card__drag-handle" {...dragHandleProps}>
34
- {GripVerticalIcon({ width: 16, height: 16 })}
40
+ {GripVerticalIcon({ width: 20, height: 20 })}
41
+ </div>
42
+ )}
43
+ {draggable && isMobile && (
44
+ <div className="zone-card__reorder-arrows">
45
+ <button
46
+ className="zone-card__arrow-btn"
47
+ disabled={isFirst}
48
+ onClick={(e) => { e.stopPropagation(); onMoveUp?.() }}
49
+ >
50
+ <ArrowUpIcon />
51
+ </button>
52
+ <button
53
+ className="zone-card__arrow-btn"
54
+ disabled={isLast}
55
+ onClick={(e) => { e.stopPropagation(); onMoveDown?.() }}
56
+ >
57
+ <ArrowDownIcon />
58
+ </button>
35
59
  </div>
36
60
  )}
37
61
  <span className="zone-card__name">{name}</span>
38
62
  <div className="zone-card__header-right">
39
- <Badge variant={statusVariant}>{statusLabel}</Badge>
40
- <span className="zone-card__total">Total: {totalCapacity}</span>
63
+ <span className="zone-card__total">{totalLabel}: {totalCapacity}</span>
41
64
  {menuItems.length > 0 && <ActionMenu items={menuItems} />}
42
65
  </div>
43
66
  </div>
@@ -8,7 +8,7 @@ export { ZoneHeader } from './ZoneHeader'
8
8
  export type { ZoneHeaderProps } from './ZoneHeader'
9
9
 
10
10
  export { ResourceRow } from './ResourceRow'
11
- export type { ResourceRowProps } from './ResourceRow'
11
+ export type { ResourceRowProps, ResourceRowLabels } from './ResourceRow'
12
12
 
13
13
  export { AddResourceButton } from './AddResourceButton'
14
14
  export type { AddResourceButtonProps } from './AddResourceButton'
@@ -67,6 +67,8 @@ export type { ZoneCardProps, ZoneResource, ZoneContainerProps, DragHandleProps,
67
67
  // Icons
68
68
  export {
69
69
  InfoIcon,
70
+ TableHeaderArrowUpIcon,
71
+ TableHeaderArrowDownIcon,
70
72
  ArrowUpIcon,
71
73
  ArrowDownIcon,
72
74
  EditIcon,