Skip to content

fix(pwa): keep the installed app's content below iOS 26's edge blur - #411

Merged
thierryvm merged 1 commit into
mainfrom
fix/ios-pwa-edge-blur-clearance
Oct 1, 2026
Merged

thierryvm merged 1 commit into
mainfrom
fix/ios-pwa-edge-blur-clearance

Conversation

@thierryvm

@thierryvm thierryvm commented Oct 1, 2026 •

Copy link
Copy Markdown
Owner

Summary

The opaque strip from #398 is as tall as the status bar. It did not stop iOS 26's Liquid Glass edge blur on the reporter's iPhone 14: the blur was still there on the installed app when it was retested on 1 October 2026. The blur is system chrome drawn over the web view, and no CSS or meta tag turns it off. Most fixes published elsewhere say they were not verified on a device. The one that was (xdoubleu/tools.xdoubleu.com#1988) keeps content below the blur instead of fighting it.

  • --inset-top (theme.css) equals env(safe-area-inset-top, 0px). In the installed app on iOS (@supports (-webkit-touch-callout: none) + display-mode: standalone, portrait), it adds 2.5rem.

  • Every top edge now uses it:

    • app layout and mobile sidebar
    • landing nav
    • /privacy, /changelog and /story navs
    • login, PWA-install and support modals
    • AI tutor drawer

    A test forbids any component from using a bare safe-area-inset-top again.

  • The strip fills that band, so content scrolling under the blur shows as a plain colour. It moves to z-[25], under the sidebar's dimmed overlay (z-30).

  • Modal overlays scroll and centre their card with my-auto, so a card taller than the screen (keyboard open, age gate) starts at its top instead of being cut off.

  • No change in a browser tab or on desktop: the variable resolves to the old values there, and the strip keeps a height of 0.

Gates

  • mobile-responsive-auditor: PASS_WITH_NOTES. Two modals without the inset and a modal that could not scroll were fixed here.
  • ui-auditor: no CRITICAL. The stale comments it flagged were updated.
  • feature-dev:code-reviewer: one IMPORTANT. The public pages outside Layout would have had their nav hidden by the taller strip. Fixed.
  • Type-check, lint and build pass. Vitest: 2967 unit tests pass. The Supabase integration tests timed out locally against the live database and are skipped in CI.

Test plan

  • CI green
  • Preview at desktop and 390 px: nothing moves in a browser
  • @Thierry on the iPhone, installed app (only a real device shows the blur): landing at the top and mid-scroll, a lesson, sidebar open, login, AI tutor

🤖 Generated with Claude Code

Résumé par Sourcery

Maintenir le contenu des apps iOS installées sous le flou des bords d’iOS 26 tout en préservant les mises en page existantes en dehors du mode portrait autonome.

Correctifs :

  • Maintenir le contenu de premier niveau des PWA iOS installées sous le flou des bords d’iOS 26 en appliquant un encart supérieur spécifique à l’app et un arrière-plan opaque correspondant.
  • Empêcher le rognage des boîtes de dialogue mobiles d’authentification, d’installation et d’assistance de grande hauteur en autorisant le défilement des superpositions et en centrant leur alignement vers le haut.

Améliorations :

  • Appliquer de manière cohérente l’encart supérieur partagé aux mises en page, à la navigation, aux barres latérales et au tuteur IA, tout en préservant les espacements existants dans les navigateurs, sur ordinateur et en mode paysage.

Documentation :

  • Documenter dans le journal des modifications et le récit du projet le comportement vérifié du flou des apps installées sous iOS 26 ainsi que l’espacement résultant du contenu supérieur.

Tests :

  • Ajouter une couverture de tests pour la définition de l’encart partagé, le comportement de l’arrière-plan et la prévention de l’utilisation directe de la zone de sécurité supérieure dans les composants.
Original summary in English

Summary by Sourcery

Keep installed iOS app content below the iOS 26 edge blur while preserving existing layouts outside portrait standalone mode.

Bug Fixes:

  • Keep installed iOS PWAs’ top-level content below the iOS 26 edge blur by applying an app-specific portrait inset and matching opaque backdrop.
  • Prevent tall mobile authentication, installation, and support dialogs from being clipped by allowing overlay scrolling and top-aligned centering.

Enhancements:

  • Apply the shared top inset consistently across layouts, navigation, sidebars, and the AI tutor while preserving existing browser, desktop, and landscape spacing.

Documentation:

  • Document the verified iOS 26 installed-app blur behavior and the resulting top-content spacing in the changelog and project story.

Tests:

  • Add coverage for the shared inset definition, backdrop behavior, and prevention of bare top safe-area usage across components.

The opaque strip of #398, as tall as the status bar, did not stop the
Liquid Glass edge blur on the reporter's iPhone 14 (retested 1 October
2026). The fix confirmed on devices elsewhere keeps content out of the
blur: --inset-top (theme.css) is the safe-area inset, plus 2.5rem in the
installed app on iOS in portrait, and every top edge uses it (app layout,
sidebar, landing, privacy/changelog/story navs, login, PWA install and
support modals, AI tutor drawer). The strip fills that band at z-25, under
the sidebar overlay. Modal overlays scroll and center their card with
my-auto, so a card taller than the screen is never cut at the top.
Nothing changes in a browser tab or on desktop.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@vercel

