@khipu/design-system 0.3.4 → 0.3.5-alpha.10

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.
@@ -13,7 +13,7 @@
13
13
  *
14
14
  * AUTO-GENERATED FILE - DO NOT EDIT MANUALLY
15
15
  * Source: design-system/src/tokens/tokens.json
16
- * Generated: 2026-08-12T21:28:55.469Z
16
+ * Generated: 2026-08-14T20:37:28.660Z
17
17
  *
18
18
  * To regenerate:
19
19
  * cd design-system && npm run tokens:generate
@@ -685,6 +685,37 @@ body.dark,
685
685
  --outline: var(--kds-color-input-border);
686
686
  --outline-variant: var(--kds-border-light);
687
687
 
688
+ /* ========================================
689
+ EXTENDED BRAND ROLES
690
+
691
+ Several roles used to resolve straight to --kds-color-primary-main, which
692
+ meant a brand could not have (say) a green link next to a navy button.
693
+ They are split into their own tokens:
694
+
695
+ --kds-color-accent form icon, expand toggle, checkbox/radio
696
+ --kds-color-accent-soft form icon backdrop
697
+ --kds-font-family-heading display/heading tier
698
+ --kds-invoice-amount-font-family
699
+ --kds-invoice-amount-color
700
+ --kds-button-font-family
701
+ --kds-button-text-transform
702
+ --kds-button-primary-bg
703
+ --kds-button-primary-bg-hover
704
+
705
+ These are deliberately NOT declared here. Each one is consumed as
706
+ var(--new-token, <the expression it used to be>), so the default is
707
+ supplied at the point of use.
708
+
709
+ Declaring them as :root aliases looks equivalent but is not. A custom
710
+ property is substituted on the element that DECLARES it, so
711
+ `--kds-color-accent: var(--kds-color-primary-main)` on :root freezes to
712
+ whatever the primary is at :root. A brand that sets its primary further
713
+ down the tree (which is how khenshin-web applies merchant styles) would
714
+ inherit the already-resolved Khipu purple and lose its own colour. Using
715
+ them as fallbacks resolves against the primary in effect at the consuming
716
+ element, so unbranded output and existing brands are both unchanged.
717
+ ======================================== */
718
+
688
719
  /* ========================================
689
720
  ONBOARDING COMPONENTS TOKENS
690
721
  ======================================== */
