@fanfare-io/fanfare-sdk-react 0.22.0 → 0.23.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.
@@ -240,8 +240,8 @@
240
240
  --ff-otp-shadow-focus: var(--ff-otp-shadow);
241
241
  --ff-otp-shadow-focus-error: var(--ff-otp-shadow-focus);
242
242
 
243
- /* Product selector row: the box a row draws and the square its thumbnail
244
- * occupies inside it. */
243
+ /* Selector rows (a product, a payment method): the box a row draws and the
244
+ * square a product thumbnail occupies inside it. */
245
245
  --ff-row-gap: 0.75rem;
246
246
  --ff-row-padding: 0.75rem;
247
247
  --ff-row-radius: 0.375rem;
@@ -487,6 +487,20 @@
487
487
  line-height: 1.4;
488
488
  }
489
489
 
490
+ /**
491
+ * The payment panel's section heading reads at body scale under its badge
492
+ * and hero stat. A retry moves focus to it so a screen reader starts from
493
+ * the explanation; it is not a control, and the Retry badge already marks
494
+ * the state, so the programmatic focus draws no ring.
495
+ */
496
+ .fanfare-themed [data-slot="checkout-title"] {
497
+ color: var(--ff-color-foreground);
498
+ font-size: 0.875rem;
499
+ font-weight: 600;
500
+ line-height: 1.25rem;
501
+ outline: none;
502
+ }
503
+
490
504
  .fanfare-themed [data-slot="panel-body"],
491
505
  .fanfare-themed [data-slot="panel-stack"] {
492
506
  gap: var(--ff-panel-gap);
@@ -536,12 +550,132 @@
536
550
  box-shadow: var(--ff-loading-shadow);
537
551
  }
538
552
 
539
- .fanfare-themed [data-slot="product-selector-row"] {
553
+ .fanfare-themed [data-slot="product-selector-row"],
554
+ .fanfare-themed [data-slot="payment-method-row"] {
540
555
  gap: var(--ff-row-gap);
541
556
  padding: var(--ff-row-padding);
542
557
  border-radius: var(--ff-row-radius);
543
558
  }
544
559
 
560
+ /**
561
+ * A payment method row draws the product selector's row, so a payment choice
562
+ * reads as the same kind of choice as the item it pays for. The native radio
563
+ * stays in the row: it carries the group's keyboard model, and the row takes
564
+ * its checked and focus states from it.
565
+ */
566
+ .fanfare-themed [data-slot="payment-method-row"] {
567
+ display: flex;
568
+ align-items: center;
569
+ width: 100%;
570
+ cursor: pointer;
571
+ border: 1px solid color-mix(in oklab, var(--ff-color-border) 40%, transparent);
572
+ background-color: var(--ff-color-background);
573
+ transition:
574
+ background-color 150ms,
575
+ border-color 150ms,
576
+ box-shadow 150ms;
577
+ }
578
+
579
+ @media (hover: hover) {
580
+ .fanfare-themed [data-slot="payment-method-row"]:hover {
581
+ background-color: var(--ff-color-secondary);
582
+ }
583
+ }
584
+
585
+ .fanfare-themed [data-slot="payment-method-row"]:has(:checked) {
586
+ border-color: var(--ff-color-foreground);
587
+ box-shadow: inset 0 0 0 1px var(--ff-color-foreground);
588
+ }
589
+
590
+ .fanfare-themed [data-slot="payment-method-row"]:has(:focus-visible) {
591
+ outline: 2px solid var(--ff-color-primary);
592
+ outline-offset: 2px;
593
+ }
594
+
595
+ .fanfare-themed [data-slot="payment-method-row"] > input {
596
+ flex-shrink: 0;
597
+ width: 1rem;
598
+ height: 1rem;
599
+ margin: 0;
600
+ outline: none;
601
+ accent-color: var(--ff-color-foreground);
602
+ }
603
+
604
+ .fanfare-themed [data-slot="payment-method-row"] > svg {
605
+ flex-shrink: 0;
606
+ width: 1.25rem;
607
+ height: 1.25rem;
608
+ color: var(--ff-color-muted);
609
+ fill: none;
610
+ stroke: currentColor;
611
+ stroke-width: 1.5;
612
+ stroke-linecap: round;
613
+ stroke-linejoin: round;
614
+ }
615
+
616
+ /**
617
+ * The card field's frame draws the variant's text input around Stripe's
618
+ * iframe. Focus and validity live inside that iframe, where no selector
619
+ * reaches, so the element's own events publish them on the frame.
620
+ */
621
+ .fanfare-themed [data-fanfare-field="stripe-card-frame"][data-framed] {
622
+ padding: 0.625rem 0.75rem;
623
+ border: 1px solid var(--ff-color-border);
624
+ border-radius: 0.375rem;
625
+ background-color: var(--ff-color-background);
626
+ transition:
627
+ border-color 200ms,
628
+ box-shadow 200ms,
629
+ background-color 200ms;
630
+ }
631
+
632
+ .fanfare-themed [data-fanfare-field="stripe-card-frame"][data-focused] {
633
+ border-color: var(--ff-color-primary);
634
+ box-shadow: 0 0 0 2px color-mix(in oklab, var(--ff-color-primary) 20%, transparent);
635
+ }
636
+
637
+ .fanfare-themed[data-fanfare-variant="retro"] [data-fanfare-field="stripe-card-frame"][data-framed] {
638
+ border: 3px solid var(--ff-color-foreground);
639
+ border-radius: 0;
640
+ box-shadow: inset 3px 3px 0 var(--ff-color-secondary);
641
+ }
642
+
643
+ .fanfare-themed[data-fanfare-variant="retro"] [data-fanfare-field="stripe-card-frame"][data-focused] {
644
+ border-color: var(--ff-color-primary);
645
+ box-shadow: inset 3px 3px 0 var(--ff-color-primary);
646
+ }
647
+
648
+ .fanfare-themed[data-fanfare-variant="rounded"] [data-fanfare-field="stripe-card-frame"][data-framed] {
649
+ border-color: color-mix(in oklab, var(--ff-color-foreground) 12%, transparent);
650
+ border-radius: 0.75rem;
651
+ background-color: color-mix(in oklch, var(--ff-color-foreground) 3%, var(--ff-color-background));
652
+ box-shadow: var(--ff-input-shadow);
653
+ }
654
+
655
+ .fanfare-themed[data-fanfare-variant="rounded"] [data-fanfare-field="stripe-card-frame"][data-focused] {
656
+ border-color: color-mix(in oklab, var(--ff-color-primary) 50%, transparent);
657
+ background-color: var(--ff-color-background);
658
+ box-shadow: var(--ff-input-shadow-focus);
659
+ }
660
+
661
+ .fanfare-themed[data-fanfare-variant="clean"] [data-fanfare-field="stripe-card-frame"][data-framed] {
662
+ padding-inline: 0;
663
+ border-width: 0 0 1px;
664
+ border-color: color-mix(in oklab, var(--ff-color-foreground) 20%, transparent);
665
+ border-radius: 0;
666
+ background-color: transparent;
667
+ }
668
+
669
+ .fanfare-themed[data-fanfare-variant="clean"] [data-fanfare-field="stripe-card-frame"][data-focused] {
670
+ border-color: var(--ff-color-primary);
671
+ box-shadow: none;
672
+ }
673
+
674
+ /* Stated after the variants, at their specificity, so every variant shows it. */
675
+ .fanfare-themed [data-fanfare-field="stripe-card-frame"][data-framed][data-invalid] {
676
+ border-color: var(--ff-color-danger);
677
+ }
678
+
545
679
  .fanfare-themed [data-slot="product-thumb"] {
546
680
  width: var(--ff-row-thumb-size);
547
681
  height: var(--ff-row-thumb-size);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fanfare-io/fanfare-sdk-react",
3
- "version": "0.22.0",
3
+ "version": "0.23.0",
4
4
  "description": "React adapter for Fanfare SDK",
5
5
  "publishConfig": {
6
6
  "registry": "https://registry.npmjs.org",
@@ -43,8 +43,8 @@
43
43
  "nanostores": "^1.1.0",
44
44
  "tailwind-merge": "^2.6.0",
45
45
  "valibot": "^1.1.0",
46
- "@fanfare-io/fanfare-sdk-core": "0.22.0",
47
- "@fanfare-io/fanfare-sdk-i18n": "0.22.0"
46
+ "@fanfare-io/fanfare-sdk-core": "0.23.0",
47
+ "@fanfare-io/fanfare-sdk-i18n": "0.23.0"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@iconify-json/heroicons": "^1.2.3",
@@ -90,8 +90,8 @@
90
90
  "vite-plugin-dts": "^4.5.4",
91
91
  "vite-tsconfig-paths": "^5.1.4",
92
92
  "vitest": "^5.0.0",
93
- "@fanfare-io/fanfare-sdk-core": "0.22.0",
94
- "@fanfare-io/fanfare-sdk-solid": "0.22.0"
93
+ "@fanfare-io/fanfare-sdk-core": "0.23.0",
94
+ "@fanfare-io/fanfare-sdk-solid": "0.23.0"
95
95
  },
96
96
  "sideEffects": [
97
97
  "**/*.css"
@@ -109,7 +109,7 @@
109
109
  {
110
110
  "name": "React adapter",
111
111
  "path": "dist/index.js",
112
- "limit": "70 KB",
112
+ "limit": "71 KB",
113
113
  "ignore": [
114
114
  "react",
115
115
  "react-dom",