@magic-spells/cart-panel 0.3.0 → 1.0.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.
package/README.md CHANGED
@@ -50,7 +50,7 @@ Or include directly in your HTML:
50
50
  <cart-panel>
51
51
  <div class="cart-header">
52
52
  <h2 id="cart-title">Shopping Cart</h2>
53
- <button data-action="hide-cart" aria-label="Close cart">&times;</button>
53
+ <button data-action-hide-cart aria-label="Close cart">&times;</button>
54
54
  </div>
55
55
 
56
56
  <div class="cart-body">
@@ -66,7 +66,7 @@ Or include directly in your HTML:
66
66
  </div>
67
67
  <div class="quantity-controls">
68
68
  <input type="number" data-cart-quantity value="1" min="1" />
69
- <button data-action="remove">Remove</button>
69
+ <button data-action-remove-item>Remove</button>
70
70
  </div>
71
71
  </cart-item-content>
72
72
  <cart-item-processing>
@@ -124,8 +124,8 @@ The component automatically handles:
124
124
  | Selector | Description | Event Triggered |
125
125
  | --------------------------- | ----------------------------------- | --------------------------- |
126
126
  | `[aria-controls="cart-id"]` | Trigger buttons to open cart | Opens modal |
127
- | `[data-action="hide-cart"]` | Close buttons inside modal | Closes modal |
128
- | `[data-action="remove"]` | Remove item buttons (via cart-item) | `cart-item:remove` |
127
+ | `[data-action-hide-cart]` | Close buttons inside modal | Closes modal |
128
+ | `[data-action-remove-item]` | Remove item buttons (via cart-item) | `cart-item:remove` |
129
129
  | `[data-cart-quantity]` | Quantity inputs (via cart-item) | `cart-item:quantity-change` |
130
130
 
131
131
  Example:
@@ -135,7 +135,7 @@ Example:
135
135
  <cart-dialog id="simple-cart">
136
136
  <cart-panel>
137
137
  <h2>Cart</h2>
138
- <button data-action="hide-cart">Close</button>
138
+ <button data-action-hide-cart>Close</button>
139
139
  <!-- Cart content here -->
140
140
  </cart-panel>
141
141
  </cart-dialog>
@@ -146,7 +146,7 @@ Example:
146
146
  <cart-panel>
147
147
  <header class="cart-header">
148
148
  <h2 id="cart-heading">Shopping Cart</h2>
149
- <button data-action="hide-cart" aria-label="Close cart">×</button>
149
+ <button data-action-hide-cart aria-label="Close cart">×</button>
150
150
  </header>
151
151
  <div class="cart-content">
152
152
  <!-- Cart items will be rendered here -->
@@ -582,7 +582,7 @@ The cart panel automatically integrates with Shopify's AJAX Cart API. Simply add
582
582
  <cart-panel>
583
583
  <header class="cart-header">
584
584
  <h2 id="cart-heading">Your Cart</h2>
585
- <button data-action="hide-cart" aria-label="hide cart">X</button>
585
+ <button data-action-hide-cart aria-label="hide cart">X</button>
586
586
  </header>
587
587
 
588
588
  <div class="cart-content">
@@ -1,208 +1,231 @@
1
+ /* =============================================================================
2
+ Cart Panel Component
3
+ ============================================================================= */
4
+
5
+ cart-panel {
6
+ display: block;
7
+ height: 100%;
8
+ overflow-y: auto;
9
+ overflow-x: hidden;
10
+ }
11
+
12
+ /* =============================================================================
13
+ Cart Item Component
14
+ ============================================================================= */
15
+
1
16
  cart-item {
2
- --cart-item-processing-duration: 250ms;
3
- --cart-item-destroying-duration: 600ms;
4
- --cart-item-appearing-duration: 400ms;
5
- --cart-item-shadow-color: rgba(0, 0, 0, 0.15);
6
- --cart-item-shadow-color-strong: rgba(0, 0, 0, 0.5);
7
- --cart-item-destroying-bg: rgba(0, 0, 0, 0.1);
8
- --cart-item-processing-scale: 0.98;
9
- --cart-item-destroying-scale: 0.85;
10
- --cart-item-appearing-scale: 0.9;
11
- --cart-item-processing-blur: 1px;
12
- --cart-item-destroying-blur: 10px;
13
- --cart-item-appearing-blur: 2px;
14
- --cart-item-destroying-opacity: 0.2;
15
- --cart-item-appearing-opacity: 0.5;
16
- --cart-item-destroying-brightness: 0.6;
17
- --cart-item-destroying-saturate: 0.3;
18
- display: block;
19
- position: relative;
20
- overflow: hidden;
21
- padding: 0px;
22
- box-shadow: inset 0px 0px 0px rgba(0, 0, 0, 0);
23
- transition: filter var(--cart-item-processing-duration) ease-out, background-color var(--cart-item-processing-duration) ease-out, box-shadow var(--cart-item-processing-duration) ease-out;
17
+ /* CSS Custom Properties for customization */
18
+ --cart-item-processing-duration: 250ms;
19
+ --cart-item-destroying-duration: 600ms;
20
+ --cart-item-appearing-duration: 400ms;
21
+ --cart-item-shadow-color: rgba(0, 0, 0, 0.15);
22
+ --cart-item-shadow-color-strong: rgba(0, 0, 0, 0.5);
23
+ --cart-item-destroying-bg: rgba(0, 0, 0, 0.1);
24
+ --cart-item-processing-scale: 0.98;
25
+ --cart-item-destroying-scale: 0.85;
26
+ --cart-item-appearing-scale: 0.9;
27
+ --cart-item-processing-blur: 1px;
28
+ --cart-item-destroying-blur: 10px;
29
+ --cart-item-appearing-blur: 2px;
30
+ --cart-item-destroying-opacity: 0.2;
31
+ --cart-item-appearing-opacity: 0.5;
32
+ --cart-item-destroying-brightness: 0.6;
33
+ --cart-item-destroying-saturate: 0.3;
34
+
35
+ display: block;
36
+ position: relative;
37
+ overflow: hidden;
38
+ padding: 0px;
39
+ box-shadow: inset 0px 0px 0px rgba(0, 0, 0, 0);
40
+ transition:
41
+ filter var(--cart-item-processing-duration) ease-out,
42
+ background-color var(--cart-item-processing-duration) ease-out,
43
+ box-shadow var(--cart-item-processing-duration) ease-out;
24
44
  }
