@bytebrand/fe-ui-core-autobahn 1.0.93 → 1.0.95

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.
@@ -22,6 +22,16 @@ const CookieModal = ({ handleSentryInit }: ICookieModal) => {
22
22
  []
23
23
  );
24
24
 
25
+ useEffect(
26
+ () => {
27
+ if (!isVisible) return undefined;
28
+ const previousOverflow = document.body.style.overflow;
29
+ document.body.style.overflow = 'hidden';
30
+ return () => { document.body.style.overflow = previousOverflow; };
31
+ },
32
+ [isVisible]
33
+ );
34
+
25
35
  const onClearModalState = () => {
26
36
  setModal('');
27
37
  };
@@ -0,0 +1,12 @@
1
+ @import '../legacy-theme/mixins.styl'
2
+
3
+ // SURFACE (Modal.tsx) sets max-height: 92vh inline for desktop — on mobile the
4
+ // modal should grow to fit its full content instead of scrolling internally.
5
+ // !important is required to win over the inline style attribute.
6
+ .surface
7
+ +media-tablet-down()
8
+ max-height: none !important
9
+
10
+ .overlay
11
+ +media-tablet-down()
12
+ padding-top: 71px !important
@@ -2,10 +2,21 @@
2
2
  // BaseModalWrapper is replaced by a plain fixed overlay + centered surface.
3
3
  // Deliberately NOT the kit ui/Modal — the cookie consent dialog has no title
4
4
  // bar / close button and must not be dismissible without a choice.
5
+ //
6
+ // Rendered via ReactDOM.createPortal into document.body (same technique as
7
+ // ui/Modal.tsx) rather than inline in the page tree: a React hydration-mismatch
8
+ // error ANYWHERE else on the page (a known, separate bug — see the
9
+ // SearchNextPage isMobile SSR/CSR mismatch) can corrupt sibling reconciliation
10
+ // enough that an inline `position: fixed` overlay ends up mounted in the wrong
11
+ // place in the DOM (observed: appearing as plain content below the footer
12
+ // instead of as an overlay). A body-level portal is immune to that — its DOM
13
+ // node never lives inside the page's own React subtree.
5
14
 
6
15
  import * as React from 'react';
16
+ import * as ReactDOM from 'react-dom';
7
17
 
8
18
  import ModalsConfig from './ModalsConfig';
19
+ import styles from './Modal.styl';
9
20
 
