Skip to content

feat(Alert): improve icon handling and Storybook controls#8

Closed
garrity-miepub wants to merge 2 commits intomainfrom
feature/alerts-update
Closed

feat(Alert): improve icon handling and Storybook controls#8
garrity-miepub wants to merge 2 commits intomainfrom
feature/alerts-update

Conversation

@garrity-miepub
Copy link
Copy Markdown
Contributor

  • Use React.isValidElement() check to handle empty objects from Storybook
  • Change icon prop type from ReactNode to ReactElement for stricter typing
  • Replace inline SVG dismiss button with Lucide X icon
  • Convert stories from render functions to args pattern for working controls
  • Add Lucide icon dropdown selector in Storybook
  • Add semantic icons to variant stories (CheckCircle, AlertTriangle, etc.)
alert-component.mov

- Use React.isValidElement() check to handle empty objects from Storybook
- Change icon prop type from ReactNode to ReactElement for stricter typing
- Replace inline SVG dismiss button with Lucide X icon
- Convert stories from render functions to args pattern for working controls
- Add Lucide icon dropdown selector in Storybook
- Add semantic icons to variant stories (CheckCircle, AlertTriangle, etc.)
Copy link
Copy Markdown

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

Improves the Alert component’s icon handling and Storybook usability by tightening icon typing, switching the dismiss glyph to a Lucide icon, and updating stories to work better with controls.

Changes:

  • Add React.isValidElement() gating for icon rendering and conditional left padding.
  • Replace inline dismiss SVG with lucide-react’s X icon.
  • Convert Alert stories to args-based stories and add a selectable icon control via an icon registry.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
src/components/Alert/Alert.tsx Updates icon rendering/padding logic and swaps dismiss SVG to Lucide X.
src/components/Alert/Alert.stories.tsx Adds Lucide icon selector mapping and refactors stories to args for working controls.

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

Comment on lines 74 to 83
className={cn(
alertVariants({ variant }),
React.isValidElement(icon) && 'pl-11',
dismissible && 'pr-10',
className
)}
{...props}
>
{icon}
{React.isValidElement(icon) && icon}
<div>{children}</div>
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

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

icon is now treated as “present” whenever it’s a valid React element, but the CSS positioning rules only target direct svg children ([&>svg] / [&>svg+div]). Passing a non-SVG element (still allowed by React.ReactElement) will now add pl-11 and render the icon in normal flow (not absolutely positioned), causing misalignment compared to previous behavior (previously padding only applied when an actual svg existed). Consider either (a) constraining icon to an SVG element type, or (b) wrapping the icon in a dedicated element/class and updating selectors to target that wrapper instead of svg specifically.

Copilot uses AI. Check for mistakes.
Comment on lines +15 to +17
// Icon registry for Storybook controls
const iconRegistry: Record<string, React.ReactElement> = {
none: undefined as unknown as React.ReactElement,
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

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

This story file references the React namespace in a type (React.ReactElement) but only imports useState from react. Unless the project has global React types enabled (uncommon), this will fail typecheck. Import the React types (e.g., import type { ReactElement } from 'react' or import type * as React from 'react') and use that in the iconRegistry type.

Copilot uses AI. Check for mistakes.
Comment on lines +16 to +17
const iconRegistry: Record<string, React.ReactElement> = {
none: undefined as unknown as React.ReactElement,
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

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

iconRegistry uses none: undefined as unknown as React.ReactElement, which defeats the stricter icon typing and relies on a cast that can hide real mistakes. Prefer making the registry value type explicitly nullable/optional (e.g., Record<string, ReactElement | null> with none: null) so the Storybook mapping and Alert prop types align without unsafe assertions.

Suggested change
const iconRegistry: Record<string, React.ReactElement> = {
none: undefined as unknown as React.ReactElement,
const iconRegistry: Record<string, React.ReactElement | null> = {
none: null,

Copilot uses AI. Check for mistakes.
Comment on lines 75 to +82
alertVariants({ variant }),
React.isValidElement(icon) && 'pl-11',
dismissible && 'pr-10',
className
)}
{...props}
>
{icon}
{React.isValidElement(icon) && icon}
Copy link

Copilot AI Jan 26, 2026

Choose a reason for hiding this comment

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

React.isValidElement(icon) is evaluated twice in the same render path (for pl-11 and for conditional rendering). Consider storing it in a local const hasIcon = React.isValidElement(icon) to avoid repetition and keep the conditions in sync.

Copilot uses AI. Check for mistakes.
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages bot commented Jan 28, 2026

Deploying ui with  Cloudflare Pages  Cloudflare Pages

Latest commit: ba54213
Status: ✅  Deploy successful!
Preview URL: https://0983293c.ui-6d0.pages.dev
Branch Preview URL: https://feature-alerts-update.ui-6d0.pages.dev

View logs

garrity-miepub added a commit that referenced this pull request Mar 23, 2026
Addresses Copilot review comment on PR #145: Step 8.3 audits raw <table>
elements but the Step 10 Compliance Summary template had no corresponding
row to record that metric. Added the missing row to keep the audit
commands and report template in sync.

This is the only change from the Copilot review we accepted. Comments #1
(Step 10 intro wording) and #3 (rule #8 append vs checkbox) were reviewed
and intentionally skipped — see PR comments for rationale.
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