@extrachill/components 0.4.9 → 0.4.11

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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.4.11] - 2026-03-25
4
+
5
+ ### Changed
6
+ - Add plain shell and mobile edge options to shared tabs
7
+
8
+ ## [0.4.10] - 2026-03-25
9
+
10
+ ### Changed
11
+ - Port shared tab styling into responsive tabs component
12
+
3
13
  ## [0.4.9] - 2026-03-25
4
14
 
5
15
  ### Changed
@@ -5,6 +5,7 @@ export interface BlockShellProps {
5
5
  classPrefix?: string;
6
6
  compact?: boolean;
7
7
  depth?: 0 | 1 | 2 | 3;
8
+ variant?: 'card' | 'plain';
8
9
  }
9
- export declare function BlockShell({ children, className, classPrefix, compact, depth, }: BlockShellProps): import("react/jsx-runtime").JSX.Element;
10
+ export declare function BlockShell({ children, className, classPrefix, compact, depth, variant, }: BlockShellProps): import("react/jsx-runtime").JSX.Element;
10
11
  //# sourceMappingURL=BlockShell.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"BlockShell.d.ts","sourceRoot":"","sources":["../src/BlockShell.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,eAAe;IAC/B,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;CACtB;AAED,wBAAgB,UAAU,CAAE,EAC3B,QAAQ,EACR,SAAc,EACd,WAA8B,EAC9B,OAAe,EACf,KAAS,GACT,EAAE,eAAe,2CASjB"}