vercel Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
terminal-learning Ready Ready Preview Oct 1, 2026 5:16pm UTC

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry @thierryvm, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 2 days and 2 hours by commenting @sourcery-ai review. Upgrade to get a review now.

@sourcery-ai

sourcery-ai Bot commented Oct 1, 2026

Copy link
Copy Markdown

Guide du reviewer

Déplace le contenu de la PWA iOS installée en mode portrait sous le flou des bords d’iOS 26 grâce à une variable partagée --inset-top, met à jour le comportement de l’arrière-plan et des modales hautes en conséquence, et ajoute des vérifications de régression au niveau du code source ainsi que de la documentation ; les mises en page dans le navigateur, sur ordinateur et en mode paysage conservent leur espacement précédent.

Diagramme de séquence du rendu d’une PWA iOS installée

sequenceDiagram
    participant CSS as theme.css
    participant App as PWA iOS installée
    participant Content as Contenu de l’application
    participant Blur as Flou des bords d’iOS 26
    participant Backdrop as StatusBarBackdrop

    CSS->>App: Résoudre --inset-top
    App->>Content: Appliquer l’encart supérieur à la mise en page et aux composants du bord supérieur
    App->>Backdrop: Afficher une bande fixe de hauteur --inset-top
    Blur-->>App: Dessiner le flou système sur le bord supérieur
    Content-->>Blur: Commence sous la bande de flou
    Backdrop-->>Blur: Afficher l’arrière-plan uni de l’application sous le flou
Loading

Diagramme de flux des modales hautes défilables

flowchart TD
    Open["Ouvrir la modale"] --> Inset["Appliquer le padding --inset-top"]
    Inset --> Scroll["Superposition défilable"]
    Scroll --> Center["La carte utilise my-auto"]
    Center --> Short["La carte courte reste centrée"]
    Center --> Tall["La carte haute peut défiler depuis son sommet"]
Loading

Modifications au niveau des fichiers

Modification Détails Fichiers
Centraliser l’espacement du bord supérieur et ajouter un dégagement en mode portrait pour les PWA iOS autonomes sous le flou Liquid Glass.
  • Définir --inset-top comme l’encart de la zone sûre, en ajoutant 2.5rem uniquement pour les PWA iOS installées en mode portrait.
  • Remplacer l’utilisation de la zone sûre supérieure au niveau des composants par la variable partagée dans la mise en page de l’application, la barre latérale, la navigation des pages publiques et l’interface du tuteur IA.
  • Mettre à jour la bande d’arrière-plan afin qu’elle couvre l’intégralité de l’encart partagé tout en la positionnant sous la superposition de la barre latérale.
src/styles/theme.css
src/app/components/Layout.tsx
src/app/components/Sidebar.tsx
src/app/components/Landing.tsx
src/app/components/MarkdownPage.tsx
src/app/components/PrivacyPolicy.tsx
src/app/components/StatusBarBackdrop.tsx
src/app/components/ai/AiTutorPanel.tsx
Rendre les superpositions modales utilisables lorsque l’encart supérieur ajouté ou une petite fenêtre d’affichage rend leurs cartes plus hautes que l’écran.
  • Basculer les superpositions concernées vers des conteneurs alignés en haut et défilables verticalement, avec le padding supérieur partagé.
  • Utiliser my-auto sur les cartes modales afin de conserver le centrage lorsqu’elles tiennent dans l’écran, tout en permettant aux cartes hautes de commencer en haut de la zone visible.
src/app/components/LoginModal.tsx
src/app/components/PWAInstallModal.tsx
src/app/components/support/SupportTicketModal.tsx
Ajouter une couverture de régression imposant le contrat d’encart partagé et documentant le comportement iOS attendu.
  • Mettre à jour les assertions de l’arrière-plan pour la variable partagée.
  • Analyser le code source des composants afin de rejeter l’utilisation directe de la zone sûre supérieure et de vérifier que tous les consommateurs attendus utilisent --inset-top.
src/test/statusBarBackdrop.test.tsx
Documenter le comportement iOS vérifié sur l’appareil et la stratégie de mise en page qui en résulte pour l’application installée.
  • Ajouter des entrées au changelog et à la story expliquant que le flou système ne peut pas être désactivé et que le contenu est déplacé en dessous.
  • Préciser que le comportement dans le navigateur, sur ordinateur et en mode paysage reste inchangé.
CHANGELOG.md
STORY.md

Conseils et commandes

