@propbinder/mobile-design 0.2.4 → 0.2.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@propbinder/mobile-design",
3
- "version": "0.2.04",
3
+ "version": "0.2.05",
4
4
  "peerDependencies": {
5
5
  "@angular/common": "^20.3.0 || ^21.0.0",
6
6
  "@angular/core": "^20.3.0 || ^21.0.0"
package/styles/ionic.css CHANGED
@@ -69,7 +69,7 @@ html {
69
69
  html,
70
70
  body {
71
71
  /* Background color must match theme-color for iOS PWA status bar */
72
- background-color: #221a4c;
72
+ background-color: var(--color-brand-secondary);
73
73
  color: var(--text-color-default-primary);
74
74
  font-family: 'Brockmann', system-ui, -apple-system, sans-serif;
75
75
 
@@ -110,7 +110,7 @@ body.backdrop-no-scroll {
110
110
  --ion-color-primary-tint: var(--color-brand-base);
111
111
 
112
112
  /* Ionic component defaults */
113
- --ion-background-color: var(--color-background-neutral-primary);
113
+ --ion-background-color: var(--color-brand-secondary);
114
114
  --ion-text-color: var(--text-color-default-primary);
115
115
  }
116
116
 
@@ -127,6 +127,21 @@ ion-content {
127
127
  --background: var(--color-background-neutral-primary);
128
128
  }
129
129
 
130
+ /* iOS: Set base ion-content background to brand secondary for pages */
131
+ .plt-ios ion-content {
132
+ background: var(--color-brand-secondary) !important;
133
+ }
134
+
135
+ /* iOS: Also target any inner background parts */
136
+ .plt-ios ion-content::part(background) {
137
+ background: var(--color-brand-secondary) !important;
138
+ }
139
+
140
+ /* iOS: Target the inner container if it exists */
141
+ .plt-ios ion-content .inner-scroll {
142
+ background: var(--color-brand-secondary) !important;
143
+ }
144
+
130
145
  /* Default: Block browser overscroll on all platforms */
131
146
  ion-content::part(scroll) {
132
147
  overscroll-behavior-y: none;
@@ -148,10 +163,37 @@ ion-content::part(scroll)::-webkit-scrollbar {
148
163
  /* iOS-specific: Enable native scroll overshoot/bounce effect */
149
164
  .plt-ios ion-content::part(scroll) {
150
165
  overscroll-behavior-y: contain;
166
+ /* iOS: Set scroll container background to match brand secondary */
167
+ /* This prevents white background from showing when header fades on scroll */
168
+ background: var(--color-brand-secondary) !important;
151
169
  }
152
170
 
153
171
  .plt-ios .ion-page {
154
172
  overscroll-behavior-y: contain;
173
+ /* Set page background to brand secondary to match header on iOS */
174
+ background: var(--color-brand-secondary) !important;
175
+ }
176
+
177
+ /* iOS-specific: Override ion-content background for pages (not modals) */
178
+ .plt-ios .ion-page > ion-content {
179
+ --background: var(--color-brand-secondary);
180
+ }
181
+
182
+ /* iOS: Ensure modal content stays with neutral background */
183
+ .plt-ios ion-modal ion-content::part(scroll) {
184
+ background: var(--color-background-neutral-primary) !important;
185
+ }
186
+
187
+ .plt-ios ion-modal ion-content {
188
+ background: var(--color-background-neutral-primary) !important;
189
+ }
190
+
191
+ .plt-ios ion-modal ion-content::part(background) {
192
+ background: var(--color-background-neutral-primary) !important;
193
+ }
194
+
195
+ .plt-ios ion-modal ion-content .inner-scroll {
196
+ background: var(--color-background-neutral-primary) !important;
155
197
  }
156
198
 
157
199
  ion-footer {
@@ -159,7 +201,8 @@ ion-footer {
159
201
  }
160
202
 
161
203
  ion-router-outlet {
162
- --background: var(--color-background-neutral-primary);
204
+ --background: var(--color-brand-secondary);
205
+ background: var(--color-brand-secondary);
163
206
  }
164
207
 
165
208
  ion-refresher {
@@ -186,7 +229,7 @@ ion-modal {
186
229
  max-height: 100vh !important;
187
230
  }
188
231
 
189
- ion-modal .modal-wrapper,
232
+ /* Prevent modal container from resizing when keyboard appears */
190
233
  ion-modal::part(content) {
191
234
  position: fixed !important;
192
235
  height: 100% !important;
@@ -484,16 +527,7 @@ ion-toast {
484
527
  }
485
528
  }
486
529
 
487
- /* Dark mode support (if needed) */
488
- @media (prefers-color-scheme: dark) {
489
- .ds-mobile-modal {
490
- --background: var(--color-background-neutral-primary-dark, #1a1a1a);
491
- }
492
-
493
- .ds-mobile-modal::part(backdrop) {
494
- background: rgba(0, 0, 0, 0.6);
495
- }
496
- }
530
+ /* Dark mode support removed - modals should not change based on system dark mode */
497
531
 
498
532
  /* Accessibility: Reduced motion */
499
533
  @media (prefers-reduced-motion: reduce) {
@@ -516,6 +550,39 @@ ion-tab-button::part(native) {
516
550
  gap: 2px;
517
551
  }
518
552
 
553
+ /* ============================================
554
+ Base Modal Styles (Shared across all modals)
555
+ ============================================ */
556
+
557
+ .ds-modal-base {
558
+ --background: var(--color-background-neutral-primary, #ffffff);
559
+ --width: 100%;
560
+ --max-width: 640px;
561
+ --height: 100dvh; /* Full viewport height - content top offset creates gap */
562
+ --border-radius: 16px 16px 0 0;
563
+ }
564
+
565
+ .ds-modal-base::part(content) {
566
+ border-radius: 16px 16px 0 0;
567
+ box-shadow: 0 10px 40px rgba(0, 0, 0, 0.15);
568
+ background: var(--color-background-neutral-primary, #ffffff);
569
+ max-width: 640px;
570
+ margin: 0 auto;
571
+ /* Use top positioning instead of margin-top to work with fixed positioning */
572
+ top: var(--app-sheet-top-offset) !important;
573
+ height: calc(100% - var(--app-sheet-top-offset)) !important;
574
+ max-height: calc(100vh - var(--app-sheet-top-offset)) !important;
575
+ }
576
+
577
+ .ds-modal-base::part(backdrop) {
578
+ background: rgba(0, 0, 0, 0.4);
579
+ backdrop-filter: blur(4px);
580
+ }
581
+
582
+ .ds-modal-base ion-content {
583
+ --background: var(--color-background-neutral-primary, #ffffff);
584
+ }
585
+
519
586
  /* ============================================
520
587
  Post Detail Modal Styles
521
588
  ============================================ */
@@ -556,11 +623,6 @@ ion-router-outlet.ion-page-hidden,
556
623
  overflow: hidden;
557
624
  }
558
625
 
559
- /* Set background to brand secondary */
560
- ion-router-outlet {
561
- background: var(--color-brand-secondary) !important;
562
- }
563
-
564
626
  /* Override Ionic's default 10px border-radius */
565
627
  body.backdrop-no-scroll ion-router-outlet {
566
628
  border-radius: 16px 16px 0 0 !important;
@@ -612,24 +674,7 @@ ion-app ion-router-outlet.ion-page-hidden {
612
674
 
613
675
  /* Safe area handling - NOT needed here since modal positioning (--app-sheet-top-offset) handles it */
614
676
 
615
- /* Dark mode support */
616
- @media (prefers-color-scheme: dark) {
617
- .ds-post-detail-modal {
618
- --background: var(--color-background-neutral-primary-dark, #1a1a1a);
619
- }
620
-
621
- .ds-post-detail-modal::part(content) {
622
- background: var(--color-background-neutral-primary-dark, #1a1a1a);
623
- }
624
-
625
- .ds-post-detail-modal::part(backdrop) {
626
- background: rgba(0, 0, 0, 0.6);
627
- }
628
-
629
- .ds-post-detail-modal ion-content {
630
- --background: var(--color-background-neutral-primary-dark, #1a1a1a);
631
- }
632
- }
677
+ /* Dark mode support removed - modals should not change based on system dark mode */
633
678
 
634
679
  /* ============================================
635
680
  Chat Modal Styles
@@ -664,24 +709,7 @@ ion-app ion-router-outlet.ion-page-hidden {
664
709
  --background: var(--color-background-neutral-primary, #ffffff);
665
710
  }
666
711
 
667
- /* Dark mode support */
668
- @media (prefers-color-scheme: dark) {
669
- .ds-chat-modal {
670
- --background: var(--color-background-neutral-primary-dark, #1a1a1a);
671
- }
672
-
673
- .ds-chat-modal::part(content) {
674
- background: var(--color-background-neutral-primary-dark, #1a1a1a);
675
- }
676
-
677
- .ds-chat-modal::part(backdrop) {
678
- background: rgba(0, 0, 0, 0.6);
679
- }
680
-
681
- .ds-chat-modal ion-content {
682
- --background: var(--color-background-neutral-primary-dark, #1a1a1a);
683
- }
684
- }
712
+ /* Dark mode support removed - modals should not change based on system dark mode */
685
713
 
686
714
  /* ============================================
687
715
  Handbook Detail Modal Styles
@@ -767,22 +795,5 @@ ion-app ion-router-outlet.ion-page-hidden {
767
795
  --background: #ffffff;
768
796
  }
769
797
 
770
- /* Dark mode support */
771
- @media (prefers-color-scheme: dark) {
772
- .ds-whitelabel-demo-modal {
773
- --background: var(--color-background-neutral-primary-dark, #1a1a1a);
774
- }
775
-
776
- .ds-whitelabel-demo-modal::part(content) {
777
- background: var(--color-background-neutral-primary-dark, #1a1a1a);
778
- }
779
-
780
- .ds-whitelabel-demo-modal::part(backdrop) {
781
- background: rgba(0, 0, 0, 0.6);
782
- }
783
-
784
- .ds-whitelabel-demo-modal ion-content {
785
- --background: var(--color-background-neutral-primary-dark, #1a1a1a);
786
- }
787
- }
798
+ /* Dark mode support removed - modals should not change based on system dark mode */
788
799
 
@@ -107,3 +107,44 @@
107
107
  margin: 0;
108
108
  }
109
109
 
110
+ /* ============================================
111
+ FORM UTILITIES
112
+ ============================================ */
113
+
114
+ /* Ghost Input/Textarea - No focus/hover outlines */
115
+ .ghost-input-clean ::ng-deep .ds-input,
116
+ .ghost-input-clean ::ng-deep .ds-textarea,
117
+ .ghost-input-clean ::ng-deep .textarea-container {
118
+ outline: none !important;
119
+ border: none !important;
120
+ }
121
+
122
+ .ghost-input-clean ::ng-deep .ds-input:hover,
123
+ .ghost-input-clean ::ng-deep .ds-textarea:hover,
124
+ .ghost-input-clean ::ng-deep .textarea-container:hover,
125
+ .ghost-input-clean ::ng-deep .ds-input:focus,
126
+ .ghost-input-clean ::ng-deep .ds-textarea:focus,
127
+ .ghost-input-clean ::ng-deep .textarea-container:focus,
128
+ .ghost-input-clean ::ng-deep .ds-input:focus-within,
129
+ .ghost-input-clean ::ng-deep .ds-textarea:focus-within,
130
+ .ghost-input-clean ::ng-deep .textarea-container:focus-within {
131
+ outline: none !important;
132
+ border: none !important;
133
+ box-shadow: none !important;
134
+ }
135
+
136
+ /* Target the actual textarea element inside ds-textarea */
137
+ .ghost-input-clean ::ng-deep textarea {
138
+ outline: none !important;
139
+ border: none !important;
140
+ box-shadow: none !important;
141
+ resize: none !important;
142
+ }
143
+
144
+ .ghost-input-clean ::ng-deep textarea:hover,
145
+ .ghost-input-clean ::ng-deep textarea:focus {
146
+ outline: none !important;
147
+ border: none !important;
148
+ box-shadow: none !important;
149
+ }
150
+
@@ -13,6 +13,9 @@
13
13
  flex-direction: column;
14
14
  align-items: center;
15
15
  height: 100%;
16
+ /* Solid background to cover overlay from page underneath during transitions */
17
+ background: var(--color-secondary-surface);
18
+ width: 100%;
16
19
  }
17
20
 
18
21
  /* ============================================
@@ -211,6 +214,12 @@
211
214
  background: var(--color-background-neutral-primary);
212
215
  border-radius: 24px 24px 0 0;
213
216
 
217
+ /* Visual styling for iOS overshoot - extend background below using box-shadow */
218
+ transform: translateZ(0);
219
+ will-change: transform;
220
+ isolation: isolate;
221
+ box-shadow: 0 200vh 0 0 var(--color-background-neutral-primary);
222
+
214
223
  /* Fixed 20px horizontal padding globally */
215
224
  padding: 20px;
216
225
  /* Add bottom padding on mobile to account for fixed tab bar */
@@ -218,13 +227,6 @@
218
227
  }
219
228
 
220
229
  :host .content-inner {
221
- /* Visual styling - background, border-radius, and shadow extend */
222
- transform: translateZ(0);
223
- will-change: transform;
224
- isolation: isolate;
225
- /* Extend white background below for iOS overshoot using box-shadow */
226
- box-shadow: 0 200vh 0 0 var(--color-background-neutral-primary);
227
-
228
230
  /* Grow to fill parent flex container */
229
231
  flex: 1;
230
232