Skip to content

feat(ui): new design system — app shell and Progress screen - #61

Merged
navidshad merged 7 commits into
devfrom
new-design
Aug 27, 2026
Merged

feat(ui): new design system — app shell and Progress screen#61
navidshad merged 7 commits into
devfrom
new-design

Conversation

@navidshad

Copy link
Copy Markdown
Contributor

Promotion PR for the new-design branch, mirroring the repo's long-running dev → main PR. It is intended to stay open and accumulate the redesign as each screen lands in new-design; right now it carries the first milestone.

What's in it so far

#60 — the subturtle-ui design system, the app shell, and the Progress screen. A new ui/ package (sibling of frontend/ and server/) replaces pilotui's chrome with components built on Subturtle's real brand — rose #f91e5a, jade, Nunito, warm paper — rather than the VRISTO admin template's leftover blue. StAppShell is now the default layout; /statistic is rebuilt with populated / empty / locked / loading states. Full rationale in ui/README.md and on #60.

ci: stop auto-generating pull request descriptions. The Generate PR Description workflow ran on every opened and synchronize and replaced the PR body wholesale, so hand-written descriptions were discarded on the next push — it did exactly that to #60. It also fabricated ClickUp links from the branch name, producing dead task references. The trigger is commented out rather than the file deleted, and it has also been disabled repo-wide via gh workflow disable, which is what actually stops it: a pull_request workflow runs from the base branch's copy, so the file edit alone would not have. Re-enabling needs both.

Status

