Skip to content

feat: #102 — chore(storybook-screenshots): refresh baseline + investigate duplicate-baseline stories#111

Open
luandro wants to merge 3 commits into
mainfrom
agent/comapeo-cloud-app/issue-102
Open

feat: #102 — chore(storybook-screenshots): refresh baseline + investigate duplicate-baseline stories#111
luandro wants to merge 3 commits into
mainfrom
agent/comapeo-cloud-app/issue-102

Conversation

@luandro

@luandro luandro commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Automated implementation of #102.

Closes #102


Implemented by the agent implementation worker.

Greptile Summary

This PR refreshes Storybook screenshot baselines and resolves duplicate-baseline stories by making previously invisible UI states (popovers, tooltips, toasts) visible in static screenshots without user interaction.

  • BasemapSwitcher: A defaultOpen prop (following React's uncontrolled-input naming convention) is added so the SatelliteSelected story can force the popover open, making the two stories visually distinct.
  • Tooltips / Toasts: Tooltip stories pass open: true (Radix UI controlled prop) and toast stories use a useEffect-based autoTrigger that fires addToast once on mount; addToast is already useCallback-memoized with [] deps, so no duplicate toasts are created.
  • CopyButton / Skeleton: CopyButtonWithLabel render helper is extracted to display the copied text above the button, and Skeleton args are moved from meta-level to the Default story so each story can specify its own dimensions independently.

Confidence Score: 5/5

Safe to merge — all changes are scoped to Storybook stories and screenshot baselines, with a minimal, convention-correct addition to BasemapSwitcher props.

The logic changes are limited to stories and test infrastructure. The one production-component change (defaultOpen on BasemapSwitcher) follows the standard React uncontrolled-input naming convention, initialises state correctly, and has no effect on existing callers that omit the prop.

No files require special attention.

Important Files Changed

Filename Overview
src/components/shared/MapContainer/BasemapSwitcher.tsx Adds defaultOpen prop (follows React uncontrolled-input convention) to allow Storybook stories to force the popover open for static screenshots; initializes useState(defaultOpen) correctly.
src/components/ui/toast.stories.tsx Adds autoTrigger prop that fires addToast in a useEffect on mount; addToast is useCallback-memoized with [] deps, so the effect fires exactly once and no duplicate toasts are created.
src/components/ui/tooltip.stories.tsx Passes open: true to all Tooltip stories so tooltips are visible in static screenshots; uses the Radix UI controlled open prop correctly.
src/components/shared/copy-button.stories.tsx Extracts a shared CopyButtonWithLabel render helper and wires it to all three stories, making the displayed text visible above the button for differentiated screenshots.
tests/e2e/storybook-screenshots-diff/.gitignore Widens the ignore pattern from *.png to *, preventing any CI-generated artifact from accidentally being committed to the diff directory.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[Storybook Screenshot CI] --> B{Story has\ninteractive UI?}
    B -- No --> C[Screenshot captured\nas-is]
    B -- Yes --> D{Fix strategy}
    D --> E[Tooltip\nopen: true\nRadix controlled prop]
    D --> F[Toast\nautoTrigger useEffect\nfires addToast on mount]
    D --> G[BasemapSwitcher\ndefaultOpen prop\ninitialises useState]
    E --> H[Visible in\nstatic screenshot]
    F --> H
    G --> H
    H --> I[Unique baseline\nper story]
Loading

Comments Outside Diff (1)

  1. tests/e2e/storybook-screenshots-diff/.gitignore

    P2 Diff screenshots now tracked by git

    Deleting this .gitignore allows pixelmatch diff images to be committed, and one already is (desktop/components-mapcontainer--non-interactive.png). Diff images are CI-generated artifacts that go stale immediately after the next screenshot run, so tracking them in the repo will silently accumulate dead-weight binaries every time any baseline changes. If the intent is to make a single diff available for review, linking the CI artifact in the PR description achieves the same goal without touching the repo's history.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: tests/e2e/storybook-screenshots-diff/.gitignore
    Line: 1-2
    
    Comment:
    **Diff screenshots now tracked by git**
    
    Deleting this `.gitignore` allows pixelmatch diff images to be committed, and one already is (`desktop/components-mapcontainer--non-interactive.png`). Diff images are CI-generated artifacts that go stale immediately after the next screenshot run, so tracking them in the repo will silently accumulate dead-weight binaries every time any baseline changes. If the intent is to make a single diff available for review, linking the CI artifact in the PR description achieves the same goal without touching the repo's history.
    
    How can I resolve this? If you propose a fix, please make it concise.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Reviews (3): Last reviewed commit: "chore: update storybook screenshot basel..." | Re-trigger Greptile

@socket-security

socket-security Bot commented Jun 9, 2026

Copy link
Copy Markdown

No dependency changes detected. Learn more about Socket for GitHub.

👍 No dependency changes detected in pull request

Comment on lines 42 to 132
/** Default copy button with a URL displayed above */
export const Default: Story = {
args: {
text: 'https://example.com/invite/abc123',
},
render: (args) => (
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: 8,
alignItems: 'center',
}}
>
<code
style={{
fontSize: 13,
color: '#172033',
background: '#F4F6FA',
padding: '4px 8px',
borderRadius: 6,
}}
>
{args.text}
</code>
<CopyButton {...args} />
</div>
),
};

/** Short text content */
/** Short text content displayed above */
export const ShortText: Story = {
args: {
text: 'abc',
},
render: (args) => (
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: 8,
alignItems: 'center',
}}
>
<code
style={{
fontSize: 13,
color: '#172033',
background: '#F4F6FA',
padding: '4px 8px',
borderRadius: 6,
}}
>
{args.text}
</code>
<CopyButton {...args} />
</div>
),
};

/** Custom label and success label */
/** Custom label and success label displayed with URL */
export const CustomLabels: Story = {
args: {
text: 'https://example.com/invite/abc123',
label: 'Copy link',
successLabel: 'Link copied!',
},
render: (args) => (
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: 8,
alignItems: 'center',
}}
>
<code
style={{
fontSize: 13,
color: '#172033',
background: '#F4F6FA',
padding: '4px 8px',
borderRadius: 6,
}}
>
{args.text}
</code>
<CopyButton {...args} />
</div>
),
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 The three stories share identical wrapper markup. Extracting it into a local render helper cuts ~45 duplicate lines and makes per-story changes (e.g. different padding, dark background) trivial to apply consistently.

Suggested change
/** Default copy button with a URL displayed above */
export const Default: Story = {
args: {
text: 'https://example.com/invite/abc123',
},
render: (args) => (
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: 8,
alignItems: 'center',
}}
>
<code
style={{
fontSize: 13,
color: '#172033',
background: '#F4F6FA',
padding: '4px 8px',
borderRadius: 6,
}}
>
{args.text}
</code>
<CopyButton {...args} />
</div>
),
};
/** Short text content */
/** Short text content displayed above */
export const ShortText: Story = {
args: {
text: 'abc',
},
render: (args) => (
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: 8,
alignItems: 'center',
}}
>
<code
style={{
fontSize: 13,
color: '#172033',
background: '#F4F6FA',
padding: '4px 8px',
borderRadius: 6,
}}
>
{args.text}
</code>
<CopyButton {...args} />
</div>
),
};
/** Custom label and success label */
/** Custom label and success label displayed with URL */
export const CustomLabels: Story = {
args: {
text: 'https://example.com/invite/abc123',
label: 'Copy link',
successLabel: 'Link copied!',
},
render: (args) => (
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: 8,
alignItems: 'center',
}}
>
<code
style={{
fontSize: 13,
color: '#172033',
background: '#F4F6FA',
padding: '4px 8px',
borderRadius: 6,
}}
>
{args.text}
</code>
<CopyButton {...args} />
</div>
),
};
function CopyButtonWithLabel(args: React.ComponentPropsWithoutRef<typeof CopyButton>) {
return (
<div
style={{
display: 'flex',
flexDirection: 'column',
gap: 8,
alignItems: 'center',
}}
>
<code
style={{
fontSize: 13,
color: '#172033',
background: '#F4F6FA',
padding: '4px 8px',
borderRadius: 6,
}}
>
{args.text}
</code>
<CopyButton {...args} />
</div>
);
}
/** Default copy button with a URL displayed above */
export const Default: Story = {
args: {
text: 'https://example.com/invite/abc123',
},
render: (args) => <CopyButtonWithLabel {...args} />,
};
/** Short text content displayed above */
export const ShortText: Story = {
args: {
text: 'abc',
},
render: (args) => <CopyButtonWithLabel {...args} />,
};
/** Custom label and success label displayed with URL */
export const CustomLabels: Story = {
args: {
text: 'https://example.com/invite/abc123',
label: 'Copy link',
successLabel: 'Link copied!',
},
render: (args) => <CopyButtonWithLabel {...args} />,
};
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/components/shared/copy-button.stories.tsx
Line: 42-132

Comment:
The three stories share identical wrapper markup. Extracting it into a local render helper cuts ~45 duplicate lines and makes per-story changes (e.g. different padding, dark background) trivial to apply consistently.

```suggestion
function CopyButtonWithLabel(args: React.ComponentPropsWithoutRef<typeof CopyButton>) {
  return (
    <div
      style={{
        display: 'flex',
        flexDirection: 'column',
        gap: 8,
        alignItems: 'center',
      }}
    >
      <code
        style={{
          fontSize: 13,
          color: '#172033',
          background: '#F4F6FA',
          padding: '4px 8px',
          borderRadius: 6,
        }}
      >
        {args.text}
      </code>
      <CopyButton {...args} />
    </div>
  );
}

/** Default copy button with a URL displayed above */
export const Default: Story = {
  args: {
    text: 'https://example.com/invite/abc123',
  },
  render: (args) => <CopyButtonWithLabel {...args} />,
};

/** Short text content displayed above */
export const ShortText: Story = {
  args: {
    text: 'abc',
  },
  render: (args) => <CopyButtonWithLabel {...args} />,
};

/** Custom label and success label displayed with URL */
export const CustomLabels: Story = {
  args: {
    text: 'https://example.com/invite/abc123',
    label: 'Copy link',
    successLabel: 'Link copied!',
  },
  render: (args) => <CopyButtonWithLabel {...args} />,
};
```

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Addressed P2 — Copy-button wrapper duplication. Extracted 3 duplicate wrappers into a shared CopyButtonWithLabel render helper.

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

Preview deployment ready: https://agent-comapeo-cloud-app-issu-7fbi.comapeo-cloud-app.pages.dev

Commit: fb6dbbd

- Extract shared CopyButtonWithLabel wrapper in copy-button.stories.tsx
- Restore .gitignore for storybook-screenshots-diff (prevent tracking diff PNGs)
- Remove committed diff PNG artifact
@luandro

luandro commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

Addressed all review feedback:\n\n1. copy-button shared wrapper — Extracted duplicate wrapper markup into a shared CopyButtonWithLabel render helper. Three stories now call the same function.\n\n2. Diff .gitignore restored — Re-created tests/e2e/storybook-screenshots-diff/.gitignore with * so diff PNGs are not tracked in git. Removed the previously committed diff artifact.\n\n🔁 Requesting a fresh review.

@luandro

luandro commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

Updated screenshot baselines to match CI environment:

  • Regenerated storybook screenshot baselines (mapcontainer diff was 23% vs 15% tolerance — baseline now matches CI rendering environment)
  • All viewports match baseline ✅

@luandro

luandro commented Jun 9, 2026

Copy link
Copy Markdown
Contributor Author

CI is fully green! All checks passed including visual-regression, storybook tests, lint, typecheck, unit tests, and E2E tests.

Changes in this PR:

  1. Extracted duplicate copy-button wrappers into shared CopyButtonWithLabel render helper (addressed Greptile P2)
  2. Restored tests/e2e/storybook-screenshots-diff/.gitignore to prevent tracking diff PNGs
  3. Regenerated storybook screenshot baselines to match CI rendering environment

🔁 Loop 2 — Requesting a fresh review. All previous feedback has been addressed and CI is green.

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.

chore(storybook-screenshots): refresh baseline + investigate duplicate-baseline stories

1 participant