10
21
  interface IBasicModal {
11
22
  isVisible: boolean;
@@ -23,20 +34,26 @@ const OVERLAY: React.CSSProperties = {
23
34
  };
24
35
 
25
36
  const SURFACE: React.CSSProperties = {
26
- background: 'var(--md-sc-lowest, #fff)',
27
- borderRadius: 'var(--md-r-lg, 16px)',
28
- boxShadow: 'var(--md-e3, 0 8px 24px rgba(0,0,0,.2))',
37
+ background: '#FFFFFF',
38
+ borderRadius: '10px',
39
+ boxShadow: '0px 0px 20px rgba(76, 78, 100, 0.4)',
29
40
  maxWidth: 640, width: '100%', maxHeight: '92vh', overflowY: 'auto'
30
41
  };
31
42
 
32
43
  const BasicModal = ({ isVisible, toggleModal, name, modalProps, handleSentryInit }: IBasicModal) => {
33
- if (!isVisible) return null;
34
- return (
35
- <div style={OVERLAY} role='dialog' aria-modal='true' aria-label='Cookie-Einstellungen'>
36
- <div style={SURFACE}>
37
- {ModalsConfig[name] && ModalsConfig[name]({ ...modalProps, toggleModal, handleSentryInit })}
44
+ if (!isVisible || typeof document === 'undefined') return null;
45
+ return ReactDOM.createPortal(
46
+ // wrapped in .md3: autobahn.css scopes every token/utility class (incl.
47
+ // .mbtn used by the modal buttons) under `.md3` and intentionally does
48
+ // nothing outside it — a bare document.body portal loses the theme.
49
+ <div className='md3'>
50
+ <div className={styles.overlay} style={OVERLAY} role='dialog' aria-modal='true' aria-label='Cookie-Einstellungen'>
51
+ <div className={styles.surface} style={SURFACE}>
52
+ {ModalsConfig[name] && ModalsConfig[name]({ ...modalProps, toggleModal, handleSentryInit })}
53
+ </div>
38
54
  </div>
39
- </div>
55
+ </div>,
56
+ document.body
40
57
  );
41
58
  };
42
59
 
@@ -1,10 +1,10 @@
1
1
  @import '../../../legacy-theme/mixins.styl';
2
2
 
3
3
  .modalWrapper
4
- padding: 13px 15px 28px;
4
+ padding: 25px;
5
5
  text-align: center
6
6
  box-sizing: border-box
7
- max-width: 600px
7
+ max-width: 100%
8
8
 
9
9
  .modalTitle
10
10
  font-family: sans-serif
@@ -24,14 +24,18 @@
24
24
  text-align: justify;
25
25
  letter-spacing: 0.15px;
26
26
  color: rgba(76, 78, 100, 0.87);
27
- margin-top: 12px
28
- margin-right: 25px
27
+ margin-top: 5px
28
+ margin-right: 7px
29
+ .accordionDescription
30
+ display: block
31
+ font-size: 14px
32
+ line-height: 18px
33
+ text-align: left
34
+ margin-bottom: 5px
29
35
 
30
- +media-tablet-up()
31
- margin-top: 20px
32
36
  .accordions
33
37
  height: 278px
34
- overflow-y: scroll
38
+ overflow-y: auto
35
39
  padding-right: 10px
36
40
  margin-top: 16px
37
41
  &::-webkit-scrollbar {
@@ -49,10 +53,7 @@
49
53
  margin-top: 20px
50
54
  display: flex
51
55
  justify-content: center
52
- gap: 18px;
53
-
54
- +media-tablet-landscape-up()
55
- gap: 36px;
56
+ gap: 36px;
56
57
 
57
58
  .modalBtn
58
59
  height: 38px
@@ -64,6 +65,23 @@
64
65
  .outlinedBtn
65
66
  border: none !important;
66
67
 
68
+ .zustimmenBtn
69
+ width: calc(50% - 18px) !important
70
+ min-width: calc(50% - 18px) !important
71
+ height: 38px !important
72
+ background: #005CCB !important
73
+ border-radius: 4px !important
74
+ display: flex !important
75
+ align-items: center !important
76
+ justify-content: center !important
77
+ text-align: center !important
78
+ font-family: 'Arial' !important
79
+ font-style: normal !important
80
+ font-weight: 400 !important
81
+ font-size: 14px !important
82
+ line-height: 16px !important
83
+ color: #FFFFFF !important
84
+
67
85
  .switchBlock
68
86
  display: flex
69
87
  align-items: center
@@ -72,6 +90,27 @@
72
90
  letter-spacing: 1px
73
91
  color: rgba(76, 78, 100, 0.87)
74
92
  text-align: left
93
+ margin-bottom: 5px
94
+
95
+ &:last-child
96
+ margin-bottom: 0
97
+
98
+ > span:last-child
99
+ display: inline-flex
100
+ align-items: center
101
+
102
+ :global
103
+ .mswitch-track
104
+ margin-left: 5px
105
+ width: 38px
106
+ height: 22px
107
+
108
+ .mswitch-thumb
109
+ width: 16px
110
+ height: 16px
111
+
112
+ .mswitch input:checked + .mswitch-track .mswitch-thumb
113
+ transform: translateX(16px)
75
114
 
76
115
  .switchBlockTitle
77
116
  width: 140px;
@@ -115,11 +115,11 @@ const ManageCookieModal = ({ toggleModal, handleSentryInit } : IManageCookieModa
115
115
  <div className={styles.accordions}>
116
116
  <MaterialAccordionGroup
117
117
  title='Notwendig'
118
- tooltipText='Notwendig'
118
+ // tooltipText='Notwendig'
119
119
  withSwitch
120
120
  switchProps={necessarySwitchProps}
121
121
  >
122
- <span>Wir verwenden Browser-Cookies, die notwendig sind, damit die Website wie vorgesehen funktioniert. Beispiel: Wir speichern Ihre Präferenzen bei der Datenerfassung auf der Website, damit wir sie berücksichtigen können, wenn Sie auf unsere Website zurückkehren. Sie können diese Cookies in den Einstellungen Ihres Browsers deaktivieren, aber wenn Sie dies tun, funktioniert die Website möglicherweise nicht wie vorgesehen.</span>
122
+ <span className={styles.accordionDescription}>Wir verwenden Browser-Cookies, die notwendig sind, damit die Website wie vorgesehen funktioniert. Beispiel: Wir speichern Ihre Präferenzen bei der Datenerfassung auf der Website, damit wir sie berücksichtigen können, wenn Sie auf unsere Website zurückkehren. Sie können diese Cookies in den Einstellungen Ihres Browsers deaktivieren, aber wenn Sie dies tun, funktioniert die Website möglicherweise nicht wie vorgesehen.</span>
123
123
  {Object.keys(COOKIE_SCHEMA.necessary).map(cookie => {
124
124
  const getLinkFromCategory = _get(COOKIE_SCHEMA_LINKS, [cookie], '');
125
125
  return (
@@ -134,10 +134,10 @@ const ManageCookieModal = ({ toggleModal, handleSentryInit } : IManageCookieModa
134
134
  <MaterialAccordionGroup
135
135
  title='Analytisch'
136
136
  withSwitch
137
- tooltipText='Analytisch'
137
+ // tooltipText='Analytisch'
138
138
  switchProps={analyticsSwitchProps}
139
139
  >
140
- <span>Um das Nutzerverhalten zu verstehen und Ihnen ein relevanteres Surferlebnis zu bieten oder den Inhalt unserer Website zu personalisieren. Beispiel: Wir sammeln Informationen darüber, welche Seiten Sie besuchen, damit wir Ihnen relevantere Informationen präsentieren können.</span>
140
+ <span className={styles.accordionDescription}>Um das Nutzerverhalten zu verstehen und Ihnen ein relevanteres Surferlebnis zu bieten oder den Inhalt unserer Website zu personalisieren. Beispiel: Wir sammeln Informationen darüber, welche Seiten Sie besuchen, damit wir Ihnen relevantere Informationen präsentieren können.</span>
141
141
  {Object.keys(COOKIE_SCHEMA.analytics).map(cookie => {
142
142
  const getItemsFromCategory = _get(COOKIE_SCHEMA, `analytics['${cookie}']`, null);
143
143
  const getLinkFromCategory = _get(COOKIE_SCHEMA_LINKS, [cookie], '');
@@ -158,10 +158,10 @@ const ManageCookieModal = ({ toggleModal, handleSentryInit } : IManageCookieModa
158
158
  <MaterialAccordionGroup
159
159
  title='Marketing'
160
160
  withSwitch
161
- tooltipText='Marketing'
161
+ // tooltipText='Marketing'
162
162
  switchProps={marketingSwitchProps}
163
163
  >
164
- <span>Zur Personalisierung und Messung der Effektivität von Werbung auf unserer Website und anderen Websites. Beispiel: Wir können Ihnen eine personalisierte Werbung auf der Grundlage der von Ihnen besuchten Seiten auf unserer Website anzeigen.</span>
164
+ <span className={styles.accordionDescription}>Zur Personalisierung und Messung der Effektivität von Werbung auf unserer Website und anderen Websites. Beispiel: Wir können Ihnen eine personalisierte Werbung auf der Grundlage der von Ihnen besuchten Seiten auf unserer Website anzeigen.</span>
165
165
  {Object.keys(COOKIE_SCHEMA.marketing).map(cookie => {
166
166
  const getItemsFromCategory = _get(COOKIE_SCHEMA, `marketing['${cookie}']`, null);
167
167
  const getLinkFromCategory = _get(COOKIE_SCHEMA_LINKS, [cookie], '');
@@ -181,8 +181,8 @@ const ManageCookieModal = ({ toggleModal, handleSentryInit } : IManageCookieModa
181
181
  </MaterialAccordionGroup>
182
182
  </div>
183
183
  <div className={styles.buttonsContainer}>
184
- <Button onClick={() => onAccept()} className={classNames(styles.modalBtn, styles.outlinedBtn)} >Auswahl speichern</Button>
185
- <Button onClick={() => onAccept({ marketing: [], analytics: [] })} className={styles.modalBtn}>Alles akzeptieren</Button>
184
+ <Button onClick={() => onAccept()} className={classNames(styles.modalBtn, styles.outlinedBtn, styles.zustimmenBtn)} >Auswahl speichern</Button>
185
+ <Button onClick={() => onAccept({ marketing: [], analytics: [] })} className={classNames(styles.modalBtn, styles.zustimmenBtn)}>Alles akzeptieren</Button>
186
186
  </div>
187
187
  </div>
188
188
  );
@@ -1,12 +1,12 @@
1
1
  @import '../../../legacy-theme/mixins.styl';
2
2
 
3
3
  .modalWrapper
4
- padding: 28px 58px 28px
4
+ padding: 25px
5
5
  text-align: center
6
6
  box-sizing: border-box
7
- max-width: 600px
7
+ max-width: 100%
8
8
  +media-tablet-down()
9
- padding: 16px 15px 28px
9
+ padding: 16px 15px 12px 15px
10
10
 
11
11
  .modalTitle
12
12
  font-family: sans-serif
@@ -17,7 +17,12 @@
17
17
  margin-top: 20px
18
18
 
19
19
  +media-tablet-down()
20
+ font-family: 'Arial';
21
+ font-weight: 700;
20
22
  font-size: 16px;
23
+ line-height: 32px;
24
+ text-align: center;
25
+ color: rgba(76, 78, 100, 0.87);
21
26
  margin-top: 8px;
22
27
 
23
28
  .modalContent
@@ -29,9 +34,13 @@
29
34
  color: rgba(76, 78, 100, 0.87);
30
35
  margin-top: 20px
31
36
  +media-tablet-down()
37
+ font-family: 'Arial';
38
+ font-weight: 400;
39
+ font-size: 14px;
40
+ line-height: 16px;
41
+ letter-spacing: 0.15px;
42
+ color: rgba(76, 78, 100, 0.87);
32
43
  column-gap: 0;
33
- max-height: 320px;
34
- overflow-y: scroll;
35
44
  padding-right: 10px;
36
45
  margin-right: -10px;
37
46
  margin-top: 8px
@@ -55,13 +64,68 @@
55
64
  +media-tablet-down()
56
65
  font-size: 11px !important
57
66
 
67
+ .necessaryCookiesBtn
68
+ display: flex !important
69
+ flex-direction: column !important
70
+ align-items: center !important
71
+ justify-content: center !important
72
+ width: 184px !important
73
+ min-width: 184px !important
74
+ height: 38px !important
75
+ background: #005CCB !important
76
+ box-shadow: 0px 4px 8px -4px rgba(76, 78, 100, 0.42) !important
77
+ border-radius: 4px !important
78
+ font-family: 'Inter' !important
79
+ font-weight: 500 !important
80
+ font-size: 14px !important
81
+ line-height: 24px !important
82
+ letter-spacing: 0.4px !important
83
+ color: #FFFFFF !important
84
+
85
+ .anpassenBtn
86
+ border: 1px solid rgba(102, 108, 255, 0.5) !important
87
+ box-shadow: none !important
88
+ border-radius: 4px !important
89
+ width: 142.5px !important
90
+ min-width: 142.5px !important
91
+ height: 38px !important
92
+ display: flex !important
93
+ align-items: center !important
94
+ justify-content: center !important
95
+ text-align: center !important
96
+ font-family: 'Arial' !important
97
+ font-weight: 400 !important
98
+ font-size: 14px !important
99
+ line-height: 16px !important
100
+ color: #1976D2 !important
101
+
102
+ .zustimmenBtn
103
+ width: 142.5px !important
104
+ min-width: 142.5px !important
105
+ height: 38px !important
106
+ background: #005CCB !important
107
+ border-radius: 4px !important
108
+ display: flex !important
109
+ align-items: center !important
110
+ justify-content: center !important
111
+ text-align: center !important
112
+ font-family: 'Arial' !important
113
+ font-style: normal !important
114
+ font-weight: 400 !important
115
+ font-size: 14px !important
116
+ line-height: 16px !important
117
+ color: #FFFFFF !important
118
+
58
119
  .outlinedBtnLeft
59
120
  display: flex;
60
121
  justify-content: flex-end;
122
+ font-family: 'Arial';
123
+ font-weight: 400;
61
124
  color: #005CCB;
62
125
  font-size: 16px;
126
+ line-height: 24px;
63
127
  text-decoration: none;
64
- margin-top: 12px;
128
+ margin-top: 3px;
65
129
  margin-bottom: 0;
66
130
  margin-left: auto;
67
131
  max-width: 80px;
@@ -32,7 +32,7 @@ const PreviewCookieModal = ({ toggleModal, setModal, handleSentryInit } : IPrevi
32
32
  <div className={styles.modalWrapper}>
33
33
  <div className={styles.logoContainer}>
34
34
  <IconSVG name='autodeLogo' customDimensions />
35
- <Button onClick={onDisableAll} className={styles.modalBtn}>Nur notwendige Cookies</Button>
35
+ <Button onClick={onDisableAll} className={`${styles.modalBtn} ${styles.necessaryCookiesBtn}`}>Nur notwendige Cookies</Button>
36
36
  </div>
37
37
  <div className={styles.modalTitle}>Nach den Cookies geht die Fahrt weiter.</div>
38
38
  <div className={styles.modalContent}>
@@ -42,8 +42,8 @@ const PreviewCookieModal = ({ toggleModal, setModal, handleSentryInit } : IPrevi
42
42
  </div>
43
43
  <a href={`${environment}/impressum/`} target='_blank' className={styles.outlinedBtnLeft}>Impressum</a>
44
44
  <div className={styles.buttonsContainer}>
45
- <Button onClick={() => setModal('MANAGE_COOKIE_MODAL')} className={styles.modalBtn} variant='outlined'>Anpassen</Button>
46
- <Button onClick={onAcceptAll} className={styles.modalBtn}>zustimmen</Button>
45
+ <Button onClick={() => setModal('MANAGE_COOKIE_MODAL')} className={`${styles.modalBtn} ${styles.anpassenBtn}`} variant='outlined'>Anpassen</Button>
46
+ <Button onClick={onAcceptAll} className={`${styles.modalBtn} ${styles.zustimmenBtn}`}>zustimmen</Button>
47
47
  </div>
48
48
  </div>
49
49
  );
@@ -32,7 +32,7 @@ const MdAccordionGroup: React.FC<IMdAccordionGroupProps> = ({ title, tooltipText
32
32
  aria-expanded={open}
33
33
  onClick={toggle}
34
34
  onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); toggle(); } }}
35
- style={{ display: 'flex', alignItems: 'center', gap: 8, cursor: 'pointer', width: '100%' }}
35
+ style={{ display: 'flex', alignItems: 'center', gap: 8, cursor: 'pointer', width: '100%', paddingLeft: 15, paddingRight: 15 }}
36
36
  >
37
37
  <span className='macc-hd-text' style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
38
38
  <span className='macc-title md-title'>{title}</span>
@@ -45,7 +45,7 @@ const MdAccordionGroup: React.FC<IMdAccordionGroupProps> = ({ title, tooltipText
45
45
  ) : null}
46
46
  <Icon name='chevron-down' cls='macc-chev' />
47
47
  </div>
48
- {open ? <div style={{ padding: '4px 15px 12px' }}>{children}</div> : null}
48
+ {open ? <div style={{ padding: '10px' }}>{children}</div> : null}
49
49
  </section>
50
50
  );
51
51
  };
@@ -85,7 +85,7 @@
85
85
  "priceRatingAria": "Preisbewertung: {{rating}}",
86
86
  "detailsShow": "Details anzeigen",
87
87
  "paymentLabel": "Zahlung",
88
- "paymentValue": "Überweisung oder bei Übergabe",
88
+ "paymentValue": "Zahlung per Überweisung",
89
89
  "warrantyLabel": "Garantie",
90
90
  "warrantyValue": "1 Jahr inklusive",
91
91
  "deliveryLabel": "Lieferung",
@@ -771,7 +771,7 @@
771
771
  },
772
772
  "step3": {
773
773
  "title": "Bezahlung",
774
- "description": "Sicher online bezahlen oder bei der Übergabe — ohne versteckte Kosten."
774
+ "description": "Sicher per Überweisung bezahlen — ohne versteckte Kosten."
775
775
  },
776
776
  "step4": {
777
777
  "title": "Übergabe",
@@ -85,7 +85,7 @@
85
85
  "priceRatingAria": "Price rating: {{rating}}",
86
86
  "detailsShow": "Show details",
87
87
  "paymentLabel": "Payment",
88
- "paymentValue": "Bank transfer or on handover",
88
+ "paymentValue": "Bank transfer",
89
89
  "warrantyLabel": "Warranty",
90
90
  "warrantyValue": "1 year included",
91
91
  "deliveryLabel": "Delivery",
@@ -771,7 +771,7 @@
771
771
  },
772
772
  "step3": {
773
773
  "title": "Payment",
774
- "description": "Pay securely online or on handover — with no hidden costs."
774
+ "description": "Pay securely by bank transfer — with no hidden costs."
775
775
  },
776
776
  "step4": {
777
777
  "title": "Handover",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bytebrand/fe-ui-core-autobahn",
3
- "version": "1.0.93",
3
+ "version": "1.0.95",
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",