Interagir avec Sourcery

  • Déclencher une nouvelle review : commenter @sourcery-ai review sur la pull request.
  • Poursuivre les discussions : répondre directement aux commentaires de review de Sourcery.
  • Générer une issue GitHub à partir d’un commentaire de review : demander à Sourcery de créer une issue à partir d’un commentaire de review en y répondant. Vous pouvez également répondre à un commentaire de review avec @sourcery-ai issue pour créer une issue à partir de celui-ci.
  • Générer un titre de pull request : écrire @sourcery-ai n’importe où dans le titre de la pull request pour générer un titre à tout moment. Vous pouvez également commenter @sourcery-ai title sur la pull request pour générer ou régénérer le titre à tout moment.
  • Générer un résumé de pull request : écrire @sourcery-ai summary n’importe où dans le corps de la pull request pour générer un résumé exactement à l’endroit souhaité. Vous pouvez également commenter @sourcery-ai summary sur la pull request pour générer ou régénérer le résumé à tout moment.
  • Générer le guide du reviewer : commenter @sourcery-ai guide sur la pull request pour générer ou régénérer le guide du reviewer à tout moment.
  • Résoudre tous les commentaires de Sourcery : commenter @sourcery-ai resolve sur la pull request pour résoudre tous les commentaires de Sourcery. Utile si vous avez déjà traité tous les commentaires et ne souhaitez plus les voir.
  • Ignorer toutes les reviews de Sourcery : commenter @sourcery-ai dismiss sur la pull request pour ignorer toutes les reviews existantes de Sourcery. Particulièrement utile si vous souhaitez repartir de zéro avec une nouvelle review — n’oubliez pas de commenter @sourcery-ai review pour déclencher une nouvelle review !

Personnaliser votre expérience

Accédez à votre tableau de bord pour :

  • Activer ou désactiver des fonctionnalités de review, telles que le résumé de pull request généré par Sourcery, le guide du reviewer, et d’autres.
  • Modifier la langue des reviews.
  • Ajouter, supprimer ou modifier des instructions de review personnalisées.
  • Ajuster les autres paramètres de review.

Obtenir de l’aide

Original review guide in English

Reviewer's Guide

Moves installed iOS portrait PWA content below iOS 26’s edge blur through a shared --inset-top variable, updates the backdrop and tall-modal behavior accordingly, and adds source-level regression checks plus documentation; browser, desktop, and landscape layouts retain their previous spacing.

Sequence diagram for installed iOS PWA rendering

sequenceDiagram
    participant CSS as theme.css
    participant App as Installed iOS PWA
    participant Content as App content
    participant Blur as iOS 26 edge blur
    participant Backdrop as StatusBarBackdrop

    CSS->>App: Resolve --inset-top
    App->>Content: Apply top inset to layout and top-edge components
    App->>Backdrop: Render fixed band with height --inset-top
    Blur-->>App: Draw system blur over top edge
    Content-->>Blur: Starts below blur band
    Backdrop-->>Blur: Shows plain app background beneath blur
Loading

Flow diagram for scrollable tall modals

flowchart TD
    Open["Open modal"] --> Inset["Apply --inset-top padding"]
    Inset --> Scroll["Scrollable overlay"]
    Scroll --> Center["Card uses my-auto"]
    Center --> Short["Short card remains centered"]
    Center --> Tall["Tall card can scroll from its top"]
Loading

File-Level Changes

Change Details Files
Centralize top-edge spacing and add an iOS standalone portrait clearance below the Liquid Glass blur.
  • Define --inset-top as the safe-area inset, adding 2.5rem only for installed iOS portrait PWAs.
  • Replace component-level top safe-area usage with the shared variable across app layout, sidebar, public-page navigation, and AI tutor UI.
  • Update the backdrop strip to cover the full shared inset while placing it below the sidebar overlay.
src/styles/theme.css
src/app/components/Layout.tsx
src/app/components/Sidebar.tsx
src/app/components/Landing.tsx
src/app/components/MarkdownPage.tsx
src/app/components/PrivacyPolicy.tsx
src/app/components/StatusBarBackdrop.tsx
src/app/components/ai/AiTutorPanel.tsx
Make modal overlays usable when the added top inset or a small viewport makes their cards taller than the screen.
  • Switch affected overlays to top-aligned, vertically scrollable containers with the shared top padding.
  • Use my-auto on modal cards to preserve centering when they fit while allowing tall cards to start at the visible top.
src/app/components/LoginModal.tsx
src/app/components/PWAInstallModal.tsx
src/app/components/support/SupportTicketModal.tsx
Add regression coverage enforcing the shared inset contract and documenting the intended iOS behavior.
  • Update backdrop assertions for the shared variable.
  • Scan component source to reject bare top safe-area usage and verify all expected consumers use --inset-top.
src/test/statusBarBackdrop.test.tsx
Document the device-verified iOS behavior and the resulting installed-app layout strategy.
  • Add changelog and story entries explaining that the system blur cannot be disabled and content is moved below it.
  • Record that browser, desktop, and landscape behavior remain unchanged.
CHANGELOG.md
STORY.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@thierryvm
thierryvm merged commit 69f1176 into main Oct 1, 2026
4 checks passed
@thierryvm
thierryvm deleted the fix/ios-pwa-edge-blur-clearance branch October 1, 2026 17:18

This branch was successfully deployed

1 active deployment
Preview — eb233b9f Deployed Oct 1, 2026 by vercel[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant