diff --git a/docs/plans/livewire-material.md b/docs/plans/livewire-material.md new file mode 100644 index 0000000..3787b43 --- /dev/null +++ b/docs/plans/livewire-material.md @@ -0,0 +1,223 @@ +# SealShare on Livewire Material (2.0.0) + +> The package itself — its decisions, the wave plan (Phases 1–10) and its tests — moved to +> the package repo on 2026-09-13: [noNameWEB/livewire-material · docs/plans/livewire-material.md](https://gitea.nonameweb.ch/noNameWEB/livewire-material/src/branch/main/docs/plans/livewire-material.md). +> This file keeps what SealShare does once the package reaches `1.0.0`. + +## Goal + +SealShare's UI is maryUI 2.9 on daisyUI 5 — a generic web-page look. After this change it runs +on **`nonameweb/livewire-material` `^1.0`**: a clean, calm indigo Material 3 Expressive app with +a top app bar, light / dark / system theme, and two Expressive moments — the upload drop zone +and "link ready" — shipped as SealShare 2.0.0. + +## Context + +**Stacks.** SealShare: Laravel 13.31, Livewire 4.4, maryUI 2.9.10 (no prefix), daisyUI 5.7, +Tailwind 4.3, Pest 5.1, Octane on FrankenPHP, PHP 8.5; public on GitHub under MIT, image +published to `ghcr.io/surtic86/sealshare`. ReStride: same Laravel / Livewire / Tailwind / Pest, +private on `gitea.nonameweb.ch`, CI through Gitea act_runner. + +**SealShare's UI surface** (inventory, 2026-09-13): + +- maryUI tags: `button` 30, `input` 18, `password` 16, `icon` 14, `card` 9 (6 `actions` + slots), `menu`/`menu-item` 1/4 (settings nav), `theme-toggle` 3, `toggle` 2, `select` 2, + `modal` 2, `table` 1 (`:headers :rows :sort-by with-pagination`, `@scope`), `textarea` 1, + `toast` 1 (never triggered). +- Raw daisyUI: `btn` (+ `-primary/-ghost/-sm/-xs/-error/-outline/-disabled`), `alert` ×6, + `card`/`card-body` (4 admin stat tiles), `join` (2 copy fields), `progress` ×2, + `loading` ×2, `badge-success/-error`, `divider`, `link link-primary` ×5, `label`, + `file-input`, `checkbox`; tokens `bg-base-*`, `border-base-300`, `text-error/success`, + `border-primary(/50)`, `bg-primary/5`; raw `text-green-600`, `bg-white` (QR code). + Secondary text is `opacity-50/60/70`. +- 20 Heroicons (outline), through `blade-heroicons` pulled in transitively by maryUI. +- No `Mary\` PHP coupling. Admin settings flashes `session('message')` into an alert + (`AdminSettings.php:116,128,135`). 3 `wire:confirm`. +- Layouts: `layouts/app` → `app/sidebar` (centered `max-w-5xl` + footer nav), used by the + Livewire pages and all settings SFCs (`config/livewire.php:47`); `layouts/auth` → + `auth/simple`. The theme script sits *outside* `
` and hard-codes dark, while maryUI's + toggle defaults from the OS. `partials/head` loads Instrument Sans from fonts.bunny.net. +- Dead: `/dashboard` (starter placeholder, and Fortify's `home`), `welcome`, + `pages/auth/register` (still referenced by `Fortify::registerView`, + `FortifyServiceProvider.php:52`), `layouts/app/header`, `layouts/auth/{card,split}`, + `components/app-logo`, `components/desktop-user-menu`, `components/placeholder-pattern`; + the `alpinejs` npm dependency; the Flux credentials step in `tests.yml` and `docker.yml`. +- Settings `profile` and `password` show "Saved." through `components/action-message`, + listening for `profile-updated` / `password-updated`; `partials/settings-heading` uses a + daisyUI `divider`. The 3 `wire:confirm` are admin settings (remove logo, clear system + password) and admin dashboard (delete share). `AdminDashboard::headers()` exists only for + maryUI's table. +- Tests assert text only, never markup; no browser tests. +- Docker: the image's caches run in `docker/entrypoint.sh` (`config:cache`, `route:cache`, + `view:cache`); `docker/dev-entrypoint.sh` runs `npm run build` against the host's mounted + `vendor/` without a `composer install`. The Flux credentials step is in `tests.yml`, + `docker.yml` **and** `lint.yml`. +- Screens: setup, system password, upload, share created, share download, admin dashboard, + admin settings, settings (profile, password, appearance, two-factor), Fortify pages (login, + forgot, reset, 2FA challenge, confirm, verify email). Stock Laravel error pages and mails. + +**Constraints found.** + +- SealShare's `Dockerfile` builds assets (stage 1) **before** `composer install` (stage 2); + CSS imported from `vendor/` needs the order swapped. +- Laravel **replaces** the `errors` view namespace at render time with + `config('view.paths')` + `/errors` and the framework's own + (`Illuminate/Foundation/Exceptions/RegisterErrorViewPaths.php`), so error views a package + adds with `addNamespace('errors', …)` are wiped; only a path in `view.paths` survives. +- The package lives at `https://gitea.nonameweb.ch/noNameWEB/livewire-material.git` (public, + anonymous reads verified 2026-09-13). + +## Decisions + +The package's decisions are in its own plan. SealShare's: + +- **Converts after `1.0.0`, in one pass, by hand** (~150 tags; no codemod), on branch + `material`, released as **2.0.0**. +- **Moving SealShare to Gitea is a separate plan** — this plan works wherever it is hosted. +- **Seed `#4f46e5` (the favicon's indigo), Tonal Spot**; Vibrant generated alongside on the + upload page for one visual comparison before committing. +- **Theme default `system`**, storage key `sealshare-theme`, legacy `mary-theme` adopted once. + Appearance is a Light / Dark / System connected button group. +- **One top app bar everywhere** — logo and site title; a theme toggle for guests, an avatar + account menu (Upload, Admin dashboard, Admin settings, Settings, theme, Log out) for users; + centered content; Admin and Settings sub-pages as secondary tabs (menu picker on a phone); + auth pages a centered card under the same bar. No rail, no bottom bar. +- **Expressive components plus two hero moments** — an Expressive shape behind the upload icon + that morphs while files are dragged over, the wavy progress indicator for uploads, a + shape-backed check when the link is ready; admin stats count up once. Instant under + `prefers-reduced-motion`. +- **The public download page uses no anchored components** (no menus, no tooltips) — it must + work for recipients on iOS below 18.4. +- **Starter-kit cleanup during the conversion** — delete the placeholder `/dashboard`, point + Fortify `home` at the admin dashboard, delete the unused views and the `registerView` + binding, drop `alpinejs` from npm and the Flux step from CI. +- **Confirmations become M3 basic dialogs** (the 3 `wire:confirm`) — the browser's native + confirm cannot be themed and reads as a different app. *(Not asked in the interview; object + in review if you prefer the native confirm.)* +- **Save feedback becomes a snackbar** through the package's `Toasts` concern — admin + settings' flashed `session('message')` alert and settings' "Saved." `action-message` alike. + *(Follows from the snackbar; not asked separately.)* +- **The font is self-hosted** — the fonts.bunny.net request goes, which also suits a + privacy-minded self-hosted app. +- **Tests: updated feature tests, the package's guard as `DesignLanguageTest`, Livewire tests + for changed behaviour, and four browser tests** with `pestphp/pest-plugin-browser` (new dev + dependency, approved). + +## Out of scope + +- ReStride adopting the package — its own plan, after `1.0.0`. +- Moving SealShare's repository, CI and image registry to Gitea — its own plan. +- Everything the package plan puts out of scope. +- Changes to SealShare's features, routes or information architecture beyond the cleanup above. + +## Implementation steps + +Step numbers continue the original plan's, so references elsewhere stay valid. + +### Phase 11 — SealShare 2.0.0 (after `1.0.0`) + +34. **Branch** `material` from `main`; open the PR so CI runs. +35. **Dependencies.** Add the `vcs` repository and `composer require nonameweb/livewire-material:^1.0`; + `composer remove robsontenorio/mary` (drops `blade-heroicons` with it); + `npm remove daisyui alpinejs`; `composer require --dev pestphp/pest-plugin-browser`. + maryUI goes **first** because its class components would shadow the package's same-named + anonymous ones; the branch is therefore red from here until step 44, which is accepted — + it merges once, green (Decisions: one pass). +36. **CI and Docker.** Remove the Flux credentials step from `.github/workflows/tests.yml`, + `docker.yml` and `lint.yml`; install Playwright browsers in `tests.yml`. `Dockerfile`: run + the Composer stage first and `COPY --from=vendor /app/vendor ./vendor` into the Node stage + before `npm run build`. `docker/entrypoint.sh`: add `php artisan icons:cache` beside the + other caches. `docker/dev-entrypoint.sh`: run `composer install` when `vendor/` is missing, + before `npm run build`. +37. **Styles and scheme.** `resources/css/app.css`: `@import 'tailwindcss'`, the package entry + from `vendor/`, `./material-scheme.css`, `@source '../views'` and the package's views; drop + the daisyUI plugin, maryUI and pagination `@source`s and the swap safelist. + `resources/js/app.js` imports the package JS. Run + `php artisan material:scheme "#4f46e5" --variant=tonal-spot`; generate Vibrant to a + temporary output, compare on the upload page in both themes, commit the chosen one. +38. **Head and theme.** `partials/head`: remove fonts.bunny.net; include `