Skip to content

Mobile: Long-term and Short-term memory tables have huge rows — content column needs truncation and/or detail modal #285

Description

@kindralai

Problem

On mobile, the Long-term and Short-term memory tables are nearly unusable. The Content column renders the full text of every memory entry inline with break-all, and memories are often full sentences or paragraphs. This makes every row disproportionately tall — a single memory can take up the whole screen, and with 25 entries per page you have to scroll endlessly past walls of text.

The same problem exists on the Short-term tab.

Current markup

<td class="text-xs break-all">
  <span x-show="!editing">{{ m.content }}</span>
</td>

break-all forces word-break at every character, and there is no truncation, max-height, or max-width. On a ~375px mobile screen the content column is maybe 200px wide — a 300-character memory wraps into 10+ lines.

Proposed solution

A layered approach that works from the simplest fix to the richest interaction:

Layer 1 — Truncate content by default (minimum viable)

Add truncate (Tailwind's single-line ellipsis) to the content cell. The user sees the first line with and the row stays compact.

<td class="text-xs truncate max-w-0">
  <span class="truncate block">{{ m.content }}</span>
</td>

max-w-0 with truncate forces the cell to shrink-to-fit within the table. This alone fixes the giant-row problem in one CSS change.

Layer 2 — Inline expand/collapse

Add an Alpine toggle so tapping the content reveals the full text in-place without leaving the table:

<td class="text-xs" x-data="{ expanded: false }">
  <span x-show="!expanded" class="truncate block cursor-pointer"
        @click="expanded = true">{{ m.content }}</span>
  <span x-show="expanded" class="cursor-pointer"
        @click="expanded = false">{{ m.content }}</span>
</td>

The hints there's more; tapping shows it all; tapping again collapses. Works on both desktop and mobile with zero JS overhead.

Layer 3 — Detail modal (best for mobile)

On small screens, replace the expandable inline text with a tap-to-open modal. When the user taps a memory row (or a dedicated "view" button), a full-screen modal/drawer slides up showing:

  • Content (full, readable text, no truncation)
  • Metadata: Category, Subject, Scope, ID, Importance, Last accessed, Created
  • Actions: Edit and Delete buttons (the same inline edit form works inside the modal)
  • Close: Tap the backdrop or a close button

The modal uses Alpine.js x-data/x-show and a simple overlay:

<!-- In each row -->
<button class="btn btn-sm" @click="$dispatch('open-memory', { id: {{ m.id }}, ... })">view</button>

<!-- Modal (outside the table, rendered once) -->
<div x-data="memoryModal()"
     x-on:open-memory.window="open($event.detail)"
     x-show="isOpen"
     class="fixed inset-0 z-50 ...">
  ...
</div>

The modal loads memory data from a data-* attribute or via a lightweight HTMX fetch (hx-get="/partials/memory/detail/{{ m.id }}").

Layer 4 (stretch) — Card layout on mobile

On very small screens (< 640px), switch from a table to a card list using Tailwind's responsive utilities. Each card shows:

[ID] Subject
Content summary...
Category · Scope
[edit] [delete]

Cards are naturally compact and tap-friendly. The table layout stays for sm: and up.

Implementation notes

  • Layer 1 is a one-line Tailwind change (truncate + max-w-0) and can be done immediately
  • Layer 2 adds an Alpine toggle per row (negligible weight)
  • Layer 3 needs a new modal partial and HTMX endpoint for memory detail
  • Layer 4 is the most involved but replaces the table with a responsive grid

Priority order: Layer 1 → Layer 2 → Layer 3 → Layer 4. Even Layer 1 alone (truncation) would be a meaningful improvement over the current state.

Acceptance criteria

  • Layer 1: Content column truncates to single line with ellipsis (mobile + desktop)
  • Layer 2: Tapping truncated content expands it inline; tapping again collapses
  • Layer 3: Mobile detail modal shows full content + metadata + edit/delete
  • Short-term tab gets the same treatment
  • No regression on desktop — editing inline still works
  • Pagination and search unaffected
  • Layer 4 (cards on mobile): stretch goal, can be a follow-up

Metadata

Metadata

Assignees

No one assigned

    Labels

    in-progressIt means someone is working on thisnewNew addition

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions