@nok-integration/storefront-react 0.18.5 → 0.19.1

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/dist/styles.css CHANGED
@@ -3647,14 +3647,14 @@
3647
3647
  gap: var(--space-20);
3648
3648
  }
3649
3649
 
3650
- ._gallery_10mch_1 {
3650
+ ._gallery_9e68b_1 {
3651
3651
  position: relative;
3652
3652
  display: flex;
3653
3653
  flex-direction: column;
3654
3654
  gap: var(--space-12);
3655
3655
  }
3656
3656
 
3657
- ._track_10mch_8 {
3657
+ ._track_9e68b_8 {
3658
3658
  display: flex;
3659
3659
  overflow-x: auto;
3660
3660
  scroll-snap-type: x mandatory;
@@ -3674,30 +3674,46 @@
3674
3674
  scrollbar-width: none;
3675
3675
  }
3676
3676
 
3677
- ._track_10mch_8::-webkit-scrollbar {
3677
+ ._track_9e68b_8::-webkit-scrollbar {
3678
3678
  display: none;
3679
3679
  }
3680
3680
 
3681
- ._slide_10mch_32 {
3681
+ ._slide_9e68b_32 {
3682
3682
  position: relative;
3683
3683
  flex: 0 0 100%;
3684
3684
  scroll-snap-align: center;
3685
3685
  aspect-ratio: 375 / 475;
3686
3686
  }
3687
3687
 
3688
- ._image_10mch_39 {
3688
+ ._image_9e68b_39 {
3689
3689
  object-fit: cover;
3690
3690
  }
3691
3691
 
3692
- ._placeholder_10mch_43 {
3692
+ ._placeholder_9e68b_43 {
3693
3693
  width: 100%;
3694
3694
  aspect-ratio: 375 / 475;
3695
3695
  background: var(--color-surface-soft);
3696
3696
  }
3697
3697
 
3698
3698
  /* Share button — top-right chrome over the image (mobile/button: 32px, soft, radius-8). */
3699
- ._share_10mch_50 {
3699
+ ._share_9e68b_50 {
3700
3700
  position: absolute;
3701
+ /*
3702
+ * **Without this the button is drawn and cannot be tapped.**
3703
+ *
3704
+ * `.share` is the gallery's first child and the image track follows it. Both the button
3705
+ * and the `fill` images inside the track are absolutely positioned and nothing here
3706
+ * declared a `z-index`, so painting order fell to DOM order and every image won. A tap
3707
+ * anywhere on the icon landed on the photograph — the control looked completely normal
3708
+ * and did nothing, which is the failure mode this repo has been bitten by before.
3709
+ *
3710
+ * The pagination dots were never affected: they come *after* the track, so they were
3711
+ * already on top by accident. That is why this survived review.
3712
+ *
3713
+ * Found by hit-testing `document.elementFromPoint` at the button's own centre, not by
3714
+ * reading the stylesheet — from the CSS it looks correct.
3715
+ */
3716
+ z-index: 1;
3701
3717
  top: var(--space-16);
3702
3718
  right: var(--space-16);
3703
3719
  display: inline-flex;
@@ -3713,13 +3729,25 @@
3713
3729
  cursor: pointer;
3714
3730
  }
3715
3731
 
3716
- ._dots_10mch_67 {
3732
+ ._dots_9e68b_83 {
3717
3733
  display: flex;
3718
3734
  justify-content: center;
3719
3735
  gap: var(--space-6);
3720
3736
  }
3721
3737
 
3722
- ._dot_10mch_67 {
3738
+ /*
3739
+ * The icon is drawn at 32px because that is the box the design gives it; the TAP is 44px.
3740
+ * Same trick as the header's controls — a negative-inset pseudo-element, so the hit area
3741
+ * grows and not one pixel moves. Measured 32px of clear space above it, so symmetric
3742
+ * expansion cannot reach the control overhead.
3743
+ */
3744
+ ._share_9e68b_50::after {
3745
+ content: '';
3746
+ position: absolute;
3747
+ inset: -6px;
3748
+ }
3749
+
3750
+ ._dot_9e68b_83 {
3723
3751
  width: 8px;
3724
3752
  height: 8px;
3725
3753
  padding: 0;
@@ -3731,13 +3759,28 @@
3731
3759
  position: relative;
3732
3760
  }
3733
3761
 
3734
- ._dot_10mch_67::after {
3762
+ /*
3763
+ * The hit area is tall, and only as wide as the dot's own column.
3764
+ *
3765
+ * It used to be `inset: -18px` on all four sides, which reads as "44px target" and behaved
3766
+ * as the opposite. The dots are 8px with a 6px gap — a 14px pitch — so an 18px horizontal
3767
+ * bleed put every dot's hit area completely over its neighbour's, and the later sibling
3768
+ * paints on top. **Only the last dot was tappable**; aiming at the first selected the
3769
+ * second. Measured by walking `elementFromPoint` outward from each dot's centre.
3770
+ *
3771
+ * 3px is half the gap, so the columns tile exactly and never overlap. That makes each dot
3772
+ * 14px wide, which is under the 44px guideline and is the widest the design's own spacing
3773
+ * allows without one dot stealing another's taps — a reliable 14x44 beats a nominal 44x44
3774
+ * that belongs to the wrong control. Swiping the track remains the primary affordance, and
3775
+ * it is unaffected.
3776
+ */
3777
+ ._dot_9e68b_83::after {
3735
3778
  content: '';
3736
3779
  position: absolute;
3737
- inset: -18px;
3780
+ inset: -18px -3px;
3738
3781
  }
3739
3782
 
3740
- ._dotActive_10mch_91 {
3783
+ ._dotActive_9e68b_134 {
3741
3784
  background: var(--color-surface-max);
3742
3785
  }
3743
3786
  /*
@@ -4115,18 +4158,18 @@
4115
4158
  animation: none;
4116
4159
  }
4117
4160
  }
4118
- ._root_9zj90_1 {
4161
+ ._root_6sbl9_1 {
4119
4162
  display: flex;
4120
4163
  flex-direction: column;
4121
4164
  gap: var(--space-12);
4122
4165
  }
4123
4166
 
4124
- ._header_9zj90_7 {
4167
+ ._header_6sbl9_7 {
4125
4168
  display: flex;
4126
4169
  align-items: center;
4127
4170
  }
4128
4171
 
4129
- ._title_9zj90_12 {
4172
+ ._title_6sbl9_12 {
4130
4173
  margin: 0;
4131
4174
  font-size: var(--type-trimmed-md-size);
4132
4175
  line-height: var(--type-trimmed-md-line);
@@ -4134,14 +4177,14 @@
4134
4177
  color: var(--color-text-default);
4135
4178
  }
4136
4179
 
4137
- ._chips_9zj90_20 {
4180
+ ._chips_6sbl9_20 {
4138
4181
  display: flex;
4139
4182
  flex-wrap: wrap;
4140
4183
  gap: var(--space-8);
4141
4184
  }
4142
4185
 
4143
4186
  /* 48px square chips per the mobile/pdp/size component (radius-xs, not radius-sm). */
4144
- ._chip_9zj90_20 {
4187
+ ._chip_6sbl9_20 {
4145
4188
  display: inline-flex;
4146
4189
  align-items: center;
4147
4190
  justify-content: center;
@@ -4158,7 +4201,7 @@
4158
4201
  cursor: pointer;
4159
4202
  }
4160
4203
 
4161
- ._selected_9zj90_44 {
4204
+ ._selected_6sbl9_44 {
4162
4205
  border-color: var(--color-surface-max);
4163
4206
  background: var(--color-surface-max);
4164
4207
  color: var(--color-text-strong);
@@ -4170,7 +4213,7 @@
4170
4213
  * range reads complete"), so a fan can see the range runs to XXL and that their size is
4171
4214
  * the one that has gone, rather than seeing a range with a hole in it.
4172
4215
  */
4173
- ._disabled_9zj90_56 {
4216
+ ._disabled_6sbl9_56 {
4174
4217
  cursor: not-allowed;
4175
4218
  border-style: dashed;
4176
4219
  color: var(--color-text-disabled);
@@ -4178,14 +4221,16 @@
4178
4221
 
4179
4222
  /* Figma: regular weight, critical token. Bold read as a second heading next to the
4180
4223
  16px "Size" label above it. */
4181
- ._error_9zj90_64 {
4224
+ ._error_6sbl9_64 {
4182
4225
  margin: 0;
4183
4226
  font-size: var(--type-trimmed-sm-size);
4184
4227
  font-weight: var(--font-weight-regular);
4185
4228
  color: var(--color-state-surface-critical-default);
4186
4229
  }
4187
4230
 
4188
- ._sizeGuide_9zj90_71 {
4231
+ ._sizeGuide_6sbl9_71 {
4232
+ /* Anchors the hit-area pseudo-element below. */
4233
+ position: relative;
4189
4234
  display: inline-flex;
4190
4235
  align-items: center;
4191
4236
  gap: var(--space-2);
@@ -4199,9 +4244,23 @@
4199
4244
  cursor: pointer;
4200
4245
  }
4201
4246
 
4202
- ._chevron_9zj90_85 {
4247
+ ._chevron_6sbl9_87 {
4203
4248
  display: block;
4204
4249
  }
4250
+
4251
+ /*
4252
+ * An 18px-tall text button is a 44px tap target.
4253
+ *
4254
+ * **Asymmetric on purpose.** There are only 11px of clear space between this row and the
4255
+ * size chips above it, so a symmetric -13px would put this control's hit area *over* the
4256
+ * chips — and a fan aiming at XL would open the size guide instead. It grows 8px up (3px
4257
+ * of the gap left clear) and 18px down, into empty space: 8 + 18 + 18 = 44.
4258
+ */
4259
+ ._sizeGuide_6sbl9_71::after {
4260
+ content: '';
4261
+ position: absolute;
4262
+ inset: -8px -8px -18px;
4263
+ }
4205
4264
  ._root_1h4ny_1 {
4206
4265
  display: flex;
4207
4266
  flex-direction: column;
@@ -4362,19 +4421,19 @@
4362
4421
  background: var(--color-surface-soft);
4363
4422
  }
4364
4423
  /* Figma mobile/pdp/details: heading+body group, then more/Less 4px under it. */
4365
- ._root_t4qba_2 {
4424
+ ._root_9cj0g_2 {
4366
4425
  display: flex;
4367
4426
  flex-direction: column;
4368
4427
  gap: var(--space-4);
4369
4428
  }
4370
4429
 
4371
- ._group_t4qba_8 {
4430
+ ._group_9cj0g_8 {
4372
4431
  display: flex;
4373
4432
  flex-direction: column;
4374
4433
  gap: var(--space-8);
4375
4434
  }
4376
4435
 
4377
- ._title_t4qba_14 {
4436
+ ._title_9cj0g_14 {
4378
4437
  margin: 0;
4379
4438
  font-size: var(--type-trimmed-md-size);
4380
4439
  line-height: var(--type-trimmed-md-line);
@@ -4382,18 +4441,18 @@
4382
4441
  color: var(--color-text-default);
4383
4442
  }
4384
4443
 
4385
- ._body_t4qba_22 {
4444
+ ._body_9cj0g_22 {
4386
4445
  color: var(--color-text-subtle);
4387
4446
  }
4388
4447
 
4389
- ._paragraph_t4qba_26 {
4448
+ ._paragraph_9cj0g_26 {
4390
4449
  margin: 0;
4391
4450
  font-size: var(--type-paragraph-size);
4392
4451
  line-height: var(--type-paragraph-line);
4393
4452
  }
4394
4453
 
4395
4454
  /* paragraph-spacing/lg between paragraphs, nothing after the last. */
4396
- ._paragraph_t4qba_26 + ._paragraph_t4qba_26 {
4455
+ ._paragraph_9cj0g_26 + ._paragraph_9cj0g_26 {
4397
4456
  margin-top: var(--space-12);
4398
4457
  }
4399
4458
 
@@ -4406,12 +4465,14 @@
4406
4465
  * lines is exactly `font-size × line-height × 3`, so the cut lands on a line boundary
4407
4466
  * rather than through the middle of one.
4408
4467
  */
4409
- ._clamped_t4qba_46 {
4468
+ ._clamped_9cj0g_46 {
4410
4469
  max-height: calc(var(--type-paragraph-size) * var(--type-paragraph-line) * 3);
4411
4470
  overflow: hidden;
4412
4471
  }
4413
4472
 
4414
- ._toggle_t4qba_51 {
4473
+ ._toggle_9cj0g_51 {
4474
+ /* Anchors the hit-area pseudo-element below. */
4475
+ position: relative;
4415
4476
  align-self: flex-start;
4416
4477
  padding: 0;
4417
4478
  border: none;
@@ -4424,6 +4485,16 @@
4424
4485
  font-weight: var(--font-weight-bold);
4425
4486
  cursor: pointer;
4426
4487
  }
4488
+
4489
+ /*
4490
+ * 36x25 drawn, 44x45 tapped. The control sits in clear space — 266px above, 72px below —
4491
+ * so this cannot overlap anything.
4492
+ */
4493
+ ._toggle_9cj0g_51::after {
4494
+ content: '';
4495
+ position: absolute;
4496
+ inset: -10px -4px;
4497
+ }
4427
4498
  ._row_l4edh_1 {
4428
4499
  display: flex;
4429
4500
  flex-wrap: wrap;
@@ -5397,7 +5468,7 @@
5397
5468
  * the sticky CTA bar (50), the size-guide sheet (60), the bottom sheets (900) and the
5398
5469
  * toast (1000).
5399
5470
  */
5400
- ._header_1yjrk_25 {
5471
+ ._header_8o3d7_25 {
5401
5472
  position: sticky;
5402
5473
  top: 0;
5403
5474
  z-index: 40;
@@ -5462,7 +5533,7 @@
5462
5533
  * Declared after `.header` so it wins the background: both are one class, so the later
5463
5534
  * rule takes it.
5464
5535
  */
5465
- ._floating_1yjrk_44 {
5536
+ ._floating_8o3d7_44 {
5466
5537
  position: sticky;
5467
5538
  top: 0;
5468
5539
  /* Out of the flow without leaving it: the artwork below starts at y=0 and is drawn
@@ -5519,12 +5590,12 @@
5519
5590
  * Fixed rather than tokenised, like the hero's own palette: it is drawn over a photograph
5520
5591
  * and does not follow the surface.
5521
5592
  */
5522
- ._floating_1yjrk_44._scrolled_1yjrk_79 {
5593
+ ._floating_8o3d7_44._scrolled_8o3d7_79 {
5523
5594
  background: rgba(8, 14, 18, 0.6);
5524
5595
  }
5525
5596
 
5526
5597
  @media (prefers-reduced-motion: reduce) {
5527
- ._floating_1yjrk_44 {
5598
+ ._floating_8o3d7_44 {
5528
5599
  transition: none;
5529
5600
  }
5530
5601
  }
@@ -5544,7 +5615,7 @@
5544
5615
  * the dark screens, and the light PDP header (5295:75116) has an empty title slot. Written
5545
5616
  * as a static white it would be invisible the first time a host passed one on a light page.
5546
5617
  */
5547
- ._title_1yjrk_172 {
5618
+ ._title_8o3d7_172 {
5548
5619
  flex: 0 0 auto;
5549
5620
  width: 222px;
5550
5621
  min-width: 0;
@@ -5557,7 +5628,27 @@
5557
5628
  white-space: nowrap;
5558
5629
  }
5559
5630
 
5560
- ._right_1yjrk_185 {
5631
+ /*
5632
+ * The same title, on a bar that carries no icons — the cart (`4661:136810`) and the order
5633
+ * screens.
5634
+ *
5635
+ * The 222px above is measured against a bar with the full 72px icon cluster on the right.
5636
+ * Take the cluster away and `space-between` has 97px of slack to share between two gaps,
5637
+ * which lands the text at x=88.5 — a title floating in the middle of an otherwise empty
5638
+ * bar. The frame puts "Cart" hard against the chevron: box at x=16..40, text from 57, so
5639
+ * one 16px gap and no more. DAZN reported it on 21 Aug 2026.
5640
+ *
5641
+ * `flex: 1 1 auto` rather than a second measured width, because there is nothing on the
5642
+ * right to measure against: the title simply takes what is left, and a long order
5643
+ * reference ellipsises instead of pushing a layout that has no other content in it.
5644
+ */
5645
+ ._title_8o3d7_172._leading_8o3d7_199 {
5646
+ flex: 1 1 auto;
5647
+ width: auto;
5648
+ margin-left: var(--space-16);
5649
+ }
5650
+
5651
+ ._right_8o3d7_205 {
5561
5652
  display: flex;
5562
5653
  align-items: center;
5563
5654
  gap: var(--space-16);
@@ -5570,12 +5661,12 @@
5570
5661
  * header without a back button would silently re-lay-out rather than simply losing one
5571
5662
  * icon. 24px is the icon box it stands in for.
5572
5663
  */
5573
- ._spacer_1yjrk_198 {
5664
+ ._spacer_8o3d7_218 {
5574
5665
  width: 24px;
5575
5666
  height: 24px;
5576
5667
  }
5577
5668
 
5578
- ._iconBtn_1yjrk_203 {
5669
+ ._iconBtn_8o3d7_223 {
5579
5670
  position: relative;
5580
5671
  display: inline-flex;
5581
5672
  align-items: center;
@@ -5591,7 +5682,7 @@
5591
5682
  }
5592
5683
 
5593
5684
  /* Expand the hit area to >=44px without moving the 24px icon off the 16px inset. */
5594
- ._iconBtn_1yjrk_203::after {
5685
+ ._iconBtn_8o3d7_223::after {
5595
5686
  content: '';
5596
5687
  position: absolute;
5597
5688
  inset: -10px;
@@ -5602,12 +5693,12 @@
5602
5693
  * its glyph on the design's centre line — 16px from the right edge, not 12. Its own icon
5603
5694
  * stays 24px.
5604
5695
  */
5605
- ._menuBtn_1yjrk_230 {
5696
+ ._menuBtn_8o3d7_250 {
5606
5697
  width: 32px;
5607
5698
  height: 32px;
5608
5699
  }
5609
5700
 
5610
- ._menuBtn_1yjrk_230::after {
5701
+ ._menuBtn_8o3d7_250::after {
5611
5702
  inset: -6px;
5612
5703
  }
5613
5704
 
@@ -5630,7 +5721,7 @@
5630
5721
  *
5631
5722
  * Sits above the ::after hit area so the number is never painted underneath it.
5632
5723
  */
5633
- ._badge_1yjrk_258 {
5724
+ ._badge_8o3d7_278 {
5634
5725
  position: absolute;
5635
5726
  top: -6px;
5636
5727
  left: 14px;
@@ -5657,13 +5748,13 @@
5657
5748
  * `context=checkout` (5295:74075). Both side slots are the 32px box the frame draws — the
5658
5749
  * left one empty, so the title centres on the screen rather than on what is left over.
5659
5750
  */
5660
- ._closeSlot_1yjrk_285 {
5751
+ ._closeSlot_8o3d7_305 {
5661
5752
  flex: 0 0 auto;
5662
5753
  width: 32px;
5663
5754
  height: 32px;
5664
5755
  }
5665
5756
 
5666
- ._closeSlot_1yjrk_285._iconBtn_1yjrk_203::after {
5757
+ ._closeSlot_8o3d7_305._iconBtn_8o3d7_223::after {
5667
5758
  inset: -6px;
5668
5759
  }
5669
5760
 
@@ -5672,7 +5763,7 @@
5672
5763
  * centres "Order #2304" between two equal slots, so it is the free space, not a measured
5673
5764
  * width. Same size, weight and colour as the shop entry's — one text style, two positions.
5674
5765
  */
5675
- ._centred_1yjrk_300 {
5766
+ ._centred_8o3d7_320 {
5676
5767
  flex: 1 1 auto;
5677
5768
  width: auto;
5678
5769
  text-align: center;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nok-integration/storefront-react",
3
- "version": "0.18.5",
3
+ "version": "0.19.1",
4
4
  "description": "Mountable React storefront components: catalogue, product detail and cart, mounted directly into a host DOM tree. No iframe.",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",