@bytebrand/fe-ui-core-autobahn 1.0.98 → 1.0.100

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.
@@ -68,11 +68,12 @@
68
68
  border: none !important;
69
69
 
70
70
  .zustimmenBtn
71
- width: calc(50% - 18px) !important
72
- min-width: calc(50% - 18px) !important
71
+ padding: 9.95px 36.87px 11.05px 35.63px !important
72
+ width: 142.5px !important
73
+ min-width: 142.5px !important
73
74
  height: 38px !important
74
- background: #005CCB !important
75
- border-radius: 4px !important
75
+ background: #005CFF !important
76
+ border-radius: 16px !important
76
77
  display: flex !important
77
78
  align-items: center !important
78
79
  justify-content: center !important
@@ -26,13 +26,14 @@
26
26
  margin-top: 8px;
27
27
 
28
28
  .modalContent
29
- font-family: sans-serif
29
+ margin-top: 3px
30
+ font-family: 'Arial'
31
+ font-weight: 400
30
32
  font-size: 14px;
31
33
  line-height: 16px;
32
34
  text-align: justify;
33
35
  letter-spacing: 0.15px;
34
36
  color: rgba(76, 78, 100, 0.87);
35
- margin-top: 20px
36
37
  +media-tablet-down()
37
38
  font-family: 'Arial';
38
39
  font-weight: 400;
@@ -65,6 +66,7 @@
65
66
  font-size: 11px !important
66
67
 
67
68
  .necessaryCookiesBtn
69
+ text-transform: none !important
68
70
  display: flex !important
69
71
  flex-direction: column !important
70
72
  align-items: center !important
@@ -72,10 +74,10 @@
72
74
  width: 184px !important
73
75
  min-width: 184px !important
74
76
  height: 38px !important
75
- background: #005CCB !important
77
+ background: #005CFF !important
76
78
  box-shadow: 0px 4px 8px -4px rgba(76, 78, 100, 0.42) !important
77
- border-radius: 4px !important
78
- font-family: 'Inter' !important
79
+ border-radius: 16px !important
80
+ font-family: 'Arial' !important
79
81
  font-weight: 500 !important
80
82
  font-size: 14px !important
81
83
  line-height: 24px !important
@@ -83,9 +85,11 @@
83
85
  color: #FFFFFF !important
84
86
 
85
87
  .anpassenBtn
86
- border: 1px solid rgba(102, 108, 255, 0.5) !important
88
+ box-sizing: border-box !important
89
+ padding: 9.95px 39.39px 11.05px 40.11px !important
90
+ border: 1px solid #005CFF !important
87
91
  box-shadow: none !important
88
- border-radius: 4px !important
92
+ border-radius: 16px !important
89
93
  width: 142.5px !important
90
94
  min-width: 142.5px !important
91
95
  height: 38px !important
@@ -94,17 +98,19 @@
94
98
  justify-content: center !important
95
99
  text-align: center !important
96
100
  font-family: 'Arial' !important
101
+ font-style: normal !important
97
102
  font-weight: 400 !important
98
103
  font-size: 14px !important
99
104
  line-height: 16px !important
100
- color: #1976D2 !important
105
+ color: #005CFF !important
101
106
 
102
107
  .zustimmenBtn
108
+ padding: 9.95px 36.87px 11.05px 35.63px !important
103
109
  width: 142.5px !important
104
110
  min-width: 142.5px !important
105
111
  height: 38px !important
106
- background: #005CCB !important
107
- border-radius: 4px !important
112
+ background: #005CFF !important
113
+ border-radius: 16px !important
108
114
  display: flex !important
109
115
  align-items: center !important
110
116
  justify-content: center !important
@@ -120,6 +126,7 @@
120
126
  display: flex;
121
127
  justify-content: flex-end;
122
128
  font-family: 'Arial';
129
+ font-style: normal;
123
130
  font-weight: 400;
124
131
  color: #005CCB;
125
132
  font-size: 16px;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bytebrand/fe-ui-core-autobahn",
3
- "version": "1.0.98",
3
+ "version": "1.0.100",
4
4
  "description": "auto.de md3 (Autobahn) design system — UI primitives, cards, chrome, VDP modules, theme CSS and locales. Ships raw TypeScript source (like fe-ui-core before it); each consumer's bundler compiles it.",
5
5
  "main": "index.ts",
6
6
  "license": "UNLICENSED",
package/theme/md3.css CHANGED
@@ -5844,9 +5844,10 @@ line-height: 31px;
5844
5844
  .md3 .vdp-bottom-bar {
5845
5845
  position: fixed;
5846
5846
  left: 0;
5847
+ right: 0;
5847
5848
  bottom: 0;
5848
5849
  z-index: 60;
5849
- width: 390px;
5850
+ width: auto;
5850
5851
  height: 196px;
5851
5852
  background: rgba(244, 243, 243, 0.95);
5852
5853
  border: 1px solid #D4DDE7;
@@ -8637,7 +8638,9 @@ color: #005CFF;
8637
8638
  font-size: 13px;
8638
8639
  line-height: 15px;
8639
8640
  color: #111820;
8641
+ margin: 0px 0px;
8640
8642
  margin-bottom: 12px;
8643
+ vertical-align: -3px;
8641
8644
  }
8642
8645
  /* "Finanzierungsdetails"/"Leasing-Details" reads as a link here (unlike CarCard's quiet
8643
8646
  .cc-terms-link, which stays text-colored on purpose) — underlined. */
@@ -8657,11 +8660,11 @@ color: #005CFF;
8657
8660
  font-weight: 700 !important;
8658
8661
  color: var(--md-on-surface-variant) !important;
8659
8662
  }
8660
- /* figma pricing-card padding is 16 (inline says 20 — hence !important); the side-by-side
8663
+ /* figma pricing-card padding is 15px 12px (inline says 20 — hence !important); the side-by-side
8661
8664
  CTAs must be allowed to SHRINK (mbtn is nowrap min-width:auto, 0-30px padding — the pair
8662
8665
  alone mins out wider than the phone card) */
8663
8666
  .md3 .vdp-aside > .mcard {
8664
- padding: 16px !important;
8667
+ padding: 15px 12px !important;
8665
8668
  }
8666
8669
  .md3 .fin-cta-row .mbtn {
8667
8670
  min-width: 0;
@@ -19,6 +19,13 @@ export function formatPct(n: number): string {
19
19
  return `${n.toFixed(2).replace('.', ',')} %`;
20
20
  }
21
21
 
22
+ /** Monetary figure → de-DE grouped string with fixed cents (e.g. 44333 → "44.333,00",
23
+ * 42243.9 → "42.243,90"). Unlike formatEur, always shows exactly 2 decimals — for the "Repräsentatives
24
+ * Beispiel" breakdown table (FinanceDetailsModal), where every € line is expected to carry cents. */
25
+ export function formatEurCents(n: number): string {
26
+ return n.toLocaleString('de-DE', { minimumFractionDigits: 2, maximumFractionDigits: 2 });
27
+ }
28
+
22
29
  export interface FinanceExampleFields {
23
30
  price: number;
24
31
  apr: number;
@@ -28,7 +28,7 @@ import { Button, Dropdown, DropdownOption, Icon, Spec, StatChip, Stars } from '.
28
28
  import { CO2_CLASSES, CO2_COLORS, TIER_LABELS, TIER_KEYS, TIER_COLORS, TIER_BACKGROUNDS } from '../constants';
29
29
  import { defaultVdpSpecs, EquipmentGroups, PriceRatingBands, VehicleDetail, VdpSpec, VdpReview } from './types';
30
30
  import { AddServicesTooltipBody, CalcRow, DocCheckIcon, EvalBar, expanderBtnStyle, FinanceMode, Slider, TermChips, ToggleRow } from './FinanceCalculator';
31
- import { formatEur as eur, formatPct as pct } from '../utils/financeFormat';
31
+ import { formatEur as eur, formatEurCents as eurCents, formatPct as pct } from '../utils/financeFormat';
32
32
 
33
33
  /** Figma "check with open arc" glyph (modern lucide circle-check-big; the bundled lucide
34
34
  * 0.288 only ships the closed-circle variant, so the two paths are inlined). */
@@ -2057,13 +2057,22 @@ export const FinanceDetailsModal: React.FunctionComponent<FinanceDetailsModalPro
2057
2057
  // "Rundum-Sorglos-Paket" one-time fee only counts toward the breakdown when the customer
2058
2058
  // actually has it switched on (cash mode forces it on upstream) AND a real cost is known.
2059
2059
  const hasAddServices = !!withAddServices && addServicesCost != null && addServicesCost > 0;
2060
- // Grand total (Figma "Gesamtbelastung inkl. Anzahlung & Paket") — down payment + the config's
2061
- // real Gesamtbetrag + the package fee. Only shown when Gesamtbetrag is known (never fabricated).
2062
- const totalCost = grossAmount != null && grossAmount > 0 ? down + grossAmount + (hasAddServices ? (addServicesCost as number) : 0) : undefined;
2063
2060
  // one-time package figure shown in the breakdown: 0 € while bundled into the rate (its cost is
2064
2061
  // already carried inside `monthly` instead), the real flat price when switched off.
2065
2062
  const addServicesRowValue = withAddServices ? 0 : addServicesCostRaw ?? 0;
2066
2063
  const hasAddServicesRow = addServicesCostRaw != null && addServicesCostRaw > 0;
2064
+ // Grand total (Figma "Gesamtbelastung inkl. Anzahlung & Paket") — down payment + the config's
2065
+ // real Gesamtbetrag + the package fee. The package is mandatory (see packageMandatoryNotice) —
2066
+ // the toggle only decides HOW it's paid (bundled into the rate vs. a separate one-time charge),
2067
+ // never WHETHER it's owed, so the total must include it either way: `addServicesCost` when
2068
+ // bundled (toggle on), the raw one-time fee (`addServicesRowValue`, same as the breakdown row
2069
+ // above it) when paid separately (toggle off) — previously dropped to 0 in the off case, so the
2070
+ // grand total silently excluded a cost the breakdown row directly above it was still showing.
2071
+ // Only shown when Gesamtbetrag is known (never fabricated).
2072
+ const totalCost =
2073
+ grossAmount != null && grossAmount > 0
2074
+ ? down + grossAmount + (hasAddServices ? (addServicesCost as number) : hasAddServicesRow ? addServicesRowValue : 0)
2075
+ : undefined;
2067
2076
 
2068
2077
  let rows: Array<[string, string, boolean?]>;
2069
2078
  if (isLease) {
@@ -2082,51 +2091,51 @@ export const FinanceDetailsModal: React.FunctionComponent<FinanceDetailsModalPro
2082
2091
  const subtotalWithPackage = ratesSum != null ? ratesSum + down + (hasAddServicesRow ? addServicesRowValue : 0) : undefined;
2083
2092
  const grandTotal = subtotalWithPackage != null ? subtotalWithPackage + residual : undefined;
2084
2093
  rows = [
2085
- [t('autobahn:modal.leaseVehiclePrice'), `${eur(price)} €`],
2094
+ [t('autobahn:modal.leaseVehiclePrice'), `${eurCents(price)} €`],
2086
2095
  [t('autobahn:modal.term'), t('autobahn:modal.months', { months: term, count: term })],
2087
2096
  ...(annualMileage != null ? ([[t('autobahn:modal.annualMileage'), `${eur(annualMileage)} km`]] as Array<[string, string]>) : []),
2088
- [t('autobahn:modal.leaseDownPayment'), `${eur(down)} €`],
2089
- [t('autobahn:modal.leasingRateCount', { count: term }), `${eur(monthly)} €`],
2090
- [t('autobahn:modal.finalPaymentDue'), `${eur(0)} €`],
2091
- ...(residual > 0 ? ([[t('autobahn:modal.residualValue'), `${eur(residual)} €`]] as Array<[string, string]>) : []),
2097
+ [t('autobahn:modal.leaseDownPayment'), `${eurCents(down)} €`],
2098
+ [t('autobahn:modal.leasingRateCount', { count: term }), `${eurCents(monthly)} €`],
2099
+ [t('autobahn:modal.finalPaymentDue'), `${eurCents(0)} €`],
2100
+ ...(residual > 0 ? ([[t('autobahn:modal.residualValue'), `${eurCents(residual)} €`]] as Array<[string, string]>) : []),
2092
2101
  ...(ratesSum != null
2093
- ? ([[t('autobahn:modal.rateSumLabel', { term, amount: eur(monthly) }), `${eur(ratesSum)} €`, true]] as Array<[string, string, boolean]>)
2102
+ ? ([[t('autobahn:modal.rateSumLabel', { term, amount: eurCents(monthly) }), `${eurCents(ratesSum)} €`, true]] as Array<[string, string, boolean]>)
2094
2103
  : []),
2095
- ...(ratesSum != null ? ([[t('autobahn:modal.leaseDownPayment'), `${eur(down)} €`]] as Array<[string, string]>) : []),
2104
+ ...(ratesSum != null ? ([[t('autobahn:modal.leaseDownPayment'), `${eurCents(down)} €`]] as Array<[string, string]>) : []),
2096
2105
  ...(ratesSum != null && hasAddServicesRow
2097
- ? ([[t('autobahn:modal.addServicesRowLease'), `${eur(addServicesRowValue)} €`]] as Array<[string, string]>)
2106
+ ? ([[t('autobahn:modal.addServicesRowLease'), `${eurCents(addServicesRowValue)} €`]] as Array<[string, string]>)
2098
2107
  : []),
2099
2108
  ...(subtotalWithPackage != null
2100
- ? ([[hasAddServicesRow ? t('autobahn:modal.subtotalWithPackage') : t('autobahn:modal.subtotalNoPackage'), `${eur(subtotalWithPackage)} €`, true]] as Array<
2109
+ ? ([[hasAddServicesRow ? t('autobahn:modal.subtotalWithPackage') : t('autobahn:modal.subtotalNoPackage'), `${eurCents(subtotalWithPackage)} €`, true]] as Array<
2101
2110
  [string, string, boolean]
2102
2111
  >)
2103
2112
  : []),
2104
- ...(residual > 0 && grandTotal != null ? ([[t('autobahn:modal.residualValue'), `${eur(residual)} €`]] as Array<[string, string]>) : []),
2113
+ ...(residual > 0 && grandTotal != null ? ([[t('autobahn:modal.residualValue'), `${eurCents(residual)} €`]] as Array<[string, string]>) : []),
2105
2114
  ...(grandTotal != null
2106
- ? ([[t('autobahn:modal.grandTotalWithResidual'), `${eur(grandTotal)} €`, true]] as Array<[string, string, boolean]>)
2115
+ ? ([[t('autobahn:modal.grandTotalWithResidual'), `${eurCents(grandTotal)} €`, true]] as Array<[string, string, boolean]>)
2107
2116
  : []),
2108
- ...(listPrice != null && listPrice > 0 ? ([[t('autobahn:modal.listPriceLease'), `${eur(listPrice)} €`]] as Array<[string, string]>) : []),
2117
+ ...(listPrice != null && listPrice > 0 ? ([[t('autobahn:modal.listPriceLease'), `${eurCents(listPrice)} €`]] as Array<[string, string]>) : []),
2109
2118
  ];
2110
2119
  } else {
2111
2120
  rows = [
2112
- [t('autobahn:modal.vehiclePrice'), `${eur(price)} €`],
2121
+ [t('autobahn:modal.vehiclePrice'), `${eurCents(price)} €`],
2113
2122
  [t('autobahn:modal.term'), t('autobahn:modal.months', { months: term, count: term })],
2114
- [t('autobahn:modal.downPayment'), `${eur(down)} €`],
2115
- [t('autobahn:modal.monthlyRateCount', { count: term }), `${eur(monthly)} €`],
2116
- ...(finalInstallment != null && finalInstallment > 0 ? ([[t('autobahn:modal.finalInstallment'), `${eur(finalInstallment)} €`]] as Array<[string, string]>) : []),
2123
+ [t('autobahn:modal.downPayment'), `${eurCents(down)} €`],
2124
+ [t('autobahn:modal.monthlyRateCount', { count: term }), `${eurCents(monthly)} €`],
2125
+ ...(finalInstallment != null && finalInstallment > 0 ? ([[t('autobahn:modal.finalInstallment'), `${eurCents(finalInstallment)} €`]] as Array<[string, string]>) : []),
2117
2126
  ...(hasAddServicesRow
2118
- ? ([[t('autobahn:modal.addServicesRow'), `${eur(addServicesRowValue)} €`]] as Array<[string, string]>)
2127
+ ? ([[t('autobahn:modal.addServicesRow'), `${eurCents(addServicesRowValue)} €`]] as Array<[string, string]>)
2119
2128
  : []),
2120
2129
  ...(nominalRate != null && nominalRate > 0 ? ([[t('autobahn:modal.nominalRate'), pct(nominalRate)]] as Array<[string, string]>) : []),
2121
2130
  [t('autobahn:modal.effectiveRate'), pct(apr)],
2122
- [t('autobahn:modal.netLoanAmount'), `${eur(netto)} €`],
2123
- ...(grossAmount != null && grossAmount > 0 ? ([[t('autobahn:modal.totalRepayment'), `${eur(grossAmount)} €`]] as Array<[string, string]>) : []),
2131
+ [t('autobahn:modal.netLoanAmount'), `${eurCents(netto)} €`],
2132
+ ...(grossAmount != null && grossAmount > 0 ? ([[t('autobahn:modal.totalRepayment'), `${eurCents(grossAmount)} €`]] as Array<[string, string]>) : []),
2124
2133
  ...(totalCost != null
2125
- ? ([[hasAddServices ? t('autobahn:modal.totalCostWithPackage') : t('autobahn:modal.totalCost'), `${eur(totalCost)} €`, true]] as Array<
2134
+ ? ([[hasAddServices || hasAddServicesRow ? t('autobahn:modal.totalCostWithPackage') : t('autobahn:modal.totalCost'), `${eurCents(totalCost)} €`, true]] as Array<
2126
2135
  [string, string, boolean]
2127
2136
  >)
2128
2137
  : []),
2129
- ...(listPrice != null && listPrice > 0 ? ([[t('autobahn:modal.listPrice'), `${eur(listPrice)} €`]] as Array<[string, string]>) : []),
2138
+ ...(listPrice != null && listPrice > 0 ? ([[t('autobahn:modal.listPrice'), `${eurCents(listPrice)} €`]] as Array<[string, string]>) : []),
2130
2139
  ];
2131
2140
  }
2132
2141
  const breakdownRows = rows.map(([l, v, bold], i) => (