What changed
Fixes two reported bugs on the preview detail page’s “Don’t have the Tuist app installed?” alert (the prompt shown when you click Run and the tuist:// deep link doesn’t open the app), plus a related Noora alert component fix:
fix(server) — alert no longer renders behind the app icon. The alert and app icon now use Noora z-index tokens instead of magic numbers (#download-tuist-app-alert → var(--noora-z-index-1); the app icon’s redundant z-index: 103 is removed).
fix(server) — the alert’s Download link now works. Gave the link_button an href.
fix(noora) — large alerts keep their description text when rich content is also present.
Why / root cause
1. Alert behind the app icon. In assets/app/css/pages/preview.css, #download-tuist-app-alert is position: absolute (top-right) but had no z-index, while the app icon ([data-part="icon"]) sets z-index: 103. None of the intermediate ancestors (#preview, [data-part="header"], [data-part="icon-with-dots"]) establish a stacking context — they’re position: relative with no z-index — so the icon’s 103 and the alert’s auto are compared in the same stacking context, and the positive z-index wins. The icon therefore painted on top of the alert.
The fix uses Noora design-system tokens rather than magic numbers:
- The app icon’s
z-index: 103 is removed entirely. It’s unnecessary: the icon comes after the decorative dots element in the DOM (preview_live.html.heex — dots, then icon), and both are positioned with auto z-index, so the icon already paints above the dots by document order.
- The alert gets
var(--noora-z-index-1) (100). With the icon now at auto, the alert’s positive z-index paints above it in the same stacking context.
This is in-page content-band layering (one in-flow element sitting just above a sibling), not a floating overlay, so --noora-z-index-1 is the correct token — not the overlay band (10/11/12) reserved for dropdowns, modals, and tooltips. It also matches the existing precedent in app_preview.css, where a stacked overlay/run-button pair uses --noora-z-index-1/--noora-z-index-2.
2. Dead Download link. The alert’s :action slot used <.link_button> with no href/navigate/patch. Noora’s link_button renders <.link href={@href} navigate={@navigate} patch={@patch}>; with all three nil the anchor has no destination, so clicking it was a no-op. It now points at ~p"/download" (TuistWeb.DownloadController).
3. Noora alert dropped its description. In a large alert, the description attribute was only rendered in the inner_block == [] branch, so when both a description and rich inner_block content were supplied, the description text was silently dropped. It now renders alongside the rich content.
Why /download over the obvious alternatives
~p"/download" is the canonical app-download entry point — the marketing navbar and footer link to the same route, and DownloadController redirects to the latest Tuist macOS app .dmg from GitHub releases. Using it keeps the preview alert consistent with the rest of the product and avoids hardcoding a release/asset URL.
Note
/download resolves in production but 404s in local development: Tuist.GitHub.Releases.get_latest_app_release/0 is hardcoded to return nil when Tuist.Environment.dev?(), so the controller raises NotFoundError locally. This is the existing, intentional behavior (it’s covered by download_controller_test.exs) and affects the marketing /download link and the account dropdown’s “Download macOS app” button identically. No behavior change to the route is included here.
User impact
When the Tuist app isn’t installed and the deep link fails, the “Don’t have the Tuist app installed?” alert is now fully visible (not hidden behind the app icon) and its Download action takes the user to the macOS app download.
Validation
- Confirmed the z-index fix visually on the running server — the alert now renders above the icon.
- Verified the icon still paints above the decorative
dots after removing its z-index, since the icon follows the dots in DOM order.
- Confirmed
GET /download → TuistWeb.DownloadController :download via mix phx.routes.
- Verified the dev 404 is the controller’s
NotFoundError (release data is nil in dev), not a routing miss — curl -i localhost:9071/download returns the NotFoundError page, matching the existing tested behavior.
Before
After
🤖 Generated with Claude Code