@@ -1010,12 +1041,12 @@ a.kds-btn {
1010
1041
  width: 100%;
1011
1042
 
1012
1043
  /* Typography - Using design tokens */
1013
- font-family: var(--kds-font-family-secondary);
1044
+ font-family: var(--kds-button-font-family, var(--kds-font-family-secondary));
1014
1045
  font-weight: var(--kds-font-weight-medium); /* 500 */
1015
1046
  font-size: var(--kds-typography-button-font-size); /* 0.875rem = 14px */
1016
1047
  line-height: var(--kds-typography-button-line-height); /* 1.5 */
1017
1048
  letter-spacing: var(--kds-typography-button-letter-spacing); /* 0.46px */
1018
- text-transform: uppercase;
1049
+ text-transform: var(--kds-button-text-transform, uppercase);
1019
1050
 
1020
1051
  /* Spacing - Using design tokens */
1021
1052
  padding: var(--kds-spacing-button-padding); /* 0 16px */
@@ -1072,16 +1103,19 @@ a.kds-btn:disabled {
1072
1103
  /* Primary button - Khipu purple */
1073
1104
  button.kds-btn-primary,
1074
1105
  a.kds-btn-primary {
1075
- background: var(--kds-color-primary-main); /* #8347AD */
1106
+ background: var(--kds-button-primary-bg, var(--kds-color-primary-main)); /* #8347AD */
1076
1107
  color: var(--kds-color-primary-contrast); /* #FFF light / dark-purple on dark (lavender bg) */
1077
1108
  border: none;
1078
1109
  box-shadow: 0 1px 2px rgba(131, 71, 173, .25);
1079
1110
  }
1080
1111
 
1081
- /* Hover State - background más oscuro */
1112
+ /* Hover State - background más oscuro.
1113
+ Its own token, not primary-dark: once a brand sets the button background
1114
+ independently of the primary, deriving hover from the primary would snap it
1115
+ back to the brand's other colour on the first pointer-over. */
1082
1116
  button.kds-btn-primary:hover:not(:disabled),
1083
1117
  a.kds-btn-primary:hover:not(:disabled) {
1084
- background: var(--kds-color-primary-dark); /* #5B3179 */
1118
+ background: var(--kds-button-primary-bg-hover, var(--kds-color-primary-dark)); /* #5B3179 */
1085
1119
  }
1086
1120
 
1087
1121
  /* Active/Focus State */
@@ -1089,7 +1123,7 @@ button.kds-btn-primary:active:not(:disabled),
1089
1123
  button.kds-btn-primary:focus-visible:not(:disabled),
1090
1124
  a.kds-btn-primary:active:not(:disabled),
1091
1125
  a.kds-btn-primary:focus-visible:not(:disabled) {
1092
- background: var(--kds-color-primary-dark);
1126
+ background: var(--kds-button-primary-bg-hover, var(--kds-color-primary-dark));
1093
1127
  }
1094
1128
 
1095
1129
  /* Dark mode: the button is a light lavender with dark text, so hover/active must
@@ -2422,12 +2456,21 @@ a.kds-btn-google:disabled {
2422
2456
  /* Llena y centra dentro de contenedores flex (pantalla de carga); en flujo
2423
2457
  normal (contenedor no-flex) se reduce a su contenido. */
2424
2458
  flex: 1 1 auto;
2425
- /* Alto propio: el loader es contenido minimo por definicion, asi que sin esto la
2426
- card queda del alto del spinner y se lee como un recorte. Ocupa el body completo
2427
- de un telefono para que la pantalla de carga se lea como una pantalla y no como
2428
- una franja. Va aca y no en la card para que el minimo aplique solo a la carga:
2429
- el resto de las pantallas crece con su contenido. */
2430
- min-height: 36rem;
2459
+ /* Alto propio: el loader es contenido minimo por definicion, asi que sin esto la card
2460
+ queda del alto del spinner y se lee como un recorte. Va aca y no en la card para que
2461
+ el minimo aplique solo a la carga: el resto de las pantallas crece con su contenido.
2462
+ El valor de escritorio es moderado a proposito: el minimo de telefono (36rem) dejaba
2463
+ la card de la carga mucho mas alta que cualquier otra pantalla, y al entrar y salir
2464
+ del loader el widget crecia y volvia a encoger. */
2465
+ min-height: 18rem;
2466
+ }
2467
+
2468
+ /* En telefono la carga si ocupa el alto util de la pantalla: ahi la card va a ancho
2469
+ completo y un loader corto se lee como una franja perdida en el medio. */
2470
+ @media (max-width: 767px) {
2471
+ .kds-secure-loader {
2472
+ min-height: 36rem;
2473
+ }
2431
2474
  }
2432
2475
 
2433
2476
  .kds-secure-loader-text {
@@ -3240,7 +3283,7 @@ label.radio span {
3240
3283
  /* Checked state */
3241
3284
  label.checkbox input[type="checkbox"]:checked,
3242
3285
  label.radio input[type="radio"]:checked {
3243
- accent-color: var(--primary);
3286
+ accent-color: var(--kds-color-accent, var(--primary));
3244
3287
  }
3245
3288
 
3246
3289
  /* Disabled state */
@@ -5009,9 +5052,12 @@ dialog#surveyModal button.circle {
5009
5052
  background-color: var(--kds-color-info-soft);
5010
5053
  }
5011
5054
 
5012
- /* ── Typography variants ── */
5055
+ /* ── Typography variants ──
5056
+ The display/heading tier resolves through --kds-font-family-heading so a
5057
+ brand can pair a display face with a different body face. Unset by default,
5058
+ so it falls through to the primary family and output is unchanged. */
5013
5059
  .kds-text-display1 {
5014
- font-family: var(--kds-font-family-primary, 'Public Sans', sans-serif);
5060
+ font-family: var(--kds-font-family-heading, var(--kds-font-family-primary, 'Public Sans', sans-serif));
5015
5061
  font-size: var(--kds-font-size-4xl, 36px);
5016
5062
  font-weight: var(--kds-font-weight-bold, 700);
5017
5063
  line-height: var(--kds-line-height-tight, 1.2);
@@ -5019,7 +5065,7 @@ dialog#surveyModal button.circle {
5019
5065
  }
5020
5066
 
5021
5067
  .kds-text-display2 {
5022
- font-family: var(--kds-font-family-primary, 'Public Sans', sans-serif);
5068
+ font-family: var(--kds-font-family-heading, var(--kds-font-family-primary, 'Public Sans', sans-serif));
5023
5069
  font-size: var(--kds-font-size-3xl, 30px);
5024
5070
  font-weight: var(--kds-font-weight-bold, 700);
5025
5071
  line-height: var(--kds-line-height-tight, 1.2);
@@ -5027,21 +5073,21 @@ dialog#surveyModal button.circle {
5027
5073
  }
5028
5074
 
5029
5075
  .kds-text-heading1 {
5030
- font-family: var(--kds-font-family-primary, 'Public Sans', sans-serif);
5076
+ font-family: var(--kds-font-family-heading, var(--kds-font-family-primary, 'Public Sans', sans-serif));
5031
5077
  font-size: var(--kds-font-size-2xl, 24px);
5032
5078
  font-weight: var(--kds-font-weight-semibold, 600);
5033
5079
  line-height: var(--kds-line-height-snug, 1.375);
5034
5080
  }
5035
5081
 
5036
5082
  .kds-text-heading2 {
5037
- font-family: var(--kds-font-family-primary, 'Public Sans', sans-serif);
5083
+ font-family: var(--kds-font-family-heading, var(--kds-font-family-primary, 'Public Sans', sans-serif));
5038
5084
  font-size: var(--kds-font-size-xl, 20px);
5039
5085
  font-weight: var(--kds-font-weight-semibold, 600);
5040
5086
  line-height: var(--kds-line-height-snug, 1.375);
5041
5087
  }
5042
5088
 
5043
5089
  .kds-text-heading3 {
5044
- font-family: var(--kds-font-family-primary, 'Public Sans', sans-serif);
5090
+ font-family: var(--kds-font-family-heading, var(--kds-font-family-primary, 'Public Sans', sans-serif));
5045
5091
  font-size: var(--kds-font-size-lg, 18px);
5046
5092
  font-weight: var(--kds-font-weight-semibold, 600);
5047
5093
  line-height: var(--kds-line-height-normal, 1.5);
@@ -6267,7 +6313,7 @@ button.kds-fab:active:not(:disabled) {
6267
6313
  irregular arriba (pegado al resumen) y abajo (~26px hasta el panel). Con height
6268
6314
  auto el botón ajusta a su contenido y el ritmo lo gobiernan los márgenes. */
6269
6315
  height: auto;
6270
- color: var(--kds-color-primary-main);
6316
+ color: var(--kds-color-accent, var(--kds-color-primary-main));
6271
6317
  font-weight: var(--kds-font-weight-medium);
6272
6318
  font-size: var(--kds-font-size-sm);
6273
6319
  cursor: pointer;
@@ -7097,11 +7143,13 @@ div.kds-invoice-header,
7097
7143
  }
7098
7144
 
7099
7145
  .kds-invoice-amount {
7146
+ /* inherit: the amount had no family of its own before, it took the body's. */
7147
+ font-family: var(--kds-invoice-amount-font-family, inherit);
7100
7148
  font-weight: var(--kds-font-weight-semibold);
7101
7149
  font-size: var(--kds-font-size-3xl);
7102
7150
  line-height: var(--kds-line-height-tight);
7103
7151
  letter-spacing: var(--kds-letter-spacing-wide);
7104
- color: var(--kds-color-gray-900);
7152
+ color: var(--kds-invoice-amount-color, var(--kds-color-gray-900));
7105
7153
  margin: 0;
7106
7154
  }
7107
7155
 
@@ -7199,6 +7247,8 @@ div.kds-invoice-header,
7199
7247
 
7200
7248
  /* -- Card Title -- */
7201
7249
  .kds-card-title {
7250
+ /* inherit: the card title had no family of its own before. */
7251
+ font-family: var(--kds-font-family-heading, inherit);
7202
7252
  font-weight: var(--kds-font-weight-semibold);
7203
7253
  font-size: var(--kds-font-size-base);
7204
7254
  line-height: 1.5;
@@ -7948,6 +7998,36 @@ svg[fill='none'] {
7948
7998
  }
7949
7999
  }
7950
8000
 
8001
+ /* Widget embebido: dentro de un iframe los media queries de ancho evalúan el viewport
8002
+ DEL IFRAME (~420px), no la pantalla, así que el flujo se ve siempre como mobile
8003
+ aunque el usuario esté en desktop — y el tope plano, pensado para cuando la card se
8004
+ pega al borde del teléfono, queda cortando una card que en realidad flota centrada.
8005
+ `hover`/`pointer` describen el dispositivo de entrada y no el viewport, así que
8006
+ sobreviven al iframe: con mouse las cards conservan las esquinas superiores. */
8007
+ @media (hover: hover) and (pointer: fine) {
8008
+ .kds-card-elevated.kds-invoice-sticky {
8009
+ border-radius: var(--kds-radius-card);
8010
+ /* El clip-path del colapso recorta con `round 0 0 R R` y eso PISA al
8011
+ border-radius: aunque la card declare las cuatro esquinas, el recorte las
8012
+ deja rectas arriba. Hay que redondearlas también acá o el fix no se ve. */
8013
+ clip-path: inset(
8014
+ 0 0
8015
+ calc(
8016
+ var(--collapse-collapsible-h) * var(--collapse-progress)
8017
+ + var(--kds-spacing-1) * var(--collapse-progress)
8018
+ )
8019
+ 0
8020
+ round var(--kds-radius-card)
8021
+ );
8022
+ }
8023
+
8024
+ .kds-screen > .kds-card-elevated.kds-card-elevated--flush-top,
8025
+ .kds-card-elevated.kds-card-elevated--flush-top {
8026
+ border-top-left-radius: var(--kds-radius-card);
8027
+ border-top-right-radius: var(--kds-radius-card);
8028
+ }
8029
+ }
8030
+
7951
8031
  /* Brand logo row (external, outside cards) */
7952
8032
  .kds-brand-row {
7953
8033
  padding: 0 var(--kds-spacing-0-5);
@@ -9080,7 +9160,11 @@ a.kds-copy-all-btn.copied:hover {
9080
9160
 
9081
9161
  .kds-form-icon-box {
9082
9162
  align-items: center;
9083
- background: var(--kds-color-background-brand-subtle, #f0f0fa);
9163
+ background: var(--kds-color-accent-soft, var(--kds-color-background-brand-subtle, #f0f0fa));
9164
+ /* The glyph inherits this, so the icon tracks the accent role without the
9165
+ markup having to name a colour utility. Falls back to the primary, which
9166
+ is what the .kds-text-primary utility on the glyph resolved to. */
9167
+ color: var(--kds-color-accent, var(--kds-color-primary-main));
9084
9168
  border-radius: var(--kds-radius-md);
9085
9169
  display: flex;
9086
9170
  height: 52px;
@@ -899,6 +899,12 @@ const ui = _context.ui;
899
899
  console.log('Material Design initialization complete!');
900
900
  }
901
901
 
902
+ // El alto de la body card cambia de golpe entre pantallas, sin animar. Hubo una
903
+ // transición acá (KTUF-239) y se quitó en KTUF-314: ver el comentario en
904
+ // KdsThemeProvider.tsx — animar el alto obliga a fijar `height` en píxeles, y con el
905
+ // alto fijado no hay forma de medir el alto natural del contenido para saber cuándo
906
+ // soltarlo, así que la card quedaba con espacio muerto abajo.
907
+
902
908
  /**
903
909
  * Initialize merchant logo backdrop (KTUF-204)
904
910
  * Los logos de comercio van sobre el fondo neutro, no sobre el color de marca (los PNG