Skip to content

Consolidate icons & improve UI#469

Merged
Blaumaus merged 29 commits intomainfrom
improvement/icons-refresh
Feb 1, 2026
Merged

Consolidate icons & improve UI#469
Blaumaus merged 29 commits intomainfrom
improvement/icons-refresh

Conversation

@Blaumaus
Copy link
Member

@Blaumaus Blaumaus commented Jan 31, 2026

Changes

Migrate from Lucide, Heroicons and Simple Icons to Phosphor Icons

If applicable, please describe what changes were made in this pull request.

Community Edition support

  • Your feature is implemented for the Swetrix Community Edition
  • This PR only updates the Cloud (Enterprise) Edition code (e.g. Paddle webhooks, blog, payouts, etc.)

Database migrations

  • Clickhouse / MySQL migrations added for this PR
  • No table schemas changed in this PR

Documentation

  • You have updated the documentation according to your PR
  • This PR did not change any publicly documented endpoints

Summary by CodeRabbit

  • Style

    • Standardized iconography across the app (new icon set), replaced the loading spinner, and slightly reduced underline thickness.
  • New Features

    • Header and mobile menus show quick community links (GitHub, Discord).
    • Added TabHeader for clearer section context.
    • Added Password Strength indicator and a reusable Alert UI.
  • Localization

    • Expanded English translations for profile/settings and added “Free tools” footer entries.
  • UI

    • Footer layout refreshed for improved navigation and icon-driven links.

✏️ Tip: You can customize this high-level summary in your review settings.

@Blaumaus Blaumaus self-assigned this Jan 31, 2026
@coderabbitai
Copy link

coderabbitai bot commented Jan 31, 2026

Warning

Rate limit exceeded

@Blaumaus has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 17 minutes and 51 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📝 Walkthrough

Walkthrough

Global migration from lucide-react/@heroicons/react to @phosphor-icons/react; many icon imports/usages updated, icon prop API adjusted (removed strokeWidth, added weight usage). Added UI primitives: TabHeader, Alert, PasswordStrength. Large UserSettings and Footer UI refactor, dependency and Vite SSR changes.

Changes

