Skip to content

feat: Make alert icons customizable via setAlertIcons function#441

Merged
ainsleyclark merged 3 commits intomainfrom
claude/global-icon-mapping-681il
Mar 18, 2026
Merged

feat: Make alert icons customizable via setAlertIcons function#441
ainsleyclark merged 3 commits intomainfrom
claude/global-icon-mapping-681il

Conversation

@ainsleyclark
Copy link
Contributor

Summary

This PR refactors the alert icon system to support global customization, allowing consumers to override default Lucide icons with their own SVG components.

Key Changes

  • Converted alertIcons to a writable store (alertIconStore) to enable runtime customization of notification icons
  • Added setAlertIcons() function that allows consumers to globally override icon configurations for Alert and Notice components
  • Updated type exports to make NotificationType and IconDetail publicly available for type safety
  • Changed icon type from typeof IconType to Component for better flexibility with custom SVG components
  • Updated Alert and Notice components to subscribe to the alertIconStore instead of directly referencing the static object
  • Exported new API through the main components index for public consumption

Implementation Details

  • The store is initialized with default Lucide icons but can be partially or fully overridden via setAlertIcons()
  • The function uses store.update() to merge overrides with existing configuration, allowing partial updates
  • Comprehensive JSDoc documentation with usage examples included
  • All components now reactively respond to icon configuration changes through store subscription

https://claude.ai/code/session_01Am2tu2GzwFut2SBD25he1E

claude added 2 commits March 18, 2026 13:29
Introduces setAlertIcons() to allow consumers to override the default
Lucide icons with their own SVG components globally, without needing
to pass a custom icon prop on every instance.

https://claude.ai/code/session_01Am2tu2GzwFut2SBD25he1E
@claude

This comment has been minimized.

Replaces Lucide-specific typeof IconType with Svelte's Component type
to match IconDetail, resolving the type mismatch when consumers pass
custom SVG components via the icon prop.

https://claude.ai/code/session_01Am2tu2GzwFut2SBD25he1E
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ed563755d1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

* Writable store holding the active icon map for all Alert and Notice components.
* Consumers can override individual or all entries via setAlertIcons().
*/
export const alertIconStore = writable<Record<NotificationType, IconDetail>>(defaultAlertIcons);

Choose a reason for hiding this comment

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

P2 Badge Avoid request-shared icon state in the module store

If a SvelteKit app follows the new docstring and calls setAlertIcons() from +layout.svelte, this writable(...) lives in module scope and is therefore shared by every SSR request handled by the same server process. Any request-specific branding or tenant override will leak into later responses until another request mutates the store again, so one user's alerts can render with another user's icons/colours. This configuration needs to be scoped per render tree (for example via props/context) rather than stored in a process-wide singleton.

Useful? React with 👍 / 👎.

@claude
Copy link

claude bot commented Mar 18, 2026

Review summary

  • Overall score: 7/10
  • Critical issues: 0
  • Warnings: 3
  • Suggestions: 2
  • Recommendation: ⚠️ Approve with comments

Clean, idiomatic Svelte implementation with good JSDoc coverage. The main concern is that a module-level singleton store in an SSR context is a footgun that the documentation actively points users towards — the rest are minor.

Critical issues 🔴

None

Warnings 🟡

1. SSR singleton risk

alertIconStore is a module-level writable store, making it a shared singleton on the server. The JSDoc explicitly instructs users to call setAlertIcons() in +layout.svelte, which executes on every server render. In a multi-user SSR environment this means a call from one request mutates state visible to all concurrent requests.

This is safe only when the icons are truly global constants (same for every user/request). As soon as someone uses it for per-tenant white-labelling or any request-scoped logic it becomes a data contamination bug. The documentation should at minimum carry a warning.

2. Missing .js extension in Notice.svelte import

Alert.svelte was updated to use './alertIcons.js' but Notice.svelte still imports without the extension — inconsistent and may fail in strict ESM environments.

3. No tests for setAlertIcons()

The new public API function has no test coverage. A minimal vitest test verifying that setAlertIcons() merges overrides correctly and that alertIconStore emits the updated value would satisfy the project's coverage expectations.

Suggestions 🟢

1. Add an SSR caveat to the JSDoc

Consider adding a @remarks note to setAlertIcons() explaining that this updates a module-level singleton and should only be called with values that are constant for all users and requests. Suggest calling it in onMount (client-only) or at module initialisation time with static configuration.

2. Confirm alertIconStore encapsulation is intentional

alertIconStore is exported from alertIcons.ts but deliberately not re-exported through notifications/index.ts or components/index.ts. This is a good encapsulation decision — worth a short comment in the module so a future contributor does not accidentally expose it thinking it was forgotten.

@codecov
Copy link

codecov bot commented Mar 18, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 70.26%. Comparing base (7f6b060) to head (9f4f755).
⚠️ Report is 526 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #441      +/-   ##
==========================================
+ Coverage   64.59%   70.26%   +5.67%     
==========================================
  Files         154      187      +33     
  Lines        6064     7439    +1375     
==========================================
+ Hits         3917     5227    +1310     
+ Misses       2064     2012      -52     
- Partials       83      200     +117     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@ainsleyclark ainsleyclark merged commit 946e027 into main Mar 18, 2026
8 checks passed
@ainsleyclark ainsleyclark deleted the claude/global-icon-mapping-681il branch March 18, 2026 13:43
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