@marianmeres/stuic 3.129.0 → 3.130.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.
package/README.md
CHANGED
|
@@ -195,7 +195,11 @@ When a stuic app is installed and launched standalone (iOS Home Screen, Android/
|
|
|
195
195
|
|
|
196
196
|
**Automatic:**
|
|
197
197
|
|
|
198
|
-
- `Notifications` — the toast stack always keeps clear of the insets in standalone (you never want a toast under the home indicator).
|
|
198
|
+
- `Notifications` — the toast stack always keeps clear of the insets in standalone (you never want a toast under the home indicator).
|
|
199
|
+
- `Modal` — when full-bleed (below the `md` breakpoint, where it fills the screen), its content is padded by the insets so header / content / footer clear the system UI. Centered desktop modals are untouched.
|
|
200
|
+
- `AssetsPreview` — the lightbox image stays edge-to-edge, but the overlay controls (close, prev/next, dots, filename) are offset so they clear the insets.
|
|
201
|
+
|
|
202
|
+
All three are no-ops in a browser tab and need no prop.
|
|
199
203
|
|
|
200
204
|
**Utility classes** — offset any edge-anchored element without writing your own `env()` rule. They are active in standalone only:
|
|
201
205
|
|
|
@@ -219,7 +223,7 @@ When a stuic app is installed and launched standalone (iOS Home Screen, Android/
|
|
|
219
223
|
|
|
220
224
|
**Pick ONE layer.** Don't pad the same edge twice in a nesting chain. E.g. a nav `Drawer` whose content is its own stuic `Header`: put `safeArea` on the inner `Header`, not also on the drawer panel/wrapper.
|
|
221
225
|
|
|
222
|
-
**Not covered:**
|
|
226
|
+
**Not covered:** remaining fixed/edge-anchored components (e.g. `Float`, or a bare `ModalDialog` used directly) do not auto-handle insets — apply a `stuic-safe-area-*` class or the variables to their content as needed.
|
|
223
227
|
|
|
224
228
|
## TypeScript
|
|
225
229
|
|
|
@@ -45,6 +45,7 @@ interface AssetPreview {
|
|
|
45
45
|
- **Touch support**: Touch gestures for pan
|
|
46
46
|
- **Auto-preload**: Preloads full-resolution images when modal opens
|
|
47
47
|
- **File type icons**: Displays appropriate icons for non-image files
|
|
48
|
+
- **PWA safe area**: when installed/standalone, the overlay controls (close, prev/next, dots, filename) are automatically offset so they clear the status bar / notch / home indicator. The image itself stays edge-to-edge. Inert in a browser tab (`env()` → `0`); no prop required.
|
|
48
49
|
|
|
49
50
|
## Translation Keys
|
|
50
51
|
|
|
@@ -658,8 +658,11 @@
|
|
|
658
658
|
<div
|
|
659
659
|
class={twMerge(
|
|
660
660
|
"absolute inset-0 flex justify-between pointer-events-none",
|
|
661
|
-
prevNextBottom ? "items-end
|
|
661
|
+
prevNextBottom ? "items-end" : "items-center"
|
|
662
662
|
)}
|
|
663
|
+
style="padding-left: var(--stuic-safe-area-left, 0px); padding-right: var(--stuic-safe-area-right, 0px);{prevNextBottom
|
|
664
|
+
? ' padding-bottom: calc(1rem + var(--stuic-safe-area-bottom, 0px));'
|
|
665
|
+
: ''}"
|
|
663
666
|
>
|
|
664
667
|
<Button
|
|
665
668
|
class={twMerge(BUTTON_CLS, "ml-4", classControls)}
|
|
@@ -681,7 +684,17 @@
|
|
|
681
684
|
</div>
|
|
682
685
|
{/if}
|
|
683
686
|
|
|
684
|
-
|
|
687
|
+
<!-- Top control bar (close, download, zoom, filename). Offset by the PWA
|
|
688
|
+
safe-area insets when installed/standalone so the controls clear the
|
|
689
|
+
status bar / notch / side notch. The vars are 0px in a browser tab. -->
|
|
690
|
+
<div
|
|
691
|
+
class="absolute flex items-center justify-between gap-3"
|
|
692
|
+
style="
|
|
693
|
+
top: calc(1rem + var(--stuic-safe-area-top, 0px));
|
|
694
|
+
left: calc(1rem + var(--stuic-safe-area-left, 0px));
|
|
695
|
+
right: calc(1rem + var(--stuic-safe-area-right, 0px));
|
|
696
|
+
"
|
|
697
|
+
>
|
|
685
698
|
{#if !noName && previewAsset?.name}
|
|
686
699
|
<span class="stuic-assets-preview-label truncate px-1">
|
|
687
700
|
{previewAsset?.name}
|
|
@@ -767,7 +780,8 @@
|
|
|
767
780
|
{#if !noDots && assets.length <= 10}
|
|
768
781
|
{#if !noName && dotTooltip}
|
|
769
782
|
<div
|
|
770
|
-
class="absolute
|
|
783
|
+
class="absolute left-0 right-0 text-center"
|
|
784
|
+
style="bottom: calc(2.5rem + var(--stuic-safe-area-bottom, 0px));"
|
|
771
785
|
transition:fade={{ duration: 100 }}
|
|
772
786
|
>
|
|
773
787
|
<span class="stuic-assets-preview-label p-1">
|
|
@@ -775,7 +789,10 @@
|
|
|
775
789
|
</span>
|
|
776
790
|
</div>
|
|
777
791
|
{/if}
|
|
778
|
-
<div
|
|
792
|
+
<div
|
|
793
|
+
class="absolute left-1/2 -translate-x-1/2 flex items-center gap-3"
|
|
794
|
+
style="bottom: calc(1rem + var(--stuic-safe-area-bottom, 0px));"
|
|
795
|
+
>
|
|
779
796
|
{#each assets as _, i}
|
|
780
797
|
<!-- svelte-ignore a11y_mouse_events_have_key_events -->
|
|
781
798
|
<button
|
|
@@ -793,7 +810,10 @@
|
|
|
793
810
|
{/each}
|
|
794
811
|
</div>
|
|
795
812
|
{:else if !noCurrentOfTotal}
|
|
796
|
-
<div
|
|
813
|
+
<div
|
|
814
|
+
class="absolute left-1/2 -translate-x-1/2"
|
|
815
|
+
style="bottom: calc(1rem + var(--stuic-safe-area-bottom, 0px));"
|
|
816
|
+
>
|
|
797
817
|
<span class="stuic-assets-preview-label px-2 py-1 text-sm opacity-60">
|
|
798
818
|
{previewIdx + 1} / {assets.length}
|
|
799
819
|
</span>
|
|
@@ -107,6 +107,10 @@ By default, Modal is:
|
|
|
107
107
|
- **Mobile**: Full screen with 1rem margins from viewport edges
|
|
108
108
|
- **Desktop (md+)**: Centered, max-width 768px, auto height with max 80vh
|
|
109
109
|
|
|
110
|
+
### PWA safe area (automatic)
|
|
111
|
+
|
|
112
|
+
When the app runs installed/standalone (display-mode standalone or fullscreen) and the Modal is **full-bleed** (below the `md` breakpoint), its content is automatically padded by the device safe-area insets so the header / content / footer clear the status bar, notch and home indicator. This is **inert in a normal browser tab** (`env()` → `0`) and on **centered desktop** modals (which don't touch the edges). No prop required. To go truly edge-to-edge, override the padding on the inner panel via `class`.
|
|
113
|
+
|
|
110
114
|
## CSS Variables
|
|
111
115
|
|
|
112
116
|
Override to customize appearance:
|
|
@@ -27,4 +27,24 @@
|
|
|
27
27
|
.stuic-modal .main {
|
|
28
28
|
scrollbar-width: thin;
|
|
29
29
|
}
|
|
30
|
+
|
|
31
|
+
/* ============================================================================
|
|
32
|
+
SAFE AREA (PWA installed / standalone) — automatic, full-bleed only.
|
|
33
|
+
The Modal is full-screen below the `md` breakpoint (size-full) and a
|
|
34
|
+
centered card at/above it (md:size-auto). Only the full-bleed case touches
|
|
35
|
+
the device edges, so we gate on `width < 48rem` (Tailwind's md) AND
|
|
36
|
+
standalone, and pad the bg-bearing .stuic-modal (a flex column) so its
|
|
37
|
+
header / content / footer clear the status bar, notch and home indicator.
|
|
38
|
+
Centered desktop modals and browser tabs (env → 0) are untouched. A
|
|
39
|
+
consumer wanting true edge-to-edge can override padding via `class`.
|
|
40
|
+
============================================================================ */
|
|
41
|
+
@media (display-mode: standalone) and (width < 48rem),
|
|
42
|
+
(display-mode: fullscreen) and (width < 48rem) {
|
|
43
|
+
.stuic-modal {
|
|
44
|
+
padding-top: env(safe-area-inset-top);
|
|
45
|
+
padding-right: env(safe-area-inset-right);
|
|
46
|
+
padding-bottom: env(safe-area-inset-bottom);
|
|
47
|
+
padding-left: env(safe-area-inset-left);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
30
50
|
}
|