Cohort / File(s) Summary
Dependencies & build config
web/package.json, docs/package.json, web/vite.config.ts
Removed lucide-react/some heroicons deps, added @phosphor-icons/react, removed lucide-react from SSR noExternal.
Global UI primitives & icons
web/app/ui/TabHeader.tsx, web/app/ui/Alert.tsx, web/app/ui/PasswordStrength.tsx, web/app/ui/icons/*, web/app/ui/Spin.tsx
Added TabHeader, Alert, PasswordStrength; replaced inline spinner with Phosphor Spinner; consolidated many icon usages to Phosphor and adjusted icon props/API (dropped strokeWidth, adopt weight/className).
Header / Footer / Nav
web/app/components/Header/index.tsx, web/app/components/Footer/index.tsx, web/app/components/ToolsNav.tsx, web/app/routes/*
Swapped header/footer/tool icons to Phosphor equivalents; Footer redesigned into typed NavItem/LegalItem-driven grid and expanded nav (Free Tools/Comparisons).
User settings & translations
web/app/pages/UserSettings/*, web/public/locales/en.json
Major UserSettings refactor: introduced TabConfig, URL-based tab selection, LANGUAGE tab, TabHeader integration, many new settings sections and many new translation keys.
Project view, sidebar & panels
web/app/pages/Project/View/..., web/app/pages/Project/View/components/ProjectSidebar.tsx, web/app/pages/Project/View/ViewProject.helpers.tsx
Large icon mapping updates for panels/devices; Tab.icon prop shape changed (strokeWidthweight), device/panel icon mappings updated to Phosphor icons.
Project tabs & components
web/app/pages/Project/tabs/*, web/app/pages/Project/View/components/*
Wide icon replacements across Alerts, Errors, Experiments, Feature Flags, Funnels, Profiles, Sessions, Traffic, AskAI, charts and filters; removed strokeWidth props and aligned to Phosphor API.
Dashboard, Projects & Cards
web/app/pages/Dashboard/*, web/app/pages/Project/*
Replaced dashboard/search/view-mode/pin/settings/mini-card icons to Phosphor and cleaned up icon props.
Settings, Organisations & Billing
web/app/pages/Organisations/*, web/app/pages/Billing/*
Icon swaps and visual adjustments; Organisation and Billing pages migrated to Phosphor icons; settings tabs receive TabHeader in many places.
Auth, Onboarding & Marketing
web/app/pages/Auth/*, web/app/pages/Onboarding/*, web/app/components/marketing/*, web/app/pages/Landings/*
Swapped CTA/feature icons to Phosphor equivalents; no behavioral changes.
Tools & routes
web/app/routes/tools.*, web/app/routes/*
Route/tool icon swaps (carets, external links, downloads, GitHub, stars) to Phosphor; icon weight adjustments in spots.
UI primitives & form controls
web/app/ui/* (Dropdown, Input, Datepicker, Select, Combobox, Checkbox, Pagination, Modal, Tooltip, TabHeader etc.)
Many core UI components updated to use Phosphor icons; small API/type tweaks (e.g., Text.as allows 'button').
** Numerous single-file icon swaps**
e.g. web/app/components/ExitIntentPopup.tsx, web/app/modals/NewFunnel.tsx, web/app/pages/Blog/Post.tsx, web/app/pages/Project/View/components/RefreshStatsButton.tsx, ...
Many one-line icon import/usage replacements across the codebase (e.g., Trash2IconTrashIcon, ChevronLeftCaretLeft, XMarkXIcon), removing strokeWidth and aligning to new API.
Styles
web/app/styles/tailwind.css
Minor tweak: underline animation height reduced (2px → 1.5px).

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Possibly related PRs

  • Free tool improvements #464 — overlaps edits to web/app/components/ToolsNav.tsx (tools icon/definitions) and may conflict with icon/tool changes.
  • Rework filters experience #423 — touches web/app/pages/Project/View/components/SearchFilters.tsx, which this PR also updated (icon substitutions).
  • UI updates #441 — modifies web/app/modals/NewFunnel.tsx where this PR changed icon imports/usages.

Poem

🐰 I nibbled at imports late last night,
Swapped carets, spinners, duotone light.
Tabs now wear a header crown,
Footers stretched the grid down.
Hoppity hop — the icons look bright!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Consolidate icons' clearly and concisely describes the main change: migrating from multiple icon libraries to a single unified icon library (Phosphor Icons).
Description check ✅ Passed The PR description follows the template structure with all required sections completed: Changes section describes the icon migration, Community Edition support is properly indicated, database migration status is marked, and documentation status is specified.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch improvement/icons-refresh

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (15)
web/app/ui/Dropdown.tsx (2)

8-8: ⚠️ Potential issue | 🟠 Major

Icon import inconsistent with PR objective.

The PR objective states that all icon libraries (including Heroicons) should be replaced with Phosphor Icons. However, this file still imports ChevronDownIcon from @heroicons/react/24/solid. This should be migrated to use the equivalent Phosphor icon (CaretDown from @phosphor-icons/react).

Proposed fix to use Phosphor Icons
-import { ChevronDownIcon } from '@heroicons/react/24/solid'
+import { CaretDown } from '@phosphor-icons/react'

Then update usages at lines 92 and 103:

-              <ChevronDownIcon
+              <CaretDown
+                weight='bold'

102-112: ⚠️ Potential issue | 🟡 Minor

Mini chevron variant now identical to regular variant.

Both chevron === 'regular' (line 92) and chevron === 'mini' now render the same ChevronDownIcon with the same h-5 w-5 size. The only difference is ml-2 vs ml-1. Previously, a separate mini icon import likely provided a visually distinct smaller icon.

If the mini variant should be visually smaller, consider adjusting the size class or using a different icon weight when migrating to Phosphor Icons.

Suggested differentiation
            {chevron === 'mini' ? (
-              <ChevronDownIcon
+              <CaretDown
+                weight='bold'
                className={cn(
-                  'ml-1 h-5 w-5 transform-gpu transition-transform',
+                  'ml-1 h-4 w-4 transform-gpu transition-transform',
                  {
                    'rotate-180': open,
                  },
                )}
web/app/pages/Project/tabs/FeatureFlags/FeatureFlagsView.tsx (2)

394-404: ⚠️ Potential issue | 🟠 Major

Phosphor Icons use weight prop, not strokeWidth.

The strokeWidth prop is a Lucide convention. Phosphor Icons use the weight prop with string values: "thin", "light", "regular", "bold", "fill", or "duotone". The current strokeWidth={1.5} will be silently ignored, and icons will render with the default "regular" weight.

Proposed fix
-                <TrashIcon className='size-4' strokeWidth={1.5} />
+                <TrashIcon className='size-4' weight='light' />
               </button>
               <CaretDownIcon
                 className={cx(
                   'size-5 text-gray-500 transition-transform dark:text-gray-400',
                   {
                     'rotate-180': isExpanded,
                   },
                 )}
-                strokeWidth={1.5}
+                weight='light'
               />

Note: This issue also affects other Phosphor icon usages in this file (CheckIcon, XIcon, FlagIcon, ToggleRightIcon, ToggleLeftIcon, PencilIcon, PlusIcon) that weren't part of the changed lines but should be addressed for consistency.


991-1001: ⚠️ Potential issue | 🟠 Major

Same strokeWidth issue on MagnifyingGlassIcon.

Replace strokeWidth={1.5} with weight='light' for Phosphor compatibility.

Additionally, the input's focus ring uses focus:ring-slate-900 / dark:focus:ring-slate-300, but the coding guidelines specify focus:ring-indigo-500 for focus states. Consider aligning with the project's design system.

,

Proposed fix
               <MagnifyingGlassIcon
                 className='absolute top-1/2 left-3 size-4 -translate-y-1/2 text-gray-400'
-                strokeWidth={1.5}
+                weight='light'
               />
               <input
                 type='text'
                 placeholder={t('featureFlags.filterFlags')}
                 value={filterQuery}
                 onChange={handleSearchChange}
-                className='w-full rounded-lg border-0 bg-white py-2 pr-4 pl-9 text-sm text-gray-900 placeholder-gray-500 ring-1 ring-gray-300 ring-inset focus:ring-slate-900 focus:outline-none sm:w-64 dark:bg-slate-900 dark:text-gray-50 dark:placeholder-gray-400 dark:ring-slate-700/80 dark:focus:ring-slate-300'
+                className='w-full rounded-lg border-0 bg-white py-2 pr-4 pl-9 text-sm text-gray-900 placeholder-gray-500 ring-1 ring-gray-300 ring-inset focus:ring-indigo-500 focus:outline-none sm:w-64 dark:bg-slate-900 dark:text-gray-50 dark:placeholder-gray-400 dark:ring-slate-700/80 dark:focus:ring-indigo-500'
               />

As per coding guidelines: "Apply ring borders to inputs with focus:ring-indigo-500 for focus states".

web/app/pages/Project/View/components/ProjectSidebar.tsx (1)

526-533: ⚠️ Potential issue | 🟠 Major

Replace strokeWidth with the weight prop for Phosphor icons.

Phosphor icons use weight to control line thickness, not strokeWidth. While strokeWidth technically passes through as an SVG attribute, it has no effect on Phosphor's stroke styling (widths are baked into each weight variant).

Proposed fix
-            <XIcon className='h-5 w-5' strokeWidth={1.5} />
+            <XIcon className='h-5 w-5' weight='regular' />
web/app/pages/Project/tabs/Errors/ErrorsView.tsx (2)

434-468: ⚠️ Potential issue | 🟡 Minor

Multiple Phosphor Icons using incorrect strokeWidth prop.

Several icons in this component use strokeWidth={1.5} which is a Lucide-specific prop. Phosphor Icons use the weight prop instead. Consider using weight="regular" or weight="light" for similar visual effect.

Affected icons: UserIcon, MonitorIcon, WarningIcon at lines 434, 441, 454, 461, 468.

Proposed fix for one instance (apply pattern to others)
-                <UserIcon className='mr-1 size-4' strokeWidth={1.5} />{' '}
+                <UserIcon className='mr-1 size-4' weight='regular' />{' '}

1285-1303: ⚠️ Potential issue | 🟡 Minor

StatCard icons also use incorrect strokeWidth prop.

The icons in StatCard components (BugIcon, PercentIcon, UsersIcon, MonitorIcon) also use strokeWidth={1.5} which should be weight for Phosphor Icons.

Proposed fix pattern
-                <BugIcon className='text-red-600' strokeWidth={1.5} />
+                <BugIcon className='text-red-600' weight='regular' />

Apply similar changes to PercentIcon, UsersIcon, and MonitorIcon.

web/app/pages/Project/tabs/Errors/ErrorDetails.tsx (1)

418-421: ⚠️ Potential issue | 🟡 Minor

Same strokeWidth issue on FileCodeIcon.

This Phosphor icon also uses strokeWidth which has no effect. Consider using weight="light" for a thinner stroke appearance.

🔧 Proposed fix
               <FileCodeIcon
                 className='size-3.5 text-gray-500'
-                strokeWidth={1.5}
+                weight='light'
               />
web/app/pages/Project/tabs/Traffic/RefRow.tsx (1)

35-35: ⚠️ Potential issue | 🟡 Minor

Phosphor Icons use weight prop instead of strokeWidth.

Both LinkIcon (line 35) and ArrowSquareOutIcon (line 64) use strokeWidth, which has no effect on Phosphor icons. Use the weight prop instead.

🔧 Proposed fix
-        <LinkIcon className='float-left mr-1.5 size-5' strokeWidth={1.5} />
+        <LinkIcon className='float-left mr-1.5 size-5' weight='light' />
           <ArrowSquareOutIcon
             className='size-3.5 opacity-0 group-hover:opacity-100 [`@media`(hover:none)]:opacity-100'
-            strokeWidth={2}
+            weight='bold'
           />

Also applies to: 64-67

web/app/pages/Project/tabs/Experiments/ExperimentResults.tsx (1)

870-871: ⚠️ Potential issue | 🟡 Minor

Multiple icons use strokeWidth which has no effect on Phosphor icons.

Several Phosphor icons in this file use strokeWidth={1.5}, which is a Lucide-specific prop. For Phosphor icons, use the weight prop instead.

Affected icons: PencilIcon, FlaskIcon, TargetIcon, InfoIcon, UsersIcon, PercentIcon.

Example fix pattern
-<FlaskIcon className='size-5 text-purple-500' strokeWidth={1.5} />
+<FlaskIcon className='size-5 text-purple-500' weight="regular" />

Apply this pattern to all icons with strokeWidth props in this file.

Also applies to: 878-878, 901-901, 951-954, 970-970, 994-994, 999-999, 1005-1005, 1011-1011

web/app/pages/Project/tabs/Sessions/Pageflow.tsx (1)

194-227: ⚠️ Potential issue | 🟡 Minor

Icon migrations are semantically correct, but strokeWidth prop is ineffective.

The icon replacements are appropriate:

  • CursorClickIcon for events
  • CurrencyDollarIcon for sales
  • ArrowCounterClockwiseIcon for refunds

However, strokeWidth={1.5} has no effect on Phosphor icons. Replace with the weight prop for consistent styling.

Proposed fix
               {type === 'pageview' ? (
                 <FileTextIcon
                   className='h-5 w-5 text-white'
                   aria-hidden='true'
-                  strokeWidth={1.5}
+                  weight="regular"
                 />
               ) : null}
               {type === 'event' ? (
                 <CursorClickIcon
                   className='h-5 w-5 text-white'
                   aria-hidden='true'
-                  strokeWidth={1.5}
+                  weight="regular"
                 />
               ) : null}
               {type === 'error' ? (
                 <BugIcon
                   className='h-5 w-5 text-white'
                   aria-hidden='true'
-                  strokeWidth={1.5}
+                  weight="regular"
                 />
               ) : null}
               {type === 'sale' ? (
                 <CurrencyDollarIcon
                   className='h-5 w-5 text-white'
                   aria-hidden='true'
-                  strokeWidth={1.5}
+                  weight="regular"
                 />
               ) : null}
               {type === 'refund' ? (
                 <ArrowCounterClockwiseIcon
                   className='h-5 w-5 text-white'
                   aria-hidden='true'
-                  strokeWidth={1.5}
+                  weight="regular"
                 />
               ) : null}
web/app/pages/UserSettings/UserSettings.tsx (1)

452-455: ⚠️ Potential issue | 🟡 Minor

strokeWidth prop is ineffective on Phosphor icons.

The tab icons are rendered with strokeWidth={1.5}, which has no effect on Phosphor icons. Use the weight prop for consistent styling.

Proposed fix
               iconExtractor={(item) => {
                 const Icon = item.icon
-                return <Icon className='h-4 w-4' strokeWidth={1.5} />
+                return <Icon className='h-4 w-4' weight="regular" />
               }}
                   <Icon
                     className={cx('mr-2 h-5 w-5 shrink-0 transition-colors', {
                       'text-gray-900 dark:text-gray-50': isCurrent,
                       'text-gray-500 group-hover:text-gray-600 dark:text-gray-400 dark:group-hover:text-gray-300':
                         !isCurrent,
                     })}
-                    strokeWidth={1.5}
+                    weight="regular"
                   />

Also applies to: 487-494

web/app/pages/Dashboard/ProjectCard.tsx (1)

401-407: ⚠️ Potential issue | 🟡 Minor

strokeWidth prop is not supported by Phosphor Icons.

Phosphor Icons use the weight prop (with values like "thin", "light", "regular", "bold", "fill", "duotone") instead of strokeWidth. The strokeWidth={1.5} prop will be ignored, and the icon will render with the default "regular" weight.

If you intended a lighter stroke, use weight="light" instead.

Proposed fix
 <PushPinIcon
   className={cx(
     'size-5 transition-transform',
     localIsPinned && 'rotate-30',
   )}
-  strokeWidth={1.5}
+  weight="regular"
 />
web/app/pages/Organisations/Organisations.tsx (1)

197-200: ⚠️ Potential issue | 🟡 Minor

strokeWidth prop is not supported by Phosphor icons.

Phosphor icons use the weight prop (with values like "thin", "light", "regular", "bold", "fill", "duotone") instead of strokeWidth. The strokeWidth={1.5} props on XIcon and MagnifyingGlassIcon will be silently ignored.

Either remove the strokeWidth prop (Phosphor defaults to "regular" weight) or replace with the appropriate weight value.

Proposed fix
                     <XIcon
                       className='h-5 w-5 cursor-pointer rounded-md text-gray-900 dark:text-gray-50'
-                      strokeWidth={1.5}
                     />
                     <MagnifyingGlassIcon
                       className='h-5 w-5 cursor-pointer rounded-md text-gray-900 dark:text-gray-50'
-                      strokeWidth={1.5}
                     />

Also applies to: 214-217

web/app/pages/Dashboard/Dashboard.tsx (1)

370-373: ⚠️ Potential issue | 🟡 Minor

strokeWidth prop is not supported by Phosphor icons.

Multiple Phosphor icons in this file have the strokeWidth prop which will be silently ignored. Phosphor icons use the weight prop instead.

Affected instances:

  • Line 372: XIcon
  • Line 389: MagnifyingGlassIcon
  • Line 403: MagnifyingGlassIcon
  • Line 455: FolderPlusIcon
  • Line 469: MagnifyingGlassIcon

Either remove strokeWidth (defaults to "regular" weight) or replace with the weight prop.

Proposed fix (example for one instance)
                     <XIcon
                       className='h-5 w-5 cursor-pointer rounded-md text-gray-900 dark:text-gray-50'
-                      strokeWidth={1.5}
                     />

Apply similar changes to all affected icons.

Also applies to: 387-390, 401-404, 455-455, 467-470

🤖 Fix all issues with AI agents
In `@web/app/pages/Project/tabs/Experiments/ExperimentsView.tsx`:
- Around line 176-179: Replace the Phosphor Icon prop strokeWidth with the
weight prop set to 'light' for the icon components in this file (e.g.,
FlaskIcon); locate each Phosphor icon usage that currently passes strokeWidth
(lines around the shown FlaskIcon instance) and change strokeWidth={1.5} to
weight='light' so the icons render the intended lighter style (apply the same
change to the other affected icon instances referenced in the review).

In `@web/app/pages/Project/tabs/FeatureFlags/FeatureFlagsView.tsx`:
- Around line 463-466: The DownloadSimpleIcon usage currently passes
strokeWidth={1.5}; update the prop to use Phosphor's weight API by replacing
strokeWidth with weight='light' on the DownloadSimpleIcon component (search for
DownloadSimpleIcon in FeatureFlagsView.tsx and remove strokeWidth={1.5} and add
weight='light' instead) so the icon uses the correct Phosphor prop.
🟡 Minor comments (20)
web/app/pages/Project/View/Panels.tsx-368-371 (1)

368-371: ⚠️ Potential issue | 🟡 Minor

Replace strokeWidth prop with weight for Phosphor Icons.

Phosphor Icons React uses the weight prop (not strokeWidth) with values like "thin", "light", "regular", "bold", "fill", or "duotone". The strokeWidth prop will be ignored.

Use weight="regular" to achieve a visual result similar to strokeWidth={1.5}.

🔧 Proposed fix (example for lines 368-371)
 <FunnelIcon
   className='ml-2 hidden h-4 w-4 shrink-0 text-gray-500 group-hover:block dark:text-gray-300'
-  strokeWidth={1.5}
+  weight="regular"
 />

Apply to all 8 FunnelIcon usages: 368-371, 769-772, 873-876, 1162-1165, 1212-1215, 1323-1326, 1410-1413, 1842-1845.

web/app/pages/Project/tabs/Funnels/FunnelsView.tsx-435-435 (1)

435-435: ⚠️ Potential issue | 🟡 Minor

Use weight prop instead of strokeWidth on FunnelIcon.
Line 435 uses strokeWidth={1.5}, which Phosphor accepts as an SVG prop but does not effectively control stroke thickness—Phosphor's per-path stroke values override it. Use the weight prop (e.g., "light") for reliable stroke control.

🔧 Suggested fix
-          <FunnelIcon className='mr-2 h-8 w-8' strokeWidth={1.5} />
+          <FunnelIcon className='mr-2 h-8 w-8' weight='light' />
web/app/pages/Project/View/components/ProjectSidebar.tsx-2-10 (1)

2-10: ⚠️ Potential issue | 🟡 Minor

Tighten icon typing with Phosphor's exported IconWeight type.

Replace weight?: string with weight?: IconWeight to enforce valid weight values ("thin" | "light" | "regular" | "bold" | "fill" | "duotone") and enable proper type checking.

Suggested refactor
 import {
   CaretDownIcon,
   CaretRightIcon,
   SidebarSimpleIcon,
   SidebarIcon,
   GearIcon,
   XIcon,
   ListIcon,
+  type IconWeight,
 } from '@phosphor-icons/react'

 interface Tab {
   id: ProjectTabKey
   label: string
-  icon: React.ComponentType<{ className?: string; weight?: string }>
+  icon: React.ComponentType<{ className?: string; weight?: IconWeight }>
 }

Also applies to: 82-86

Additionally, remove strokeWidth={1.5} from the XIcon at line 532 — Phosphor icons use the weight prop instead.

web/app/routes/google-analytics-alternative.tsx-409-409 (1)

409-409: ⚠️ Potential issue | 🟡 Minor

Align warning accent with amber-500/600 in dark mode.
The dark theme uses text-amber-400; guideline calls for amber-600. Consider bumping it for consistency.

🔧 Suggested change
-                <LightningIcon className='size-5 text-amber-500 dark:text-amber-400' />
+                <LightningIcon className='size-5 text-amber-500 dark:text-amber-600' />

As per coding guidelines: “Apply danger color as red-500/600, success as emerald-500/600, warning as amber-500/600 for semantic status indicators.”

web/app/pages/Dashboard/PeriodSelector.tsx-71-71 (1)

71-71: ⚠️ Potential issue | 🟡 Minor

Phosphor Icons use weight prop instead of strokeWidth.

The strokeWidth prop is from Lucide and will be ignored by Phosphor Icons. Use the weight prop with values like "regular", "light", "bold", etc.

Proposed fix
-            <CalendarDotsIcon className='mr-1 h-5 w-5' strokeWidth={1.5} />
+            <CalendarDotsIcon className='mr-1 h-5 w-5' weight='regular' />
web/app/components/pricing/MarketingPricing.tsx-71-74 (1)

71-74: ⚠️ Potential issue | 🟡 Minor

Phosphor Icons styling incompatibility.

Two issues with QuestionIcon:

  1. strokeWidth is a Lucide prop; Phosphor uses weight (e.g., "regular", "light")
  2. stroke-gray-50 won't work - Phosphor icons use fill for coloring, so use text-gray-50 instead
Proposed fix
                         <QuestionIcon
-                            className='size-4 stroke-gray-50'
-                            strokeWidth={1.5}
+                            className='size-4 text-gray-50'
+                            weight='regular'
                          />
web/app/components/pricing/BillingPricing.tsx-373-376 (1)

373-376: ⚠️ Potential issue | 🟡 Minor

Phosphor Icons styling incompatibility.

Same issue as in MarketingPricing.tsx - strokeWidth should be weight, and stroke-* classes should be text-* for Phosphor icons.

Proposed fix
                           <QuestionIcon
-                              className='size-4 stroke-yellow-800 dark:stroke-yellow-500'
-                              strokeWidth={1.5}
+                              className='size-4 text-yellow-800 dark:text-yellow-500'
+                              weight='regular'
                            />
web/app/pages/Organisations/OrganisationCard.tsx-124-124 (1)

124-124: ⚠️ Potential issue | 🟡 Minor

Phosphor Icons use weight prop instead of strokeWidth.

SlidersHorizontalIcon from @phosphor-icons/react doesn't support strokeWidth. Use the weight prop for stroke thickness control.

🔧 Proposed fix
-              <SlidersHorizontalIcon className='size-5' strokeWidth={1.5} />
+              <SlidersHorizontalIcon className='size-5' weight='light' />
web/app/pages/Project/Settings/tabs/DangerZone.tsx-83-86 (1)

83-86: ⚠️ Potential issue | 🟡 Minor

Phosphor Icons use weight prop instead of strokeWidth.

TrashIcon uses strokeWidth={1.5}, which has no effect on Phosphor icons. Use the weight prop instead.

🔧 Proposed fix
             <TrashIcon
               className='mt-0.5 h-5 w-5 text-red-700 dark:text-red-500'
-              strokeWidth={1.5}
+              weight='light'
             />
web/app/pages/Project/tabs/Errors/ErrorDetails.tsx-155-158 (1)

155-158: ⚠️ Potential issue | 🟡 Minor

Use weight prop instead of strokeWidth for Phosphor Icons.

ArrowSquareOutIcon and FileCodeIcon from @phosphor-icons/react don't support strokeWidth. Phosphor icons use the weight prop with values: "thin", "light", "regular", "bold", "fill", or "duotone".

Fix both instances at lines 157 and 420:

Line 157
       <ArrowSquareOutIcon
         className='mt-0.5 size-4 shrink-0 text-gray-400 transition-colors group-hover:text-gray-600 dark:group-hover:text-gray-300'
-        strokeWidth={1.5}
+        weight='light'
       />
Line 420
               <FileCodeIcon
                 className='size-3.5 text-gray-500'
-                strokeWidth={1.5}
+                weight='light'
               />
web/app/pages/Project/tabs/Traffic/TrafficView.tsx-986-989 (1)

986-989: ⚠️ Potential issue | 🟡 Minor

Incorrect prop: strokeWidth is not supported by Phosphor Icons.

The strokeWidth={1.5} prop will be ignored by ProhibitIcon. Phosphor Icons use the weight prop with values like "thin", "light", "regular", "bold", "fill", or "duotone".

🔧 Proposed fix
                       <ProhibitIcon
                         className='mr-2 h-4 w-4'
-                        strokeWidth={1.5}
+                        weight='light'
                       />
web/app/pages/Dashboard/NoProjects.tsx-30-33 (1)

30-33: ⚠️ Potential issue | 🟡 Minor

Incorrect prop: strokeWidth is not supported by Phosphor Icons.

Phosphor Icons use the weight prop instead of strokeWidth. The strokeWidth={1.5} prop will be ignored, and the icon will render with its default weight. To achieve a lighter stroke similar to strokeWidth={1.5}, use weight="light" or weight="regular".

🔧 Proposed fix
       <FolderSimpleIcon
         className='size-7 text-gray-700 dark:text-gray-200'
-        strokeWidth={1.5}
+        weight='light'
       />
web/app/pages/Organisations/Settings/index.tsx-254-254 (1)

254-254: ⚠️ Potential issue | 🟡 Minor

Incorrect prop: strokeWidth is not supported by Phosphor Icons.

The strokeWidth={1.5} prop will be ignored by TrashIcon. Use the weight prop instead.

🔧 Proposed fix
-               <TrashIcon className='mr-1 h-5 w-5' strokeWidth={1.5} />
+               <TrashIcon className='mr-1 h-5 w-5' weight='light' />
web/app/ui/Tooltip.tsx-58-61 (1)

58-61: ⚠️ Potential issue | 🟡 Minor

Phosphor icons styling differs from Lucide icons.

Two issues with this icon usage:

  1. strokeWidth={1.5} has no effect on Phosphor icons—use weight prop instead (e.g., weight="regular").
  2. The fill-* and stroke-* classes work differently with Phosphor icons. Phosphor icons are single-color SVGs that inherit from color/currentColor. Consider using text-* classes or the color prop instead.
Proposed fix
         {tooltipNode || (
           <QuestionIcon
-            className='size-4.5 fill-slate-700 stroke-gray-50 dark:fill-slate-200 dark:stroke-slate-800'
-            strokeWidth={1.5}
+            className='size-4.5 text-slate-700 dark:text-slate-200'
+            weight="regular"
           />
         )}
web/app/pages/Project/tabs/Captcha/CaptchaView.tsx-48-53 (1)

48-53: ⚠️ Potential issue | 🟡 Minor

Use Phosphor's weight prop instead of strokeWidth for icon styling.

Phosphor React icons don't support strokeWidth for controlling stroke thickness. Use the documented weight prop with values like "thin", "light", "regular", "bold", "fill", or "duotone" instead.

Proposed fix
 const panelIconMapping: Record<string, React.ReactNode> = {
-  cc: <MapPinIcon className={iconClassName} strokeWidth={1.5} />,
-  dv: <DevicesIcon className={iconClassName} strokeWidth={1.5} />,
-  br: <CompassIcon className={iconClassName} strokeWidth={1.5} />,
-  os: <MonitorIcon className={iconClassName} strokeWidth={1.5} />,
+  cc: <MapPinIcon className={iconClassName} weight="regular" />,
+  dv: <DevicesIcon className={iconClassName} weight="regular" />,
+  br: <CompassIcon className={iconClassName} weight="regular" />,
+  os: <MonitorIcon className={iconClassName} weight="regular" />,
 }
web/app/pages/Project/tabs/Sessions/Sessions.tsx-7-12 (1)

7-12: ⚠️ Potential issue | 🟡 Minor

Icon imports correctly migrated to Phosphor.

Same observations as Profiles.tsx:

  1. ChevronRightIcon (line 1) remains from Heroicons - consider migrating for consistency.
  2. Multiple icons use strokeWidth={1.5} which is not a valid Phosphor prop (lines 258, 279, 288, 302, 325, 334, 340).
web/app/pages/Project/tabs/Goals/GoalsView.tsx-10-19 (1)

10-19: ⚠️ Potential issue | 🟡 Minor

Icon imports correctly migrated, but strokeWidth props will be ignored.

Multiple icons in this file use strokeWidth which is not supported by Phosphor Icons:

  • Lines 339, 344: FileTextIcon, CursorClickIcon
  • Line 430: PencilIcon
  • Line 442: TrashIcon
  • Line 451: CaretDownIcon
  • Line 859: TargetIcon
  • Line 881: MagnifyingGlassIcon
  • Line 892: PlusIcon

Replace with weight prop or remove if default weight is acceptable.

web/app/pages/Project/tabs/Profiles/Profiles.tsx-173-173 (1)

173-173: ⚠️ Potential issue | 🟡 Minor

strokeWidth prop is not supported by Phosphor Icons.

This applies to multiple icons in this file (CursorClickIcon, CalendarDotsIcon, UsersIcon, FileTextIcon, BugIcon). Phosphor uses the weight prop instead. The strokeWidth will be silently ignored.

Consider removing strokeWidth or replacing with weight="regular" (or another appropriate weight) across all affected lines: 158, 165, 173, 182, 196, 203, 213, 222, 228.

web/app/pages/Dashboard/ProjectCard.tsx-420-420 (1)

420-420: ⚠️ Potential issue | 🟡 Minor

Same issue: strokeWidth prop not supported on Phosphor Icons.

Remove or replace with the weight prop for consistency.

Proposed fix
-<SlidersHorizontalIcon className='size-5' strokeWidth={1.5} />
+<SlidersHorizontalIcon className='size-5' weight="regular" />
web/app/pages/Organisations/Organisations.tsx-228-231 (1)

228-231: ⚠️ Potential issue | 🟡 Minor

Same strokeWidth prop issue on remaining MagnifyingGlassIcon instances.

These two instances also have the unsupported strokeWidth prop that should be removed or replaced with weight.

Proposed fix
                       <MagnifyingGlassIcon
                         className='ml-2 h-5 w-5 cursor-pointer text-gray-900 hover:opacity-80 dark:text-gray-50'
-                        strokeWidth={1.5}
                       />
                   <MagnifyingGlassIcon
                     className='ml-2 h-5 w-5 cursor-pointer text-gray-900 hover:opacity-80 dark:text-gray-50'
-                    strokeWidth={1.5}
                   />

Also applies to: 261-264

🧹 Nitpick comments (10)
web/app/ui/Dropdown.tsx (3)

70-70: Missing dark mode support for description text.

The description paragraph uses text-gray-900 but lacks a corresponding dark mode class. As per coding guidelines, full light and dark mode support should be implemented.

Proposed fix
-            <p className='mb-2 text-sm text-gray-900'>{desc}</p>
+            <p className='mb-2 text-sm text-gray-900 dark:text-gray-50'>{desc}</p>

115-124: Transition timing and reduced-motion preferences.

Per coding guidelines, the default transition should be 200ms with ease-out for entrances and ease-in for exits. Additionally, animations should respect reduced-motion preferences.

Current: duration-100 enter, duration-75 leave, no reduced-motion handling.

Suggested adjustment
          <Transition
            show={open}
            as={Fragment}
-            enter='transition ease-out duration-100'
+            enter='transition ease-out duration-200 motion-reduce:duration-0'
            enterFrom='transform opacity-0 scale-95'
            enterTo='transform opacity-100 scale-100'
-            leave='transition ease-in duration-75'
+            leave='transition ease-in duration-200 motion-reduce:duration-0'
            leaveFrom='transform opacity-100 scale-100'
            leaveTo='transform opacity-0 scale-95'
          >

80-81: Focus ring color deviates from guidelines.

The coding guidelines specify using focus:ring-indigo-500 for focus states, but this component uses focus:ring-slate-900 / focus:ring-slate-300. Consider aligning with the design system.

web/app/pages/Project/tabs/Experiments/ExperimentsView.tsx (1)

239-239: Other icons in this file also need strokeWidthweight migration.

The icons PlayIcon, PauseIcon, CheckCircleIcon, PencilIcon, and PlusIcon (lines 239, 255, 280, 290, 324, 745) are now imported from @phosphor-icons/react but still use the strokeWidth prop. Consider updating these as well for consistency.

web/app/pages/Project/tabs/Funnels/FunnelsList.tsx (1)

75-75: Use Phosphor weight prop instead of strokeWidth for consistent icon styling.

Phosphor icons v2.x defines visual weights via the weight prop (thin, light, regular, bold, fill, duotone). The strokeWidth attribute is a generic SVG prop that may not visibly affect Phosphor icons since their weight variants bake specific stroke widths into internal path elements. Apply the weight prop consistently across all Phosphor icons in this PR.

Example adjustments
-<SlidersHorizontalIcon className='size-5' strokeWidth={1.5} />
+<SlidersHorizontalIcon className='size-5' weight='regular' />

-<TrashIcon className='size-5' strokeWidth={1.5} />
+<TrashIcon className='size-5' weight='regular' />

-<FunnelSimpleIcon className='mx-auto h-12 w-12 ...' strokeWidth={1} />
+<FunnelSimpleIcon className='mx-auto h-12 w-12 ...' weight='light' />

Affects lines 75, 93, and 116–118.

web/app/routes/tools.ctr-calculator.tsx (1)

295-295: Add reduced‑motion handling to the caret rotation.

The caret uses a transform transition; add motion-reduce:* utilities so the rotation respects reduced‑motion preferences.

Possible adjustment
-<CaretDownIcon className='h-5 w-5 text-gray-500 transition-transform group-open:rotate-180' />
+<CaretDownIcon className='h-5 w-5 text-gray-500 transition-transform motion-reduce:transition-none motion-reduce:transform-none group-open:rotate-180' />
web/app/pages/Project/tabs/Profiles/Profiles.tsx (1)

6-12: Icon migration looks correct, but note the inconsistent library usage.

The Phosphor icons import is correct. However, ChevronRightIcon on line 1 is still imported from @heroicons/react/24/outline. If the goal is to consolidate all icons to Phosphor, this should also be migrated to CaretRightIcon from Phosphor.

web/app/pages/Project/tabs/Experiments/ExperimentSettingsModal.tsx (2)

12-17: Consider per‑icon Phosphor imports if build times grow.
Phosphor’s docs warn that root-module imports can make some bundlers transpile thousands of icon modules; subpath imports (or bundler import optimization) avoid that overhead. (github.com)

♻️ Example change (per‑icon import)
-import {
-  PlusIcon,
-  TrashIcon,
-  CaretDownIcon,
-  TrendUpIcon,
-  TrendDownIcon,
-} from '@phosphor-icons/react'
+import { PlusIcon } from '@phosphor-icons/react/dist/csr/Plus'
+import { TrashIcon } from '@phosphor-icons/react/dist/csr/Trash'
+import { CaretDownIcon } from '@phosphor-icons/react/dist/csr/CaretDown'
+import { TrendUpIcon } from '@phosphor-icons/react/dist/csr/TrendUp'
+import { TrendDownIcon } from '@phosphor-icons/react/dist/csr/TrendDown'

787-792: Add reduced‑motion handling for the caret rotation.
Consider disabling the transform transition for users with reduced‑motion preferences.

🛠️ Suggested tweak
-                          className={cx(
-                            'size-4 text-gray-400 transition-transform',
+                          className={cx(
+                            'size-4 text-gray-400 transition-transform motion-reduce:transition-none motion-reduce:transform-none',
                             showAdvanced && 'rotate-180',
                           )}

As per coding guidelines: Respect reduced-motion preferences in animations and transitions.

web/app/pages/Project/tabs/Alerts/ProjectAlertsView.tsx (1)

57-70: Align warning banner palette to amber tokens.
This banner communicates a warning state but uses yellow shades; the guideline calls for amber for warnings.

🎨 Suggested palette update
-    <div className='mb-4 flex items-center gap-3 rounded-lg border border-yellow-200 bg-yellow-50 px-4 py-3 dark:border-yellow-500/20 dark:bg-yellow-500/10'>
+    <div className='mb-4 flex items-center gap-3 rounded-lg border border-amber-200 bg-amber-50 px-4 py-3 dark:border-amber-500/20 dark:bg-amber-500/10'>
       <WarningIcon
-        className='size-5 shrink-0 text-yellow-600 dark:text-yellow-500'
+        className='size-5 shrink-0 text-amber-600 dark:text-amber-500'
         strokeWidth={1.5}
       />
-      <p className='flex-1 text-sm text-yellow-800 dark:text-yellow-200'>
+      <p className='flex-1 text-sm text-amber-800 dark:text-amber-200'>
         {t('alert.noNotificationChannel')}
       </p>
       <Link
         to={routes.user_settings}
-        className='shrink-0 rounded-md bg-yellow-600 px-3 py-1.5 text-sm font-medium text-white transition-colors hover:bg-yellow-700 dark:bg-yellow-600 dark:hover:bg-yellow-500'
+        className='shrink-0 rounded-md bg-amber-600 px-3 py-1.5 text-sm font-medium text-white transition-colors hover:bg-amber-700 dark:bg-amber-600 dark:hover:bg-amber-500'
       >
         {t('common.fixIt')}
       </Link>

As per coding guidelines: Apply danger color as red-500/600, success as emerald-500/600, warning as amber-500/600 for semantic status indicators.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 8

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
web/app/pages/Project/View/components/RefreshStatsButton.tsx (1)

101-122: ⚠️ Potential issue | 🟡 Minor

Respect reduced-motion preferences for animate-spin.

The animate-spin class is used on lines 105 and 121 without a motion-reduce: variant. Per coding guidelines, animations should respect reduced-motion preferences.

♿ Proposed fix to respect reduced-motion
         <ArrowClockwiseIcon
           className={cn(
             'absolute inset-0 h-5 w-5 text-gray-400/80 dark:text-slate-600',
             {
-              'animate-spin': showSpinner,
+              'animate-spin motion-reduce:animate-none': showSpinner,
             },
           )}
         />
         {showSpinner ? (
-          <ArrowClockwiseIcon className='absolute inset-0 h-5 w-5 animate-spin text-gray-700 dark:text-gray-50' />
+          <ArrowClockwiseIcon className='absolute inset-0 h-5 w-5 animate-spin motion-reduce:animate-none text-gray-700 dark:text-gray-50' />
         ) : null}

As per coding guidelines: "Respect reduced-motion preferences in animations and transitions".

web/app/pages/Project/tabs/FeatureFlags/FeatureFlagSettingsModal.tsx (1)

731-787: ⚠️ Potential issue | 🟡 Minor

Use emerald for success state instead of green.

Copy confirmation is a success indicator; replace text-green-500 with text-emerald-500 for all three CheckIcon elements (lines 733, 757, 781).

🎨 Proposed fixes
-                                  <CheckIcon className='size-4 text-green-500' />
+                                  <CheckIcon className='size-4 text-emerald-500' />
-                                  <CheckIcon className='size-4 text-green-500' />
+                                  <CheckIcon className='size-4 text-emerald-500' />
-                                  <CheckIcon className='size-4 text-green-500' />
+                                  <CheckIcon className='size-4 text-emerald-500' />

Per coding guidelines, success indicators must use emerald-500/600.

🤖 Fix all issues with AI agents
In `@web/app/pages/Project/tabs/Profiles/Profiles.tsx`:
- Line 173: Replace unsupported strokeWidth props on Phosphor icons in
Profiles.tsx: locate CursorClickIcon (and other uses like UsersIcon,
FileTextIcon, BugIcon) and remove strokeWidth={...} or replace it with the
Phosphor weight prop (e.g., weight="light" for a thinner stroke) so icons render
correctly; ensure you use the weight values ("thin" | "light" | "regular" |
"bold" | "fill" | "duotone") consistently across those icon components.

In `@web/app/pages/Project/tabs/Sessions/NoSessionDetails.tsx`:
- Around line 10-13: The SmileySadIcon usage is passing a Heroicons prop
(strokeWidth) which Phosphor Icons ignores; in the JSX where SmileySadIcon is
rendered (SmileySadIcon component), remove the strokeWidth={1.5} prop and add
weight="light" to achieve the intended thin stroke appearance while keeping the
existing className and other props intact.

In `@web/app/pages/Project/tabs/Traffic/CustomMetrics.tsx`:
- Around line 105-108: Replace the clickable XIcon with an accessible button
wrapper and use the Phosphor weight prop instead of a CSS stroke class: wrap the
XIcon in a <button> (matching the pattern used in CustomMetric) that calls
resetMetrics on click and is keyboard-focusable, add an aria-label using the t
hook (import/use t inside CustomMetrics and use the correct i18n key), and
remove the ineffective 'stroke-2' class from the XIcon while setting
weight="bold" (or appropriate weight) to control stroke thickness; ensure
classNames for visuals remain on the button/icon as needed.

In `@web/app/pages/Project/View/components/LockedDashboard.tsx`:
- Around line 48-49: The LockIcon in LockedDashboard.tsx is using yellow
classes; update its className to use the warning amber palette instead (replace
'text-yellow-500 dark:text-yellow-400' with 'text-amber-500
dark:text-amber-600') so the semantic warning color matches the design system;
locate the LockIcon JSX in the LockedDashboard component and adjust the Tailwind
color tokens accordingly.

In `@web/app/pages/Project/View/ViewProject.helpers.tsx`:
- Line 2295: The JSX uses a non‑supported prop on the Phosphor icon: remove the
invalid strokeWidth attribute from the QuestionMarkIcon usage (the element
rendered as QuestionMarkIcon in ViewProject.helpers.tsx) and ensure no other
Phosphor icon instances nearby use strokeWidth; if a different visual weight is
needed, use the icon's supported props (e.g., weight or size) instead.
- Around line 2147-2160: Remove the non-idiomatic strokeWidth prop from the
Phosphor icons in panelIconMapping and deviceIconMapping and from the standalone
QuestionMarkIcon; specifically, edit panelIconMapping entries for DevicesIcon
and MonitorPlayIcon, deviceIconMapping entries for DeviceMobileIcon,
DeviceTabletIcon, TelevisionIcon, and GameControllerIcon, and the
QuestionMarkIcon usage to drop strokeWidth (rely on the default "regular" weight
or set weight="regular" if you prefer explicitness) so the components use the
Phosphor API correctly.

In `@web/app/root.tsx`:
- Line 138: The WarningIcon uses yellow tokens; update its className on the
WarningIcon element to use the amber semantic tokens instead (replace
text-yellow-400 with text-amber-500 and replace dark:text-yellow-600 with
dark:text-amber-600) so the warning indicator follows the amber-500/600
guideline while keeping the existing sizing classes (e.g., h-24 w-auto).

In `@web/app/ui/Select.tsx`:
- Around line 92-95: The caret icon (CaretUpDownIcon) currently hardcodes a
light-mode color via its className; update the className on the CaretUpDownIcon
element so it uses a warm gray for light mode and a slate tone for dark mode
(e.g., add a dark: text token alongside the existing text-gray-400) so the icon
follows the app's light/dark palette; locate the CaretUpDownIcon JSX in
Select.tsx and modify its className prop accordingly.
🧹 Nitpick comments (8)
web/app/pages/Project/View/components/LiveVisitorsDropdown.tsx (1)

54-90: Consider HeadlessUI for dropdown in a future refactor.

The current dropdown uses a custom OutsideClickHandler implementation. For consistency across the codebase, consider migrating to HeadlessUI's Menu or Popover component in a future PR, which would provide built-in keyboard navigation, focus management, and standardized fade/slide transitions.

This is out of scope for the current icon migration PR. Based on learnings: "Use HeadlessUI for modals and dropdowns with fade/slide transitions."

web/app/pages/Organisations/Settings/Projects.tsx (1)

175-175: Minor inconsistency: size-5 vs h-5 w-5 sizing pattern.

This line uses size-5 while other icons in this file (lines 81, 268, 275, 293, 301) use h-5 w-5. Consider using a consistent sizing approach throughout the file for maintainability.

Additionally, the text-gray-400 color lacks a dark mode variant, while similar icons elsewhere (e.g., XIcon at line 268) include dark:text-gray-50. For full dark mode support, consider adding a dark variant if the gray-400 appears too muted on dark backgrounds.

♻️ Optional fix for consistency
-              tooltipNode={<InfoIcon className='size-5 text-gray-400' />}
+              tooltipNode={<InfoIcon className='h-5 w-5 text-gray-400 dark:text-gray-500' />}
web/app/components/marketing/DitchGoogle.tsx (1)

41-41: Consider using square dimensions for Phosphor icon.

Phosphor icons are designed as square SVGs. The current h-4 w-5 creates a non-square aspect ratio (16×20px) which may cause slight distortion. Consider using consistent dimensions.

♻️ Suggested fix
-                <ArrowRightIcon className='mt-[1px] h-4 w-5' />
+                <ArrowRightIcon className='mt-[1px] size-5' />
web/app/pages/Captcha/CaptchaDemo.tsx (1)

274-274: Consider using the size prop for Phosphor Icons.

Phosphor Icons idiomatically use the size prop for dimensions rather than Tailwind width/height classes. While the current approach works, using size is more explicit and consistent with the library's API.

♻️ Suggested improvement
-            <ArrowRightIcon className='ml-2 h-4 w-4' />
+            <ArrowRightIcon className='ml-2' size={16} />
web/app/pages/Project/View/components/NoEvents.tsx (2)

1-1: Optional: avoid root @phosphor-icons/react import if build times spike.

Phosphor docs warn that root imports can make bundlers transpile thousands of icon modules; consider per‑icon path imports or bundler optimizePackageImports if dev builds slow. (github.com)


27-30: Align dark‑mode icon color with the slate palette.

Use slate tones in dark mode and keep both icons consistent.

🔧 Proposed update
-            <FunnelIcon className='size-7 text-gray-700 dark:text-gray-200' />
+            <FunnelIcon className='size-7 text-gray-700 dark:text-slate-200' />-            <CalendarIcon className='size-7 text-gray-700 dark:text-gray-200' />
+            <CalendarIcon className='size-7 text-gray-700 dark:text-slate-200' />

As per coding guidelines “Implement full light and dark mode support with warm grays for light mode and slate tones for dark mode”.

web/app/components/ToolsNav.tsx (1)

144-148: Honor reduced‑motion for the caret rotation.

Add motion‑reduce utilities so the dropdown arrow doesn’t animate for users who prefer reduced motion.

♿ Suggested tweak
-            'h-5 w-5 shrink-0 text-gray-400 transition-transform',
+            'h-5 w-5 shrink-0 text-gray-400 transition-transform motion-reduce:transition-none motion-reduce:transform-none',

As per coding guidelines: Respect reduced-motion preferences in animations and transitions.

web/app/routes/tools.sitemap-validator.tsx (1)

1066-1069: Add reduced‑motion fallback to the FAQ caret rotation.

The FAQ caret rotates with a transition; add motion‑reduce utilities so the animation is suppressed when users prefer reduced motion.

♿ Suggested tweak
-                      <CaretDownIcon className='h-5 w-5 shrink-0 text-gray-400 transition-transform group-open:rotate-180' />
+                      <CaretDownIcon className='h-5 w-5 shrink-0 text-gray-400 transition-transform group-open:rotate-180 motion-reduce:transition-none motion-reduce:transform-none' />

As per coding guidelines: Respect reduced-motion preferences in animations and transitions.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@web/app/ui/Button.tsx`:
- Line 84: The spinner is invisible on dark-background Button variants because
it uses a fixed color; update the Spin component (Spin.tsx) to draw using
currentColor (use CSS currentColor for stroke/fill) so it inherits the Button
text color, leaving Button.tsx's usage ({loading ? <Spin /> : null}) unchanged;
alternatively, if you prefer per-variant control, set the alwaysLight prop from
Button.tsx for the dark-background variants (e.g., inside the Button render
branch that handles the primary/danger variants and their mode) so the spinner
contrasts correctly.
🧹 Nitpick comments (1)
web/app/ui/icons/Spin.tsx (1)

10-19: Consider adding reduced-motion support for accessibility.

Per coding guidelines, animations should respect reduced-motion preferences. Users with vestibular disorders may have prefers-reduced-motion: reduce set.

♿ Proposed fix to respect reduced-motion
     className={cn(
-      'mr-2 -ml-1 h-4 w-4 animate-spin text-slate-900 dark:text-white',
+      'mr-2 -ml-1 h-4 w-4 animate-spin motion-reduce:animate-none text-slate-900 dark:text-white',
       {

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
web/app/routes/_index.tsx (2)

772-783: ⚠️ Potential issue | 🟡 Minor

Adjust dark-mode indigo accents to indigo-500.

The new icons still use dark:text-indigo-400, which is off the primary accent token for dark mode.

🎨 Suggested tweaks
-                    <FileTextIcon className='size-4 text-indigo-600 dark:text-indigo-400' />
+                    <FileTextIcon className='size-4 text-indigo-600 dark:text-indigo-500' />
...
-                    <CursorClickIcon className='size-4 text-indigo-600 dark:text-indigo-400' />
+                    <CursorClickIcon className='size-4 text-indigo-600 dark:text-indigo-500' />
-          <FlaskIcon className='size-4 text-indigo-600 dark:text-indigo-400' />
+          <FlaskIcon className='size-4 text-indigo-600 dark:text-indigo-500' />
As per coding guidelines: Use indigo-600 as the primary accent color in light mode and indigo-500 in dark mode.

Also applies to: 1519-1522


923-936: ⚠️ Potential issue | 🟡 Minor

Align success/warning/danger colors with the semantic palette.

These status indicators use non-standard shades (emerald-400/700, amber-400, rose). The design tokens call for emerald/red/amber 500–600.

🎨 Suggested tweaks
-            className={cn('flex items-center gap-1 text-[10px]', {
-              'text-emerald-600 dark:text-emerald-400': isUp,
-              'text-rose-600 dark:text-rose-400': !isUp,
-            })}
+            className={cn('flex items-center gap-1 text-[10px]', {
+              'text-emerald-600 dark:text-emerald-500': isUp,
+              'text-red-600 dark:text-red-500': !isUp,
+            })}
-            <BellRingingIcon className='size-4 text-amber-600 dark:text-amber-400' />
+            <BellRingingIcon className='size-4 text-amber-600 dark:text-amber-500' />
...
-          <BellRingingIcon className='size-4 text-amber-600 dark:text-amber-400' />
+          <BellRingingIcon className='size-4 text-amber-600 dark:text-amber-500' />
-        <div className='flex items-center gap-1 rounded-full bg-emerald-100 px-2.5 py-1 text-xs font-medium text-emerald-700 dark:bg-emerald-900/40 dark:text-emerald-400'>
+        <div className='flex items-center gap-1 rounded-full bg-emerald-100 px-2.5 py-1 text-xs font-medium text-emerald-600 dark:bg-emerald-900/40 dark:text-emerald-500'>
-                  <TrendUpIcon className='size-3 text-emerald-600 dark:text-emerald-400' />
+                  <TrendUpIcon className='size-3 text-emerald-600 dark:text-emerald-500' />
As per coding guidelines: Apply danger color as red-500/600, success as emerald-500/600, warning as amber-500/600 for semantic status indicators.

Also applies to: 1244-1267, 1347-1350, 1571-1574

🤖 Fix all issues with AI agents
In `@web/app/components/Header/index.tsx`:
- Around line 412-426: Update the dark-mode accent classes in the CommunityLinks
component: replace dark:text-indigo-400 with dark:text-indigo-500 and update any
corresponding dark:hover/text variants (e.g., dark:hover:text-indigo-100) to use
the indigo-500 token for consistency; locate the CommunityLinks JSX
(DiscordLogoIcon usage and its parent anchor) and make the same change in the
other similar component occurrences referenced (the other block using
Discord/Community links) so dark-mode uses indigo-500 as the primary accent.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
web/app/pages/Project/tabs/Errors/NoErrorDetails.tsx (1)

8-16: ⚠️ Potential issue | 🟡 Minor

Align layout, typography, and color tokens with the design system.

This block currently diverges from the specified max-width/padding, warm gray + slate palette, and semantic warning color, and uses non-compliant font weights for heading/body text.

✅ Suggested adjustments
-    <div className='mx-auto w-full max-w-2xl py-16 text-center text-gray-900 dark:text-gray-50'>
-      <div className='mx-auto mb-6 flex size-14 items-center justify-center rounded-xl bg-gray-100 dark:bg-slate-800'>
-        <WarningIcon className='size-7 text-gray-700 dark:text-gray-200' />
+    <div className='mx-auto w-full max-w-7xl px-4 sm:px-6 lg:px-8 py-16 text-center text-stone-900 dark:text-slate-100'>
+      <div className='mx-auto mb-6 flex size-14 items-center justify-center rounded-xl bg-gray-50 dark:bg-slate-800 ring-1 ring-black/5 dark:ring-white/10'>
+        <WarningIcon className='size-7 text-amber-600 dark:text-amber-500' />
       </div>
-      <h3 className='text-xl font-medium tracking-tight'>
+      <h3 className='text-xl font-bold tracking-tight'>
         {t('project.noErrorDetails')}
       </h3>
-      <p className='mx-auto mt-2 max-w-md text-sm whitespace-pre-line text-gray-800 dark:text-gray-200'>
+      <p className='mx-auto mt-2 max-w-md text-sm font-medium whitespace-pre-line text-stone-700 dark:text-slate-200'>
         {t('project.noErrorDesc')}
       </p>
     </div>

If the parent already handles max-w-7xl + section padding, you can drop those from this component.
As per coding guidelines: Use indigo-600/500 for accents, warm grays in light mode, slate in dark mode, gray-50 for light backgrounds, amber-500/600 for warning indicators, and font weights (bold headings, medium body text).

web/app/pages/Project/tabs/Sessions/Sessions.tsx (1)

282-289: ⚠️ Potential issue | 🟡 Minor

Inconsistent error color: use text-red-500 for danger indicators.

The mobile error indicator uses text-red-400 while the desktop view (Line 328) uses text-red-500. The coding guidelines specify red-500/600 for danger colors.

🎨 Proposed fix for color consistency
               {session.errors > 0 ? (
                 <span
-                  className='flex items-center text-red-400'
+                  className='flex items-center text-red-500'
                   title={t('dashboard.errors')}
                 >
                   <WarningIcon className='mr-1 size-4' /> {session.errors}
                 </span>
               ) : null}

As per coding guidelines: "Apply danger color as red-500/600".

web/app/components/Footer/index.tsx (2)

74-399: ⚠️ Potential issue | 🟡 Minor

Bump icon colors to the required accent/semantic tokens.

Several nav items use 400-level hues (e.g., indigo-400/amber-400/rose-400/emerald-400). The design tokens call for indigo-600/500 and semantic colors at 500/600. Consider uplifting these across the navigation arrays.

🎨 Suggested update (apply similarly across arrays)
-    iconColor: 'text-indigo-400',
+    iconColor: 'text-indigo-600 dark:text-indigo-500',

-    iconColor: 'text-amber-400',
+    iconColor: 'text-amber-500',

-    iconColor: 'text-rose-400',
+    iconColor: 'text-red-500',

-    iconColor: 'text-emerald-400',
+    iconColor: 'text-emerald-500',

As per coding guidelines: Use indigo-600 as the primary accent color in light mode and indigo-500 in dark mode; Apply danger color as red-500/600, success as emerald-500/600, warning as amber-500/600 for semantic status indicators.


503-582: ⚠️ Potential issue | 🟡 Minor

Use medium weight for body link text.

Footer links are body text and should use font-medium per typography guidance.

📝 Suggested update
-        className='underline-animate text-sm text-white transition-colors'
+        className='underline-animate text-sm font-medium text-white transition-colors'
-      className='underline-animate text-sm text-gray-200 transition-colors hover:text-white'
+      className='underline-animate text-sm font-medium text-gray-200 transition-colors hover:text-white'

As per coding guidelines: Use font weights: medium for body text, semibold for labels, bold for headings.

🤖 Fix all issues with AI agents
In `@web/app/components/Header/index.tsx`:
- Around line 82-105: Update the analytics solution item's accent token by
changing its className where icon: ChartBarIcon is defined in Header
(index.tsx); replace 'text-indigo-500 dark:text-indigo-400' with the primary
accent tokens 'text-indigo-600 dark:text-indigo-500' so light mode uses
indigo-600 and dark mode uses indigo-500.

In `@web/app/components/pricing/BillingPricing.tsx`:
- Line 373: The QuestionIcon instance in BillingPricing.tsx is using stroke
classes which Phosphor icons ignore; change the Tailwind classes on QuestionIcon
from 'stroke-yellow-800 dark:stroke-yellow-500' to color classes that affect
currentColor (e.g., 'text-yellow-800 dark:text-yellow-500') so the icon picks up
the intended color via currentColor; update the className passed to QuestionIcon
accordingly.

In `@web/app/pages/Project/tabs/Errors/ErrorsView.tsx`:
- Around line 1279-1295: The PercentIcon for the errorRate StatCard is using the
orange warning color; update the semantic warning color to amber by changing the
className on PercentIcon from 'text-orange-600' to 'text-amber-600' in the
StatCard that renders value={`${overview?.stats?.errorRate || 0}%`} (look for
the PercentIcon and the StatCard rendering errorRate) so it follows the
project's semantic color guidelines.

In `@web/app/pages/Project/View/components/Filters.tsx`:
- Line 335: In the Filters.tsx render where the XIcon component is used, remove
the ineffective Tailwind class "stroke-2" from the className and instead set
Phosphor's weight prop (e.g., weight="bold" or "regular" as appropriate) on the
XIcon component to control stroke thickness; locate the XIcon usage to update
className and add the weight prop so visual styling is handled by Phosphor
rather than a CSS stroke utility.

In `@web/app/routes/_index.tsx`:
- Around line 782-783: The CursorClickIcon (and any similar icon instances)
currently use "text-indigo-600 dark:text-indigo-400"; update the className to
"text-indigo-600 dark:text-indigo-500" so light mode keeps indigo-600 and dark
mode uses indigo-500; search for other occurrences (noted also around the other
occurrence) and apply the same replacement to any elements using
"dark:text-indigo-400".

In `@web/app/ui/FilterValueInput.tsx`:
- Around line 81-89: FilterValueInput.tsx currently defines a duplicate
deviceIconMapping; remove the local deviceIconMapping and instead import the
canonical mapping exported from ViewProject.helpers.tsx (the same mapping used
by CaptchaView.tsx), or better yet move the mapping into a new shared utility
that accepts an icon size parameter; then update the usage in FilterValueInput
(where icons are rendered) to apply the desired "size-4" class (either by
calling the shared factory with size="4" or by setting the className via
React.cloneElement or a small wrapper) so you avoid duplication and keep
consistent size control between ViewProject.helpers.tsx (size-5) and
FilterValueInput (size-4).

In `@web/app/ui/Modal.tsx`:
- Around line 102-115: The info/warning color classes in Modal.tsx use the wrong
design tokens; update the JSX branches where type === 'info' (InfoIcon) and type
=== 'warning' (WarningOctagonIcon) to use indigo for info and amber for warning:
replace bg-blue-100 with bg-indigo-100 and text-blue-600 with text-indigo-600 in
the info block, and replace bg-orange-100 with bg-amber-100 (keeping
text-amber-600) in the warning block, ensuring both div and Icon className
tokens follow the indigo-600 / amber-600 and bg-indigo-100 / bg-amber-100
conventions used elsewhere for semantic status colors.
🧹 Nitpick comments (8)
web/app/styles/tailwind.css (1)

85-105: Add reduced-motion handling for underline animation.

The underline animation uses transform transitions but doesn’t respect prefers-reduced-motion. Please add a reduced-motion override to disable the transition.
As per coding guidelines: Respect reduced-motion preferences in animations and transitions.

🛠️ Suggested fix
 .underline-animate::after {
   content: '';
   position: absolute;
   left: 0;
   right: 0;
   bottom: -2px;
   height: 1.5px;
   transform: scaleX(0);
   transform-origin: center;
   transition: transform var(--default-transition-duration, 250ms) ease;
   background: currentColor;
   opacity: 1;
 }
 .underline-animate:hover::after,
 .underline-animate:focus-visible::after {
   transform: scaleX(1);
 }
+
+@media (prefers-reduced-motion: reduce) {
+  .underline-animate::after {
+    transition: none;
+  }
+}
web/app/pages/Project/tabs/Profiles/Profiles.tsx (1)

176-183: Minor: Inconsistent error color between mobile and desktop views.

The mobile error indicator uses text-red-400 (line 178), while the desktop version uses text-red-500 (line 216). Per coding guidelines, danger colors should use red-500/600 for semantic status indicators. Consider aligning the mobile view for visual consistency.

🎨 Suggested fix
               {profile.errorsCount > 0 ? (
                 <span
-                  className='flex items-center text-red-400'
+                  className='flex items-center text-red-500'
                   title={t('dashboard.errors')}
                 >
web/app/pages/Project/tabs/Alerts/ProjectAlertsView.tsx (3)

57-58: Minor: Warning uses yellow instead of amber.

Per coding guidelines, warning semantic indicators should use amber-500/600. This component uses yellow-* colors throughout. Consider updating to amber-* for consistency with design tokens if this is the intended warning pattern.


460-460: Nit: Inconsistent icon sizing syntax.

Uses h-8 w-8 while other icons in this file use the size-* shorthand (e.g., size-4, size-5). Consider using size-8 for consistency.

♻️ Suggested change
-              <BellRingingIcon className='mr-2 h-8 w-8' />
+              <BellRingingIcon className='mr-2 size-8' />

516-516: Nit: Same sizing inconsistency.

Same as above—consider using size-8 for consistency with other icons in the file.

♻️ Suggested change
-              <BellRingingIcon className='mr-2 h-8 w-8' />
+              <BellRingingIcon className='mr-2 size-8' />
web/app/ui/FilterValueInput.tsx (2)

368-368: Minor inconsistency: prefer size-4 for consistent class usage.

The CaretUpDownIcon uses h-4 w-4 while most other icons in this file use size-4. Same applies to PlusIcon (line 399) and CheckIcon (line 450). Consider using size-4 throughout for consistency.

♻️ Suggested unification
-            <CaretUpDownIcon className='h-4 w-4 text-gray-400' />
+            <CaretUpDownIcon className='size-4 text-gray-400' />

Similarly for line 399:

-                  <PlusIcon className='h-4 w-4' />
+                  <PlusIcon className='size-4' />

And line 450:

-                        <CheckIcon className='ml-auto h-4 w-4 shrink-0 text-indigo-600 dark:text-indigo-400' />
+                        <CheckIcon className='ml-auto size-4 shrink-0 text-indigo-600 dark:text-indigo-400' />

374-374: Ring opacity deviates from coding guidelines.

The dropdown uses ring-black/10 but the coding guidelines specify ring-black/5 for light borders. Consider aligning with the guidelines unless the higher opacity is intentionally needed for this dropdown's visibility.

♻️ Align with coding guidelines
-        <div className='absolute z-50 mt-1 w-full min-w-[200px] rounded-md bg-white text-sm shadow-lg ring-1 ring-black/10 dark:bg-slate-800'>
+        <div className='absolute z-50 mt-1 w-full min-w-[200px] rounded-md bg-white text-sm shadow-lg ring-1 ring-black/5 dark:bg-slate-800 dark:ring-white/10'>

As per coding guidelines: "ring-1 ring-black/5 for light borders, ring-white/10 for dark borders".

docs/package.json (1)

25-25: Consider alphabetical ordering of dependencies.

The @phosphor-icons/react package is placed after clsx, breaking alphabetical order. For consistency with common package.json conventions, consider placing it with other @-scoped packages at the top.

📦 Suggested reordering
   "dependencies": {
     "@docusaurus/core": "3.9.2",
     "@docusaurus/preset-classic": "3.9.2",
     "@mdx-js/react": "^3.0.0",
     "@node-rs/jieba": "^1.7.0",
+    "@phosphor-icons/react": "^2.1.10",
     "autoprefixer": "^10.4.14",
     "clsx": "^2.1.0",
-    "@phosphor-icons/react": "^2.1.10",
     "postcss": "^8.4.23",

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
web/app/pages/Project/tabs/FeatureFlags/FeatureFlagsView.tsx (1)

980-987: ⚠️ Potential issue | 🟡 Minor

Update input ring tokens and focus color to match design guidelines.

This input still uses gray/slate rings and focus colors; guidelines call for ring-black/5 + ring-white/10 and focus:ring-indigo-500.

Suggested fix
-                  className='w-full rounded-lg border-0 bg-white py-2 pr-4 pl-9 text-sm text-gray-900 placeholder-gray-500 ring-1 ring-gray-300 ring-inset focus:ring-slate-900 focus:outline-none sm:w-64 dark:bg-slate-900 dark:text-gray-50 dark:placeholder-gray-400 dark:ring-slate-700/80 dark:focus:ring-slate-300'
+                  className='w-full rounded-lg border-0 bg-white py-2 pr-4 pl-9 text-sm text-gray-900 placeholder-gray-500 ring-1 ring-black/5 ring-inset focus:ring-indigo-500 focus:outline-none sm:w-64 dark:bg-slate-900 dark:text-gray-50 dark:placeholder-gray-400 dark:ring-white/10 dark:focus:ring-indigo-500'

As per coding guidelines, apply ring-1 ring-black/5 (light) and ring-white/10 (dark) plus focus:ring-indigo-500 for inputs.

🤖 Fix all issues with AI agents
In `@web/app/pages/Project/tabs/FeatureFlags/FeatureFlagsView.tsx`:
- Line 227: The ToggleRightIcon currently uses a single color class
'text-indigo-500'; update its className to apply indigo-600 in light mode and
indigo-500 in dark mode by replacing the class with a conditional Tailwind dark
variant (e.g., use 'text-indigo-600 dark:text-indigo-500' alongside existing
classes) on ToggleRightIcon to align with the indigo guideline.
🧹 Nitpick comments (7)
web/app/ui/TabHeader.tsx (1)

16-36: Align TabHeader styling with design tokens + body text weight.

Consider using ring-based borders and medium body text for the description to match the design system.

♻️ Suggested tweaks
-        <div className='flex h-14 w-14 shrink-0 items-center justify-center rounded-lg border border-gray-200 p-2 dark:border-slate-700'>
+        <div className='flex h-14 w-14 shrink-0 items-center justify-center rounded-lg ring-1 ring-black/5 p-2 dark:ring-white/10'>
           <Icon
             className={cx('h-full w-full', iconColorClass)}
             weight='duotone'
           />
         </div>
         <div>
           <Text as='h2' size='lg' weight='semibold'>
             {label}
           </Text>
-          <Text as='p' size='sm' colour='muted'>
+          <Text as='p' size='sm' weight='medium' colour='muted'>
             {description}
           </Text>
         </div>
       </div>
-      <hr className='mt-6 border-gray-200 dark:border-slate-700/80' />
+      <hr className='mt-6 border-black/5 dark:border-white/10' />
     </div>
   )
 }

As per coding guidelines: Use Tailwind CSS design tokens: gray-50 for light backgrounds, slate-900 for dark backgrounds, white/slate-800 for cards, ring-1 ring-black/5 for light borders, ring-white/10 for dark borders; Use font weights: medium for body text, semibold for labels, bold for headings.

web/app/pages/UserSettings/components/Socialisations.tsx (1)

1-1: Use semantic status colors and card ring tokens for the SSO table.

Status icons should use red-500/emerald-500 and the card should use ring borders + slate-800 in dark mode per design tokens.

♻️ Suggested tweaks
-    <div className='mt-2 overflow-hidden rounded-lg border border-gray-200 bg-white dark:border-slate-700 dark:bg-slate-900'>
+    <div className='mt-2 overflow-hidden rounded-lg bg-white ring-1 ring-black/5 dark:bg-slate-800 dark:ring-white/10'>
@@
-                      <XCircleIcon
-                        className='mr-1.5 h-5 w-5 shrink-0 text-red-400'
+                      <XCircleIcon
+                        className='mr-1.5 h-5 w-5 shrink-0 text-red-500'
                         aria-hidden='true'
                       />
@@
-                      <CheckCircleIcon
-                        className='mr-1.5 h-5 w-5 shrink-0 text-green-400'
+                      <CheckCircleIcon
+                        className='mr-1.5 h-5 w-5 shrink-0 text-emerald-500'
                         aria-hidden='true'
                       />

As per coding guidelines: Use Tailwind CSS design tokens: gray-50 for light backgrounds, slate-900 for dark backgrounds, white/slate-800 for cards, ring-1 ring-black/5 for light borders, ring-white/10 for dark borders; Apply danger color as red-500/600, success as emerald-500/600, warning as amber-500/600 for semantic status indicators.

Also applies to: 175-229

web/app/pages/Project/Settings/ProjectSettings.tsx (1)

49-49: TabHeader integration is clean; tweak revenue icon color to semantic success.

Everything composes well with the new header + activeTabConfig. Consider switching the revenue tab icon to emerald-500.

♻️ Suggested tweak
-          iconColor: 'text-green-500',
+          iconColor: 'text-emerald-500',

As per coding guidelines: Apply danger color as red-500/600, success as emerald-500/600, warning as amber-500/600 for semantic status indicators.

Also applies to: 359-461, 912-913, 946-1377

web/app/pages/Project/View/components/ProjectSidebar.tsx (2)

532-532: Consider adding weight='duotone' to XIcon for consistency.

All other icons in this file use weight='duotone', but the XIcon here doesn't have the weight prop. While this works (defaults to 'regular'), it creates visual inconsistency with other icons.

Suggested fix
-            <XIcon className='h-5 w-5' />
+            <XIcon className='h-5 w-5' weight='duotone' />

734-734: Consider adding weight='duotone' to ListIcon for consistency.

Similar to the XIcon above, the ListIcon in the mobile trigger lacks the weight='duotone' prop that other icons in this file use.

Suggested fix
-        <ListIcon className='h-5 w-5' />
+        <ListIcon className='h-5 w-5' weight='duotone' />
web/app/pages/UserSettings/UserSettings.tsx (2)

149-176: Consider extracting SettingsSection to a shared component.

The SettingsSection component is well-structured and reusable. Since it appears to serve a common UI pattern for settings pages, consider moving it to ~/ui/SettingsSection for reuse across other settings pages (e.g., project settings).


663-703: Duplicate table markup for shared projects.

The shared projects table is duplicated between the isSelfhosted branch (lines 668-702) and the non-selfhosted branch (lines 731-766). Consider extracting this into a reusable component or variable to reduce duplication.

Suggested approach

Extract the shared projects table into a variable or sub-component:

const SharedProjectsTable = () => (
  <div className='overflow-hidden rounded-lg border border-gray-200 dark:border-slate-700'>
    <table className='min-w-full divide-y divide-gray-200 dark:divide-slate-700'>
      <thead className='bg-gray-50 dark:bg-slate-800'>
        <tr>
          <th scope='col' className='px-4 py-3 text-left text-xs font-bold tracking-wider text-gray-900 uppercase dark:text-white'>
            {t('profileSettings.sharedTable.project')}
          </th>
          <th scope='col' className='px-4 py-3 text-left text-xs font-bold tracking-wider text-gray-900 uppercase dark:text-white'>
            {t('profileSettings.sharedTable.role')}
          </th>
          <th scope='col' className='px-4 py-3 text-left text-xs font-bold tracking-wider text-gray-900 uppercase dark:text-white'>
            {t('profileSettings.sharedTable.joinedOn')}
          </th>
          <th scope='col' />
        </tr>
      </thead>
      <tbody className='divide-y divide-gray-200 bg-white dark:divide-slate-700 dark:bg-slate-900'>
        {_map(user?.sharedProjects, (item) => (
          <ProjectList key={item.id} item={item} />
        ))}
      </tbody>
    </table>
  </div>
)

Then use <SharedProjectsTable /> in both branches.

Also applies to: 726-766

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@web/app/pages/UserSettings/UserSettings.tsx`:
- Around line 592-607: Replace the clickable Text that toggles email fields to
render as a semantic button by using the Text component's as="button" prop and
moving the onClick handler to that button (target the Text component instance
that uses toggleShowEmailFields and showEmailFields and includes CaretDownIcon);
ensure it retains existing classes, aria-expanded reflecting showEmailFields,
and keyboard focusability. Do the same change for the password toggle Text (the
other Text with its onClick that shows/hides password fields), adding
as="button", aria-expanded, and preserving visual styles and the CaretDownIcon
behavior.
🧹 Nitpick comments (3)
web/app/ui/Text.tsx (1)

39-39: Consider defaulting type="button" when rendering as a button element.

When as="button" is used, the HTML <button> element defaults to type="submit", which can cause unintended form submissions. Consumers can override via spread props, but you may want to add a safeguard.

💡 Optional safeguard
 export const Text = ({
   children,
   as: Component = 'span',
   size = 'base',
   weight = 'normal',
   colour = 'primary',
   tracking = 'normal',
   truncate,
   code,
   className,
   ...props
 }: TextProps) => (
   <Component
     className={cn(
       sizeClasses[size],
       weightClasses[weight],
       colourClasses[colour],
       trackingClasses[tracking],
       { truncate },
       code &&
         'rounded bg-gray-200/80 px-1.5 py-0.5 font-mono dark:bg-slate-700',
       className,
     )}
+    {...(Component === 'button' && !('type' in props) ? { type: 'button' } : {})}
     {...props}
   >
     {children}
   </Component>
 )
web/app/pages/UserSettings/UserSettings.tsx (2)

719-762: Consider extracting the shared projects table to reduce duplication.

The shared projects table (lines 722-762 and 785-825) is duplicated between the isSelfhosted and !isSelfhosted branches. Since both render identical markup, consider extracting it or moving outside the conditional.

💡 Refactoring idea

Extract a SharedProjectsTable component or move the SettingsSection for shared projects outside of the isSelfhosted conditional since it appears in both branches.

// Rendered once, outside the conditional:
<SettingsSection
  title={t('profileSettings.shared')}
  description={t('profileSettings.sharedDesc')}
>
  {/* shared projects table */}
</SettingsSection>

Also applies to: 784-825


912-916: Nit: Empty spacer div for alignment.

The empty <div className='h-5' /> appears to be a height spacer to align with the icon in the adjacent button. Consider using consistent button styling or a transparent icon placeholder instead.

Comment on lines +592 to +607
<Text
size='sm'
weight='medium'
colour='primary'
className='mb-2 flex cursor-pointer items-center'
onClick={toggleShowEmailFields}
>
{showEmailFields
? t('common.cancel')
: t('profileSettings.changeEmailBtn')}
<CaretDownIcon
className={cx('ml-2 size-3 transition-transform', {
'rotate-180': showEmailFields,
})}
/>
</Text>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Accessibility: Use as="button" for keyboard navigation.

This interactive Text element uses onClick but renders as a <span>, making it inaccessible to keyboard users and screen readers. Now that Text supports as="button", use it here.

The same issue applies to the password toggle at lines 633-648.

♿ Proposed fix for email toggle
                     <Text
+                      as='button'
+                      type='button'
                       size='sm'
                       weight='medium'
                       colour='primary'
-                      className='mb-2 flex cursor-pointer items-center'
+                      className='mb-2 flex items-center'
                       onClick={toggleShowEmailFields}
                     >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<Text
size='sm'
weight='medium'
colour='primary'
className='mb-2 flex cursor-pointer items-center'
onClick={toggleShowEmailFields}
>
{showEmailFields
? t('common.cancel')
: t('profileSettings.changeEmailBtn')}
<CaretDownIcon
className={cx('ml-2 size-3 transition-transform', {
'rotate-180': showEmailFields,
})}
/>
</Text>
<Text
as='button'
type='button'
size='sm'
weight='medium'
colour='primary'
className='mb-2 flex items-center'
onClick={toggleShowEmailFields}
>
{showEmailFields
? t('common.cancel')
: t('profileSettings.changeEmailBtn')}
<CaretDownIcon
className={cx('ml-2 size-3 transition-transform', {
'rotate-180': showEmailFields,
})}
/>
</Text>
🤖 Prompt for AI Agents
In `@web/app/pages/UserSettings/UserSettings.tsx` around lines 592 - 607, Replace
the clickable Text that toggles email fields to render as a semantic button by
using the Text component's as="button" prop and moving the onClick handler to
that button (target the Text component instance that uses toggleShowEmailFields
and showEmailFields and includes CaretDownIcon); ensure it retains existing
classes, aria-expanded reflecting showEmailFields, and keyboard focusability. Do
the same change for the password toggle Text (the other Text with its onClick
that shows/hides password fields), adding as="button", aria-expanded, and
preserving visual styles and the CaretDownIcon behavior.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
web/app/components/Footer/index.tsx (2)

476-485: ⚠️ Potential issue | 🟡 Minor

Use indigo-500 for the dark-mode accent.

The dark-mode accent in the ThemeSelector should be indigo-500 instead of indigo-400.

Suggested change
-            'dark:text-indigo-400': item.key === 'dark',
+            'dark:text-indigo-500': item.key === 'dark',

589-591: ⚠️ Potential issue | 🟠 Major

Add light-mode variants and align dark text with slate tones.

The footer is locked to a dark palette (bg-slate-900, text-gray-200) with no light-mode support, despite the component having theme awareness via useTheme. This violates the coding guidelines requiring full light/dark mode support with warm grays for light mode and slate tones for dark mode.

Update the footer container (line 589), all headings (lines 605, 628, 654, 677, 703, 726), description paragraphs (lines 753, 775), SimpleLegalLink component (lines 552-575), and footer text (lines 823, 832) to include light-mode variants. Also update the SwetrixLogo hardcoded theme='dark' prop to be theme-aware, and ensure the GitHub button (line 807) colors are consistent with the footer's color scheme.

Suggested starting point
-    <footer
-      className='relative overflow-hidden border-t border-white/10 bg-slate-900 pt-16 pb-8'
+    <footer
+      className='relative overflow-hidden bg-gray-50 pt-16 pb-8 text-slate-900 ring-1 ring-black/5 dark:bg-slate-900 dark:text-slate-100 dark:ring-white/10'
-                <h3 className='mb-4 text-sm font-semibold text-gray-200'>
+                <h3 className='mb-4 text-sm font-semibold text-slate-900 dark:text-slate-200'>
-              <p className='mt-4 max-w-72 text-sm text-gray-200'>
+              <p className='mt-4 max-w-72 text-sm text-slate-700 dark:text-slate-200'>
-        className='text-sm text-gray-200 transition-colors hover:text-white'
+        className='text-sm text-slate-700 transition-colors hover:text-slate-900 dark:text-slate-200 dark:hover:text-white'
🤖 Fix all issues with AI agents
In `@web/app/components/Footer/index.tsx`:
- Around line 605-606: The footer component's section headings currently use the
utility class "font-semibold" (e.g., the h3 elements rendering section titles in
the Footer component) but should use "font-bold" per the style guide; update
each h3 that includes "font-semibold" (for example the h3 with classes 'mb-4
text-sm font-semibold text-gray-200' and the other similar h3 elements) to use
"font-bold" instead so all footer headings use bold weight.

In `@web/app/pages/UserSettings/UserSettings.tsx`:
- Around line 31-35: There is a formatting failure around the import block that
includes whitelist, languages, languageFlag and changeLanguage; run the
project's formatter (e.g., `oxfmt` or the repo's format command) on
UserSettings.tsx to reformat the import lines and surrounding code, then stage
the resulting changes so the CI pipeline passes.
- Around line 1126-1152: The language selection buttons lack a visible keyboard
focus ring; update the button element used in the language list (the button that
calls changeLanguage and renders the Flag and Text components) to include a
focus ring class such as focus:ring-indigo-500 (and optionally
focus:outline-none and focus:ring-2 or focus:ring-offset-1 for contrast) in its
className composition so the selected/hover styles remain but a clear indigo
focus indicator appears when the button receives keyboard focus.
🧹 Nitpick comments (3)
web/app/routes/_index.tsx (1)

