@colixsystems/widget-sdk 0.156.0 → 0.157.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
@@ -73,7 +73,15 @@ See the design reference for the full architecture: [`docs/architecture/widget-m
73
73
 
74
74
  ## Status
75
75
 
76
- `v0.156.0` — pre-publish. The package surface (types, function names, export paths) is the v1 contract; runtime behaviour for some hooks is stubbed (each hook documents what's wired and what isn't). It is **not yet published to npm**.
76
+ `v0.157.0` — pre-publish. The package surface (types, function names, export paths) is the v1 contract; runtime behaviour for some hooks is stubbed (each hook documents what's wired and what isn't). It is **not yet published to npm**.
77
+
78
+ ### What's new in 0.157.0 (contract 1.122.0 — unchanged)
79
+
80
+ **The app header's row has its own text colour (sc-8518).** `resolveTopStripeLayout(theme)` now returns **`tintColor`** and **`titleColor`** beside the resolved `backgroundColor`, each reading `theme.sidebar.stripe.textColor` and falling back through `resolveTopBarTokens` when it is unset — exactly as the surface already falls back. One authored colour drives both, as the bar's own does; unset they part, the icons taking slate and the app name the brand.
81
+
82
+ Before this the row's ink lived on `topBar.textColor`, which also paints the tab row every top navigation bar draws — so recolouring the app header moved every one of those tab rows with it. What the two colours reach is what `slots` describes: the phone header, the desktop strip, the full-width bar, and the export's screen header. The drawer's own account rows, the sign-in control, the notification bell and the site-mode sheet are not that row and keep reading the bar.
83
+
84
+ Additive — nothing in the existing `./host` surface changed, an unset value resolves to what it resolved to before, and the contract is untouched.
77
85
 
78
86
  ### What's new in 0.156.0 (contract 1.122.0)
79
87
 
@@ -111,7 +119,7 @@ Behaviour: a bare date given to a `mode="datetime"` picker now shows local midni
111
119
 
112
120
  **The app header's row is arrangeable, and `./host` publishes the resolver both hosts read (sc-8023).** The row runs across the top of the content outside the side panel, and is drawn three times — as the phone header where the panel is a drawer, as the desktop strip, and as the full-width bar when one is switched on. Each surface hard-coded its own copy of it, so an author could colour the row but never move anything in it.
113
121
 
114
- - **`resolveTopStripeLayout(theme)`** reads `theme.sidebar.stripe` and returns the arrangement fully resolved: `slots` (already filtered and sequenced, so no host re-derives it), `order`, the box (`height`, `paddingX`, `contentOffsetY`), the resolved `backgroundColor`, and `menuSide` — which edge the drawer must arrive from, since the brand grows and a burger ordered after it sits at the trailing edge. The web Player picks the drawer's side with it; the export makes it `drawerPosition`.
122
+ - **`resolveTopStripeLayout(theme)`** reads `theme.sidebar.stripe` and returns the arrangement fully resolved: `slots` (already filtered and sequenced, so no host re-derives it), `order`, the box (`height`, `paddingX`, `contentOffsetY`), the resolved `backgroundColor` (joined in 0.155.0 by `tintColor` and `titleColor`), and `menuSide` — which edge the drawer must arrive from, since the brand grows and a burger ordered after it sits at the trailing edge. The web Player picks the drawer's side with it; the export makes it `drawerPosition`.
115
123
  - **`TOP_STRIPE_SLOTS`** is the vocabulary (`back`, `menu`, `brand`, `notifications`) and **`TOP_STRIPE_ALWAYS_SHOWN_SLOTS`** the slots that move but never hide. The burger is the only member: it is drawn only where the panel is a drawer, and there it is the sole route into the menu, so hiding it would strand the visitor. It keeps its place in `order` regardless.
116
124
  - **`topStripeShowKey(slot)`** derives the `theme_config` key that shows or hides one slot, in one place, so a control, the write path and the resolver cannot spell it differently.
117
125
  - **The bounds travel with the resolver** — `MIN`/`MAX_TOP_STRIPE_HEIGHT_PX`, `MIN`/`MAX_TOP_STRIPE_PADDING_X_PX`, `MAX_TOP_STRIPE_OFFSET_Y_PX` — so a control offers exactly the range the resolver clamps to. `DEFAULT_TOP_STRIPE_HEIGHT_PX` / `DEFAULT_TOP_STRIPE_PADDING_X_PX` are what the DESKTOP row measures with nothing stored, published so a control can show the number an author is departing from; the resolver still answers `null`, because each surface keeps its own box until one is named.
@@ -403,15 +403,17 @@ function topStripeOrder(value) {
403
403
  * bar left holding nothing is not drawn at all.
404
404
  *
405
405
  * @param {unknown} theme — the whole `theme_config`.
406
- * @returns {{ backgroundColor: string, height: number|null,
407
- * paddingX: number|null, contentOffsetY: number, order: string[],
408
- * slots: string[], menuSide: "start"|"end" }}
406
+ * @returns {{ backgroundColor: string, tintColor: string, titleColor: string,
407
+ * height: number|null, paddingX: number|null, contentOffsetY: number,
408
+ * order: string[], slots: string[], menuSide: "start"|"end" }}
409
409
  */
410
410
  function resolveTopStripeLayout(theme) {
411
411
  const config = isPlainObject(theme) ? theme : {};
412
412
  const sidebar = isPlainObject(config.sidebar) ? config.sidebar : {};
413
413
  const stripe = isPlainObject(sidebar.stripe) ? sidebar.stripe : {};
414
414
  const order = topStripeOrder(stripe.order);
415
+ // Resolved once: the row's colours all fall back through the app-header bar.
416
+ const barTokens = resolveTopBarTokens(theme);
415
417
  const shown = (slot) => {
416
418
  if (TOP_STRIPE_ALWAYS_SHOWN_SLOTS.includes(slot)) return true;
417
419
  const value = stripe[topStripeShowKey(slot)];
@@ -449,10 +451,30 @@ function resolveTopStripeLayout(theme) {
449
451
  // page's top navigation bar no longer repaints the stripe above the panel by
450
452
  // accident. Fully resolved here, not raw-or-null, for the reason sc-8033
451
453
  // resolved the footer's: a default that lives in each host drifts.
452
- backgroundColor: hexOr(
453
- stripe.backgroundColor,
454
- resolveTopBarTokens(theme).backgroundColor,
455
- ),
454
+ backgroundColor: hexOr(stripe.backgroundColor, barTokens.backgroundColor),
455
+ // sc-8518: the row's OWN text, the half sc-8023 left on the bar. An author
456
+ // recolouring the app header used to move every top navigation bar's tab
457
+ // labels with it, because both read `topBar.textColor` — and had to open a
458
+ // panel named after the other part to do it.
459
+ //
460
+ // One authored colour drives BOTH slots, exactly as the bar's own does:
461
+ // unset they part (icons take slate, the app name takes the brand), and
462
+ // naming one is a decision about the whole row. Unset inherits the bar,
463
+ // so an app that never opens this field is unmoved.
464
+ //
465
+ // The row is what `slots` above describes — the desktop bar, the phone
466
+ // header, and native's screen header. The drawer's own account rows, the
467
+ // sign-in control and the site-mode sheet are NOT this row and keep
468
+ // reading the bar; so does the SITE header, which is shown instead of this
469
+ // row rather than beside it.
470
+ //
471
+ // The notification bell is the one member of `slots` this does not reach.
472
+ // It keeps its own resting colour on both hosts — web reads the authored
473
+ // `topBar.textColor` and the export tints it not at all — and moving it
474
+ // here would widen that difference rather than close it. Whoever closes it
475
+ // should move both hosts at once.
476
+ tintColor: hexOr(stripe.textColor, barTokens.tintColor),
477
+ titleColor: hexOr(stripe.textColor, barTokens.titleColor),
456
478
  order,
457
479
  slots,
458
480
  // sc-8023: which edge the panel the burger opens should come in from. The
@@ -394,15 +394,17 @@ function topStripeOrder(value) {
394
394
  * bar left holding nothing is not drawn at all.
395
395
  *
396
396
  * @param {unknown} theme — the whole `theme_config`.
397
- * @returns {{ backgroundColor: string, height: number|null,
398
- * paddingX: number|null, contentOffsetY: number, order: string[],
399
- * slots: string[], menuSide: "start"|"end" }}
397
+ * @returns {{ backgroundColor: string, tintColor: string, titleColor: string,
398
+ * height: number|null, paddingX: number|null, contentOffsetY: number,
399
+ * order: string[], slots: string[], menuSide: "start"|"end" }}
400
400
  */
401
401
  export function resolveTopStripeLayout(theme) {
402
402
  const config = isPlainObject(theme) ? theme : {};
403
403
  const sidebar = isPlainObject(config.sidebar) ? config.sidebar : {};
404
404
  const stripe = isPlainObject(sidebar.stripe) ? sidebar.stripe : {};
405
405
  const order = topStripeOrder(stripe.order);
406
+ // Resolved once: the row's colours all fall back through the app-header bar.
407
+ const barTokens = resolveTopBarTokens(theme);
406
408
  const shown = (slot) => {
407
409
  if (TOP_STRIPE_ALWAYS_SHOWN_SLOTS.includes(slot)) return true;
408
410
  const value = stripe[topStripeShowKey(slot)];
@@ -440,10 +442,30 @@ export function resolveTopStripeLayout(theme) {
440
442
  // page's top navigation bar no longer repaints the stripe above the panel by
441
443
  // accident. Fully resolved here, not raw-or-null, for the reason sc-8033
442
444
  // resolved the footer's: a default that lives in each host drifts.
443
- backgroundColor: hexOr(
444
- stripe.backgroundColor,
445
- resolveTopBarTokens(theme).backgroundColor,
446
- ),
445
+ backgroundColor: hexOr(stripe.backgroundColor, barTokens.backgroundColor),
446
+ // sc-8518: the row's OWN text, the half sc-8023 left on the bar. An author
447
+ // recolouring the app header used to move every top navigation bar's tab
448
+ // labels with it, because both read `topBar.textColor` — and had to open a
449
+ // panel named after the other part to do it.
450
+ //
451
+ // One authored colour drives BOTH slots, exactly as the bar's own does:
452
+ // unset they part (icons take slate, the app name takes the brand), and
453
+ // naming one is a decision about the whole row. Unset inherits the bar,
454
+ // so an app that never opens this field is unmoved.
455
+ //
456
+ // The row is what `slots` above describes — the desktop bar, the phone
457
+ // header, and native's screen header. The drawer's own account rows, the
458
+ // sign-in control and the site-mode sheet are NOT this row and keep
459
+ // reading the bar; so does the SITE header, which is shown instead of this
460
+ // row rather than beside it.
461
+ //
462
+ // The notification bell is the one member of `slots` this does not reach.
463
+ // It keeps its own resting colour on both hosts — web reads the authored
464
+ // `topBar.textColor` and the export tints it not at all — and moving it
465
+ // here would widen that difference rather than close it. Whoever closes it
466
+ // should move both hosts at once.
467
+ tintColor: hexOr(stripe.textColor, barTokens.tintColor),
468
+ titleColor: hexOr(stripe.textColor, barTokens.titleColor),
447
469
  order,
448
470
  slots,
449
471
  // sc-8023: which edge the panel the burger opens should come in from. The
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@colixsystems/widget-sdk",
3
- "version": "0.156.0",
3
+ "version": "0.157.0",
4
4
  "description": "Common widget interface for AppStudio. Implements WidgetManifest, WidgetContext, property schema, and helper hooks.",
5
5
  "homepage": "https://github.com/Colix-AB/AppStudio",
6
6
  "type": "module",