Skip to content

feat(site): span-driven demo blocks + fix findQuantities span anchoring - #7

Open
Aymericr wants to merge 6 commits into
mainfrom
cursor/visual-components-and-blocks-6be6
Open

Aymericr wants to merge 6 commits into
mainfrom
cursor/visual-components-and-blocks-6be6

Conversation

@Aymericr

@Aymericr Aymericr commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

What

Three docs-site demos built on lingo's spans, reworked after an adversarial review, plus one library bug the demos surfaced.

Site (apps/site)

  • Token highlighter — regexes propose slices of a sentence; parseDate / parseDateRange / parseDuration confirm each one. A color only appears where lingo actually read something; the whole-input reading (single date / range / duration / declined) is shown alongside, with lingo's own issue message when it declines.
  • Remind me popover — a Base UI Popover whose presets (tomorrow, next week, this weekend, someday) and free-text field go through the same reader. No hard-coded times: a preset row shows exactly what typing its phrase would give, or when lingo has no reading.
  • Workflow rules — automation sentences where findQuantities pulls the numeric bounds (below $10k, over 15 minutes) out with spans into the original string; entity chips are vendor-neutral and icon-labelled.
  • Token colors are --token-* OKLCH variables in globals.css with light and dark values, applied via data-token.
  • Shared lib/date-display.ts (day / clock / range / zone formatters) and ui/popover.tsx.
  • Docs page + sidebar entries under Dates & durations and One schema; landing sections.

Library (packages/lingo)

  • findQuantities returned mid-word spans for open-bound ranges and fuzzy spreads that did not start the input (call mom over 5 min[2, 19)): the qualifier branch of parseRangeOrQty passed a token index where okRange expects a normalized offset. Spans now start at the qualifier. Regression test in grammar.test.ts; CHANGELOG under [Unreleased].

Hydration fix (pre-existing, site-wide)

/docs, /forms and /escalation on production throw React #418 for any visitor whose browser zone is not UTC, and React re-renders the whole page client-side. Cause: demos hold a local wall-clock SSR_NOW through hydration, and the calendar demo's Output JSON / coverage table print UTC instants, which differ per zone. Instant-bearing text now fills in after hydration (useHydrated); wall-clock labels were already zone-stable.

Adversarial review → changes

The first version was reviewed adversarially; every finding was addressed:

  • Default readouts that showed garbage or empty placeholders (presets lingo could not parse, parseRange on full sentences) → presets are phrases lingo reads; the one deliberately declined sentence is labelled as such.
  • eight pm classified as a quantity → word-number hours handled; overlap resolution is priority → length → position instead of earliest-start-wins.
  • Dead now parameter, un-memoised new Date() in render, timezone label hydration mismatch → fixed.
  • Marketing copy and brand names (Superhuman, Linear, gpu-time, "zero-latency", "production-ready") → removed; copy describes what the code does.
  • Hand-rolled dropdown, invisible input, emoji icons, mouse-only tooltips → Base UI Select / Popover, visible Input, aria-pressed presets, Lucide icons.
  • Hard-coded hex colors → OKLCH design tokens.
  • Duplicate / inverted headings → DemoFrame everywhere; section headings are thesis-style like their neighbours.

Verification

  • bun run check (typecheck, tests, build, size budgets, corpus gates, zero-deps, docs sync, schema artifacts): green.
  • bun run lint: clean. React Doctor: no new issues on 9b1f3a9.
  • Site production build served with TZ=UTC, loaded in headless Chrome with TZ=America/Los_Angeles and Pacific/Auckland: no console errors on /, /docs, /forms, /escalation, /integrations.
  • Same check against the Vercel preview of this PR: clean; against current production lingo.pascal.app/docs: React #418.

lingo_reworked_blocks_walkthrough.mp4

Token highlighter: a sentence lingo declines whole, with the three slices it did confirm

Workflow rule: two thresholds extracted from a typed sentence

Deploy

Production deploys from main through the Vercel Git integration; merging this PR ships it.

To show artifacts inline, enable in settings.

Open in Web Open in Cursor 

…rkflow trigger blocks

Co-authored-by: Aymeric Rabot <Aymericr@users.noreply.github.com>
@vercel

vercel Bot commented Sep 11, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
lingo Ready Ready Preview Sep 13, 2026 5:39am UTC

@Aymericr
Aymericr marked this pull request as ready for review September 11, 2026 20:56
@pascal

pascal Bot commented Sep 11, 2026

Copy link
Copy Markdown

I hit an error while handling your request (Model unavailable on AI Gateway free tier: Free tier users do not have access to this model. Upgrade to paid credits at https://vercel.com/d?to=%2F%5Bteam%5D%2F%7E%2Fai%3Fmodal%3Dtop-up for unrestricted…).

Please try again, rephrase, or reach out if it keeps failing.

Error id: 56cf829b-902f-432e-a8dd-69cf6c3c82d0

@github-actions

github-actions Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

React Doctor found no new issues. 🎉

Reviewed by React Doctor for commit 9b1f3a9.

cursoragent and others added 2 commits September 13, 2026 05:01
…ntities

okRange expects a normalized offset, but the open-bound and fuzzy-spread
branches of parseRangeOrQty passed the token index. Any range that did not
start the input got a span starting at the token index instead of its source
offset ('call mom over 5 min' -> [2, 19)). Pass p.tokens[i].start, matching
buildRange.

Co-authored-by: Aymeric Rabot <Aymericr@users.noreply.github.com>
- Token highlighter: regexes only propose slices; parseDate/parseDateRange/
  parseDuration confirm each one, so a color only appears where lingo read
  something. Real priority-first overlap resolution, per-token readings,
  presets that all parse, visible Input instead of an opacity-0 overlay,
  aria-pressed preset group, zone label deferred to hydration, memoized now.
- Remind me: a real Base UI Popover (new ui/popover.tsx) with a trigger,
  presets that are phrases read through ./date (no hard-coded clocks or
  fallback times), lingo's own message on failure, Select for the condition,
  design tokens instead of hex colors, works in light mode.
- Workflow rule: editable prompt, findQuantities with span slicing, range
  min/max via format(), issues surfaced with issueClass, vendor-neutral
  entity chips with lucide icons, event-only readout when no bound.
- Shared date-display helpers; four --token-* category tints in globals.css
  (light + dark) replace hard-coded Tailwind hues.
- Copy: drop 'zero-latency', 'production-ready', brand name-drops and the
  'gpu-time' search keyword; wrap all three in DemoFrame like neighbours.

Co-authored-by: Aymeric Rabot <Aymericr@users.noreply.github.com>
The calendar, token-highlighter, and remind-me demos print parsed dates as
UTC instants in their Output JSON, and the coverage table prints them in
its value column. Their SSR reference time is a local wall clock, so the
same wall clock is a different instant on the server and in the visitor's
browser, and React 19 raised #418 and re-rendered the whole page client
side. Instant-bearing text now fills in after hydration; wall-clock labels
were already zone-stable and are unchanged.

Co-authored-by: Aymeric Rabot <Aymericr@users.noreply.github.com>
Keeps every locale-dependent formatter in one module, which is also what
React Doctor's no-locale-format-in-render check expects to see.

Co-authored-by: Aymeric Rabot <Aymericr@users.noreply.github.com>
The sub-heading repeated the demo frame's own title directly above it.
Neighbouring sections name the idea and let the frame name the widget.

Co-authored-by: Aymeric Rabot <Aymericr@users.noreply.github.com>
@cursor cursor Bot changed the title feat(site): add semantic token highlighter, remind-me popover, and workflow trigger blocks feat(site): span-driven demo blocks + fix findQuantities span anchoring Sep 13, 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.

2 participants