@licklist/design 0.78.5-dev.59 → 0.78.5-dev.60

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 (77) hide show
  1. package/dist/index.d.ts +3 -1
  2. package/dist/index.d.ts.map +1 -1
  3. package/dist/index.js +8 -2
  4. package/dist/v2/components/Button/Button.scss.js +1 -1
  5. package/dist/v2/components/Checkbox/Checkbox.scss.js +1 -1
  6. package/dist/v2/components/IconButton/IconButton.d.ts +9 -0
  7. package/dist/v2/components/IconButton/IconButton.d.ts.map +1 -0
  8. package/dist/v2/components/IconButton/IconButton.js +137 -0
  9. package/dist/v2/components/IconButton/IconButton.scss.js +6 -0
  10. package/dist/v2/components/IconButton/index.d.ts +3 -0
  11. package/dist/v2/components/IconButton/index.d.ts.map +1 -0
  12. package/dist/v2/components/NewInput/NewInput.d.ts.map +1 -1
  13. package/dist/v2/components/NewInput/NewInput.js +4 -3
  14. package/dist/v2/components/ZoneCard/AddResourceButton.d.ts +8 -0
  15. package/dist/v2/components/ZoneCard/AddResourceButton.d.ts.map +1 -0
  16. package/dist/v2/components/ZoneCard/AddResourceButton.js +17 -0
  17. package/dist/v2/components/ZoneCard/ResourceRow.d.ts +17 -0
  18. package/dist/v2/components/ZoneCard/ResourceRow.d.ts.map +1 -0
  19. package/dist/v2/components/ZoneCard/ResourceRow.js +127 -0
  20. package/dist/v2/components/ZoneCard/ZoneCard.d.ts +26 -0
  21. package/dist/v2/components/ZoneCard/ZoneCard.d.ts.map +1 -0
  22. package/dist/v2/components/ZoneCard/ZoneCard.js +44 -0
  23. package/dist/v2/components/ZoneCard/ZoneCard.scss.js +6 -0
  24. package/dist/v2/components/ZoneCard/ZoneContainer.d.ts +12 -0
  25. package/dist/v2/components/ZoneCard/ZoneContainer.d.ts.map +1 -0
  26. package/dist/v2/components/ZoneCard/ZoneContainer.js +16 -0
  27. package/dist/v2/components/ZoneCard/ZoneHeader.d.ts +15 -0
  28. package/dist/v2/components/ZoneCard/ZoneHeader.d.ts.map +1 -0
  29. package/dist/v2/components/ZoneCard/ZoneHeader.js +102 -0
  30. package/dist/v2/components/ZoneCard/index.d.ts +11 -0
  31. package/dist/v2/components/ZoneCard/index.d.ts.map +1 -0
  32. package/dist/v2/components/index.d.ts +5 -1
  33. package/dist/v2/components/index.d.ts.map +1 -1
  34. package/dist/v2/icons/index.d.ts +16 -0
  35. package/dist/v2/icons/index.d.ts.map +1 -1
  36. package/dist/v2/icons/index.js +57 -1
  37. package/dist/v2/index.d.ts +10 -0
  38. package/dist/v2/index.d.ts.map +1 -1
  39. package/dist/v2/pages/Settings/components/SidebarCustomisation.js +5 -0
  40. package/dist/v2/pages/Settings/components/SidebarNavItem.js +5 -0
  41. package/dist/v2/pages/ZonesResources/ZonesResourcesPage.d.ts +12 -0
  42. package/dist/v2/pages/ZonesResources/ZonesResourcesPage.d.ts.map +1 -0
  43. package/dist/v2/pages/ZonesResources/ZonesResourcesPage.js +43 -0
  44. package/dist/v2/pages/ZonesResources/ZonesResourcesPage.scss.js +6 -0
  45. package/dist/v2/pages/ZonesResources/index.d.ts +3 -0
  46. package/dist/v2/pages/ZonesResources/index.d.ts.map +1 -0
  47. package/dist/v2/styles/components/Button.scss +1 -0
  48. package/dist/v2/styles/form/NewInput.scss +10 -6
  49. package/dist/v2/styles/form/NewInput.scss.js +1 -1
  50. package/package.json +1 -1
  51. package/src/index.ts +3 -1
  52. package/src/v2/components/ActionMenu/ActionMenu.stories.tsx +58 -0
  53. package/src/v2/components/ActionMenu/ActionMenu.tsx +1 -1
  54. package/src/v2/components/Checkbox/Checkbox.scss +1 -1
  55. package/src/v2/components/IconButton/IconButton.scss +75 -0
  56. package/src/v2/components/IconButton/IconButton.stories.tsx +51 -0
  57. package/src/v2/components/IconButton/IconButton.tsx +50 -0
  58. package/src/v2/components/IconButton/index.ts +2 -0
  59. package/src/v2/components/NewInput/NewInput.tsx +2 -1
  60. package/src/v2/components/NewPageHeader/NewPageHeader.stories.tsx +28 -0
  61. package/src/v2/components/ZoneCard/AddResourceButton.tsx +20 -0
  62. package/src/v2/components/ZoneCard/ResourceRow.tsx +64 -0
  63. package/src/v2/components/ZoneCard/ZoneCard.scss +142 -0
  64. package/src/v2/components/ZoneCard/ZoneCard.stories.tsx +140 -0
  65. package/src/v2/components/ZoneCard/ZoneCard.tsx +72 -0
  66. package/src/v2/components/ZoneCard/ZoneContainer.tsx +26 -0
  67. package/src/v2/components/ZoneCard/ZoneHeader.tsx +45 -0
  68. package/src/v2/components/ZoneCard/index.ts +14 -0
  69. package/src/v2/components/index.ts +11 -1
  70. package/src/v2/icons/index.tsx +24 -0
  71. package/src/v2/index.ts +21 -0
  72. package/src/v2/pages/ZonesResources/ZonesResourcesPage.scss +22 -0
  73. package/src/v2/pages/ZonesResources/ZonesResourcesPage.stories.tsx +46 -0
  74. package/src/v2/pages/ZonesResources/ZonesResourcesPage.tsx +45 -0
  75. package/src/v2/pages/ZonesResources/index.ts +2 -0
  76. package/src/v2/styles/components/Button.scss +1 -0
  77. package/src/v2/styles/form/NewInput.scss +10 -6
package/src/index.ts CHANGED
@@ -29,7 +29,8 @@ export * from './report'
29
29
  export * from './venue-map-sets'
30
30
  export * from './affiliate'
31
31
  export * from './typeahead-helper'
32
- export * from './zone'
32
+ export { ZoneForm } from './zone/form'
33
+ export type { ZoneFormProps } from './zone/form'
33
34
  export * from './resource'
34
35
  export * from './virtualized'
35
36
  export * from './customers'
@@ -49,4 +50,5 @@ export * from './UnderMaintenance'
49
50
  export * from './v2/dashboard-analytics'
50
51
  export * from './v2/navigation/DashboardLayout'
51
52
  export * from './v2/pages/Settings'
53
+ export * from './v2/pages/ZonesResources'
52
54
  export * from './v2/components'
@@ -0,0 +1,58 @@
1
+ import React from 'react'
2
+ import { Meta, StoryObj } from '@storybook/react'
3
+ import { ActionMenu } from './ActionMenu'
4
+
5
+ export default {
6
+ title: 'v2/Components/ActionMenu',
7
+ component: ActionMenu,
8
+ } as Meta<typeof ActionMenu>
9
+
10
+ type Story = StoryObj<typeof ActionMenu>
11
+
12
+ const defaultItems = [
13
+ { label: 'Edit', onClick: () => console.log('Edit') },
14
+ { label: 'Duplicate', onClick: () => console.log('Duplicate') },
15
+ { label: 'Delete', onClick: () => console.log('Delete'), variant: 'danger' as const },
16
+ ]
17
+
18
+ export const Default: Story = {
19
+ args: {
20
+ items: defaultItems,
21
+ },
22
+ decorators: [
23
+ (Story) => (
24
+ <div style={{ display: 'flex', justifyContent: 'flex-end', paddingTop: 200 }}>
25
+ <Story />
26
+ </div>
27
+ ),
28
+ ],
29
+ }
30
+
31
+ export const OpenDown: Story = {
32
+ args: {
33
+ items: defaultItems,
34
+ direction: 'down',
35
+ },
36
+ decorators: [
37
+ (Story) => (
38
+ <div style={{ display: 'flex', justifyContent: 'flex-end', paddingTop: 20 }}>
39
+ <Story />
40
+ </div>
41
+ ),
42
+ ],
43
+ }
44
+
45
+ export const WithCustomIconColour: Story = {
46
+ args: {
47
+ items: defaultItems,
48
+ iconColour: '#E0423A',
49
+ direction: 'down',
50
+ },
51
+ }
52
+
53
+ export const SingleItem: Story = {
54
+ args: {
55
+ items: [{ label: 'Edit', onClick: () => console.log('Edit') }],
56
+ direction: 'down',
57
+ },
58
+ }
@@ -112,4 +112,4 @@ export const ActionMenu: React.FC<ActionMenuProps> = ({ items, className = '', i
112
112
  )}