dev is currently 2 commits ahead of new-design (#59, the chunk-util refactor). Mergeability is noted below once GitHub finishes computing it; if it conflicts I'll merge dev in and resolve rather than let it drift.

pilotui is still installed and still required. Removing it is blocked on more than components: pilotui/style.css supplies global classes the app markup uses directly (panel, btn, form-input, badge, animate__*, screen_loader, main-section) across 15+ files, plus pilotui/toast (12 call sites) and useAppStore from pilotui/store (all four layouts). Un-migrated screens render inside the new shell and keep working.

Dark mode is light-only for now, by product decision — the theme switcher stays, :root.dark is scaffolded and empty, so toggling dark leaves migrated surfaces in their light palette while un-migrated pilotui pages go dark.

Still to come on this branch

The other eight designed screens (Board, Bundles, Bundle detail, Start session, Session history, Review session, Review settings, Subscription), one PR each, and the remaining library components as each screen needs them.

Convention note

CLAUDE.md now requires a ClickUp #<taskId> in commit subjects and PR titles (ea095dc). No task id was available for this work, so neither this PR nor #60 carries one — happy to amend if you have it.

🤖 Generated with Claude Code

navidshad and others added 7 commits August 27, 2026 18:35
…screen

Replaces pilotui's chrome with an in-house component library built on Subturtle's
real brand (rose #f91e5a, jade, Nunito, warm paper) rather than the VRISTO admin
template's leftover blue. First milestone: the library, the app shell, and the
Progress screen (/statistic). The remaining eight designed screens follow one per
PR; pilotui stays installed until the last usage is gone.

New ui/ package (subturtle-ui), a sibling of frontend/ and server/:
- Vite lib mode, single ESM+CJS entry, real .d.ts, one prebuilt dist/style.css,
  vue as the only peer dependency.
- Tailwind is compiled away at build time, with prefix 'st-' and preflight off.
  The library's CSS loads beside each consumer's own Tailwind build, so an
  unprefixed .rounded-lg or .bg-primary would collide and load order would decide
  styling app-wide. This also frees the library's config from having to agree with
  any consumer's, which is what lets subturtle-extension-apps adopt it unchanged.
- Design tokens keep the names used in the design source, but store colors as RGB
  channels so opacity modifiers work and a dark theme is a pure-CSS override.
  :root.dark is scaffolded and empty; the theme switcher stays, so dark currently
  leaves these components in their light palette.
- Icons are inlined from @iconify/json at build time: the design calls icons by
  runtime name, which Tailwind selectors cannot pre-generate, and the iconify-icon
  web component fetches from a CDN, which content scripts cannot rely on.
- Components: StAppShell, StSidebarNav, StButton, StIconButton, StCard, StBadge,
  StAvatar, StEmptyState, StSkeleton, StIcon, StStatTile, StBundleCard. Nav hover
  states, focus-visible rings and the collapsible rail are added rather than
  ported; the design's React sources are styled with inline style objects and
  cannot express them.

Frontend:
- StAppShell becomes the default layout. pilotui's <App> stays as the theming
  provider every un-migrated screen still reads from.
- /statistic rebuilt with populated, empty, locked and loading states. The
  week-over-week delta and streak are derived client-side from a 14-day series;
  the RPC drops interior zero-days, so the series is re-expanded against real
  dates before use. Tiles read "—" rather than 0 when the tier lock hides the
  underlying numbers.
- subturtle-ui/tailwind-tokens is spread into the app's Tailwind config so page
  markup can use the same tokens (bg-st-card, text-st-strong, rounded-st-lg).

Known gap: the streak counts days a phrase was saved, not days reviewed. It is the
closest signal available client-side; a real streak belongs on the server.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two conflicts, both where dev's work overlapped the new shell:

- useDashboardNavigatorItems.ts: kept the redesigned StNavGroup shape, but took
  dev's nav terminology for the settings entry. /settings/preferences became a
  tabbed Review + Pool page on dev, so the design's original "Review settings"
  label would now under-describe it; it uses t('preferences.nav') instead. The
  now-unused nav.review-settings locale key is dropped.

- layouts/default.vue: pilotui's DashboardShell had a dedicated #footer slot
  "right below of the content", which dev used for the global version footer.
  StAppShell has no footer slot, so PartialAppVersionFooter moves to the end of
  the content column, which renders in the same place.

Nothing dev added was dropped: of the six files both sides touched, four
auto-merged (locales, nuxt.config, package.json, yarn.lock) and dev's changes to
statistic.vue and the other rewritten files did not exist.
…brary-b74a18

feat(ui): add subturtle-ui design system, new app shell and progress screen
The workflow ran on every `opened` and `synchronize` and replaced the pull request
body wholesale, so a hand-written description was discarded on the next push. It
also fabricated ClickUp links from whatever it inferred from the branch name,
producing dead task references.

The trigger is commented out rather than the file deleted, so the setup stays
recoverable. Note that this file change alone does not stop it: a `pull_request`
workflow runs from the base branch's copy, so it has also been disabled repo-wide
(`gh workflow disable auto-pr-description.yml`). Re-enabling needs both.
Left behind when the nav conflict was resolved in favour of dev's terminology:
the sidebar entry uses t('preferences.nav') ("Study Settings"), because
/settings/preferences is now a tabbed Review + Pool page. The merge commit said
this key was dropped, but the edit was never staged.
subturtle-ui is a `link:../ui` dependency and its dist/ is gitignored, so it only
existed on the machine that built it. Everywhere else — CI, the Docker image, a
fresh clone — `subturtle-ui/style.css` resolved to nothing and `nuxt build` failed
with "Rollup failed to resolve import". This broke the E2E job and would have
broken the deploy.

- frontend postinstall now runs `build:ui`, so any `yarn install` produces a built
  library. That covers CI and fresh clones without either having to know about it.
- Dockerfile copies /ui, since the image previously only received frontend/ and
  two server modules. The path has to stay ../ui relative to WORKDIR.
- ui's `build` no longer regenerates icons. icons.generated.ts is committed, and
  @iconify/json is only needed to regenerate it, so a consumer's build no longer
  depends on that package being installed. Run `yarn icons` deliberately to add
  icons.

Verified by deleting ui/dist and running the frontend install and `yarn build`
from clean.
…ock copy

The E2E suite caught two regressions from the shell rewrite.

StAppShell had no responsive behaviour, unlike pilotui's DashboardShell which it
replaced. The sidebar sat in normal flow at a fixed 272px, so on a 375px viewport
it left the content column ~100px wide; with overflow hidden on the shell root the
column clipped its own children, which stayed in the DOM but measured as hidden.
Five Mobile Chrome specs failed on that. Below md the sidebar is now an off-canvas
drawer with a backdrop, opened from a hamburger in the topbar and closed on
navigate; the rail collapse toggle is desktop-only, and the topbar and content
gutters tighten. At md and above nothing changes.

The /statistic spec asserted the shared FeatureLocked copy ("Weekly progress
insights is part of Learner."). The redesign gives that screen its own locked panel
with the design's wording, so the assertion follows the new copy while keeping the
behavioural check that the global tier-limit modal still defers to it. /sessions
still uses the shared panel, so the two read differently until it migrates.

Full Playwright suite passes locally, 18/18 across chromium and Mobile Chrome.
@navidshad
navidshad merged commit e70d318 into dev Aug 27, 2026
5 checks passed
@navidshad navidshad mentioned this pull request Aug 27, 2026
Closed
@github-actions

Copy link
Copy Markdown

🎉 This PR is included in version 1.0.0-dev.6 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant