Skip to content

feat: add <Placeholder> component with ASCII bird states#5949

Merged
boojack merged 12 commits into
mainfrom
feat/placeholder-component
May 12, 2026
Merged

feat: add <Placeholder> component with ASCII bird states#5949
boojack merged 12 commits into
mainfrom
feat/placeholder-component

Conversation

@boojack

@boojack boojack commented May 12, 2026

Copy link
Copy Markdown
Member

Summary

  • Adds a new <Placeholder variant="empty | loading | noResults | notFound"> component that renders a hand-curated ASCII bird from a pool-shaped data file, with subtle CSS-only motion that respects prefers-reduced-motion.
  • Replaces the single-purpose Empty.tsx everywhere it was used (Inboxes.tsx, PagedMemoList.tsx) with <Placeholder variant="empty">.
  • ASCII art is from Joan Stark's (jgs) classic collection — attribution lives in a co-located CREDITS.md and on each AsciiPiece.credit field (not rendered in the UI).
  • Only the empty variant is wired up in this PR — the other three variants ship as a reusable surface for future PRs to consume.

Architecture

web/src/components/Placeholder/
  index.tsx              # the <Placeholder> component (default export)
  Placeholder.css        # keyframes + .placeholder-motion-* classes
  ascii-pool.ts          # AsciiPiece type, ASCII_POOL array, pickPiece()
  messages.ts            # DEFAULT_MESSAGES map (i18n-ready seam)
  CREDITS.md             # Joan Stark attribution + link to oldcompcz/jgs

The pool is variant-tagged and extensible: future PRs can drop additional entries into ASCII_POOL without touching the component. pickPiece(variant) returns a random matching entry on mount.

Out of scope (follow-up opportunities)

  • Wire <Placeholder variant="noResults"> into the memo search results page.
  • Wire <Placeholder variant="notFound"> into the router 404 catch-all.
  • Wire <Placeholder variant="loading"> into Suspense fallbacks.
  • Seed additional ASCII pieces per variant — the pool architecture supports it; just append entries to ASCII_POOL.

Test plan

  • pnpm lint clean
  • pnpm test green (17 new assertions across placeholder-pool + placeholder-component suites, 94 total)
  • pnpm build succeeds
  • Inbox empty state shows the ASCII parrot, bobs gently, and renders the filter-specific message
  • Home / memo list empty state shows the same parrot placeholder
  • prefers-reduced-motion: reduce produces a static bird

🤖 Generated with Claude Code

@boojack boojack requested a review from a team as a code owner May 12, 2026 14:47
@boojack boojack merged commit 8c16ffa into main May 12, 2026
2 checks passed
@boojack boojack deleted the feat/placeholder-component branch May 12, 2026 14:48
@coderabbitai

coderabbitai Bot commented May 12, 2026

Copy link
Copy Markdown
Contributor

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 603cb536-0d40-48a7-88cb-4250d193e4ae

📥 Commits

Reviewing files that changed from the base of the PR and between f1e2a06 and 01d6a9b.

📒 Files selected for processing (12)
  • docs/superpowers/plans/2026-05-12-placeholder-component.md
  • docs/superpowers/specs/2026-05-12-placeholder-component-design.md
  • web/src/components/Empty.tsx
  • web/src/components/PagedMemoList/PagedMemoList.tsx
  • web/src/components/Placeholder/CREDITS.md
  • web/src/components/Placeholder/Placeholder.css
  • web/src/components/Placeholder/ascii-pool.ts
  • web/src/components/Placeholder/index.tsx
  • web/src/components/Placeholder/messages.ts
  • web/src/pages/Inboxes.tsx
  • web/tests/placeholder-component.test.tsx
  • web/tests/placeholder-pool.test.ts

📝 Walkthrough

Walkthrough

This PR introduces a new Placeholder React component to replace the existing Empty component. The component features variant-driven ASCII art selection from a pool, CSS animations with accessibility support, and integration across page components. Includes design specs, planning docs, and comprehensive tests.

Changes

Placeholder Component Implementation

Layer / File(s) Summary
ASCII pool and variant types
web/src/components/Placeholder/ascii-pool.ts, web/tests/placeholder-pool.test.ts
Defines PlaceholderVariant ("empty" | "loading" | "noResults" | "notFound"), MotionStyle ("bob" | "flutter" | "none"), and AsciiPiece shape. Exports ASCII_POOL seeded with artist-credited pieces per variant and pickPiece(variant) selector. Tests validate pool integrity (per-variant coverage, unique IDs, credit attribution, valid motion types).
Default messages and animations
web/src/components/Placeholder/messages.ts, web/src/components/Placeholder/Placeholder.css
Introduces DEFAULT_MESSAGES mapping each variant to a default UI string with an i18n seam comment. Adds CSS keyframes for "bob" and "flutter" animations guarded by prefers-reduced-motion: no-preference media query.
Placeholder component
web/src/components/Placeholder/index.tsx, web/tests/placeholder-component.test.tsx
Implements the default-exported Placeholder component: selects a memoized ASCII piece per variant, resolves message from prop or defaults, renders centered layout with ASCII art (decorated <pre aria-hidden>), message text, and optional children. Sets role="status" and aria-live="polite" only when variant="loading". Motion class applied via MOTION_CLASS map. Tests cover variant rendering, custom messages, ASCII presence, aria attributes, and className merging.
Integration and deletion
web/src/pages/Inboxes.tsx, web/src/components/PagedMemoList/PagedMemoList.tsx, web/src/components/Empty.tsx (deleted), web/src/components/Placeholder/CREDITS.md
Replaces Empty with Placeholder variant="empty" in both Inboxes.tsx and PagedMemoList.tsx. Removes the now-unused Empty.tsx file. Adds CREDITS.md with attribution links and pool-extension guidelines acknowledging Joan Stark's ASCII art source.
Design specification and planning
docs/superpowers/specs/2026-05-12-placeholder-component-design.md, docs/superpowers/plans/2026-05-12-placeholder-component.md
Specifies the public <Placeholder> API, pool/message/animation architecture, file layout, accessibility contract, and testing strategy. Planning doc outlines step-by-step TDD workflow, ASCII seeding, CSS/messaging/component/integration tasks, verification steps, and self-review checklist.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

dgalanberasaluce pushed a commit to dgalanberasaluce/infra-personal that referenced this pull request Jun 13, 2026
This PR contains the following updates:

| Package | Update | Change |
|---|---|---|
| [neosmemo/memos](https://github.com/usememos/memos) | minor | `0.28.0` → `0.29.0` |

---

### Release Notes

<details>
<summary>usememos/memos (neosmemo/memos)</summary>

### [`v0.29.0`](https://github.com/usememos/memos/blob/HEAD/CHANGELOG.md#0290-2026-05-27)

[Compare Source](usememos/memos@v0.28.0...v0.29.0)

##### Features

- **about:** add about page with bird sprites ([411ba7b](usememos/memos@411ba7b))
- **activity-calendar:** aggregate by ViewContext.timeBasis ([8daef1d](usememos/memos@8daef1d))
- add \<Placeholder> component with ASCII bird states ([#&#8203;5949](usememos/memos#5949)) ([8c16ffa](usememos/memos@8c16ffa))
- add configurable `--log-level` flag ([#&#8203;5934](usememos/memos#5934)) ([f1e2a06](usememos/memos@f1e2a06))
- add dedicated shortcuts page ([#&#8203;5942](usememos/memos#5942)) ([1df6479](usememos/memos@1df6479))
- add link metadata endpoints ([9c5c604](usememos/memos@9c5c604))
- **frontend:** add pixel bird tilemaps ([cf55f11](usememos/memos@cf55f11))
- **memo:** add task list quick actions ([#&#8203;5983](usememos/memos#5983)) ([648b3bd](usememos/memos@648b3bd))
- **memo:** create memos on the selected calendar date ([#&#8203;5925](usememos/memos#5925)) ([ef55013](usememos/memos@ef55013))
- **notification:** add smtp email settings ([cd4f28a](usememos/memos@cd4f28a))
- **placeholder:** add woodpecker tilemap ([638e4f3](usememos/memos@638e4f3))
- render link metadata cards ([0bc5669](usememos/memos@0bc5669))
- **stats:** admin instance resource statistics ([ea0625d](usememos/memos@ea0625d))
- **stats:** support filtered all-user stats ([88ac3ec](usememos/memos@88ac3ec))
- **transcription:** explicit STT settings with provider, model, prompt ([#&#8203;5926](usememos/memos#5926)) ([238f27d](usememos/memos@238f27d))

##### Bug Fixes

- avoid update event on memo create attachments ([#&#8203;5961](usememos/memos#5961)) ([3c3382a](usememos/memos@3c3382a))
- delete user cleanup ([#&#8203;5981](usememos/memos#5981)) ([e53b7d9](usememos/memos@e53b7d9))
- **editor:** wrap selected text when pasting URL ([e0bb3a2](usememos/memos@e0bb3a2))
- **fileserver:** preserve HDR image metadata in thumbnails ([c724232](usememos/memos@c724232))
- **frontend:** correct static cache headers ([084f40b](usememos/memos@084f40b))
- **frontend:** use correct url path for memos in sitemap.xml ([#&#8203;5921](usememos/memos#5921)) ([603781f](usememos/memos@603781f))
- **httpgetter:** prevent DNS rebinding in link metadata fetch ([078488c](usememos/memos@078488c))
- **markdown:** align list items with checkboxes ([e008b1a](usememos/memos@e008b1a))
- **memo:** enforce parent visibility for comments ([4a1e401](usememos/memos@4a1e401))
- **s3presign:** preserve motion media payload ([7f1f53f](usememos/memos@7f1f53f))
- **security:** enforce attachment ownership on memo updates ([35bf761](usememos/memos@35bf761))
- **sse:** stream initial response and refresh tokens ([21303e8](usememos/memos@21303e8))
- **user:** omit internal settings from list responses ([#&#8203;5917](usememos/memos#5917)) ([1df3fe7](usememos/memos@1df3fe7))
- **web:** sync avatar changes immediately after profile update ([#&#8203;5903](usememos/memos#5903)) ([328396a](usememos/memos@328396a))

##### Performance Improvements

- lazy load heavy first-screen dependencies ([#&#8203;5947](usememos/memos#5947)) ([a6024ee](usememos/memos@a6024ee))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0My43My4yIiwidXBkYXRlZEluVmVyIjoiNDMuNzMuMiIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOlsicmVub3ZhdGUiXX0=-->

Reviewed-on: https://forgejo.internal/forgejo_admin/infra-personal/pulls/96
Co-authored-by: Renovate Bot <renovatebot@forgejo.internal>
Co-committed-by: Renovate Bot <renovatebot@forgejo.internal>
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