Skip to content

Component library modularization (v0.5.0) + RichTextEditor - #21

Merged
jansaldo merged 83 commits into
mainfrom
feat/document-workflow-ui
Jul 28, 2026
Merged

Component library modularization (v0.5.0) + RichTextEditor#21
jansaldo merged 83 commits into
mainfrom
feat/document-workflow-ui

Conversation

@jansaldo

@jansaldo jansaldo commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Summary

Two independent bodies of work landed on this branch since v0.4.3:

1. Component library modularization (v0.5.0)

  • New components: AppFooter, ArchiveRow, CardTool, FeaturesMenu/FeaturesMenuItem, FileDropZone, TutorialGrid/TutorialDialog, WorkflowStepLayout, ContextMenu
  • Responsive size variants added to Dialog (sm/md/lg/full), SidePanel (sm/md/lg), ArchiveView (sm/lg + loading state + configurable selection)
  • Layout fixes: Toolbar wraps responsively (anonymizer/search-switch), AppHeader stepper stays vertically centered regardless of logo width
  • Cross-cutting margin-reset sweep (margin: "0") on bare <p>/<h*> — this package has no Panda preflight, so UA default margins were leaking through
  • Icon migration complete: phosphor-reactIcon-suffixed @phosphor-icons/react exports (verified zero remaining phosphor-react imports)

2. New RichTextEditor component

  • Built on @tiptap/react (useEditor/EditorContent), with a toolbar for bold/italic/underline, multicolor highlight, native lists (autoformat + continue-on-Enter), and table editing (context menu, resizing off)
  • Added a Markdown-import path (documentFromMarkdown) for LLM-summary ingestion, and JSONContent-based plain-text helpers (tiptap-text.ts)
  • Backed by ~1,300 lines of behavioral tests exercising real editor behavior (not mocked), including an empirical stress test proving the component recovers cleanly from a forced DOM/state mismatch
  • Net-new component — no existing consumer, so no breaking-change surface

Breaking changes for desktop-app

Verified against the current desktop-app checkout — no call sites affected:

  • ArchiveProgress drops the "replace" status and dismiss action (unused in desktop-app)
  • Dialog's default content width is now capped by size="md" (520px) instead of the old unsized 700px max (every desktop-app DialogContent already passes an explicit size)
  • SidePanel now defaults to a fixed 479px width instead of filling its parent (every desktop-app SidePanel already passes an explicit size)

Test plan

  • pnpm vitest run — 58/58 tests passing across 5 files
  • pnpm typecheck clean
  • pnpm lint (biome) clean
  • Grepped live desktop-app checkout for status="replace", bare onDismiss on ArchiveProgress, and Dialog/SidePanel usages missing an explicit size — none found
  • Follow-up (optional, not blocking): extract shared Tiptap extension config (StarterKit/Highlight/TableKit) out of RichTextEditor.tsx and markdown.ts to remove drift risk

Summary by Sourcery

Release v0.5.0 of the shared UI library with a redesigned component showcase, new workflow/layout primitives, and a RichTextEditor built on Tiptap, while finishing the icon migration and tightening visual/layout consistency across components.

New Features:

  • Introduce a Tiptap-based RichTextEditor component with formatting toolbar, table context menu, Markdown import helpers, and plain-text serialization utilities.
  • Add AppFooter, WorkflowStepLayout, PageTitle, CardTool, FeaturesMenu/FeaturesMenuItem, FileDropZone, ArchiveRow, TutorialGrid/TutorialDialog, and ContextMenu components to cover shared workflow, navigation, and tutorial patterns.
  • Expose rich-text utilities and types (JSONContent, markdown and text helpers) and new Storybook showcase stories in both Spanish and English locales.

Bug Fixes:

  • Prevent toolbar and layout overflow by making Toolbar and AppHeader responsive and ensuring the stepper and controls stay centered and wrap correctly.
  • Eliminate UA-default margins on paragraphs and headings in multiple components to align with the design system’s spacing tokens and avoid layout glitches.
  • Fix the CheckCircle icon to match the Figma reference (solid stroke with checkmark) instead of the previous gradient-only ring.

Enhancements:

  • Add size variants to DialogContent (sm/md/lg/full) and SidePanel (sm/md/lg) with viewport-aware widths and intrinsic widths matching real product usage.
  • Extend Select with descriptions, clearable selection, improved internal value handling, and tooltipped options while keeping it compatible with ref-based forms.
  • Generalize ArchiveView with size variants, a loading preview type, configurable selectability, and a large-preview mode designed to pair with ArchiveRow.
  • Refine Callout, Popover, Card, Search, TextField, Player, ToolButton, AvatarPill, ArchiveTabs, TranscriptBlock, and Logo behaviors and styling for better accessibility, clarity, and consistency.
  • Rebuild the Storybook Showcase page into a responsive, token-based gallery that demonstrates real workflows, localized copy, and all new components in context.

Build:

  • Bump the package version to 0.5.0 and add a Vitest+Testing Library setup (with jsdom) to the build tooling.
  • Update Vite externals to depend on @phosphor-icons/react instead of phosphor-react.

Tests:

  • Add extensive behavioral tests for RichTextEditor, including formatting, list behavior, table context menu actions, clipboard integration, and error-boundary resilience.
  • Add unit tests for ToolButton accessibility behavior and rich-text plain-text/markdown helpers, plus a jsdom smoke test for the Vitest setup.

Chores:

  • Complete the icon migration from phosphor-react to @phosphor-icons/react across components and stories and adjust design tokens (borders, shadows) to match current Figma references.

jansaldo and others added 30 commits July 21, 2026 11:00
Search+Switch capped the search input at a fixed 711.5px and disallowed
wrapping, so the Modo Edición switch overflowed the bar on narrow
viewports. Mirrors the anonimizador fix: the search input now shrinks to
a 320px floor and grows up to the 711.5px Figma reference as a max-width,
and the row wraps the switch onto a second line, right-aligned, when
there isn't room.
Figma still documents a "Replace archive" status and a dismiss (X)
control on every state, but desktop-app never used either — VTT hid the
dismiss button with a CSS hack targeting aria-label='Descartar', and no
consumer ever set status="replace". Removed both from the component
(props, styles, story, Figma-state doc) so desktop-app no longer needs
the hack. "Reemplazar" stays, scoped to the real failure case: status
"error" only.
Formalizes the hand-rolled "Transcribiendo audio…" notice from
desktop-app's Voz a Texto flow as size="compact": padding/gap/icon
already matched the default size, only the radius (xs, 2px) and text
style (subtitle.sm.strong, 14px/600) differ. No dedicated Figma frame
exists for this size — spec verified pixel-for-pixel against the
existing desktop-app implementation instead.
Adds size="sm|md|lg|full" to DialogContent (default "md"). No Dialog/Modal
family exists in the Figma UI Library file, so breakpoints are lifted from
desktop-app's real per-usage overrides instead: confirmations (~420px),
forms (~520px), and the "¿Cómo funciona?" tutorial (~900-1024px via a
minWidth:900px + maxW:5xl! hack). Every size stays viewport-bound
(min(px, vw)) rather than a hard minWidth, which is what let the tutorial
dialog overflow narrow windows. max-height (90vh) + internal scroll now
apply to every size, not just the one that previously set it inline.
SidePanel had no intrinsic width (root was w:"full"), so every consumer
had to impose one itself. Adds size="sm|md|lg" (default "lg"): "lg"
(479px) matches the only width Figma documents for this component (node
40002322:53113, no size variants exist there); "sm" (360px) and "md"
(400px) formalize desktop-app's own real widths instead — the fixed
wrapper around this component in the Voz a Texto turn editor, and the
fully-custom (not yet using this component) entities panel in
Anonimizador, respectively. maxW:"full" lets it still shrink under a
narrower ancestor instead of forcing overflow.
New purely-presentational component for Dataset, Anonimizador and Voz a
Texto onboarding. No Figma frame documents it; it formalizes
desktop-app's own DropArea instead, which is already byte-identical
across all three flows (verified: only copy/icon/extensions differ per
call site — visuals, dragging and layout were already 100% shared).

Fills two real gaps DropArea never had: a disabled state (opacity: 0.5,
following Search's prev/next button convention) and :focus-visible
styling (outline + shadow, matching Button). dragging is self-managed via
the same dragenter/dragleave counter DropArea used, but accepts a
controlled override for Storybook. onDrop only ever hands back raw
File[] — extension filtering, single/multiple selection and the hidden
file input all stay in desktop-app.
- type="preview-loading": formalizes desktop-app's ad-hoc loadingPreview
  spinner box shown while a dropped file is still being parsed.
- selectable prop: replaces desktop-app's withoutSelection CSS hack
  (hiding the checkbox via `button[role='checkbox'] { display: none }`)
  with an actual prop.
- size="lg" (367x426px): the single-document preview from the redesigned
  "Anonimizador - Preview" screen (Figma node 40002579:88220) — product
  moved Dataset/Anonimizador to one document at a time, always requiring
  manual validation, instead of a batch grid. size="lg" never renders its
  own filename/error caption (no Figma type covers this combination); the
  screen pairs it with a separate ArchiveRow for that instead.

Also fixes a layout bug surfaced while verifying the new size against
Figma: the filename/error <p> elements had no margin reset, so with no
preflight they carried the browser's default UA margin on top of the
intended gap.
Icon + title + description + optional leading/trailing action slots.
Formalizes the file-info row from the single-document preview screen
(Figma node 40002579:88220 — icon, filename, "N pag. - X mb", trailing
Trash) and doubles as the row shape Voz a Texto's file list already
uses (icon/play button, name, duration, delete), so both consumers can
share one implementation. Actions are passed as fully-built elements —
this component only places them.

Also fixes the same missing margin reset bug (see previous commit) in
FileDropZone's title/description <p> elements, caught while verifying
ArchiveRow's title/description spacing against Figma.
Sweeps the rest of the library for the same bug found and fixed in
ArchiveRow/ArchiveView/FileDropZone: no preflight means any <p>/<h*>
without an explicit margin:"0" keeps the browser's UA default margin on
top of the component's intended gap.

- CardTool: title (<h2>) + description (<p>), 4px gap.
- SidePanel: card title, section headings, and the merge-conflict
  confirm dialog's title + description.
- TranscriptBlock: transcript body — visible as accumulating extra
  whitespace between every turn in a scrolling transcript.
- TextField: helper and error message text.

Verified each visually in Storybook against its previous (broken)
spacing.
No Figma frame documents this; it formalizes desktop-app's own
HowItWorks/Card (used in every pipeline's "¿Cómo funciona?" modal) —
same 200x130 image, numbered badge, and card chrome. Adds the
responsiveness the plan calls for that the original never had: two
columns by default, one column on narrow windows. No i18next — image,
alt text, title and description all come from the consumer; the step
number is derived from each step's position.
Composes TutorialGrid over DialogContent size="lg", so it inherits the
viewport-bound width that replaced desktop-app's minWidth:900px +
maxW:5xl! hack for this exact screen. Every pipeline (Dataset,
Anonimizador, Voz a Texto) can share this one dialog — only title,
steps and trigger differ per consumer.
AymurAI UI Library "bar" node 40002579:88245 (bottom bar of the
"Anonimizador - Preview" screen) — border-top, bg.secondary, 48px/24px
padding, leading/actions slots via justify-content:space-between.

leading and actions are pre-built content (desktop-app keeps BuiltBy,
since DataGénero branding belongs to the product, not the library).
Adds flexWrap + ml:"auto" on the actions slot so it stays right-aligned
even when it wraps onto its own line on narrow windows — same pattern
already used in Toolbar. mt:"auto" pushes the footer to the bottom when
it's the last child of a flex-column page wrapper (the standard
sticky-footer pattern); the library can't force this without owning the
whole page's layout.
AymurAI UI Library "Menu" node 40000732:79289 (the header's apps
dropdown) — until now fully desktop-side and inconsistent: the home
grid used CardTool (4px card / 14px icon-box radius) while the header
dropdown used a bespoke Card+local-FeatureIcon composition (16px/16px).
Neither matched Figma, which specs 8px uniformly for both.

FeaturesMenuItem: icon + label only (no description — a distinct,
smaller card than CardTool), disabled styling follows Card's convention
for the outer card and CardTool's for the icon box. `fullWidth` spans
both columns for a trailing item, e.g. desktop-app's "Configuración"
row — no Figma reference for that one, kept anyway since desktop needs
it; the item is generic enough to not care.

FeaturesMenu: just the grid chrome (bg, padding, radius, a new "menu"
shadow token pixel-matched to Figma) — children are individual
FeaturesMenuItems, wired up by the consumer (onClick/router navigation),
matching the CardTool convention of leaving navigation to desktop.
Verified it drops into a real Popover without doubling up the Popover's
own chrome (override via className/style, same technique as elsewhere
in this library).

Left out of scope per product: the mocked-up "PDF a Word" item — not a
real feature yet.
border.secondary was #EDF2F7 (near-white), but Figma's border/secondary
variable is #9F99A5. This is the border applied to TextField's typed state,
Select's dropdown panel, and Search's field/suggestion states — so a field
with a value rendered an almost-invisible border instead of the intended
medium gray. Search had already worked around it with a hardcoded
[1px_solid_#9F99A5] escape; fold that back onto the corrected token.

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

The Select was controlled purely on the `value` prop with no internal state,
so consumers that drive it through a ref/register pattern (the dataset
validation forms) could never change the selection — picking an option
reverted immediately. Manage the selection internally (seeded from `value`,
synced via effect, exposed through the ref) so it works both controlled and
ref-driven.

Also add an opt-out `clearable` control (XCircle, highlights on hover to match
the entity manager) and darken the label to text.default once a value is
present, per Figma.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
jansaldo and others added 26 commits July 23, 2026 22:20
…rd no-op highlight clicks

Empty-runs paragraphs (list-exit, all-text-deleted) now render a <br>
fallback instead of a zero-height <p>, so contentEditable can host a
caret there and native typing lands in the right paragraph. Highlight
swatch clicks with no active selection no longer flip the swatch's
active-border state when applyMark is a no-op.
Adds AppFooter, Avatar, AvatarPill, ArchiveRow, CardTool, CategoryItem,
FeaturesMenu, FeaturesMenuItem, FileDropZone, Option, PageTitle, Player,
RichTextEditor, SidePanel, TranscriptBlock, TutorialDialog, TutorialGrid,
and WorkflowStepLayout to the showcase page.
Three leftover phosphor-react references the library-wide migration missed:

- SidePanel.tsx: the vendored ArrowsMerge glyph (needed because
  phosphor-react@1.4.1 predated this icon) is now available directly from
  @phosphor-icons/react, so ArrowsMergeIcon.tsx is no longer needed.
- vite.config.ts: the Rollup external list still named the old package,
  which would have bundled @phosphor-icons/react into the library output
  instead of leaving it to the consumer.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…eEditor/EditorContent

Swaps RichTextEditor's hand-rolled Selection-API editing engine for
Tiptap's useEditor/EditorContent, and changes RichTextEditorProps'
document/onChange from the custom RichTextDocument model to Tiptap's
JSONContent. Toolbar buttons (bold/italic/underline/highlight/copy)
are temporarily wired to no-ops with TODO(Task 4/5/6) markers; the
old selection.ts/reconcile.ts modules and their tests are removed.

RichTextEditor.stories.tsx and Showcase.stories.tsx are updated to
pass JSONContent literals so the interface change type-checks.

Also pins the @tiptap/* dependency versions (added in the previous
task) to a mutually-compatible 3.28.0 set — @tiptap/core was
previously ^3.29.0 while @tiptap/react peers on an exact 3.28.0,
which caused pnpm to install two separate @tiptap/core copies and
broke useEditor's TS overloads with cross-instance type mismatches.

Also guards the editable-sync effect with an equality check:
Editor#setEditable unconditionally emits a synthetic "update" event,
so calling it unconditionally on every mount/readOnly-change (as a
literal reading of the plan's snippet would) fired a spurious
onChange with unchanged content.
… sync

setContent defaults emitUpdate to true, so the effect that syncs an
externally-changed `document` prop into Tiptap was firing onChange back
with the very content it was just given — a controlled-component
update-loop risk, and inconsistent with the already-guarded editable-sync
effect in the same file. Pass emitUpdate: false and add a regression test
proving an external document change never triggers onChange.
Toolbar Bold/Italic/Underline buttons now call editor.chain().focus()
.toggleBold/toggleItalic/toggleUnderline().run() and reflect live
active state via editor.isActive(...), forced to re-render on Tiptap's
selectionUpdate/transaction events. Highlight and Copy remain no-ops
(Tasks 5/6).
…t extension

Wires the 12 highlight swatches to editor.chain().focus().setHighlight()/
unsetHighlight(), with active-swatch border state driven by
editor.isActive("highlight", { color }). No-op if there's no active
selection. Also fixes two highlight tests that set a DOM Range/Selection
without first focusing the contentEditable root, which ProseMirror's view
requires in order to pick up the selectionchange event in jsdom.

Copy button remains a no-op TODO for Task 6.
StarterKit's bundled list extensions work fully out of the box; no
configuration or custom keydown logic needed. Adds jsdom layout-API
stubs required for reliable userEvent typing simulation into a
Tiptap-backed contentEditable.
…d-rolled parser

documentFromMarkdown() runs markdown through a headless Editor with the
same StarterKit(link:false)+Highlight(multicolor)+@tiptap/markdown schema
RichTextEditor uses, so headings/lists/marks come out shaped identically
to what live editing produces. The official @tiptap/markdown package
(Markdown extension, contentType: "markdown") satisfied every brief test
case, including malformed-emphasis and accented-Spanish-text handling, so
no fallback to marked+sanitized-HTML was needed.

Also updates the FromMarkdown story to derive its sample doc from real
markdown via the new function instead of a hand-authored JSONContent
literal.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
BREAKING CHANGE: RichTextEditor now uses Tiptap JSONContent instead of the
custom RichTextDocument model. See CHANGELOG.md for the full list of
removed/renamed exports.
It was a public export via src/utils/rich-text/model.ts (re-exported from
src/index.ts) and is now only an unexported internal helper in
tiptap-text.ts. Verified unused by desktop-app.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…s no longer load-bearing under Tiptap

The final whole-branch review flagged that EditableRecoveryBoundary's
continued necessity (it defends against a React "removeChild" crash from
native contentEditable DOM mutation desyncing React's fiber) was never
actually verified against the new Tiptap/ProseMirror engine.

Added stress tests, including one that directly rips DOM nodes out of a
live .ProseMirror element and forces a React re-render. No crash
reproduces: @tiptap/react's EditorContent renders an empty <div> with no
`children` prop, so ProseMirror owns and re-diffs the entire editor
subtree itself, outside React's reconciliation, meaning there's nothing
for a native mutation to desync from a React fiber tree anymore.

Kept the boundary in place (removal was not requested) as defense-in-depth,
with a comment documenting the empirical finding.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The option-hover tooltip and single-highlight behavior existed in
desktop-app's local select.tsx primitive but were dropped when it was
ported into this shared package. SelectOption now carries an optional
description again, wrapped item-by-item in a delayed-hover Tooltip, and
the checked item no longer competes with the hovered item for the
same highlight background.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Required by the rich-text editor's upcoming table support (RichTextEditor's markdown parser and live schema both need TableKit registered).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…embedded variant

- Register TableKit in both the live editor and the markdown-to-JSONContent
  parser, so tables round-trip through the same schema headings/lists
  already do.
- Fix multicolor highlight: Tiptap writes attrs.color straight into an
  inline style, so a `category.*` token path was invalid CSS and every
  highlight silently fell back to the UA default. Swatches and stored marks
  now use real hex values instead.
- Add heading/blockquote/hr/table typography rules that Panda's preflight
  was stripping (headings reset to inherit, lists to `list-style: none`),
  so markdown-parsed content renders with visible sizes/markers.
- Add `variant="embedded"` — renders just the formatted content with no
  toolbar/title/card chrome, for consumers that supply their own frame
  (e.g. the Resumen finish screen's read-only preview) instead of building
  a second renderer.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Resumen shipped as a real feature, so its FeaturesMenuItem in stories/showcase no longer needs `disabled`; also switches to the *Icon-suffixed phosphor imports the rest of the story files already use.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Every bare icon import (Copy, TextB, Question, CheckCircle, File, ...)
is deprecated in favor of its *Icon-suffixed canonical export. Renames
imports and JSX/prop usages across all affected components and stories;
no behavior change.
…lidate

Adds a small mustExist(value, description) helper and replaces every
`!` non-null assertion with it, so a failed lookup throws a descriptive
error instead of relying on a compile-only assertion. Fixes all 20
lint/style/noNonNullAssertion warnings pnpm validate was reporting;
no test behavior change.
TS 5.9 flags baseUrl as deprecated (removed in TS 7). With
moduleResolution "bundler", the "@/*" path mapping already resolves
relative to this config file without it.
The Tiptap migration isn't a breaking change to a shipped release —
it's still work in progress. Reverts the version to 0.5.0 and removes
the CHANGELOG entry that framed it as a breaking 1.0.0 release.
…buttons, fix list/table plain-text export

- Add a right-click context menu for tables: add/delete row, add/delete
  column, delete table — wired to @tiptap/extension-table's existing
  commands. New @radix-ui/react-context-menu dependency, wrapped as a
  ContextMenu primitive following the same pattern as Popover/Dialog.
  Only active in editable mode and while the caret is inside a table;
  otherwise the native browser context menu shows through.
- Add Bullet List / Ordered List toolbar buttons next to Bold/Italic/
  Underline, using StarterKit's already-registered toggleBulletList/
  toggleOrderedList commands.
- Fix serializeDocumentToPlainText: it only ever read a top-level block's
  *direct* text children, so bulletList/orderedList/table nodes (whose
  children are listItem/tableRow wrappers, not text) silently collapsed to
  an empty string instead of vanishing gracefully or rendering. Now
  recurses through list wrappers (each item becomes its own line) and
  renders tables as a lightweight markdown-style block (header row, `---`
  separator, pipe-separated body rows).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

@sourcery-ai sourcery-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Sorry @jansaldo, your pull request is larger than the review limit of 150000 diff characters

@sourcery-ai

sourcery-ai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Reviewer's Guide

Modularizes the component library for v0.5.0 (new layout primitives, size variants, icon migration, and archive/workflow refinements) and introduces a fully tested, Tiptap-based RichTextEditor with Markdown import, plain-text helpers, and Storybook/showcase integrations.

File-Level Changes

Change Details Files
Rebuilds the Storybook Showcase into a responsive, localized showroom that exercises all components (including new workflow, archive, chrome, and RichTextEditor primitives).
  • Replaces the old kitchen-sink Showcase with a structured, CSS/cva-based layout (sections, grids, demo cards) and adds Spanish/English localization helpers.
  • Adds new demo compositions for AppHeader/AppFooter, WorkflowStepLayout, ArchiveView/ArchiveRow, SidePanel sizes, RichTextEditor (editable/read-only), and other components.
  • Integrates new components like FeaturesMenu, CardTool, FileDropZone, TutorialGrid/Dialog, PageTitle, TranscriptBlock, and Player into the showcase.
src/showcase/Showcase.stories.tsx
.storybook/preview.ts
Adds and exports the new RichTextEditor component plus rich-text utilities, with extensive behavior tests and Storybook coverage.
  • Implements RichTextEditor on top of @tiptap/react with StarterKit, multicolor Highlight, and TableKit, including formatting toolbar, highlight palette, table context menu, title editing, copy-to-clipboard, and panel/embedded variants.
  • Adds markdown and plain-text adapters (documentFromMarkdown, documentFromPlainText, serializeDocumentToPlainText) so external summaries can be ingested and exported consistently.
  • Introduces ~1,300 lines of vitest-based tests for RichTextEditor behavior (formatting, lists, highlight palette, table menu, clipboard, recovery boundary) and text utilities, plus Storybook stories demonstrating editable, read-only, list, markdown, and layout variants.
  • Exports JSONContent and the rich-text helpers from the package index, and wires vitest/jsdom config and setup (including Tiptap-friendly DOM shims).
src/components/rich-text-editor/RichTextEditor.tsx
src/components/rich-text-editor/RichTextEditor.stories.tsx
src/components/rich-text-editor/RichTextEditor.test.tsx
src/utils/rich-text/markdown.ts
src/utils/rich-text/markdown.test.ts
src/utils/rich-text/tiptap-text.ts
src/utils/rich-text/tiptap-text.test.ts
src/utils/rich-text/setupTests.ts
src/utils/rich-text/smoke.test.ts
src/components/rich-text-editor/index.ts
vitest.config.ts
src/index.ts
Extends and refines archive and workflow-related components (ArchiveView, ArchiveProgress, ArchiveRow, SidePanel, WorkflowStepLayout, FileDropZone, Tutorial* components, PageTitle, AppFooter).
  • Adds ArchiveView size variants (sm/lg), a preview-loading state, selectable flag, and margin resets; introduces ArchiveRow and its stories; updates ArchiveView stories accordingly.
  • Simplifies ArchiveProgress states by removing the unused 'replace' status and dismiss action, updates icons, and adjusts stories to match the remaining 4-state matrix.
  • Adds FileDropZone with controllable dragging state, disabled support, and stories; creates WorkflowStepLayout, PageTitle, AppFooter, TutorialGrid/TutorialDialog components and stories for shared workflow layout and tutorials.
  • Updates SidePanel with intrinsic size variants (sm/md/lg), width behavior tweaks, margin resets, and story coverage for sizes, narrow containers, and existing behaviors.
src/components/archives/ArchiveView.tsx
src/components/archives/ArchiveView.stories.tsx
src/components/archives/ArchiveProgress.tsx
src/components/archives/ArchiveProgress.stories.tsx
src/components/archives/ArchiveRow.tsx
src/components/archives/ArchiveRow.stories.tsx
src/components/archives/index.ts
src/components/file-drop-zone/FileDropZone.tsx
src/components/file-drop-zone/FileDropZone.stories.tsx
src/components/file-drop-zone/index.ts
src/components/side-panel/SidePanel.tsx
src/components/side-panel/SidePanel.stories.tsx
src/components/workflow-step-layout/WorkflowStepLayout.tsx
src/components/workflow-step-layout/WorkflowStepLayout.stories.tsx
src/components/workflow-step-layout/index.ts
src/components/page-title/PageTitle.tsx
src/components/page-title/PageTitle.stories.tsx
src/components/page-title/index.ts
src/components/app-footer/AppFooter.tsx
src/components/app-footer/AppFooter.stories.tsx
src/components/app-footer/index.ts
src/components/tutorial/TutorialGrid.tsx
src/components/tutorial/TutorialGrid.stories.tsx
src/components/tutorial/TutorialDialog.tsx
src/components/tutorial/TutorialDialog.stories.tsx
src/components/tutorial/index.ts
Adds FeaturesMenu and ContextMenu primitives and integrates them into AppHeader and other overlays/popovers.
  • Implements FeaturesMenu and FeaturesMenuItem as a menu grid for switching between product areas, with disabled/fullWidth support and Storybook stories (including popover integration).
  • Introduces a Radix-based ContextMenu wrapper with AymurAI styling (content, item, separator) for right-click behaviors such as RichTextEditor table controls.
  • Updates AppHeader to center the Stepper via absolute positioning, supports a logoVariant prop, passes a markSlot into Logo, and documents slot behavior; adjusts stories for a home-wordmark variant.
  • Adjusts Popover to support disabling its default surface (so content can own its own bg/radius/shadow) and adds a 'NoSurface' story.
src/components/features-menu/FeaturesMenu.tsx
src/components/features-menu/FeaturesMenuItem.tsx
src/components/features-menu/FeaturesMenu.stories.tsx
src/components/features-menu/index.ts
src/components/context-menu/ContextMenu.tsx
src/components/context-menu/index.ts
src/components/app-header/AppHeader.tsx
src/components/app-header/AppHeader.stories.tsx
src/components/logo/Logo.tsx
src/components/popover/Popover.tsx
src/components/popover/Popover.stories.tsx
Adjusts existing input and surface components (Select, TextField, Dialog, Callout, Popover, Card, Toolbar, Search, Player, etc.) for new UX requirements and to fix layout/typography issues.
  • Refactors Select to be self-managed with a clearable control, tooltip-backed option descriptions, priority ordering, improved highlighting semantics, and label-color behavior; extends SelectOption to carry an optional description.
  • Moves TextField suggestion into a suffix-affix, updates typed/border/label behavior, and fixes paragraph default margins across multiple components (TextField, SidePanel, TranscriptBlock, etc.).
  • Adds size variants to DialogContent (sm/md/lg/full) with viewport-bounded widths/heights and Storybook stories; introduces Callout size='compact' and a specific Voz a Texto processing notice; updates Popover to have an optional surface layer.
  • Relaxes Toolbar layout to wrap in anonimizador/search-switch contexts instead of clipping right-side controls; tweaks Search to use border.secondary and migrate icon usage; updates Player to new icons.
  • Makes Card accept standard div HTML attributes; tweaks preset tokens (shadows, borders) to align with new card/document styles; minor story updates for Button, ButtonLink, BigIconButton, Callout, Toast, ToolButton (extra actions, tests).
src/components/select/Select.tsx
src/components/text-field/TextField.tsx
src/components/dialog/Dialog.tsx
src/components/dialog/Dialog.stories.tsx
src/components/callout/Callout.tsx
src/components/callout/Callout.stories.tsx
src/components/popover/Popover.tsx
src/components/popover/Popover.stories.tsx
src/components/card/Card.tsx
src/components/toolbar/Toolbar.tsx
src/components/search/Search.tsx
src/components/player/Player.tsx
src/components/button/Button.tsx
src/components/button/Button.stories.tsx
src/components/button-link/ButtonLink.tsx
src/components/button-link/ButtonLink.stories.tsx
src/components/big-icon-button/BigIconButton.stories.tsx
src/components/toast/Toast.tsx
src/components/toast/Toast.stories.tsx
src/components/tool-button/ToolButton.tsx
src/components/tool-button/ToolButton.stories.tsx
src/components/tool-button/ToolButton.test.tsx
src/components/transcript-block/TranscriptBlock.tsx
src/preset.ts
Migrates icons from phosphor-react to @phosphor-icons/react and cleans up related usages across the library.
  • Replaces all phosphor-react imports/usages with size-appropriate Icon-suffixed exports from @phosphor-icons/react across components and stories (Button, BigIconButton, Callout, Player, Search, Toolbar, Archive components, etc.).
  • Removes the vendored ArrowsMergeIcon in favor of the library-provided ArrowsMergeIcon, and updates SidePanel actions to use it.
  • Updates CheckCircle to match the true Figma reference (solid stroke + tick) instead of the previous custom gradient ring implementation.
package.json
vite.config.ts
src/components/app-header/AppHeader.tsx
src/components/archives/ArchiveProgress.tsx
src/components/archives/ArchiveTabs.tsx
src/components/avatar-pill/AvatarPill.tsx
src/components/big-icon-button/BigIconButton.stories.tsx
src/components/button/Button.tsx
src/components/button/Button.stories.tsx
src/components/button-link/ButtonLink.tsx
src/components/button-link/ButtonLink.stories.tsx
src/components/callout/Callout.tsx
src/components/callout/Callout.stories.tsx
src/components/check-circle/CheckCircle.tsx
src/components/checkbox/Checkbox.tsx
src/components/option/Option.tsx
src/components/player/Player.tsx
src/components/search/Search.tsx
src/components/side-panel/SidePanel.tsx
src/components/side-panel/SidePanel.stories.tsx
src/components/text-field/TextField.tsx
src/components/toast/Toast.stories.tsx
src/components/tool-button/ToolButton.tsx
src/components/transcript-block/TranscriptBlock.tsx
src/components/archives/ArchiveView.tsx
src/components/archives/ArchiveView.stories.tsx
src/components/toolbar/Toolbar.tsx
Bumps library version to 0.5.0 and wires testing/linting/tooling for the new code paths.
  • Updates package.json version to 0.5.0 and adds test script plus dependencies for Tiptap, @phosphor-icons/react, Testing Library, vitest, jsdom, and Radix context menu.
  • Adjusts tsconfig path resolution and Vite externals to account for new dependencies.
  • Ensures README documents new components (CardTool, AppHeader, AppFooter, WorkflowStepLayout, PageTitle, Archives, etc.) and their intended usage patterns.
package.json
tsconfig.json
vite.config.ts
README.md

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@jansaldo
jansaldo merged commit d56feb1 into main Jul 28, 2026
2 checks passed
@jansaldo
jansaldo deleted the feat/document-workflow-ui branch July 28, 2026 14:53
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