Skip to content

fix(editor): keep the saved-block delete confirm on one line and keyboard focus in place - #898

Merged
orkhanahmadov merged 3 commits into
mainfrom
claude/saved-block-confirm-wrap-0fb6b2
Oct 9, 2026
Merged

orkhanahmadov merged 3 commits into
mainfrom
claude/saved-block-confirm-wrap-0fb6b2

Conversation

@orkhanahmadov

Copy link
Copy Markdown
Member

Summary

This PR fixes two problems with the card actions in the saved-blocks browser, both in the card's bottom row of SavedBlocksBrowserModal.vue.

The delete confirm wrapped in crowded cards. A card's bottom row holds up to five 14px type icons, a "+N" count, the timestamp and the actions. On an entry with seven block types, the armed confirm ("Delete this saved block?") wrapped onto two lines: 108×36px instead of 21px tall. That grew the card by 20px and squeezed the icons to 11px, and de/fr/es/ca/nl/ja were worse.

whitespace-nowrap alone can't fix it. With five icons and "+2", the fixed items take 113.8px of the 242px row, and the full question needs 133–199px. So even with the timestamp at 0, the row would overflow the card by 4.9px in en and up to 70px in ja.

The confirm now shows a short label from a new key, savedBlocks.deleteConfirmShort: "Delete?" · "Löschen?" · "¿Eliminar?" · "Supprimer ?" · "Excluir?" · "Eliminar?" · "Verwijderen?" · "削除しますか?". It keeps the full question as its aria-label. That means:

  • Screen readers keep the context.
  • Tests that find the button by its exact name ("Delete this saved block?") keep working.
  • WCAG 2.5.3 (Label in Name) holds: every locale's label is part of its question, and a guard checks this per locale.

Everything in the row except the timestamp is shrink-0, so only the timestamp truncates. Its tooltip still shows the full date.

Keyboard focus fell to the page. Arming a delete, confirming it and closing an inline rename each unmounted the focused control, which dropped focus to <body>. Escape on an armed confirm closed the whole browser. Now:

  • Arming moves focus to the confirm. Escape on the confirm disarms it, returns focus to Delete and leaves the browser open.
  • After a delete, focus goes to the entry that took the deleted one's place. If there is none, it goes to the previous entry, and if the list is empty, to the search box. A failed delete returns focus to that entry's Delete.
  • Enter or Escape in a rename returns focus to Rename. A commit triggered by focus leaving the row keeps focus where the user moved it.

Mouse users see no change. Programmatic focus after a click doesn't match :focus-visible, so no ring appears (checked in light and shadow DOM).

Linked issues

n/a

Type of change

  • Bug fix (non-breaking change that fixes an issue)
  • New feature (non-breaking change that adds functionality)
  • Breaking change (fix or feature that changes existing behavior)
  • Refactor (no functional change)
  • Documentation
  • Tests / tooling / CI
  • Dependency update

Affected packages

@templatical/editor: the component and all 8 locale files. apps/playground: e2e only.

Checklist

  • Tests added or updated (and they fail without my change)
    • Unit, "delete confirm label": checks the en text and accessible name, plus label-in-name for every locale.
    • Unit, "keyboard focus": 9 tests.
    • e2e, "crowded card confirm": renders a real en card, then a per-locale fit loop that swaps in each locale's label and timestamp.
    • e2e, "keyboard focus": 2 tests using the real keyboard.
    • The crowded-card e2e failed on main (36px vs a 21px one-line height). The focus e2e failed against the first commit.
  • format:check, lint, typecheck (including the playground), build and test pass locally. All packages are green; the editor runs 3417/3417.
  • e2e: saved-blocks.spec.ts passes locally in both projects (58/58).
  • Docs: n/a. The docs only say "Delete asks for confirmation", which is still true.
  • i18n keys added to every locale file (savedBlocks.deleteConfirmShort in all 8)
  • Changesets added: two patch, one per fix
  • PR title is descriptive and follows the existing convention

Screenshots / recordings

All measurements are on a 7-type card at the browser's 300px list width:

Card (rest → armed) Confirm Icons
main, en 80 → 100px 108×36 (2 lines) 11px
main, de 80 → 100px 127×36 (2 lines) 8.7px
this PR, en/de/nl/ja 80 → 85px one line, 21px 14px

The +5px is the nudge an uncrowded card already gets when armed. The rest state is byte-identical to main (2× screenshots, light and shadow DOM).

Notes for reviewers

  • fix(editor): stop saved-block surfaces rendering with square corners #896 (radius tokens) edits other lines of the same component and the focus-ring e2e. The diffs don't overlap, so whichever PR merges second only needs to sync.
  • No native speaker has checked the ca or ja short labels.
  • On a card with five icons and a 3-digit day count, de's timestamp truncates by under 1px and nl's by about 18px. Both show an ellipsis, with the full date in the tooltip. Every other locale fits.
  • Focus is handed on once a provider call resolves. If the user tabs elsewhere while a slow remove/update is pending, focus still moves when it completes. That case is rare and not guarded.

In a crowded saved-block card (five type icons plus a "+N" count) the
full confirm question wrapped onto two lines, grew the card and squeezed
the icons, and the longer locales made it worse. The confirm now shows a
short label (savedBlocks.deleteConfirmShort) and keeps the full question
as its accessible name, and only the timestamp gives way in the row.
Arming a delete, confirming it and closing an inline rename each
unmounted the focused control, dropping focus to the page, and Escape on
an armed confirm closed the whole browser. Focus now moves to the
confirm when it appears; a delete hands it to the entry that took the
deleted one's place (else the previous one, else the search box); Enter
or Escape in a rename returns it to Rename; and Escape on the confirm
disarms back to Delete with the browser left open.
@orkhanahmadov
orkhanahmadov enabled auto-merge (squash) October 9, 2026 20:46
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Deploying templatical-docs with  Cloudflare Pages  Cloudflare Pages

Latest commit: ca7cf75
Status: ✅  Deploy successful!
Preview URL: https://ed12dc7a.templatical-docs.pages.dev
Branch Preview URL: https://claude-saved-block-confirm-w.templatical-docs.pages.dev

View logs

@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Deploying templatical-playground with  Cloudflare Pages  Cloudflare Pages

Latest commit: ca7cf75
Status: ✅  Deploy successful!
Preview URL: https://642514b9.templatical-playground.pages.dev
Branch Preview URL: https://claude-saved-block-confirm-w.templatical-playground.pages.dev

View logs

@codecov

codecov Bot commented Oct 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.87234% with 1 line in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
.../editor/src/components/SavedBlocksBrowserModal.vue 97.87% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@orkhanahmadov
orkhanahmadov merged commit 96ae215 into main Oct 9, 2026
22 checks passed
@orkhanahmadov
orkhanahmadov deleted the claude/saved-block-confirm-wrap-0fb6b2 branch October 9, 2026 21:57
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