1
+ {"version":3,"file":"BlockShell.d.ts","sourceRoot":"","sources":["../src/BlockShell.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,MAAM,WAAW,eAAe;IAC/B,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC3B;AAED,wBAAgB,UAAU,CAAE,EAC3B,QAAQ,EACR,SAAc,EACd,WAA8B,EAC9B,OAAe,EACf,KAAS,EACT,OAAgB,GAChB,EAAE,eAAe,2CAUjB"}
@@ -1,9 +1,10 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
- export function BlockShell({ children, className = '', classPrefix = 'ec-block-shell', compact = false, depth = 0, }) {
2
+ export function BlockShell({ children, className = '', classPrefix = 'ec-block-shell', compact = false, depth = 0, variant = 'card', }) {
3
3
  const shellClass = [
4
4
  classPrefix,
5
5
  compact ? `${classPrefix}--compact` : '',
6
6
  `${classPrefix}--depth-${depth}`,
7
+ `${classPrefix}--${variant}`,
7
8
  className,
8
9
  ].filter(Boolean).join(' ');
9
10
  return _jsx("div", { className: shellClass, children: children });
@@ -12,6 +12,7 @@ export interface ResponsiveTabsProps {
12
12
  mobileBreakpoint?: number;
13
13
  accordionClassName?: string;
14
14
  showDesktopTabs?: boolean;
15
+ mobileEdgeToEdge?: boolean;
15
16
  }
16
- export declare function ResponsiveTabs({ tabs, active, onChange, renderPanel, className, classPrefix, tabsClassName, tabsClassPrefix, mobileBreakpoint, accordionClassName, showDesktopTabs, }: ResponsiveTabsProps): import("react/jsx-runtime").JSX.Element | null;
17
+ export declare function ResponsiveTabs({ tabs, active, onChange, renderPanel, className, classPrefix, tabsClassName, tabsClassPrefix, mobileBreakpoint, accordionClassName, showDesktopTabs, mobileEdgeToEdge, }: ResponsiveTabsProps): import("react/jsx-runtime").JSX.Element | null;
17
18
  //# sourceMappingURL=ResponsiveTabs.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ResponsiveTabs.d.ts","sourceRoot":"","sources":["../src/ResponsiveTabs.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAQ,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,CAAE,EAAE,EAAE,MAAM,KAAM,IAAI,CAAC;IACjC,WAAW,EAAE,CAAE,EAAE,EAAE,MAAM,KAAM,SAAS,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,eAAe,CAAC,EAAE,OAAO,CAAC;CAC1B;AAED,wBAAgB,cAAc,CAAE,EAC/B,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,WAAW,EACX,SAAc,EACd,WAAkC,EAClC,aAAkB,EAClB,eAA2B,EAC3B,gBAAsB,EACtB,kBAAuB,EACvB,eAAsB,GACtB,EAAE,mBAAmB,kDA8ErB"}
1
+ {"version":3,"file":"ResponsiveTabs.d.ts","sourceRoot":"","sources":["../src/ResponsiveTabs.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,EAAQ,KAAK,OAAO,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,CAAE,EAAE,EAAE,MAAM,KAAM,IAAI,CAAC;IACjC,WAAW,EAAE,CAAE,EAAE,EAAE,MAAM,KAAM,SAAS,CAAC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAgB,cAAc,CAAE,EAC/B,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,WAAW,EACX,SAAc,EACd,WAAkC,EAClC,aAAkB,EAClB,eAA2B,EAC3B,gBAAsB,EACtB,kBAAuB,EACvB,eAAsB,EACtB,gBAAwB,GACxB,EAAE,mBAAmB,kDAmFrB"}
@@ -1,7 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useMemo, useState } from 'react';
3
3
  import { Tabs } from "./Tabs.js";
4
- export function ResponsiveTabs({ tabs, active, onChange, renderPanel, className = '', classPrefix = 'ec-responsive-tabs', tabsClassName = '', tabsClassPrefix = 'ec-tabs', mobileBreakpoint = 768, accordionClassName = '', showDesktopTabs = true, }) {
4
+ export function ResponsiveTabs({ tabs, active, onChange, renderPanel, className = '', classPrefix = 'ec-responsive-tabs', tabsClassName = '', tabsClassPrefix = 'ec-tabs', mobileBreakpoint = 768, accordionClassName = '', showDesktopTabs = true, mobileEdgeToEdge = false, }) {
5
5
  const [isMobile, setIsMobile] = useState(() => {
6
6
  if (typeof window === 'undefined') {
7
7
  return false;
@@ -19,9 +19,14 @@ export function ResponsiveTabs({ tabs, active, onChange, renderPanel, className
19
19
  window.addEventListener('resize', handleResize);
20
20
  return () => window.removeEventListener('resize', handleResize);
21
21
  }, [mobileBreakpoint]);
22
- const rootClass = useMemo(() => [classPrefix, isMobile ? `${classPrefix}--mobile` : `${classPrefix}--desktop`, className]
22
+ const rootClass = useMemo(() => [
23
+ classPrefix,
24
+ isMobile ? `${classPrefix}--mobile` : `${classPrefix}--desktop`,
25
+ mobileEdgeToEdge ? `${classPrefix}--mobile-edge-to-edge` : '',
26
+ className,
27
+ ]
23
28
  .filter(Boolean)
24
- .join(' '), [className, classPrefix, isMobile]);
29
+ .join(' '), [className, classPrefix, isMobile, mobileEdgeToEdge]);
25
30
  if (tabs.length === 0) {
26
31
  return null;
27
32
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@extrachill/components",
3
- "version": "0.4.9",
3
+ "version": "0.4.11",
4
4
  "description": "Shared React components for the Extra Chill Platform.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -6,6 +6,7 @@ export interface BlockShellProps {
6
6
  classPrefix?: string;
7
7
  compact?: boolean;
8
8
  depth?: 0 | 1 | 2 | 3;
9
+ variant?: 'card' | 'plain';
9
10
  }
10
11
 
11
12
  export function BlockShell( {
@@ -14,11 +15,13 @@ export function BlockShell( {
14
15
  classPrefix = 'ec-block-shell',
15
16
  compact = false,
16
17
  depth = 0,
18
+ variant = 'card',
17
19
  }: BlockShellProps ) {
18
20
  const shellClass = [
19
21
  classPrefix,
20
22
  compact ? `${ classPrefix }--compact` : '',
21
23
  `${ classPrefix }--depth-${ depth }`,
24
+ `${ classPrefix }--${ variant }`,
22
25
  className,
23
26
  ].filter( Boolean ).join( ' ' );
24
27
 
@@ -14,6 +14,7 @@ export interface ResponsiveTabsProps {
14
14
  mobileBreakpoint?: number;
15
15
  accordionClassName?: string;
16
16
  showDesktopTabs?: boolean;
17
+ mobileEdgeToEdge?: boolean;
17
18
  }
18
19
 
19
20
  export function ResponsiveTabs( {
@@ -28,6 +29,7 @@ export function ResponsiveTabs( {
28
29
  mobileBreakpoint = 768,
29
30
  accordionClassName = '',
30
31
  showDesktopTabs = true,
32
+ mobileEdgeToEdge = false,
31
33
  }: ResponsiveTabsProps ) {
32
34
  const [ isMobile, setIsMobile ] = useState( () => {
33
35
  if ( typeof window === 'undefined' ) {
@@ -53,10 +55,15 @@ export function ResponsiveTabs( {
53
55
  }, [ mobileBreakpoint ] );
54
56
 
55
57
  const rootClass = useMemo(
56
- () => [ classPrefix, isMobile ? `${ classPrefix }--mobile` : `${ classPrefix }--desktop`, className ]
58
+ () => [
59
+ classPrefix,
60
+ isMobile ? `${ classPrefix }--mobile` : `${ classPrefix }--desktop`,
61
+ mobileEdgeToEdge ? `${ classPrefix }--mobile-edge-to-edge` : '',
62
+ className,
63
+ ]
57
64
  .filter( Boolean )
58
65
  .join( ' ' ),
59
- [ className, classPrefix, isMobile ]
66
+ [ className, classPrefix, isMobile, mobileEdgeToEdge ]
60
67
  );
61
68
 
62
69
  if ( tabs.length === 0 ) {
@@ -151,6 +151,14 @@
151
151
 
152
152
  .ec-responsive-tabs__desktop-panel {
153
153
  display: grid;
154
+ background: var(--background-color, #fff);
155
+ border: 1px solid var(--border-color, #ddd);
156
+ border-radius: 0 var(--border-radius-md, 8px) var(--border-radius-md, 8px) var(--border-radius-md, 8px);
157
+ padding: var(--spacing-lg, 1.5rem) var(--spacing-md, 1rem);
158
+ margin-bottom: var(--spacing-sm, 0.5rem);
159
+ position: relative;
160
+ z-index: 1;
161
+ box-sizing: border-box;
154
162
  }
155
163
 
156
164
  .ec-responsive-tabs__accordion {
@@ -160,9 +168,15 @@
160
168
 
161
169
  .ec-responsive-tabs__item {
162
170
  border: 1px solid var(--border-color, #ddd);
163
- border-radius: var(--border-radius-md, 6px);
171
+ border-radius: var(--border-radius-md, 8px);
172
+ margin-bottom: var(--spacing-md, 1rem);
164
173
  overflow: hidden;
165
174
  background: var(--card-background, #f8f8f8);
175
+ box-sizing: border-box;
176
+ }
177
+
178
+ .ec-responsive-tabs__item:last-of-type {
179
+ margin-bottom: 0;
166
180
  }
167
181
 
168
182
  .ec-responsive-tabs__trigger {
@@ -176,14 +190,17 @@
176
190
  border-bottom: 1px solid var(--border-color, #ddd);
177
191
  background: var(--card-background, #f8f8f8);
178
192
  color: var(--text-color, #111);
179
- font: inherit;
193
+ font-family: var(--font-family-body, inherit);
194
+ font-size: var(--font-size-body, 1.125rem);
180
195
  font-weight: 600;
196
+ line-height: 1.4;
181
197
  cursor: pointer;
182
198
  text-align: left;
199
+ transition: background 0.15s ease, color 0.15s ease;
183
200
  }
184
201
 
185
- .ec-responsive-tabs__trigger:not(.is-active) {
186
- border-bottom-color: transparent;
202
+ .ec-responsive-tabs__item:last-of-type .ec-responsive-tabs__trigger:not(.is-active) {
203
+ border-bottom: 0;
187
204
  }
188
205
 
189
206
  .ec-responsive-tabs__trigger.is-active {
@@ -191,14 +208,81 @@
191
208
  color: var(--link-color, #0b5394);
192
209
  }
193
210
 
211
+ .ec-responsive-tabs__trigger:hover {
212
+ background: var(--background-color, #fff);
213
+ color: var(--link-color, #0b5394);
214
+ }
215
+
216
+ .ec-responsive-tabs__trigger:focus-visible {
217
+ outline: 2px solid var(--focus-border-color, #53940b);
218
+ outline-offset: -2px;
219
+ box-shadow: inset 0 0 0 1px var(--focus-border-color, #53940b);
220
+ }
221
+
194
222
  .ec-responsive-tabs__panel {
195
223
  padding: var(--spacing-sm, 0.5rem);
196
224
  background: var(--background-color, #fff);
225
+ margin-bottom: 0;
226
+ }
227
+
228
+ .ec-responsive-tabs__panel > .ec-panel:first-child {
229
+ margin-top: 0;
197
230
  }
198
231
 
199
232
  .ec-responsive-tabs__arrow {
200
233
  flex-shrink: 0;
201
234
  font-size: var(--font-size-sm, 0.875rem);
235
+ margin-left: var(--spacing-sm, 0.5rem);
236
+ color: currentColor;
237
+ }
238
+
239
+ @media (min-width: 769px) {
240
+ .ec-responsive-tabs__accordion {
241
+ display: none;
242
+ }
243
+
244
+ .ec-responsive-tabs .ec-tabs__tabs {
245
+ display: flex;
246
+ flex-wrap: wrap;
247
+ margin-bottom: -1px;
248
+ position: relative;
249
+ }
250
+
251
+ .ec-responsive-tabs .ec-tabs__tab {
252
+ border: 1px solid var(--border-color, #ddd);
253
+ border-bottom: 1px solid var(--border-color, #ddd);
254
+ border-radius: var(--border-radius-md, 8px) var(--border-radius-md, 8px) 0 0;
255
+ padding: var(--spacing-sm, 0.5rem) var(--spacing-md, 1rem);
256
+ font-size: var(--font-size-base, 1rem);
257
+ position: relative;
258
+ top: 1px;
259
+ margin-right: var(--spacing-xs, 0.25rem);
260
+ background: var(--card-background, #f8f8f8);
261
+ color: var(--text-color, #111);
262
+ z-index: 2;
263
+ }
264
+
265
+ .ec-responsive-tabs .ec-tabs__tab.is-active {
266
+ background: var(--background-color, #fff);
267
+ color: var(--link-color, #0b5394);
268
+ border-bottom: 1px solid var(--background-color, #fff);
269
+ z-index: 3;
270
+ }
271
+ }
272
+
273
+ @media (max-width: 768px) {
274
+ .ec-responsive-tabs .ec-tabs__tabs,
275
+ .ec-responsive-tabs__desktop-panel {
276
+ display: none;
277
+ }
278
+
279
+ .ec-responsive-tabs--mobile-edge-to-edge .ec-responsive-tabs__item {
280
+ margin-left: calc(var(--spacing-md, 1rem) * -1);
281
+ margin-right: calc(var(--spacing-md, 1rem) * -1);
282
+ border-left: 0;
283
+ border-right: 0;
284
+ border-radius: 0;
285
+ }
202
286
  }
203
287
 
204
288
  // Panel
@@ -222,6 +306,13 @@
222
306
  gap: var(--spacing-lg, 1.5rem);
223
307
  }
224
308
 
309
+ .ec-block-shell--plain {
310
+ background: transparent;
311
+ border: 0;
312
+ border-radius: 0;
313
+ padding: 0;
314
+ }
315
+
225
316
  .ec-block-shell--depth-0 {
226
317
  background: var(--card-background, #f1f5f9);
227
318
  }