Skip to content

feat(human): animated background, responsive layout, collapsible chat panel#2957

Closed
graycyrus wants to merge 5 commits into
tinyhumansai:mainfrom
graycyrus:feat/human-page-redesign
Closed

feat(human): animated background, responsive layout, collapsible chat panel#2957
graycyrus wants to merge 5 commits into
tinyhumansai:mainfrom
graycyrus:feat/human-page-redesign

Conversation

@graycyrus
Copy link
Copy Markdown
Contributor

@graycyrus graycyrus commented May 29, 2026

Summary

Redesigns the /human page to feel alive and responsive:

  • Animated background: 3 large blurred gradient blobs with CSS @keyframes drift animations (20-30s cycles). Pure CSS, zero JS overhead. Layered behind mascot at z-0.
  • Responsive flex layout: Replaces hardcoded absolute inset-y-0 left-0 right-[436px] with a flex layout. Mascot fills available space, chat panel shrinks gracefully.
  • Collapsible chat panel: Toggle button (chat bubble icon) slides the 420px sidebar in/out with transition-transform. State persisted to localStorage. Panel header with collapse chevron.
  • Top controls in flow: Push to Talk and Send to Meeting moved from absolute positioning to a proper flex row above the content area.

Changes

File Change
app/src/features/human/HumanPage.tsx Full layout rewrite: flex structure, animated blobs, collapsible chat
app/src/features/human/HumanPage.test.tsx 7 new tests for collapsible chat panel + blob rendering
app/tailwind.config.js 3 blob drift keyframes + animation classes
app/src/lib/i18n/en.ts + 14 chunk files human.openChat, human.collapseChat keys

Test plan

  • All 16 unit tests pass (9 existing + 7 new)
  • pnpm typecheck — clean
  • pnpm lint — 0 errors
  • pnpm format:check — clean
  • pnpm build — clean
  • pnpm i18n:check — 0 missing keys across all locales
  • Visual smoke: animated blobs drift calmly, mascot stays prominent
  • Collapse/expand chat panel, verify localStorage persistence across reload
  • Resize window from >1024px to 768px — no overlap or clipping

Closes #2955

…yout, collapsible chat (tinyhumansai#2955)

- Add 3 CSS-only animated gradient blobs drifting behind the mascot
- Replace absolute positioning with flex layout for responsive behavior
- Add collapsible chat sidebar with toggle button and localStorage persistence
- Move top controls (Push to Talk, Send to Meeting) into a proper flex bar
- Add i18n keys for chat toggle across all 14 locales
- Add 7 new tests for collapsible chat panel behavior

Closes tinyhumansai#2955
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 29, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: aec941a0-270e-4d8b-af5e-98581922c2e1

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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

@sanil-23 sanil-23 self-assigned this May 29, 2026
Copy link
Copy Markdown
Contributor

@sanil-23 sanil-23 left a comment

Choose a reason for hiding this comment

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

Nice direction overall — the flex restructure is a real improvement over the absolute-positioned layout, the localStorage persistence mirrors the existing speakReplies pattern cleanly, and the test coverage on the collapse/toggle behavior is solid. A couple of things need attention before this is ready, plus a few smaller notes.

Change summary

Area Change Notes
HumanPage.tsx Flex layout, animated blobs, collapsible chat Core logic sound; collapse doesn't reclaim space (see inline)
HumanPage.test.tsx 7 new tests Good coverage, but assert on class presence, not computed layout
tailwind.config.js 3 blob keyframes Color tokens (accent-lavender, accent-mint, primary-*) all resolve
i18n (en + 14 chunks) human.openChat, human.collapseChat Keys present, but all locales got English values (see below)

Blocking

Collapsing the chat panel doesn't reclaim the space. The panel slides out via translate-x-full, but the <aside> keeps shrink-0 w-[420px] in the flex row. A CSS transform is purely visual — the layout box still reserves 420px. So when collapsed, the panel slides off-screen but leaves a 420px empty gap, and the mascot stays in its narrower flex track instead of expanding. That directly contradicts the stated goal ("Mascot fills available space, chat panel shrinks gracefully"). Details inline.

Issue alignment (#2955)

Issue #2955 specifies three breakpoints: large (>1024px) side-by-side, medium (768–1024px) slide-over, small (<768px) bottom sheet / full overlay. The implementation has no responsive variants (sm:/md:/lg:) at all — it's a single fixed layout with max-w-[90vw] on the panel. The mascot doesn't shrink on small screens and there's no bottom-sheet behavior. Since the PR is marked Closes #2955, either implement the remaining breakpoints or narrow the issue's scope so it isn't auto-closed with criteria unmet.

Minor

  • i18n placeholders: all 14 locale chunks received the literal English strings ("Open chat" / "Collapse chat"). i18n:check passes because the keys exist, but ar/bn/de/hi/ko/ru/zh-CN etc. will render English. Fine as a placeholder if intentional — worth queueing real translations so non-English users don't see untranslated UI.

Happy to re-review once the collapse layout reclaims space. The rest is close.

Comment thread app/src/features/human/HumanPage.tsx Outdated
{/* Chat sidebar — collapsible panel */}
<aside
data-testid="human-chat-panel"
className={`shrink-0 w-[420px] max-w-[90vw] flex flex-col transition-transform duration-300 ease-in-out ${
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[major] Collapsing here only applies translate-x-full, but the aside keeps shrink-0 w-[420px] in the flex row. A transform doesn't change layout flow, so the 420px is still reserved — the panel slides off-screen and leaves a dead 420px gap on the right, and the mascot's flex-1 track never grows to fill it. The collapse looks broken rather than reclaiming space.

To actually reclaim the width, collapse the box itself, e.g. animate the width:

className={`shrink-0 overflow-hidden flex flex-col transition-all duration-300 ease-in-out ${
  chatOpen ? 'w-[420px] max-w-[90vw]' : 'w-0'
}`}

(or unmount the panel / use a negative margin). The current tests pass because jsdom asserts on class presence, not computed layout, so they won't catch this.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Fixed in d698a22. The aside now animates its own box width to w-0 (with overflow-hidden) on collapse instead of translate-x-full, so the layout box no longer reserves 420px and the mascot's flex-1 track reclaims the freed space. Also took the chance to add the three #2955 breakpoints: small (<md) full-width slide-over overlay, medium (md,<lg) narrower slide-over, large (lg+) side-by-side. Tests updated to assert the width-based collapse and responsive classes.

Comment thread app/src/features/human/HumanPage.tsx Outdated
<div className="absolute inset-0 bg-stone-100 dark:bg-neutral-950 overflow-hidden flex flex-col">
{/* ── Animated background blobs (CSS-only, z-0) ── */}
<div className="pointer-events-none absolute inset-0 overflow-hidden" aria-hidden="true">
<div className="absolute -top-1/4 -left-1/4 w-[60%] h-[60%] rounded-full bg-primary-400/10 dark:bg-primary-500/[0.07] blur-3xl animate-blob-drift-1" />
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

[minor] These blobs animate infinitely (20–30s). The global prefers-reduced-motion block in app/src/index.css only covers the cmd-palette classes, so motion-sensitive users will still see all three drifting. Consider adding the animate-blob-drift-* classes to that media block, or use Tailwind's motion-reduce:animate-none variant on each blob.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Fixed in d698a22 — added motion-reduce:animate-none to all three blob divs so prefers-reduced-motion users don't see the infinite drift. New test asserts the class is present on each blob.

@sanil-23 sanil-23 assigned sanil-23 and unassigned sanil-23 May 31, 2026
sanil-23 added 2 commits May 31, 2026 19:06
Resolve i18n chunk modify/delete conflicts: main retired the chunked
locale layout (chunks/<locale>-N.ts) for flat per-locale files. Carry the
PR's two new keys (human.openChat, human.collapseChat) into the flat files
with real translations for all 13 non-English locales instead of the
English placeholders the PR had added to the deleted chunk files.
… reduced-motion

Addresses @sanil-23 review on HumanPage.tsx:

- [blocking] Collapsing the chat panel only applied translate-x-full, which
  is purely visual — the <aside> kept shrink-0 w-[420px] so the layout box
  still reserved 420px and the mascot's flex-1 track never grew. Animate the
  box width to w-0 (with overflow-hidden) instead so the panel collapses its
  own width and the mascot reclaims the freed space.
- [tinyhumansai#2955 alignment] Add the three responsive breakpoints the issue specifies:
  small (<md) full-width slide-over overlay, medium (md,<lg) narrower
  slide-over, large (lg+) side-by-side in the flex row. Below lg the panel is
  an absolute overlay so it no longer squeezes the mascot.
- [minor] Add motion-reduce:animate-none to the three background blobs so
  prefers-reduced-motion users don't see the infinite 20-30s drift.

Tests updated to assert width-based collapse (w-0) and the responsive +
reduced-motion classes instead of the removed translate-* classes.
@sanil-23
Copy link
Copy Markdown
Contributor

Pushed d698a22 addressing the review:

  • [blocking] collapse reclaims space — panel now animates its own width to w-0 (overflow-hidden) instead of a transform, so the mascot's flex-1 track expands into the freed width.
  • [Redesign Human page — animated background, responsive layout, collapsible chat panel #2955] responsive breakpoints — added all three: small (<md) full-width slide-over overlay, medium (md,<lg) narrower slide-over, large (lg+) side-by-side. Below lg the panel is an absolute overlay so it no longer squeezes the mascot.
  • [minor] reduced-motionmotion-reduce:animate-none on all three background blobs.
  • [minor] i18n placeholders — replaced the English placeholder values with real translations for all 13 non-English locales (ar, bn, de, es, fr, hi, id, it, ko, pl, pt, ru, zh-CN).

Also resolved the merge conflict against current main: main retired the chunked chunks/<locale>-N.ts i18n layout in favor of flat per-locale files, so the two new keys were carried into the flat files (with the real translations above) and the deleted chunks were dropped.

Local checks: tsc --noEmit ✓, eslint ✓, prettier ✓, HumanPage unit tests 17/17 ✓, i18n unit tests 43/43 ✓, i18n:check key parity ✓.

sanil-23 added 2 commits May 31, 2026 19:34
PR tinyhumansai#3075 changed the 'app.openhumanLink.notifications.sent' copy in en.ts
from a curly apostrophe (didn’t) to a straight one (didn't) without updating
OpenhumanLinkModal.notifications.test.tsx, leaving 2 assertions matching the
old curly form. Those tests fail on main and were pulled into this branch by
the main merge, failing the Frontend Coverage (Vitest) job — which produces no
lcov on failure — and thereby blocking the Coverage Gate.

Make the assertions apostrophe-agnostic ([' or ’]) so they match the shipped
copy and stay robust to future typography changes.
…lock

inference_provider_admin_round22_raw_coverage_e2e.rs runs its #[tokio::test]
cases on parallel libtest threads (default). Three of them mutate the same
process-global env vars (OPENHUMAN_WORKSPACE, OPENHUMAN_OLLAMA_BASE_URL) via
EnvVarGuard, so a sibling test could clobber the workspace/config path while
provider_admin_model_listing_... was between set and read — surfacing the wrong
config and flaking 'assertion failed: object_error.contains("nested provider
failure")'. This intermittently fails Rust Core Coverage (cargo-llvm-cov),
whose instrumented (slower) build widens the race window, which in turn blocks
the Coverage Gate that depends on it.

Adopt the repo's existing env_lock() pattern (channels_round26,
tools_agent_credentials_state): an OnceLock<Mutex<()>> each env-mutating test
holds for its whole body, making the set -> read -> restore cycle atomic
regardless of --test-threads. Pre-existing flake (test added in tinyhumansai#3023, pulled
in by the main merge); not introduced by this PR's frontend changes.

Verified: the file's 5 tests pass across repeated runs locally.
@sanil-23 sanil-23 removed their assignment May 31, 2026
@graycyrus graycyrus closed this Jun 2, 2026
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.

Redesign Human page — animated background, responsive layout, collapsible chat panel

2 participants