Skip to content

feat(Chore): MisticaAI update doc to improve code generation#1552

Open
Marcosld wants to merge 1 commit into
masterfrom
WEB-2446
Open

feat(Chore): MisticaAI update doc to improve code generation#1552
Marcosld wants to merge 1 commit into
masterfrom
WEB-2446

Conversation

@Marcosld
Copy link
Copy Markdown
Contributor

@Marcosld Marcosld commented May 28, 2026

Introduction

The objective of this task was investigating if we needed new doc to cover the Inline new prop expanded. In order to do so we added some new rules to the doc and tested it against the pristine mistica version with JSDoc only.

We tested a single Figma design (iPhone 14 product detail page) 6 times: 3 runs with the MODIFIED doc folder live and 3 runs with the PRISTINE published @telefonica/mistica@16.63.1 doc folder swapped in. All 6 iterations were independent fresh claude -p --permission-mode auto --model claude-opus-4-7 processes of the same prompt — each one read the mistica-react skill, called Figma MCP on the root frame and its sub-sections, then wrote a single React component. Auto-memory was permanently deleted before the runs (a prior pass was discarded after we found the user's auto-memory already encoded the same rules — that's a confounder).

Summary

Across 6 runs on the same design, MOD docs produced consistent, idiomatic Mistica layout code; PRI docs produced inconsistent results — half the time correct, half the time the <div style={{flex:1}}> anti-pattern the new rules target. The differentiator was specifically the Inline expand API usage and the avoidance of raw flex/style fallbacks, not visual fidelity (both arms render the page faithfully).