45
+
25
46
  cart-item::after {
26
- content: "";
27
- display: block;
28
- position: absolute;
29
- background: rgba(0, 0, 0, 0);
30
- width: 100%;
31
- pointer-events: none;
32
- height: 100%;
33
- top: 0px;
34
- left: 0px;
35
- transition: background-color var(--cart-item-processing-duration) ease;
36
- }
37
- cart-item[state=ready] {
38
- transition: filter var(--cart-item-processing-duration) ease-out, background-color var(--cart-item-processing-duration) ease-out, box-shadow var(--cart-item-processing-duration) ease-out, height var(--cart-item-appearing-duration) ease-out;
39
- }
40
- cart-item[state=ready] cart-item-content {
41
- transform: scale(1);
42
- filter: blur(0px);
43
- opacity: 1;
44
- transition: transform var(--cart-item-appearing-duration) ease-out, filter var(--cart-item-appearing-duration) ease-out, opacity var(--cart-item-appearing-duration) ease-out;
45
- }
46
- cart-item[state=ready] cart-item-processing {
47
- opacity: 0;
48
- visibility: hidden;
49
- }
50
- cart-item[state=processing] {
51
- box-shadow: inset 0px 2px 10px var(--cart-item-shadow-color);
52
- }
53
- cart-item[state=processing]::after {
54
- background: rgba(0, 0, 0, 0.15);
55
- }
56
- cart-item[state=processing] cart-item-content {
57
- transform: scale(var(--cart-item-processing-scale));
58
- filter: blur(var(--cart-item-processing-blur));
59
- opacity: 0.9;
60
- pointer-events: none;
61
- transition: transform var(--cart-item-processing-duration) ease-out, filter var(--cart-item-processing-duration) ease-out, opacity var(--cart-item-processing-duration) ease-out;
62
- }
63
- cart-item[state=processing] cart-item-processing {
64
- opacity: 1;
65
- visibility: visible;
66
- }
67
- cart-item[state=destroying] {
68
- background-color: var(--cart-item-destroying-bg);
69
- box-shadow: inset 0px 2px 20px var(--cart-item-shadow-color-strong);
70
- margin-top: 0px;
71
- margin-bottom: 0px;
72
- transition: filter var(--cart-item-destroying-duration) ease, background-color var(--cart-item-destroying-duration) ease, box-shadow var(--cart-item-destroying-duration) ease, margin var(--cart-item-destroying-duration) ease;
73
- }
74
- cart-item[state=destroying]::after {
75
- background: rgba(0, 0, 0, 0.9);
76
- transition: background-color var(--cart-item-destroying-duration) ease;
77
- }
78
- cart-item[state=destroying] cart-item-content {
79
- transition: transform var(--cart-item-destroying-duration) ease, filter var(--cart-item-destroying-duration) ease, opacity var(--cart-item-destroying-duration) ease;
80
- transform: scale(var(--cart-item-destroying-scale));
81
- filter: blur(var(--cart-item-destroying-blur)) saturate(var(--cart-item-destroying-saturate));
82
- opacity: var(--cart-item-destroying-opacity);
83
- pointer-events: none;
84
- }
85
- cart-item[state=destroying] cart-item-processing {
86
- opacity: 0;
87
- transition: opacity var(--cart-item-processing-duration) ease;
88
- }
89
- cart-item[state=appearing] {
90
- height: 0px;
91
- overflow: hidden;
92
- transition: height var(--cart-item-appearing-duration) ease-out, filter var(--cart-item-appearing-duration) ease-out, opacity var(--cart-item-appearing-duration) ease-out;
93
- }
94
- cart-item[state=appearing] cart-item-content {
95
- transform: scale(var(--cart-item-appearing-scale));
96
- filter: blur(var(--cart-item-appearing-blur));
97
- opacity: var(--cart-item-appearing-opacity);
98
- transition: transform var(--cart-item-appearing-duration) ease-out, filter var(--cart-item-appearing-duration) ease-out, opacity var(--cart-item-appearing-duration) ease-out;
99
- }
100
- cart-item[state=appearing] cart-item-processing {
101
- opacity: 0;
102
- visibility: hidden;
47
+ content: '';
48
+ display: block;
49
+ position: absolute;
50
+ background: rgba(0, 0, 0, 0);
51
+ width: 100%;
52
+ pointer-events: none;
53
+ height: 100%;
54
+ top: 0px;
55
+ left: 0px;
56
+ transition: background-color var(--cart-item-processing-duration) ease;
57
+ }
58
+
59
+ /* Ready state (default) */
60
+ cart-item[state='ready'] {
61
+ transition:
62
+ filter var(--cart-item-processing-duration) ease-out,
63
+ background-color var(--cart-item-processing-duration) ease-out,
64
+ box-shadow var(--cart-item-processing-duration) ease-out,
65
+ height var(--cart-item-appearing-duration) ease-out;
66
+ }
67
+
68
+ cart-item[state='ready'] cart-item-content {
69
+ transform: scale(1);
70
+ filter: blur(0px);
71
+ opacity: 1;
72
+ transition:
73
+ transform var(--cart-item-appearing-duration) ease-out,
74
+ filter var(--cart-item-appearing-duration) ease-out,
75
+ opacity var(--cart-item-appearing-duration) ease-out;
76
+ }
77
+
78
+ cart-item[state='ready'] cart-item-processing {
79
+ opacity: 0;
80
+ visibility: hidden;
81
+ }
82
+
83
+ /* Processing state - content slightly scaled and blurred, processing overlay visible */
84
+ cart-item[state='processing'] {
85
+ box-shadow: inset 0px 2px 10px var(--cart-item-shadow-color);
103
86
  }
104
87
 
88
+ cart-item[state='processing']::after {
89
+ background: rgba(0, 0, 0, 0.15);
90
+ }
91
+
92
+ cart-item[state='processing'] cart-item-content {
93
+ transform: scale(var(--cart-item-processing-scale));
94
+ filter: blur(var(--cart-item-processing-blur));
95
+ opacity: 0.9;
96
+ pointer-events: none;
97
+ transition:
98
+ transform var(--cart-item-processing-duration) ease-out,
99
+ filter var(--cart-item-processing-duration) ease-out,
100
+ opacity var(--cart-item-processing-duration) ease-out;
101
+ }
102
+
103
+ cart-item[state='processing'] cart-item-processing {
104
+ opacity: 1;
105
+ visibility: visible;
106
+ }
107
+
108
+ /* Destroying state - heavy effects on content, darker background */
109
+ cart-item[state='destroying'] {
110
+ background-color: var(--cart-item-destroying-bg);
111
+ box-shadow: inset 0px 2px 20px var(--cart-item-shadow-color-strong);
112
+ margin-top: 0px;
113
+ margin-bottom: 0px;
114
+ transition:
115
+ filter var(--cart-item-destroying-duration) ease,
116
+ background-color var(--cart-item-destroying-duration) ease,
117
+ box-shadow var(--cart-item-destroying-duration) ease,
118
+ margin var(--cart-item-destroying-duration) ease;
119
+ }
120
+
121
+ cart-item[state='destroying']::after {
122
+ background: rgba(0, 0, 0, 0.9);
123
+ transition: background-color var(--cart-item-destroying-duration) ease;
124
+ }
125
+
126
+ cart-item[state='destroying'] cart-item-content {
127
+ transition:
128
+ transform var(--cart-item-destroying-duration) ease,
129
+ filter var(--cart-item-destroying-duration) ease,
130
+ opacity var(--cart-item-destroying-duration) ease;
131
+ transform: scale(var(--cart-item-destroying-scale));
132
+ filter: blur(var(--cart-item-destroying-blur)) saturate(var(--cart-item-destroying-saturate));
133
+ opacity: var(--cart-item-destroying-opacity);
134
+ pointer-events: none;
135
+ }
136
+
137
+ cart-item[state='destroying'] cart-item-processing {
138
+ opacity: 0;
139
+ transition: opacity var(--cart-item-processing-duration) ease;
140
+ }
141
+
142
+ /* Appearing state - reverse of destroying for smooth entry animation */
143
+ cart-item[state='appearing'] {
144
+ height: 0px;
145
+ overflow: hidden;
146
+ transition:
147
+ height var(--cart-item-appearing-duration) ease-out,
148
+ filter var(--cart-item-appearing-duration) ease-out,
149
+ opacity var(--cart-item-appearing-duration) ease-out;
150
+ }
151
+
152
+ cart-item[state='appearing'] cart-item-content {
153
+ transform: scale(var(--cart-item-appearing-scale));
154
+ filter: blur(var(--cart-item-appearing-blur));
155
+ opacity: var(--cart-item-appearing-opacity);
156
+ transition:
157
+ transform var(--cart-item-appearing-duration) ease-out,
158
+ filter var(--cart-item-appearing-duration) ease-out,
159
+ opacity var(--cart-item-appearing-duration) ease-out;
160
+ }
161
+
162
+ cart-item[state='appearing'] cart-item-processing {
163
+ opacity: 0;
164
+ visibility: hidden;
165
+ }
166
+
167
+ /* =============================================================================
168
+ Cart Item Child Components
169
+ ============================================================================= */
170
+
105
171
  cart-item-content {
106
- display: block;
172
+ display: block;
107
173
  }
108
174
 
109
175
  cart-item-processing {
110
- position: absolute;
111
- top: 0;
112
- left: 0;
113
- right: 0;
114
- bottom: 0;
115
- display: flex;
116
- align-items: center;
117
- justify-content: center;
118
- background: transparent;
119
- opacity: 0;
120
- visibility: hidden;
121
- transition: opacity var(--cart-item-processing-duration) ease-out, visibility var(--cart-item-processing-duration) ease-out;
122
- z-index: 10;
176
+ position: absolute;
177
+ top: 0;
178
+ left: 0;
179
+ right: 0;
180
+ bottom: 0;
181
+ display: flex;
182
+ align-items: center;
183
+ justify-content: center;
184
+ background: transparent;
185
+ opacity: 0;
186
+ visibility: hidden;
187
+ transition:
188
+ opacity var(--cart-item-processing-duration) ease-out,
189
+ visibility var(--cart-item-processing-duration) ease-out;
190
+ z-index: 10;
123
191
  }