448-451: Duplicate ring classes in dark mode.

The FeatureCard has dark:ring-slate-800/60 dark:ring-white/10 which applies two conflicting ring colors. The second one (dark:ring-white/10) will override the first.

🎨 Suggested fix - keep only one dark ring color
-      'flex h-full flex-col overflow-hidden bg-white ring-1 ring-gray-200 dark:bg-slate-800/25 dark:ring-slate-800/60 dark:ring-white/10',
+      'flex h-full flex-col overflow-hidden bg-white ring-1 ring-gray-200 dark:bg-slate-800/25 dark:ring-white/10',
web/app/pages/UserSettings/UserSettings.tsx (2)

905-926: Consider consistent button content alignment.

The "Logout all sessions" button uses an empty <div className='h-5' /> as a spacer while the "Delete account" button uses an actual icon. For consistency, either add an icon to both buttons or remove the spacer and handle alignment differently.

♻️ Suggested fix - either add icon or remove spacer

Option 1: Remove the empty div spacer

 <Button
   onClick={() => {
     logout(true)
   }}
   semiSmall
   semiDanger
 >
-  <>
-    <div className='h-5' />
-    {t('profileSettings.logoutAll')}
-  </>
+  {t('profileSettings.logoutAll')}
 </Button>

Option 2: Add a relevant icon (e.g., SignOutIcon from Phosphor)

+import { SignOutIcon } from '@phosphor-icons/react'
...
 <Button
   onClick={() => {
     logout(true)
   }}
   semiSmall
   semiDanger
 >
-  <>
-    <div className='h-5' />
-    {t('profileSettings.logoutAll')}
-  </>
+  <>
+    <SignOutIcon className='mr-1 h-5 w-5' />
+    {t('profileSettings.logoutAll')}
+  </>
 </Button>

1129-1129: Consider adding confirmation or loading state before page reload.

The changeLanguage function triggers a full page reload. If users have unsaved changes in other tabs/forms, they could lose data. Consider either:

  • Adding a brief loading indicator before reload
  • Showing a confirmation if there are pending changes

This is a UX enhancement and not blocking.

Comment on lines +605 to +606
<h3 className='mb-4 text-sm font-semibold text-gray-200'>
{t('footer.products')}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

head -n 610 web/app/components/Footer/index.tsx | tail -n 15

Repository: Swetrix/swetrix

Length of output: 873


🏁 Script executed:

rg 'font-semibold' web/app/components/Footer/index.tsx -n

Repository: Swetrix/swetrix

Length of output: 526


Headings should use bold font weight, not semibold.

The h3 section headings in the footer currently use font-semibold, but per the coding guidelines (Use font weights: medium for body text, semibold for labels, bold for headings), headings should use font-bold. This pattern affects multiple headings throughout the component (lines 605, 628, 654, 677, 703, 726).

🛠️ Suggested change
-                <h3 className='mb-4 text-sm font-semibold text-gray-200'>
+                <h3 className='mb-4 text-sm font-bold text-gray-200'>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<h3 className='mb-4 text-sm font-semibold text-gray-200'>
{t('footer.products')}
<h3 className='mb-4 text-sm font-bold text-gray-200'>
{t('footer.products')}
🤖 Prompt for AI Agents
In `@web/app/components/Footer/index.tsx` around lines 605 - 606, The footer
component's section headings currently use the utility class "font-semibold"
(e.g., the h3 elements rendering section titles in the Footer component) but
should use "font-bold" per the style guide; update each h3 that includes
"font-semibold" (for example the h3 with classes 'mb-4 text-sm font-semibold
text-gray-200' and the other similar h3 elements) to use "font-bold" instead so
all footer headings use bold weight.

Comment on lines 1126 to 1152
<button
key={lng}
type='button'
onClick={() => changeLanguage(lng)}
className={cx(
'flex flex-col items-center justify-center rounded-lg px-4 py-6 ring-1 ring-inset transition-all',
isSelected
? 'bg-gray-100 ring-gray-300 dark:bg-slate-800 dark:ring-slate-600'
: 'ring-gray-200 hover:bg-gray-50 hover:ring-gray-300 dark:ring-slate-700 dark:hover:bg-slate-800/50 dark:hover:ring-slate-600',
)}
>
<Flag
country={languageFlag[lng]}
size={32}
alt={languages[lng]}
className='mb-3'
/>
<Text
as='span'
size='sm'
weight={isSelected ? 'semibold' : 'medium'}
colour='inherit'
className='text-gray-900 dark:text-gray-100'
>
{languages[lng]}
</Text>
</button>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add visible focus states for keyboard accessibility.

The language selection buttons lack visible focus indicators. Per coding guidelines, interactive elements should have focus:ring-indigo-500 for focus states to support keyboard navigation.

♿ Proposed fix to add focus ring
 <button
   key={lng}
   type='button'
   onClick={() => changeLanguage(lng)}
   className={cx(
-    'flex flex-col items-center justify-center rounded-lg px-4 py-6 ring-1 ring-inset transition-all',
+    'flex flex-col items-center justify-center rounded-lg px-4 py-6 ring-1 ring-inset transition-all focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400',
     isSelected
       ? 'bg-gray-100 ring-gray-300 dark:bg-slate-800 dark:ring-slate-600'
       : 'ring-gray-200 hover:bg-gray-50 hover:ring-gray-300 dark:ring-slate-700 dark:hover:bg-slate-800/50 dark:hover:ring-slate-600',
   )}
 >
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<button
key={lng}
type='button'
onClick={() => changeLanguage(lng)}
className={cx(
'flex flex-col items-center justify-center rounded-lg px-4 py-6 ring-1 ring-inset transition-all',
isSelected
? 'bg-gray-100 ring-gray-300 dark:bg-slate-800 dark:ring-slate-600'
: 'ring-gray-200 hover:bg-gray-50 hover:ring-gray-300 dark:ring-slate-700 dark:hover:bg-slate-800/50 dark:hover:ring-slate-600',
)}
>
<Flag
country={languageFlag[lng]}
size={32}
alt={languages[lng]}
className='mb-3'
/>
<Text
as='span'
size='sm'
weight={isSelected ? 'semibold' : 'medium'}
colour='inherit'
className='text-gray-900 dark:text-gray-100'
>
{languages[lng]}
</Text>
</button>
<button
key={lng}
type='button'
onClick={() => changeLanguage(lng)}
className={cx(
'flex flex-col items-center justify-center rounded-lg px-4 py-6 ring-1 ring-inset transition-all focus:outline-none focus:ring-2 focus:ring-indigo-500 dark:focus:ring-indigo-400',
isSelected
? 'bg-gray-100 ring-gray-300 dark:bg-slate-800 dark:ring-slate-600'
: 'ring-gray-200 hover:bg-gray-50 hover:ring-gray-300 dark:ring-slate-700 dark:hover:bg-slate-800/50 dark:hover:ring-slate-600',
)}
>
<Flag
country={languageFlag[lng]}
size={32}
alt={languages[lng]}
className='mb-3'
/>
<Text
as='span'
size='sm'
weight={isSelected ? 'semibold' : 'medium'}
colour='inherit'
className='text-gray-900 dark:text-gray-100'
>
{languages[lng]}
</Text>
</button>
🤖 Prompt for AI Agents
In `@web/app/pages/UserSettings/UserSettings.tsx` around lines 1126 - 1152, The
language selection buttons lack a visible keyboard focus ring; update the button
element used in the language list (the button that calls changeLanguage and
renders the Flag and Text components) to include a focus ring class such as
focus:ring-indigo-500 (and optionally focus:outline-none and focus:ring-2 or
focus:ring-offset-1 for contrast) in its className composition so the
selected/hover styles remain but a clear indigo focus indicator appears when the
button receives keyboard focus.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@web/app/ui/Alert.tsx`:
- Around line 66-98: The file currently uses both a named export and a default
export for the Alert component (export const Alert ... and export default
Alert), causing duplicate/unused export warnings; remove the named export by
changing the component declaration from "export const Alert = (...)" to a plain
"const Alert = (...)" (keeping the AlertProps type and existing default export
"export default Alert"), and update any internal/other imports that assumed a
named import to use the default import instead.
- Around line 50-63: The success and tip variant style objects in Alert.tsx
still use green-* Tailwind classes; update the classes in the success and tip
objects (iconClass, containerClass, titleClass, textClass) to use the emerald
semantic palette (e.g., emerald-500/600 and matching dark variants) so
success/tip align with the semantic success color; locate the success and tip
objects in the Alert component and replace green-* values with corresponding
emerald-* values and ensure dark: variants use the emerald equivalents.

In `@web/app/ui/PasswordStrength.tsx`:
- Line 39: The file currently exports the PasswordStrength component twice
(named export "PasswordStrength" and a separate default export), causing
duplicate/unused export warnings; pick one style and remove the other—preferably
keep a single default export: make PasswordStrength a local/const/component and
export it as default (or alternatively remove the default export and keep only
the named export "PasswordStrength"), then update any imports across the
codebase to match the chosen export style to eliminate the duplicate/unused
export warnings.
🧹 Nitpick comments (2)
web/app/ui/PasswordStrength.tsx (1)

86-123: Consider adding accessibility attributes for screen readers.

The visual strength indicator isn't accessible to screen reader users. Adding an aria-label or role="status" with aria-live="polite" would announce strength changes.

♿ Suggested accessibility improvement
   return (
-    <div className={cx('space-y-1.5', className)}>
+    <div
+      className={cx('space-y-1.5', className)}
+      role='status'
+      aria-live='polite'
+      aria-label={strength !== 'empty' ? `Password strength: ${currentConfig.label}` : undefined}
+    >
       <div className='flex gap-1'>
web/app/pages/Project/Settings/ProjectSettings.tsx (1)

365-440: Align tab icon colors with the design token palette and add dark variants.

The new iconColor values introduce several non-standard accents and lack dark: variants. Consider standardizing to indigo for primary accents and to the semantic palette for warning/success/danger, with light/dark variants.

♻️ Suggested adjustment (example across the tab config)
-          iconColor: 'text-blue-500',
+          iconColor: 'text-indigo-600 dark:text-indigo-500',
...
-          iconColor: 'text-amber-500',
+          iconColor: 'text-amber-600 dark:text-amber-500',
...
-          iconColor: 'text-emerald-500',
+          iconColor: 'text-emerald-600 dark:text-emerald-500',
...
-          iconColor: 'text-teal-500',
+          iconColor: 'text-amber-600 dark:text-amber-500',
...
-          iconColor: 'text-purple-500',
+          iconColor: 'text-indigo-600 dark:text-indigo-500',
...
-          iconColor: 'text-green-500',
+          iconColor: 'text-emerald-600 dark:text-emerald-500',
...
-          iconColor: 'text-sky-500',
+          iconColor: 'text-indigo-600 dark:text-indigo-500',
...
-          iconColor: 'text-indigo-500',
+          iconColor: 'text-indigo-600 dark:text-indigo-500',
...
-          iconColor: 'text-orange-500',
+          iconColor: 'text-amber-600 dark:text-amber-500',
...
-          iconColor: 'text-red-500',
+          iconColor: 'text-red-600 dark:text-red-500',

As per coding guidelines: Use indigo-600 as the primary accent color in light mode and indigo-500 in dark mode; Apply danger color as red-500/600, success as emerald-500/600, warning as amber-500/600 for semantic status indicators.

Comment on lines +50 to +63
success: {
icon: CheckCircleIcon,
containerClass: 'bg-green-50 dark:bg-emerald-900/50',
iconClass: 'text-green-600 dark:text-emerald-400',
titleClass: 'text-green-900 dark:text-emerald-50',
textClass: 'text-green-800 dark:text-emerald-50',
},
tip: {
icon: LightbulbIcon,
containerClass: 'bg-green-50 dark:bg-emerald-900/50',
iconClass: 'text-green-600 dark:text-emerald-400',
titleClass: 'text-green-900 dark:text-green-50',
textClass: 'text-green-800 dark:text-green-50',
},
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Align success/tip colors with emerald semantic palette.

Success and tip variants still use green-* classes; use emerald to match the semantic success palette for consistency.

🎨 Suggested palette alignment
   success: {
     icon: CheckCircleIcon,
-    containerClass: 'bg-green-50 dark:bg-emerald-900/50',
-    iconClass: 'text-green-600 dark:text-emerald-400',
-    titleClass: 'text-green-900 dark:text-emerald-50',
-    textClass: 'text-green-800 dark:text-emerald-50',
+    containerClass: 'bg-emerald-50 dark:bg-emerald-900/50',
+    iconClass: 'text-emerald-600 dark:text-emerald-400',
+    titleClass: 'text-emerald-900 dark:text-emerald-50',
+    textClass: 'text-emerald-800 dark:text-emerald-50',
   },
   tip: {
     icon: LightbulbIcon,
-    containerClass: 'bg-green-50 dark:bg-emerald-900/50',
-    iconClass: 'text-green-600 dark:text-emerald-400',
-    titleClass: 'text-green-900 dark:text-green-50',
-    textClass: 'text-green-800 dark:text-green-50',
+    containerClass: 'bg-emerald-50 dark:bg-emerald-900/50',
+    iconClass: 'text-emerald-600 dark:text-emerald-400',
+    titleClass: 'text-emerald-900 dark:text-emerald-50',
+    textClass: 'text-emerald-800 dark:text-emerald-50',
   },
As per coding guidelines, Apply danger color as red-500/600, success as emerald-500/600, warning as amber-500/600 for semantic status indicators.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
success: {
icon: CheckCircleIcon,
containerClass: 'bg-green-50 dark:bg-emerald-900/50',
iconClass: 'text-green-600 dark:text-emerald-400',
titleClass: 'text-green-900 dark:text-emerald-50',
textClass: 'text-green-800 dark:text-emerald-50',
},
tip: {
icon: LightbulbIcon,
containerClass: 'bg-green-50 dark:bg-emerald-900/50',
iconClass: 'text-green-600 dark:text-emerald-400',
titleClass: 'text-green-900 dark:text-green-50',
textClass: 'text-green-800 dark:text-green-50',
},
success: {
icon: CheckCircleIcon,
containerClass: 'bg-emerald-50 dark:bg-emerald-900/50',
iconClass: 'text-emerald-600 dark:text-emerald-400',
titleClass: 'text-emerald-900 dark:text-emerald-50',
textClass: 'text-emerald-800 dark:text-emerald-50',
},
tip: {
icon: LightbulbIcon,
containerClass: 'bg-emerald-50 dark:bg-emerald-900/50',
iconClass: 'text-emerald-600 dark:text-emerald-400',
titleClass: 'text-emerald-900 dark:text-emerald-50',
textClass: 'text-emerald-800 dark:text-emerald-50',
},
🤖 Prompt for AI Agents
In `@web/app/ui/Alert.tsx` around lines 50 - 63, The success and tip variant style
objects in Alert.tsx still use green-* Tailwind classes; update the classes in
the success and tip objects (iconClass, containerClass, titleClass, textClass)
to use the emerald semantic palette (e.g., emerald-500/600 and matching dark
variants) so success/tip align with the semantic success color; locate the
success and tip objects in the Alert component and replace green-* values with
corresponding emerald-* values and ensure dark: variants use the emerald
equivalents.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@web/app/components/Header/index.tsx`:
- Around line 144-147: The CaretDownIcon instances use a direct
'transition-transform' and 'rotate-180' class which ignores users'
reduced-motion preferences; update the className usage for CaretDownIcon (and
the other similar occurrences in this file where CaretDownIcon or the same
cx('size-3 transition-transform', ...) pattern is used) to use motion-aware
Tailwind variants — e.g., wrap transition and rotation classes with motion-safe:
and provide motion-reduce: classes (or remove transforms) to respect
prefers-reduced-motion; modify the CX call for the CaretDownIcon components so
the transition and rotate classes are applied only under motion-safe and a
non-animating alternative is used under motion-reduce.
- Around line 100-115: The dark-mode color variants in the Header component's
solutions array use "-400" shades; update the objects for warning, danger, and
success to use semantic 500/600 dark shades: change the object with icon
WarningIcon (warning) to className 'text-amber-500 dark:text-amber-600', the one
with icon WarningIcon? (ensure correct mapping) — actually the danger entry with
icon WarningIcon should be 'text-red-500 dark:text-red-600', and the success
entry with icon ShieldCheckIcon to 'text-emerald-500 dark:text-emerald-600';
update the corresponding className strings (and any similar entries referencing
t('header.solutions.*')) to use -500/-600 as specified.

Comment on lines +100 to 115
className: 'text-amber-500 dark:text-amber-400',
},
{
name: t('header.solutions.errors.title'),
description: t('header.solutions.errors.desc'),
link: routes.errorTracking,
icon: BugIcon,
icon: WarningIcon,
className: 'text-red-500 dark:text-red-400',
},
{
name: t('header.solutions.captcha.title'),
description: t('header.solutions.captcha.desc'),
link: routes.captchaLanding,
icon: PuzzleIcon,
icon: ShieldCheckIcon,
className: 'text-emerald-500 dark:text-emerald-400',
},
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Use 500/600 shades for warning/danger/success in dark mode.
Dark-mode variants currently use *-400; the semantic palette calls for *-500/600.

🎨 Suggested update
-    className: 'text-amber-500 dark:text-amber-400',
+    className: 'text-amber-500 dark:text-amber-500',
...
-    className: 'text-red-500 dark:text-red-400',
+    className: 'text-red-500 dark:text-red-500',
...
-    className: 'text-emerald-500 dark:text-emerald-400',
+    className: 'text-emerald-500 dark:text-emerald-500',

As per coding guidelines: Apply danger color as red-500/600, success as emerald-500/600, warning as amber-500/600 for semantic status indicators.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
className: 'text-amber-500 dark:text-amber-400',
},
{
name: t('header.solutions.errors.title'),
description: t('header.solutions.errors.desc'),
link: routes.errorTracking,
icon: BugIcon,
icon: WarningIcon,
className: 'text-red-500 dark:text-red-400',
},
{
name: t('header.solutions.captcha.title'),
description: t('header.solutions.captcha.desc'),
link: routes.captchaLanding,
icon: PuzzleIcon,
icon: ShieldCheckIcon,
className: 'text-emerald-500 dark:text-emerald-400',
},
className: 'text-amber-500 dark:text-amber-500',
},
{
name: t('header.solutions.errors.title'),
description: t('header.solutions.errors.desc'),
link: routes.errorTracking,
icon: WarningIcon,
className: 'text-red-500 dark:text-red-500',
},
{
name: t('header.solutions.captcha.title'),
description: t('header.solutions.captcha.desc'),
link: routes.captchaLanding,
icon: ShieldCheckIcon,
className: 'text-emerald-500 dark:text-emerald-500',
},
🤖 Prompt for AI Agents
In `@web/app/components/Header/index.tsx` around lines 100 - 115, The dark-mode
color variants in the Header component's solutions array use "-400" shades;
update the objects for warning, danger, and success to use semantic 500/600 dark
shades: change the object with icon WarningIcon (warning) to className
'text-amber-500 dark:text-amber-600', the one with icon WarningIcon? (ensure
correct mapping) — actually the danger entry with icon WarningIcon should be
'text-red-500 dark:text-red-600', and the success entry with icon
ShieldCheckIcon to 'text-emerald-500 dark:text-emerald-600'; update the
corresponding className strings (and any similar entries referencing
t('header.solutions.*')) to use -500/-600 as specified.

Comment on lines +144 to 147
<CaretDownIcon
className={cx('size-3 transition-transform', {
'rotate-180': open,
})}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Respect reduced-motion for caret rotation transitions.
Add motion-safe/motion-reduce variants to the new transition classes.

♿ Suggested update
-              className={cx('size-3 transition-transform', {
+              className={cx('size-3 motion-safe:transition-transform motion-reduce:transition-none', {
                 'rotate-180': open,
               })}
-                className={cx(
-                  'ml-1 size-4 transform-gpu transition-transform',
+                className={cx(
+                  'ml-1 size-4 transform-gpu motion-safe:transition-transform motion-reduce:transition-none',
                   {
                     'rotate-180': open,
                   },
                 )}
-                      className={cx(
-                        open ? 'rotate-180' : '',
-                        '-mr-1 ml-2 size-5 transform-gpu transition-transform',
-                      )}
+                      className={cx(
+                        open ? 'rotate-180' : '',
+                        '-mr-1 ml-2 size-5 transform-gpu motion-safe:transition-transform motion-reduce:transition-none',
+                      )}

As per coding guidelines: Respect reduced-motion preferences in animations and transitions.

Also applies to: 272-275, 319-323

🤖 Prompt for AI Agents
In `@web/app/components/Header/index.tsx` around lines 144 - 147, The
CaretDownIcon instances use a direct 'transition-transform' and 'rotate-180'
class which ignores users' reduced-motion preferences; update the className
usage for CaretDownIcon (and the other similar occurrences in this file where
CaretDownIcon or the same cx('size-3 transition-transform', ...) pattern is
used) to use motion-aware Tailwind variants — e.g., wrap transition and rotation
classes with motion-safe: and provide motion-reduce: classes (or remove
transforms) to respect prefers-reduced-motion; modify the CX call for the
CaretDownIcon components so the transition and rotate classes are applied only
under motion-safe and a non-animating alternative is used under motion-reduce.

@Blaumaus Blaumaus changed the title Consolidate icons Consolidate icons & improve UI Feb 1, 2026
@Blaumaus Blaumaus merged commit f112ce3 into main Feb 1, 2026
4 checks passed
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
web/app/components/Footer/index.tsx (1)

757-762: ⚠️ Potential issue | 🟡 Minor

Use indigo‑500 for the primary accent link in the dark footer.
The Swetrix link currently uses text-indigo-400 hover:text-indigo-300; for dark mode the primary accent should be indigo‑500 with a lighter hover.

🛠️ Suggested change
-                          className='text-indigo-400 hover:text-indigo-300'
+                          className='text-indigo-500 hover:text-indigo-400'

As per coding guidelines: Use indigo-600 as the primary accent color in light mode and indigo-500 in dark mode.

🤖 Fix all issues with AI agents
In `@web/app/routes/google-analytics-alternative.tsx`:
- Around line 403-406: Update the ShieldCheckIcon instances to use indigo-600
for the light-mode accent and indigo-500 for dark mode by changing the className
dark color token from dark:text-indigo-400 to dark:text-indigo-500; locate the
ShieldCheckIcon components (the one shown and the similar instance around the
other occurrence) and adjust their className strings so they read 'size-5
text-indigo-600 dark:text-indigo-500' to satisfy the light/dark accent
guideline.
- Around line 435-438: The LightningIcon currently uses an incorrect dark-mode
amber shade; update its className on the LightningIcon element to use the
semantic warning pair (amber-500 for light mode and amber-600 for dark mode)
instead of dark:text-amber-400 so it reads something like "text-amber-500
dark:text-amber-600" while preserving the existing sizing classes.
- Line 358: The negative status indicator is using non-standard 'rose-*' classes
on the XIcon; update the XIcon's className to use the project's danger palette
(e.g., replace 'text-rose-600 dark:text-rose-400' with the standard danger
shades such as 'text-red-600 dark:text-red-500' or 'text-red-500/600' per
guidelines) so the XIcon matches the prescribed semantic colors in the
google-analytics-alternative component.
🧹 Nitpick comments (6)
web/app/pages/UserSettings/components/Organisations.tsx (1)

94-129: Clean refactor from CSS-based hiding to explicit conditional rendering.

The change correctly removes the CLSX-based hidden class approach in favor of explicit null rendering for owners. This is more readable and maintainable.

One optional improvement: the Modal (lines 114-128) is rendered for all roles, but owners can never trigger it since they have no button to set showDeleteModal. Consider moving the Modal inside the non-owner conditional to avoid rendering unused JSX.

,

♻️ Optional: Move Modal inside non-owner branch
       <td className='px-4 py-3 text-right text-sm whitespace-nowrap'>
-        {role === 'owner' ? null : confirmed ? (
+        {role !== 'owner' && (
+          <>
+            {confirmed ? (
               <Button onClick={() => setShowDeleteModal(true)} danger small>
                 {t('common.quit')}
               </Button>
             ) : (
               <>
                 <Button
                   className='mr-2'
                   onClick={() => setShowDeleteModal(true)}
                   primary
                   small
                 >
                   {t('common.reject')}
                 </Button>
                 <Button onClick={onAccept} loading={isLoading} primary small>
                   {t('common.accept')}
                 </Button>
               </>
             )}
-        <Modal
-          onClose={() => {
-            setShowDeleteModal(false)
-          }}
-          onSubmit={() => {
-            setShowDeleteModal(false)
-            onQuit()
-          }}
-          submitText={t('common.yes')}
-          type='confirmed'
-          closeText={t('common.no')}
-          title={t('profileSettings.quitEntity', { entity: organisation.name })}
-          message={t('profileSettings.quitOrganisation')}
-          isOpened={showDeleteModal}
-        />
+            <Modal
+              onClose={() => setShowDeleteModal(false)}
+              onSubmit={() => {
+                setShowDeleteModal(false)
+                onQuit()
+              }}
+              submitText={t('common.yes')}
+              type='confirmed'
+              closeText={t('common.no')}
+              title={t('profileSettings.quitEntity', { entity: organisation.name })}
+              message={t('profileSettings.quitOrganisation')}
+              isOpened={showDeleteModal}
+            />
+          </>
+        )}
       </td>
web/app/ui/PasswordStrength.tsx (2)

64-75: Align “good/strong” colors with the semantic palette and make the label semibold.
“Good” currently uses yellow, which isn’t in the semantic palette, and the label weight is medium rather than semibold. Suggest updating to emerald variants and font-semibold for labels.

Suggested change
       good: {
         label: t('auth.passwordStrength.good'),
-        color: 'bg-yellow-500',
+        color: 'bg-emerald-500',
         bgColor: 'bg-gray-200 dark:bg-slate-700',
         segments: 3,
       },
       strong: {
         label: t('auth.passwordStrength.strong'),
-        color: 'bg-emerald-500',
+        color: 'bg-emerald-600',
         bgColor: 'bg-gray-200 dark:bg-slate-700',
         segments: 4,
       },
@@
-              'text-xs font-medium',
+              'text-xs font-semibold',
               strength === 'weak' && 'text-red-600 dark:text-red-400',
               strength === 'fair' && 'text-amber-600 dark:text-amber-400',
-              strength === 'good' && 'text-yellow-600 dark:text-yellow-400',
-              strength === 'strong' && 'text-emerald-600 dark:text-emerald-400',
+              strength === 'good' && 'text-emerald-500 dark:text-emerald-400',
+              strength === 'strong' && 'text-emerald-600 dark:text-emerald-400',

As per coding guidelines: Apply danger color as red-500/600, success as emerald-500/600, warning as amber-500/600 for semantic status indicators; Use font weights: medium for body text, semibold for labels, bold for headings.

Also applies to: 101-106


90-94: Respect reduced-motion preferences and use the small-radius token for segments.
These bars are small elements, and transitions should opt out under reduced motion.

Suggested change
-              'h-1 flex-1 rounded-full transition-colors duration-200',
+              'h-1 flex-1 rounded-md transition-colors duration-200 motion-reduce:transition-none motion-reduce:duration-0',

As per coding guidelines: Use border radius: rounded-md for small elements, rounded-lg for medium, rounded-xl for large, rounded-2xl for cards; Respect reduced-motion preferences in animations and transitions.

web/app/pages/Project/tabs/FeatureFlags/FeatureFlagsView.tsx (2)

148-155: Align semantic success colors with the emerald palette.

These status indicators still use green-* tokens; the design guideline calls for emerald-* for success states.

♻️ Suggested update
-              profile.lastResult
-                ? 'bg-green-100 text-green-700 dark:bg-green-900/30 dark:text-green-400'
+              profile.lastResult
+                ? 'bg-emerald-100 text-emerald-700 dark:bg-emerald-900/30 dark:text-emerald-400'
                 : 'bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400',
-                    flag.enabled
-                      ? 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400'
+                    flag.enabled
+                      ? 'bg-emerald-100 text-emerald-800 dark:bg-emerald-900/30 dark:text-emerald-400'
                       : 'bg-gray-100 text-gray-600 dark:bg-gray-700 dark:text-gray-400',
-                  flag.enabled
-                    ? 'text-green-600 hover:border-green-300 hover:bg-green-50 dark:text-green-400 hover:dark:border-green-700/80 dark:hover:bg-green-900/30'
+                  flag.enabled
+                    ? 'text-emerald-600 hover:border-emerald-300 hover:bg-emerald-50 dark:text-emerald-400 hover:dark:border-emerald-700/80 dark:hover:bg-emerald-900/30'
                     : 'text-gray-400 hover:border-gray-300 hover:bg-gray-50 dark:text-gray-500 hover:dark:border-slate-700/80 dark:hover:bg-slate-800',

As per coding guidelines, apply danger color as red-500/600, success as emerald-500/600, warning as amber-500/600 for semantic status indicators.

Also applies to: 230-236, 352-356


979-986: Add dark-mode icon color and use indigo focus ring for the search input.

The search icon lacks a dark-mode color, and the input focus ring should use indigo per the input focus guideline.

♻️ Suggested update
-                <MagnifyingGlassIcon className='absolute top-1/2 left-3 size-4 -translate-y-1/2 text-gray-400' />
+                <MagnifyingGlassIcon className='absolute top-1/2 left-3 size-4 -translate-y-1/2 text-gray-400 dark:text-slate-400' />
...
-                  className='w-full rounded-lg border-0 bg-white py-2 pr-4 pl-9 text-sm text-gray-900 placeholder-gray-500 ring-1 ring-gray-300 ring-inset focus:ring-slate-900 focus:outline-none sm:w-64 dark:bg-slate-900 dark:text-gray-50 dark:placeholder-gray-400 dark:ring-slate-700/80 dark:focus:ring-slate-300'
+                  className='w-full rounded-lg border-0 bg-white py-2 pr-4 pl-9 text-sm text-gray-900 placeholder-gray-500 ring-1 ring-gray-300 ring-inset focus:ring-indigo-500 focus:outline-none sm:w-64 dark:bg-slate-900 dark:text-gray-50 dark:placeholder-gray-400 dark:ring-slate-700/80 dark:focus:ring-indigo-500'

As per coding guidelines, implement full light and dark mode support with warm grays for light mode and slate tones for dark mode, and apply ring borders to inputs with focus:ring-indigo-500 for focus states.

web/app/components/Footer/index.tsx (1)

804-807: Align the GitHub CTA with the shared HeadlessUI button styling and tokenized colors.
The CTA uses bg-white/border-gray-300 and doesn’t follow the HeadlessUI primary button pattern or dark-mode ring tokens. Consider swapping to the shared HeadlessUI button component (if available) or updating the classes to match the token guidance.

🛠️ Suggested class alignment (if staying inline)
-                  className='inline-flex items-center justify-center rounded-md border border-gray-300 bg-white px-3 py-2 text-sm font-medium text-gray-700 transition-colors hover:bg-gray-50'
+                  className='inline-flex items-center justify-center rounded-md bg-slate-900 px-3 py-2 text-sm font-medium text-white ring-1 ring-white/10 transition-colors hover:bg-slate-800 dark:bg-slate-800'

As per coding guidelines: Use HeadlessUI-based buttons as primary components with bg-slate-900 for light mode and bg-slate-800 for dark mode; Use Tailwind CSS design tokens: gray-50 for light backgrounds, slate-900 for dark backgrounds, white/slate-800 for cards, ring-1 ring-black/5 for light borders, ring-white/10 for dark borders.

<td className='px-6 py-4 text-sm text-slate-700 dark:text-gray-200'>
<span className='inline-flex items-center gap-2'>
<XMarkIcon className='size-4 text-rose-600 dark:text-rose-400' />
<XIcon className='size-4 text-rose-600 dark:text-rose-400' />
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Use the standard danger palette for the negative indicator.
rose-* doesn’t match the prescribed danger colors for semantic negatives.

✅ Suggested fix
-                      <XIcon className='size-4 text-rose-600 dark:text-rose-400' />
+                      <XIcon className='size-4 text-red-600 dark:text-red-500' />

As per coding guidelines: Apply danger color as red-500/600, success as emerald-500/600, warning as amber-500/600 for semantic status indicators.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<XIcon className='size-4 text-rose-600 dark:text-rose-400' />
<XIcon className='size-4 text-red-600 dark:text-red-500' />
🤖 Prompt for AI Agents
In `@web/app/routes/google-analytics-alternative.tsx` at line 358, The negative
status indicator is using non-standard 'rose-*' classes on the XIcon; update the
XIcon's className to use the project's danger palette (e.g., replace
'text-rose-600 dark:text-rose-400' with the standard danger shades such as
'text-red-600 dark:text-red-500' or 'text-red-500/600' per guidelines) so the
XIcon matches the prescribed semantic colors in the google-analytics-alternative
component.

Comment on lines +403 to +406
<ShieldCheckIcon
className='size-5 text-indigo-600 dark:text-indigo-400'
weight='duotone'
/>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Align dark-mode accent to indigo-500.
The dark variant should use indigo-500 for the primary accent.

✅ Suggested fix
-                className='size-5 text-indigo-600 dark:text-indigo-400'
+                className='size-5 text-indigo-600 dark:text-indigo-500'
-                  className='size-5 text-indigo-600 dark:text-indigo-400'
+                  className='size-5 text-indigo-600 dark:text-indigo-500'

As per coding guidelines: Use indigo-600 as the primary accent color in light mode and indigo-500 in dark mode.

Also applies to: 422-425

🤖 Prompt for AI Agents
In `@web/app/routes/google-analytics-alternative.tsx` around lines 403 - 406,
Update the ShieldCheckIcon instances to use indigo-600 for the light-mode accent
and indigo-500 for dark mode by changing the className dark color token from
dark:text-indigo-400 to dark:text-indigo-500; locate the ShieldCheckIcon
components (the one shown and the similar instance around the other occurrence)
and adjust their className strings so they read 'size-5 text-indigo-600
dark:text-indigo-500' to satisfy the light/dark accent guideline.

Comment on lines +435 to +438
<LightningIcon
className='size-5 text-amber-500 dark:text-amber-400'
weight='duotone'
/>
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Align amber shades with the warning palette.
Dark mode should use amber-500/600 for semantic indicators.

✅ Suggested fix
-                  className='size-5 text-amber-500 dark:text-amber-400'
+                  className='size-5 text-amber-600 dark:text-amber-500'

As per coding guidelines: Apply danger color as red-500/600, success as emerald-500/600, warning as amber-500/600 for semantic status indicators.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<LightningIcon
className='size-5 text-amber-500 dark:text-amber-400'
weight='duotone'
/>
<LightningIcon
className='size-5 text-amber-600 dark:text-amber-500'
weight='duotone'
/>
🤖 Prompt for AI Agents
In `@web/app/routes/google-analytics-alternative.tsx` around lines 435 - 438, The
LightningIcon currently uses an incorrect dark-mode amber shade; update its
className on the LightningIcon element to use the semantic warning pair
(amber-500 for light mode and amber-600 for dark mode) instead of
dark:text-amber-400 so it reads something like "text-amber-500
dark:text-amber-600" while preserving the existing sizing classes.

@coderabbitai coderabbitai bot mentioned this pull request Feb 1, 2026
6 tasks
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