Patterns

  • Same idiomatic Mistica components in every run. All 6 iterations independently picked up MainNavigationBar, NavigationBreadcrumbs, ResponsiveLayout, GridLayout, Slideshow, Image, Tag, Title1/4, Text2/3/7, InfoRating, RadioGroup, BoxedRow/BoxedRowList, Chip, ButtonPrimary, TextLink, MediaCard, Tabs, Accordion/AccordionItem, ProgressBar, Box, Stack, Inline, skinVars, plus the same set of icons.
  • Inline expand adoption is the cleanest discriminating signal — 3/3 MOD, 1/3 PRI. All three MOD runs used <Inline … expand={N}> for the rating-distribution rows. Only one of three PRI runs did; the other two fell back to <div style={{flex:1, …}}>/<div style={{flexGrow:1}}> nested inside an Inline — exactly the silent-no-op the new layout.md "common mistakes" call-out warns about.
  • <Box width={N}> is only triggered by the docs — 6 sites across MOD, 0 sites across PRI. Every MOD run used <Box width={80}> (or width={90}) for the fixed label column next to a ProgressBar. No PRI run used a Box width anywhere — they either inlined <div style={{width:80, flexShrink:0}}> or fell back to space="between" and let the layout breathe.
  • The model already knows expand exists (it's in dist/inline.d.ts: expand?: number | ReadonlyArray<number>, and Mistica is public on GitHub). So PRI isn't a "no knowledge" baseline — the prop is in the typed API surface. The docs aren't teaching the prop; they're putting it (and the worked example) in front of the agent during the task, which is what makes adoption reliable.

Random failures

Despite identical prompts and identical context, the iterations fail in different places:

  • "Comprados juntos" 3-card row is rendered slightly differently across runs. Layout primitive choice varies but ends up mostly correct on all 6.
  • Hero gallery: some runs picked Slideshow, one picked Carousel (per its own justification of containment). Both are valid Mistica primitives.
  • Accordion default open/closed state varies — most runs opened all three; PRI_3 left them collapsed.

Methodology

  1. Spawned 3 parallel fresh claude -p subprocesses with the MODIFIED doc folder live in node_modules/@telefonica/mistica/doc/. Each independently:
    • Read mistica-react skill and called Figma MCP on the root frame and sub-sections.
    • Wrote a single React component to its own output directory.
  2. Replaced node_modules/.../doc/ with the PRISTINE published @telefonica/mistica@16.63.1 docs. Repeated with 3 fresh subprocesses. Restored the modified docs afterwards.
  3. Each generated ProductPage.tsx was mounted in a wrapper ThemeContextProvider (Movistar New skin), built with Vite (base: './', no dev server), served on a unique localhost port, and captured by Playwright/Chromium at 1368 px wide, full page, 2× DPR.
  4. Per-run rule scan: counted <Inline, expand=, raw flex-div lines (<div … flex/flexGrow/flexShrink/flex:N), <Box width={, and inline-style layout hacks (style={{…}} excluding cursor:'pointer').

Iterations

The reference Figma is the same for all 6 runs:
https://www.figma.com/design/puOwn8pBJCrMYksvXeCiJO/AI-Test---Figma-MCP-2-code?node-id=1-67192&m=dev


Pair 1 — MOD_1 vs PRI_1

Modified docs (MOD_1) Pristine docs (PRI_1)
MOD_1 PRI_1
<Inline expand={N}> for rating rows ✓ 1 use ✓ 1 use (knew expand probably from .d.ts)
Raw <div … flex/flexGrow/flexShrink> lines 0 0
<Box width={N}> for fixed label column ✓ 2 sites 0
Inline style={{…}} 0 0
Rule score (4 signals) 4 / 4 3 / 4 (no Box width)

Net. Visual tie, both clean code-wise. PRI1 is the one PRI run that reached for expand on its own — likely from the typed API in dist/inline.d.ts. It still skipped <Box width={N}> for the fixed label column (handled the fixed width implicitly via Inline space=…), which only the docs trigger. This pair is the _best case for PRI: when the model happens to spelunk the .d.ts, it gets close to MOD.


Pair 2 — MOD_2 vs PRI_2

Modified docs (MOD_2) Pristine docs (PRI_2)
MOD_2 PRI_2
<Inline expand={N}> for rating rows ✓ 2 uses 0 — fell back to <div style={{flex:1}}> anti-pattern
Raw <div … flex/flexGrow/flexShrink> lines 0 3<div style={{width:80, flexShrink:0}}>, <div style={{flexGrow:1, minWidth:0}}>, <div style={{width:40, flexShrink:0}}> on the rating-distribution rows
<Box width={N}> for fixed label column ✓ 2 sites 0
Inline style={{…}} 0 3 — same lines as above
Rule score (4 signals) 4 / 4 0 / 4

Net. In the rating-distribution row, MOD_2 wrote <Inline … expand={1}><Box width={80}>…<ProgressBar/></Inline> and PRI_2 wrote three raw <div style={{…}}> wrappers nested inside an Inline — the canonical anti-pattern the new patterns.md DO/DON'T documents. This is the headline contrast.


Pair 3 — MOD_3 vs PRI_3

Modified docs (MOD_3) Pristine docs (PRI_3)
MOD_3 PRI_3
<Inline expand={N}> for rating rows ✓ 1 use 0 — fell back to flex divs
Raw <div … flex/flexGrow/flexShrink> lines 0 3
<Box width={N}> for fixed label column ✓ 2 sites 0
Inline style={{…}} 0 4
Rule score (4 signals) 4 / 4 0 / 4

Net. PRI_3 reached for raw flex divs and inline width styles for the rating rows; MOD_3 used the documented Inline expand + Box width pattern. Visually MOD_3 is slightly worse (its images didn't bundle)

Results

Rule-adherence at a glance

Counts across the 6 runs' main ProductPage.tsx (PRI_1 is structured as a full vite app, so its main file is at src/ProductPage.tsx):

Iteration lines <Inline expand= rawFlexDivLines <Box width={ style hacks
MOD_1 501 19 1 0 2 0
MOD_2 524 18 2 0 2 0
MOD_3 497 14 1 0 2 0
PRI_1 395 12 1 0 0 0
PRI_2 469 14 0 3 0 3
PRI_3 603 21 0 3 0 4
Rule signal MOD PRI
<Inline … expand={N}> for growing children 3/3 1/3
Avoids raw <div … flex/flexGrow/flexShrink> 3/3 1/3
Uses <Box width={N}> for fixed-width siblings 3/3 0/3
No style={{…}} layout hacks 3/3 1/3

Run metadata

run duration (min) total tokens (incl. cache)
MOD_1 18.0 7,955,293
MOD_2 11.4 5,912,631
MOD_3 11.3 6,919,185
PRI_1 12.9 6,234,771
PRI_2 8.9 2,931,614
PRI_3 10.2 4,370,949

Conclusions

  • The three new doc rules don't teach the model what expand is — it's in the typed API surface (dist/inline.d.ts), but sometimes agents don't read that files. This effect seems to be especially strong when there's doc available through a skill like in mistica.
  • Agents consistently use expand prop when doc is available (3/3 MOD vs 1/3 PRI for expand, 0 layout style hacks for MOD vs 7 for PRI), and small-to-zero on visual fidelity (both arms render the page faithfully). The benefit is code quality and maintainability, not what an end user sees.
  • <Box width={N}> is only used when documented. 6 sites across MOD, 0 across PRI. The layout.md fixed-width example is the trigger. When not documented agents tend to use divs.
  • The "read .d.ts first" rule is the structural lever. It's the one that explains why PRI_1 succeeded — the agent independently spelunked the type definitions and discovered expand. Codifying that as default behaviour (which the modified components.md does) is what would make PRI behave like MOD. Worth keeping in the docs even though we can't score it from artifacts.

@github-actions
Copy link
Copy Markdown

Size stats

master this branch diff
Total JS 16.1 MB 16.1 MB 0 B
JS without icons 2.03 MB 2.03 MB 0 B
Lib overhead 93.9 kB 93.9 kB 0 B
Lib overhead (gzip) 20 kB 20 kB 0 B

@github-actions
Copy link
Copy Markdown

Deploy preview for mistica-web ready!

Project:mistica-web
Status: ✅  Deploy successful!
Preview URL:https://mistica-mq5hk2oq5-flows-projects-65bb050e.vercel.app
Latest Commit:24a1db1

Deployed with vercel-action

@github-actions
Copy link
Copy Markdown

Accessibility report
✔️ No issues found

ℹ️ You can run this locally by executing yarn audit-accessibility.

@Marcosld Marcosld marked this pull request as ready for review May 28, 2026 14:18
Copilot AI review requested due to automatic review settings May 28, 2026 14:18
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates Mistica’s documentation (patterns/layout/components) to improve LLM-generated React code, specifically by encouraging idiomatic layout composition using Inline expand and avoiding raw flexbox/style workarounds.

Changes:

  • Added Inline expand guidance and “common mistakes” explanations to steer models away from flexbox div wrappers.
  • Documented Box width as a fixed-width sibling pattern alongside Inline expand.
  • Updated the components reference with a rule to consult .d.ts definitions before using components.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 6 comments.

File Description
doc/patterns.md Adds DO/DON’T guidance for using Inline expand instead of raw flexbox/style hacks.
doc/layout.md Expands layout docs with Box width example and a new Inline “Grow” section describing expand usage and pitfalls.
doc/components.md Adds a new rule instructing readers/agents to consult .d.ts files for prop/JSDoc context.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread doc/patterns.md

### DO: Fill remaining horizontal space with `Inline` `expand`

To make a row child grow into the leftover width next to a fixed-width sibling , use `Inline`'s `expand` prop
Comment thread doc/patterns.md
Comment on lines +116 to +120
// ❌ raw flexbox div — breaks; Inline already wraps each child in a div
<div style={{display: 'flex'}}>
<div style={{flex: 1}}>...</div>
<div style={{flex: '0 0 394px'}}>...</div>
</div>
Comment thread doc/layout.md
Comment on lines +170 to +172
### Grow

Use the `expand` prop to make one or more children of an `Inline` grow to fill the remaining horizontal space.
Comment thread doc/layout.md
Comment on lines +173 to +175
It takes the index (or an array of indexes) of the children that should grow. Indexes follow
`React.Children.toArray` order, so empty nodes (`null`, `false`) are skipped but rendered elements always
count. You don't wrap the growing child in anything — `Inline` already wraps every child in its own element:
Comment thread doc/layout.md
Comment on lines +201 to +203
`<div style={{flex: 1}}>` (or `flex-grow`) does nothing useful. Neither does `<Box style={{...}}>` — `Box` has
no `style` prop, so a flex or width passed that way is silently dropped and the row collapses or overflows its
container. Reach for `expand` (and `<Box width={N}>` for any fixed sibling) instead.
Comment thread doc/components.md
# Components Reference

All components are imported from `@telefonica/mistica`.
All components are imported from `@telefonica/mistica`. Before using any component, you should **always** read the definition .d.ts files located in `node_modules` so you have all the props and JSDoc context.
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.

3 participants