192
+
193
+ /* Default loader animation */
124
194
  cart-item-processing .cart-item-loader {
125
- width: 60px;
126
- aspect-ratio: 2;
127
- --_g: no-repeat radial-gradient(circle closest-side, #000 90%, #0000);
128
- background: var(--_g) 0% 50%, var(--_g) 50% 50%, var(--_g) 100% 50%;
129
- background-size: 33.3333333333% 50%;
130
- animation: cart-item-loader 1s infinite linear;
195
+ width: 60px;
196
+ aspect-ratio: 2;
197
+ --_g: no-repeat radial-gradient(circle closest-side, #000 90%, #0000);
198
+ background:
199
+ var(--_g) 0% 50%,
200
+ var(--_g) 50% 50%,
201
+ var(--_g) 100% 50%;
202
+ background-size: calc(100% / 3) 50%;
203
+ animation: cart-item-loader 1s infinite linear;
131
204
  }
132
205
 
133
206
  @keyframes cart-item-loader {
134
- 20% {
135
- background-position: 0% 0%, 50% 50%, 100% 50%;
136
- }
137
- 40% {
138
- background-position: 0% 100%, 50% 0%, 100% 50%;
139
- }
140
- 60% {
141
- background-position: 0% 50%, 50% 100%, 100% 0%;
142
- }
143
- 80% {
144
- background-position: 0% 50%, 50% 50%, 100% 100%;
145
- }
146
- }
147
- :root {
148
- --cart-dialog-z-index: 1000;
149
- --cart-overlay-z-index: 1000;
150
- --cart-panel-z-index: 1001;
151
- --cart-panel-width: min(400px, 90vw);
152
- --cart-overlay-background: rgba(0, 0, 0, 0.15);
153
- --cart-overlay-backdrop-filter: blur(4px);
154
- --cart-panel-background: #ffffff;
155
- --cart-panel-shadow: -5px 0 25px rgba(0, 0, 0, 0.15);
156
- --cart-panel-border-radius: 0;
157
- --cart-transition-duration: 350ms;
158
- --cart-transition-timing: cubic-bezier(0.4, 0, 0.2, 1);
159
- }
160
-
161
- cart-dialog {
162
- display: contents;
163
- }
164
- cart-dialog[aria-hidden=false] cart-overlay,
165
- cart-dialog[aria-hidden=false] cart-panel {
166
- pointer-events: auto;
167
- opacity: 1;
168
- }
169
- cart-dialog[aria-hidden=false] cart-panel {
170
- transform: translateX(0);
171
- }
172
-
173
- cart-overlay {
174
- position: fixed;
175
- top: 0;
176
- left: 0;
177
- width: 100vw;
178
- height: 100vh;
179
- opacity: 0;
180
- pointer-events: none;
181
- z-index: var(--cart-overlay-z-index);
182
- background-color: var(--cart-overlay-background);
183
- backdrop-filter: var(--cart-overlay-backdrop-filter);
184
- transition: opacity var(--cart-transition-duration) var(--cart-transition-timing), backdrop-filter var(--cart-transition-duration) var(--cart-transition-timing);
207
+ 20% {
208
+ background-position:
209
+ 0% 0%,
210
+ 50% 50%,
211
+ 100% 50%;
212
+ }
213
+ 40% {
214
+ background-position:
215
+ 0% 100%,
216
+ 50% 0%,
217
+ 100% 50%;
218
+ }
219
+ 60% {
220
+ background-position:
221
+ 0% 50%,
222
+ 50% 100%,
223
+ 100% 0%;
224
+ }
225
+ 80% {
226
+ background-position:
227
+ 0% 50%,
228
+ 50% 50%,
229
+ 100% 100%;
230
+ }
185
231
  }
186
-
187
- cart-panel {
188
- position: fixed;
189
- top: 0;
190
- right: 0;
191
- width: var(--cart-panel-width);
192
- height: 100dvh;
193
- transform: translateX(100%);
194
- pointer-events: none;
195
- z-index: var(--cart-panel-z-index);
196
- background: var(--cart-panel-background);
197
- box-shadow: var(--cart-panel-shadow);
198
- border-radius: var(--cart-panel-border-radius);
199
- overflow: hidden;
200
- transition: transform var(--cart-transition-duration) var(--cart-transition-timing);
201
- }
202
- cart-panel.hidden {
203
- display: none;
204
- }
205
-
206
- body.overflow-hidden {
207
- overflow: hidden;
208
- }