113
113
  </div>
114
114
  )
115
- }
115
+ }
@@ -13,7 +13,7 @@
13
13
 
14
14
  &__wrapper {
15
15
  display: flex;
16
- align-items: flex-start;
16
+ align-items: center;
17
17
  gap: 11px;
18
18
  cursor: pointer;
19
19
  user-select: none;
@@ -0,0 +1,75 @@
1
+ .icon-button {
2
+ display: inline-flex;
3
+ align-items: center;
4
+ gap: var(--spacing-sm, 8px);
5
+ padding: 0 16px 0 12px;
6
+ height: 34px;
7
+ background: transparent;
8
+ border: 1px solid var(--border-primary);
9
+ border-radius: 8px;
10
+ cursor: pointer;
11
+ transition: all 0.2s ease;
12
+ font-family: var(--font-family-sans, 'Geist', sans-serif);
13
+
14
+ &:hover {
15
+ background: var(--surface-secondary);
16
+ color: var(--label-primary);
17
+
18
+ .icon-button__icon {
19
+ color: var(--label-primary);
20
+ }
21
+
22
+ .icon-button__label {
23
+ color: var(--label-primary);
24
+ }
25
+ }
26
+
27
+ &:active {
28
+ background: var(--surface-tertiary);
29
+ }
30
+
31
+ &__icon {
32
+ display: flex;
33
+ align-items: center;
34
+ color: var(--label-primary);
35
+ }
36
+
37
+ &__label {
38
+ font-size: 13px;
39
+ font-weight: 500;
40
+ line-height: 16px;
41
+ color: var(--label-primary);
42
+ }
43
+ }
44
+
45
+ // Icon-only variant (no label)
46
+ .icon-button--icon-only {
47
+ display: inline-flex;
48
+ align-items: center;
49
+ justify-content: center;
50
+ width: 32px;
51
+ height: 32px;
52
+ border: 1px solid var(--border-primary);
53
+ border-radius: 8px;
54
+ background: transparent;
55
+ color: var(--label-primary);
56
+ cursor: pointer;
57
+ transition: all 0.2s ease;
58
+
59
+ &:hover {
60
+ background: var(--surface-primary, #fff);
61
+ }
62
+
63
+ &:active {
64
+ background: var(--surface-tertiary);
65
+ }
66
+ }
67
+
68
+ // Danger variant
69
+ .icon-button--danger {
70
+ color: var(--label-danger, #cc3c35);
71
+
72
+ &:hover {
73
+ background: var(--surface-primary, #fff);
74
+ }
75
+ }
@@ -0,0 +1,51 @@
1
+ import React from 'react'
2
+ import { Meta, StoryObj } from '@storybook/react'
3
+ import { IconButton } from './IconButton'
4
+
5
+ export default {
6
+ title: 'v2/Components/IconButton',
7
+ component: IconButton,
8
+ } as Meta<typeof IconButton>
9
+
10
+ type Story = StoryObj<typeof IconButton>
11
+
12
+ export const BackWithLabel: Story = {
13
+ args: {
14
+ label: 'Go Back',
15
+ icon: 'back',
16
+ },
17
+ }
18
+
19
+ export const AddWithLabel: Story = {
20
+ args: {
21
+ label: 'Add Item',
22
+ icon: 'add',
23
+ },
24
+ }
25
+
26
+ export const DeleteWithLabel: Story = {
27
+ args: {
28
+ label: 'Remove Item',
29
+ icon: 'delete',
30
+ variant: 'danger',
31
+ },
32
+ }
33
+
34
+ export const IconOnlyBack: Story = {
35
+ args: {
36
+ icon: 'back',
37
+ },
38
+ }
39
+
40
+ export const IconOnlyAdd: Story = {
41
+ args: {
42
+ icon: 'add',
43
+ },
44
+ }
45
+
46
+ export const IconOnlyDelete: Story = {
47
+ args: {
48
+ icon: 'delete',
49
+ variant: 'danger',
50
+ },
51
+ }
@@ -0,0 +1,50 @@
1
+ import { ButtonHTMLAttributes, ReactNode } from 'react'
2
+ import { ArrowLeftIcon, PlusIcon, DeleteIcon } from '../../icons'
3
+ import './IconButton.scss'
4
+
5
+ export interface IconButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
6
+ label?: string
7
+ icon?: 'back' | 'add' | 'delete' | ReactNode
8
+ variant?: 'default' | 'danger'
9
+ }
10
+
11
+ export function IconButton({
12
+ label,
13
+ icon = 'back',
14
+ variant = 'default',
15
+ className = '',
16
+ ...props
17
+ }: IconButtonProps) {
18
+ const isIconOnly = !label
19
+ const classes = [
20
+ isIconOnly ? 'icon-button--icon-only' : 'icon-button',
21
+ variant === 'danger' ? 'icon-button--danger' : '',
22
+ className,
23
+ ].filter(Boolean).join(' ')
24
+
25
+ const iconSize = isIconOnly ? 32 : 16
26
+
27
+ const renderIcon = () => {
28
+ if (icon === 'back') return ArrowLeftIcon({ width: iconSize, height: iconSize })
29
+ if (icon === 'add') return PlusIcon({ width: iconSize, height: iconSize })
30
+ if (icon === 'delete') return DeleteIcon({ width: iconSize, height: iconSize })
31
+ return icon
32
+ }
33
+
34
+ if (isIconOnly) {
35
+ return (
36
+ <button type="button" className={classes} {...props}>
37
+ {renderIcon()}
38
+ </button>
39
+ )
40
+ }
41
+
42
+ return (
43
+ <button className={classes} {...props}>
44
+ <span className="icon-button__icon">
45
+ {renderIcon()}
46
+ </span>
47
+ <span className="icon-button__label">{label}</span>
48
+ </button>
49
+ )
50
+ }
@@ -0,0 +1,2 @@
1
+ export { IconButton } from './IconButton'
2
+ export type { IconButtonProps } from './IconButton'
@@ -94,7 +94,8 @@ export const NewInput = forwardRef<HTMLInputElement | HTMLTextAreaElement, NewIn
94
94
  <div className={containerClasses}>
95
95
  {(label || optional) && (
96
96
  <label className="new-form-input__label">
97
- {label} {optional && <span className="new-form-input__label-optional">(Optional)</span>}
97
+ <span>{label}</span>
98
+ {optional && <span className="new-form-input__label-optional">(optional)</span>}
98
99
  </label>
99
100
  )}
100
101
 
@@ -1,5 +1,6 @@
1
1
  import type { Meta, StoryObj } from '@storybook/react'
2
2
  import { NewPageHeader } from './NewPageHeader'
3
+ import { Button, ButtonText } from '../Button'
3
4
 
4
5
  const meta: Meta<typeof NewPageHeader> = {
5
6
  title: 'V2/Components/NewPageHeader',
@@ -42,3 +43,30 @@ export const CustomCancelLabel: Story = {
42
43
  onCancel: () => alert('Go Back clicked'),
43
44
  },
44
45
  }
46
+
47
+ export const WithAction: Story = {
48
+ args: {
49
+ title: 'Zones & Resources',
50
+ renderRight: () => (
51
+ <Button variant="primary" onClick={() => alert('Add Zone clicked')}>
52
+ <ButtonText color="white">+ Add Zone</ButtonText>
53
+ </Button>
54
+ ),
55
+ },
56
+ }
57
+
58
+ export const WithMultipleActions: Story = {
59
+ args: {
60
+ title: 'Zones & Resources',
61
+ renderRight: () => (
62
+ <>
63
+ <Button variant="secondary" onClick={() => alert('Export clicked')}>
64
+ <ButtonText color="action">Export</ButtonText>
65
+ </Button>
66
+ <Button variant="primary" onClick={() => alert('Add Zone clicked')}>
67
+ <ButtonText color="white">+ Add Zone</ButtonText>
68
+ </Button>
69
+ </>
70
+ ),
71
+ },
72
+ }
@@ -0,0 +1,20 @@
1
+ import React from 'react'
2
+ import { IconButton } from '../IconButton'
3
+
4
+ export interface AddResourceButtonProps {
5
+ label?: string
6
+ onClick: () => void
7
+ className?: string
8
+ }
9
+
10
+ export const AddResourceButton: React.FC<AddResourceButtonProps> = ({
11
+ label = 'Add Resource',
12
+ onClick,
13
+ className = '',
14
+ }) => {
15
+ return (
16
+ <div className={`zone-card__add-resource-wrapper ${className}`}>
17
+ <IconButton label={label} icon='add' onClick={onClick} />
18
+ </div>
19
+ )
20
+ }
@@ -0,0 +1,64 @@
1
+ import React from 'react'
2
+ import { ActionMenu, ActionMenuItem } from '../ActionMenu'
3
+ import { GripVerticalIcon } from '../../icons'
4
+ import { DragHandleProps } from './ZoneContainer'
5
+ import './ZoneCard.scss'
6
+
7
+ export interface ResourceRowProps {
8
+ name: string
9
+ quantity: number
10
+ capacity: number
11
+ menuItems?: ActionMenuItem[]
12
+ draggable?: boolean
13
+ dragHandleProps?: DragHandleProps
14
+ onClick?: () => void
15
+ className?: string
16
+ style?: React.CSSProperties
17
+ }
18
+
19
+ export const ResourceRow = React.forwardRef<HTMLDivElement, ResourceRowProps>(({
20
+ name,
21
+ quantity,
22
+ capacity,
23
+ menuItems = [],
24
+ draggable = true,
25
+ dragHandleProps,
26
+ onClick,
27
+ className = '',
28
+ style,
29
+ }, ref) => {
30
+ const classes = [
31
+ 'zone-card__resource',
32
+ onClick ? 'zone-card__resource--clickable' : '',
33
+ className,
34
+ ].filter(Boolean).join(' ')
35
+
36
+ return (
37
+ <div ref={ref} className={classes} style={style} onClick={onClick}>
38
+ {draggable && (
39
+ <div
40
+ className="zone-card__drag-handle zone-card__drag-handle--resource"
41
+ {...dragHandleProps}
42
+ onClick={(e) => e.stopPropagation()}
43
+ >
44
+ {GripVerticalIcon({ width: 14, height: 14 })}
45
+ </div>
46
+ )}
47
+ <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}
53
+ </span>
54
+ </div>
55
+ {menuItems.length > 0 && (
56
+ <div className="zone-card__resource-actions" onClick={(e) => e.stopPropagation()}>
57
+ <ActionMenu items={menuItems} />
58
+ </div>
59
+ )}
60
+ </div>
61
+ )
62
+ })
63
+
64
+ ResourceRow.displayName = 'ResourceRow'
@@ -0,0 +1,142 @@
1
+ .zone-card {
2
+ border: 1px solid var(--border-primary);
3
+ border-radius: 8px;
4
+ overflow: visible;
5
+ background: var(--surface-primary);
6
+
7
+ &__header {
8
+ display: flex;
9
+ align-items: center;
10
+ gap: 12px;
11
+ padding: 12px 16px;
12
+ background: var(--surface-secondary);
13
+ }
14
+
15
+ &__drag-handle {
16
+ display: flex;
17
+ align-items: center;
18
+ padding: 4px;
19
+ border-radius: 4px;
20
+ cursor: grab;
21
+ color: var(--label-secondary);
22
+ transition: all 0.2s ease;
23
+
24
+ &:hover {
25
+ color: var(--label-primary);
26
+ background: var(--surface-primary);
27
+ }
28
+
29
+ &:active {
30
+ cursor: grabbing;
31
+ }
32
+
33
+ &--resource {
34
+ color: var(--label-secondary);
35
+ }
36
+ }
37
+
38
+ &__name {
39
+ flex: 1;
40
+ min-width: 0;
41
+ font-family: var(--font-family-sans, 'Geist', sans-serif);
42
+ font-size: 15px;
43
+ font-weight: 600;
44
+ line-height: 20px;
45
+ color: var(--label-primary);
46
+ }
47
+
48
+ &__header-right {
49
+ display: flex;
50
+ align-items: center;
51
+ gap: 12px;
52
+ flex-shrink: 0;
53
+ }
54
+
55
+ &__total {
56
+ font-family: var(--font-family-sans, 'Geist', sans-serif);
57
+ font-size: 13px;
58
+ font-weight: 400;
59
+ line-height: 16px;
60
+ color: var(--label-secondary);
61
+ white-space: nowrap;
62
+ }
63
+
64
+ // Resource rows
65
+ &__resource {
66
+ display: flex;
67
+ align-items: center;
68
+ gap: 12px;
69
+ padding: 10px 16px 10px 32px;
70
+ border-top: 1px solid var(--border-primary);
71
+ transition: background 0.2s ease;
72
+
73
+ &--clickable {
74
+ cursor: pointer;
75
+
76
+ &:hover {
77
+ background: var(--surface-secondary);
78
+ }
79
+ }
80
+ }
81
+
82
+ &__resource-name {
83
+ flex: 1;
84
+ min-width: 0;
85
+ font-family: var(--font-family-sans, 'Geist', sans-serif);
86
+ font-size: 15px;
87
+ font-weight: 400;
88
+ line-height: 20px;
89
+ color: var(--label-primary);
90
+ }
91
+
92
+ &__resource-stats {
93
+ display: flex;
94
+ align-items: center;
95
+ gap: 32px;
96
+ flex-shrink: 0;
97
+ }
98
+
99
+ &__resource-stat {
100
+ font-family: var(--font-family-sans, 'Geist', sans-serif);
101
+ font-size: 13px;
102
+ font-weight: 400;
103
+ line-height: 16px;
104
+ color: var(--label-secondary);
105
+ white-space: nowrap;
106
+ min-width: 56px;
107
+
108
+ &--total {
109
+ min-width: 56px;
110
+ text-align: right;
111
+ }
112
+ }
113
+
114
+ &__resource-actions {
115
+ flex-shrink: 0;
116
+ width: 32px;
117
+ display: flex;
118
+ justify-content: flex-end;
119
+ }
120
+
121
+ // Add resource button wrapper
122
+ &__add-resource-wrapper {
123
+ padding: 12px 16px;
124
+ border-top: 1px solid var(--border-primary);
125
+ }
126
+ }
127
+
128
+ @media (max-width: 768px) {
129
+ .zone-card {
130
+ &__resource {
131
+ padding-left: 16px;
132
+ }
133
+
134
+ &__resource-stats {
135
+ gap: 16px;
136
+ }
137
+
138
+ &__resource-stat {
139
+ min-width: auto;
140
+ }
141
+ }
142
+ }
@@ -0,0 +1,140 @@
1
+ import React from 'react'
2
+ import { Meta, StoryObj } from '@storybook/react'
3
+ import { ZoneCard } from './ZoneCard'
4
+ import { ZoneContainer } from './ZoneContainer'
5
+ import { ZoneHeader } from './ZoneHeader'
6
+ import { ResourceRow } from './ResourceRow'
7
+ import { AddResourceButton } from './AddResourceButton'
8
+
9
+ export default {
10
+ title: 'v2/Components/ZoneCard',
11
+ component: ZoneCard,
12
+ parameters: {
13
+ layout: 'padded',
14
+ },
15
+ } as Meta<typeof ZoneCard>
16
+
17
+ type Story = StoryObj<typeof ZoneCard>
18
+
19
+ const zoneMenuItems = [
20
+ { label: 'Edit Zone', onClick: () => alert('Edit Zone') },
21
+ { label: 'Delete Zone', onClick: () => alert('Delete Zone'), variant: 'danger' as const },
22
+ ]
23
+
24
+ const resourceMenuItems = [
25
+ { label: 'Edit Resource', onClick: () => alert('Edit Resource') },
26
+ { label: 'Delete Resource', onClick: () => alert('Delete Resource'), variant: 'danger' as const },
27
+ ]
28
+
29
+ // Composed ZoneCard (all-in-one)
30
+ export const Default: Story = {
31
+ args: {
32
+ name: 'Bowling',
33
+ status: 'active',
34
+ totalCapacity: 2,
35
+ menuItems: zoneMenuItems,
36
+ onAddResource: () => alert('Add Resource'),
37
+ resources: [
38
+ { id: '1', name: 'Table', quantity: 1, capacity: 1, menuItems: resourceMenuItems },
39
+ { id: '2', name: 'Lane', quantity: 1, capacity: 1, menuItems: resourceMenuItems },
40
+ ],
41
+ },
42
+ }
43
+
44
+ export const DisabledZone: Story = {
45
+ args: {
46
+ name: 'VIP Lounge',
47
+ status: 'disabled',
48
+ totalCapacity: 0,
49
+ menuItems: zoneMenuItems,
50
+ onAddResource: () => alert('Add Resource'),
51
+ resources: [],
52
+ },
53
+ }
54
+
55
+ // Individual components composed manually
56
+ export const ComposedManually: Story = {
57
+ render: () => (
58
+ <ZoneContainer>
59
+ <ZoneHeader
60
+ name="Bowling"
61
+ status="active"
62
+ totalCapacity={2}
63
+ menuItems={zoneMenuItems}
64
+ />
65
+ <ResourceRow
66
+ name="Table"
67
+ quantity={1}
68
+ capacity={1}
69
+ menuItems={resourceMenuItems}
70
+ onClick={() => alert('Edit Table')}
71
+ />
72
+ <ResourceRow
73
+ name="Lane"
74
+ quantity={1}
75
+ capacity={1}
76
+ menuItems={resourceMenuItems}
77
+ onClick={() => alert('Edit Lane')}
78
+ />
79
+ <AddResourceButton onClick={() => alert('Add Resource')} />
80
+ </ZoneContainer>
81
+ ),
82
+ }
83
+
84
+ // Standalone ZoneHeader
85
+ export const StandaloneHeader: Story = {
86
+ render: () => (
87
+ <ZoneContainer>
88
+ <ZoneHeader
89
+ name="Main Floor"
90
+ status="active"
91
+ totalCapacity={50}
92
+ menuItems={zoneMenuItems}
93
+ />
94
+ </ZoneContainer>
95
+ ),
96
+ }
97
+
98
+ // Standalone ResourceRow
99
+ export const StandaloneResource: Story = {
100
+ render: () => (
101
+ <ZoneContainer>
102
+ <ResourceRow
103
+ name="Table"
104
+ quantity={10}
105
+ capacity={4}
106
+ menuItems={resourceMenuItems}
107
+ onClick={() => alert('Edit Table')}
108
+ />
109
+ </ZoneContainer>
110
+ ),
111
+ }
112
+
113
+ // Multiple zones
114
+ export const MultipleZones: Story = {
115
+ render: () => (
116
+ <div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
117
+ <ZoneCard
118
+ name="Bowling"
119
+ status="active"
120
+ totalCapacity={2}
121
+ menuItems={zoneMenuItems}
122
+ onAddResource={() => alert('Add Resource')}
123
+ resources={[
124
+ { id: '1', name: 'Table', quantity: 1, capacity: 1, menuItems: resourceMenuItems },
125
+ { id: '2', name: 'Lane', quantity: 1, capacity: 1, menuItems: resourceMenuItems },
126
+ ]}
127
+ />
128
+ <ZoneCard
129
+ name="VIP Lounge"
130
+ status="active"
131
+ totalCapacity={20}
132
+ menuItems={zoneMenuItems}
133
+ onAddResource={() => alert('Add Resource')}
134
+ resources={[
135
+ { id: '3', name: 'Sofa', quantity: 4, capacity: 5, menuItems: resourceMenuItems },
136
+ ]}
137
+ />
138
+ </div>
139
+ ),
140
+ }