Skip to content

squiggles: add VS Code-style wavy error, warning and info lines with a hover message - #16

Open
ewels wants to merge 2 commits into
mainfrom
feat/squiggles
Open

ewels wants to merge 2 commits into
mainfrom
feat/squiggles

Conversation

@ewels

@ewels ewels commented Oct 13, 2026 •

Copy link
Copy Markdown
Owner

Adds a new feature, squiggles, which draws a wavy line under code as VS Code does for linter and compiler problems, with an optional message that shows on hover.

import { join } from 'node:path'; // [!warning /join/] `join` is declared but its value is never read.
// [!error /readFle/] Cannot find name `readFle`. Did you mean `readFile`?
const config = JSON.parse(await readFle('config.json', 'utf8'));

A TypeScript block with a yellow wavy line under join and a red wavy line under readFle.

  • Syntax
    • [!error /text/], [!warning /text/] and [!info /text/], with warn and note as other names, the same as line states.
    • Placed like inline callouts: at the end of the line, or on its own line above. Without /text/, the squiggle covers the line from its first character that is not a space.
    • The message is optional and can hold inline code, links and bold text. squiggles: false turns the feature off.
  • Look
    • VS Code's own 6 × 3 px squiggle SVG, used as a CSS mask so the colour is a theme variable (codeblocksSquiggles.error, .warning, .info), derived from editorError/Warning/Info.foreground with 3:1 contrast on the code and on the popover background.
    • The annotation renders in EC's latest phase, so a range across several tokens is one element and the wave runs on without breaks.
    • The hover has a severity icon and label (Error, Warning, Info), then the message. It opens above the text from its first character, and flips below or to the other side when there is no room.
  • Behaviour and accessibility
    • Hover opens the message after 300 ms, as in VS Code. Keyboard focus opens it at once, and Escape closes it (WCAG 1.4.13).
    • Every squiggle gets a hover and a tab stop, also with no message, so the severity is never carried by colour alone.
    • Screen readers read the severity and the message after the code. The copied text is unchanged. In print, the messages are a list under the block.
    • A small client module (client/squiggles.ts) loads only on blocks with squiggles. It also moves a message back inside the window when the block scrolls the text past the window edge, which position-try cannot see.
  • Not included
    • VS Code's hint severity (three faint dots), and its unnecessary and deprecated tags. These are recorded as rejected in DECISIONS.md.
  • Docs and tests
    • New docs page under Draw attention, a carousel slide, a README entry with an image, the agent skill, the EC plugins reference and the feature counts (26 to 27).
    • Vitest coverage for every severity and alias, placement, messages, warnings, print list, the feature turned off and contrast across the shared themes. Playwright coverage for keyboard, hover, Escape, phones and reduced motion.
    • The home page carousel now has 26 buttons, which cannot fill five even columns, so the carousel test no longer requires even column lengths.

🤖 Generated with Claude Code

ewels and others added 2 commits October 13, 2026 02:46
…a hover message

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

This branch has not been deployed

No deployments
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