Skip to content

feat(brand): implement procedural paint daube SVG icon system#71

Merged
jbdevprimary merged 5 commits into
mainfrom
feat/brand-paint-daube-icons
Jan 19, 2026
Merged

feat(brand): implement procedural paint daube SVG icon system#71
jbdevprimary merged 5 commits into
mainfrom
feat/brand-paint-daube-icons

Conversation

@jbdevprimary
Copy link
Copy Markdown
Contributor

@jbdevprimary jbdevprimary commented Jan 19, 2026

Summary

  • Implement procedural paint daube SVG icon system with feTurbulence filters
  • Replace all emojis across the codebase with brand-aligned icons
  • Add 30+ icon variants with organic paint texture effects

Changes

  • Add PaintDaubeIcon component with seeded pseudo-random offset generation
  • Create icon presets (AgentIcon, SecurityIcon, SuccessIcon, LightbulbIcon, etc.)
  • Update all onboarding screens with brand icons
  • Update tab navigation with consistent iconography
  • Replace feedback component icons (Toast, Progress, Modal, BottomSheet)
  • Update form components (Checkbox, Select) with organic checkmarks
  • Update settings screens with brand-aligned icons
  • Add Icon component pattern for dynamic icon rendering

Test plan

  • TypeScript build passes (npx tsc --noEmit)
  • Visual review of icon rendering on iOS/Android
  • Verify icon colors match brand palette
  • Test icon turbulence effects at different sizes

Closes #70

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Style

    • Replaced emoji glyphs across the app with a unified, branded icon system for consistent visuals (onboarding, tabs, projects, settings, dialogs, badges, empty states, toasts, forms, file tree, errors).
  • New Features

    • Introduces a comprehensive icon set and presets used throughout the UI, improving clarity and brand consistency.
  • Refactor

    • Standardized icon APIs so components accept icon components and colors, preserving flows while enabling cohesive theming.

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

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Jan 19, 2026

📝 Walkthrough

Walkthrough

This PR adds a procedural PaintDaube SVG icon system and replaces emoji/string glyphs across the app with typed icon components (size, color, turbulence), updating many screens and shared UI primitives to use the new icons and adjusting affected public component props where applicable.

Changes

Cohort / File(s) Summary
Icon System Foundation
src/components/icons/PaintDaubeIcon.tsx, src/components/icons/index.ts
Adds a single-file procedural SVG icon system (BRAND_COLORS, IconColor/IconVariant, generateOrganicOffset, PaintDaubeFilter) and ~40+ preset icon components; exports new public API (IconColor, IconVariant, many Icon components). High logic density and new public surface.
Onboarding Screens
app/(onboarding)/welcome.tsx, app/(onboarding)/api-keys.tsx, app/(onboarding)/create-project.tsx, app/(onboarding)/github-auth.tsx, app/(onboarding)/complete.tsx
Replaces emoji/status glyphs with Icon components; introduces typed feature/capability shapes (Icon props) and updates layouts to render icons with size/color/turbulence. Visual/layout adjustments only.
Tab Navigation & Home
app/(tabs)/_layout.tsx, app/(tabs)/index.tsx, app/(tabs)/agents.tsx, app/(tabs)/chat.tsx, app/(tabs)/projects.tsx, app/index.tsx
Converts tab bar and screen icons to Icon components; replaces activity/quickstat emojis with ActivityIcon and other Icon components; updates agent avatar rendering to AvatarIcon components.
Settings & Credentials
app/(tabs)/settings.tsx, app/settings/credentials.tsx, app/settings/agents.tsx
Changes icon props from string to Icon component (+ iconColor) for SettingsItem/CredentialItem; swaps tip/security emojis for LightbulbIcon/SecurityIcon and updates call sites.
Shared UI Components
src/components/display/Badge.tsx, src/components/display/EmptyState.tsx, src/components/feedback/Toast.tsx, src/components/feedback/Progress.tsx, src/components/feedback/BottomSheet.tsx, src/components/feedback/Modal.tsx, src/components/form/Checkbox.tsx, src/components/form/Select.tsx
Migrates component icon APIs from string to component props (Icon/IconColor); updates rendering to instantiate icons (checkmarks, chevrons, close buttons, toast icons); public prop signatures changed for Badge and EmptyState.
Component-Specific Refactors
src/components/code/FileTree.tsx, src/components/chat/ApprovalCard.tsx, src/components/error/ErrorFallback.tsx
FileTree now maps filenames/extensions to Icon components; ApprovalCard uses Icon metadata for actions; ErrorFallback replaces error emoji with ErrorIcon.
Agent & Project Screens
app/agent/[id].tsx, app/(onboarding)/create-project.tsx, app/(tabs)/projects.tsx
Agent mock data and avatars now use AvatarIcon + avatarColor; capability checks and repo items use SuccessIcon/FolderIcon/SecurityIcon/StarIcon with star counts; layout tweaks added.
Not Found & Misc UI
app/+not-found.tsx, small screens
Replaces remaining emoji icons (e.g., search) with SearchIcon and other preset icons; minor layout adjustments.
Build / Config
.github/workflows/deploy-gh-pages.yml, app.json
Adds a staging step injecting no-cache meta tags into built HTML; adds expo.experiments.baseUrl = "/thumbcode" to app.json.

Sequence Diagram(s)

(Skipped — changes are UI/icon replacements and API surface updates rather than new multi-component control flows requiring sequential visualization.)

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Possibly related PRs

Poem

🎨 I’m a rabbit with a tiny brush,
Coral, teal, gold in a gentle rush,
No more emojis hopping through the view,
Paint daube swirls make every screen feel new,
🐰✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR contains one minor out-of-scope change: adding baseUrl configuration to app.json for deployment purposes, which is unrelated to the icon system implementation. Remove the baseUrl addition from app.json or move it to a separate PR focused on configuration changes, as it is not part of the brand icon system objectives.
Docstring Coverage ⚠️ Warning Docstring coverage is 13.64% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main change: implementing a procedural paint daube SVG icon system, which is the core feature of this PR.
Linked Issues check ✅ Passed The PR fully implements all coding requirements from issue #70: procedural SVG icon system with feTurbulence, brand colors, 30+ icon variants, and emoji replacement across onboarding, tabs, feedback, forms, and settings components.

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

✨ Finishing touches
  • 📝 Generate docstrings

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.

Comment thread src/components/icons/PaintDaubeIcon.tsx Fixed
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jan 19, 2026

🚀 Expo preview is ready!

  • Project → thumbcode
  • Platforms → android, ios
  • Scheme → thumbcode
  • Runtime Version → 0.1.0
  • More info

Learn more about 𝝠 Expo Github Action

Copy link
Copy Markdown
Contributor

@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: 0

Caution

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

⚠️ Outside diff range comments (4)
src/components/chat/ApprovalCard.tsx (3)

59-61: React Native does not support CSS string values for borderRadius.

The style borderRadius: '16px 12px 16px 14px' uses CSS string syntax, which is invalid in React Native. React Native requires individual numeric corner radius properties.

🐛 Proposed fix
       style={{
-        borderRadius: '16px 12px 16px 14px',
+        borderTopLeftRadius: 16,
+        borderTopRightRadius: 12,
+        borderBottomRightRadius: 16,
+        borderBottomLeftRadius: 14,
         borderLeftWidth: 4,

77-79: Same borderRadius issue with CSS string syntax.

This also uses invalid React Native syntax.

🐛 Proposed fix
           <View
             className={`px-2 py-0.5 ${wasApproved ? 'bg-teal-600' : 'bg-coral-500'}`}
-            style={{ borderRadius: '6px 8px 6px 8px' }}
+            style={{
+              borderTopLeftRadius: 6,
+              borderTopRightRadius: 8,
+              borderBottomRightRadius: 6,
+              borderBottomLeftRadius: 8,
+            }}
           >

97-99: Same issue on action button styles.

These also use string syntax for borderRadius.

🐛 Proposed fix
           <Pressable
             onPress={onReject}
             className="px-4 py-2 bg-neutral-700 active:bg-neutral-600"
-            style={{ borderRadius: '8px 10px 8px 12px' }}
+            style={{
+              borderTopLeftRadius: 8,
+              borderTopRightRadius: 10,
+              borderBottomRightRadius: 8,
+              borderBottomLeftRadius: 12,
+            }}
             accessibilityRole="button"
           <Pressable
             onPress={onApprove}
             className="px-4 py-2 bg-teal-600 active:bg-teal-700 ml-2"
-            style={{ borderRadius: '8px 10px 8px 12px' }}
+            style={{
+              borderTopLeftRadius: 8,
+              borderTopRightRadius: 10,
+              borderBottomRightRadius: 8,
+              borderBottomLeftRadius: 12,
+            }}
             accessibilityRole="button"

Also applies to: 105-108

src/components/display/Badge.tsx (1)

67-100: Apply variant text color to textIcon.
Right now text-based icons render without the variant’s color, so status dots can appear inconsistent.

✅ Proposed fix
-      {textIcon && !Icon && <Text className={`mr-1 ${sizing.text}`}>{textIcon}</Text>}
+      {textIcon && !Icon && (
+        <Text className={`mr-1 ${sizing.text} ${colors.text}`}>{textIcon}</Text>
+      )}
🧹 Nitpick comments (4)
src/components/icons/PaintDaubeIcon.tsx (1)

798-975: Consider extracting a shared base path for file variants.*
file, fileCode, fileData, fileDoc, fileStyle, fileWeb, fileMedia, fileConfig repeat the same outline. A helper (base file path + overlay) would cut duplication and keep tweaks consistent.

src/components/code/FileTree.tsx (1)

67-91: Hoist the icon map to avoid per-call allocation.
iconMap is recreated on every call; moving it to module scope avoids repeated allocations when rendering large trees.

♻️ Proposed refactor
+const FILE_ICON_MAP: Record<string, FileIconInfo> = {
+  ts: { Icon: FileCodeIcon, color: 'teal' },
+  tsx: { Icon: FileCodeIcon, color: 'teal' },
+  js: { Icon: FileCodeIcon, color: 'gold' },
+  jsx: { Icon: FileCodeIcon, color: 'gold' },
+  json: { Icon: FileDataIcon, color: 'gold' },
+  md: { Icon: FileDocIcon, color: 'warmGray' },
+  css: { Icon: FileStyleIcon, color: 'coral' },
+  scss: { Icon: FileStyleIcon, color: 'coral' },
+  html: { Icon: FileWebIcon, color: 'teal' },
+  png: { Icon: FileMediaIcon, color: 'coral' },
+  jpg: { Icon: FileMediaIcon, color: 'coral' },
+  jpeg: { Icon: FileMediaIcon, color: 'coral' },
+  svg: { Icon: FileMediaIcon, color: 'coral' },
+  gif: { Icon: FileMediaIcon, color: 'coral' },
+  git: { Icon: FileConfigIcon, color: 'warmGray' },
+  env: { Icon: FileConfigIcon, color: 'warmGray' },
+  lock: { Icon: FileConfigIcon, color: 'warmGray' },
+  yaml: { Icon: FileConfigIcon, color: 'warmGray' },
+  yml: { Icon: FileConfigIcon, color: 'warmGray' },
+};
+
 function getFileIconInfo(name: string): FileIconInfo {
   const ext = name.split('.').pop()?.toLowerCase();
-  const iconMap: Record<string, FileIconInfo> = {
-    ts: { Icon: FileCodeIcon, color: 'teal' },
-    tsx: { Icon: FileCodeIcon, color: 'teal' },
-    js: { Icon: FileCodeIcon, color: 'gold' },
-    jsx: { Icon: FileCodeIcon, color: 'gold' },
-    json: { Icon: FileDataIcon, color: 'gold' },
-    md: { Icon: FileDocIcon, color: 'warmGray' },
-    css: { Icon: FileStyleIcon, color: 'coral' },
-    scss: { Icon: FileStyleIcon, color: 'coral' },
-    html: { Icon: FileWebIcon, color: 'teal' },
-    png: { Icon: FileMediaIcon, color: 'coral' },
-    jpg: { Icon: FileMediaIcon, color: 'coral' },
-    jpeg: { Icon: FileMediaIcon, color: 'coral' },
-    svg: { Icon: FileMediaIcon, color: 'coral' },
-    gif: { Icon: FileMediaIcon, color: 'coral' },
-    git: { Icon: FileConfigIcon, color: 'warmGray' },
-    env: { Icon: FileConfigIcon, color: 'warmGray' },
-    lock: { Icon: FileConfigIcon, color: 'warmGray' },
-    yaml: { Icon: FileConfigIcon, color: 'warmGray' },
-    yml: { Icon: FileConfigIcon, color: 'warmGray' },
-  };
-  return iconMap[ext || ''] || { Icon: FileIcon, color: 'warmGray' };
+  return FILE_ICON_MAP[ext || ''] || { Icon: FileIcon, color: 'warmGray' };
 }
app/agent/[id].tsx (1)

25-26: Avoid relying on global React namespace for React.FC.
If allowUmdGlobalAccess isn’t enabled, this can fail type-checking. Prefer a typed import.

♻️ Suggested fix
-import { useState } from 'react';
+import { useState, type FC } from 'react';
@@
-type AgentAvatarIcon = React.FC<{ size?: number; color?: IconColor; turbulence?: number }>;
+type AgentAvatarIcon = FC<{ size?: number; color?: IconColor; turbulence?: number }>;
app/(onboarding)/welcome.tsx (1)

14-73: Narrow Feature.icon to supported variants and avoid fallback masking.

IconVariant includes many options, but FeatureIcon only supports four and defaults to AgentIcon, which can silently hide mismatches if a new feature is added. Consider narrowing the type and using a mapping for exhaustiveness.

♻️ Suggested refactor
-import {
+import {
   AgentIcon,
   MobileIcon,
   SecurityIcon,
   LightningIcon,
   ThumbIcon,
-  type IconVariant,
 } from '@/components/icons';
 
+type FeatureIconVariant = 'agent' | 'mobile' | 'security' | 'lightning';
+
 interface Feature {
-  icon: IconVariant;
+  icon: FeatureIconVariant;
   title: string;
   description: string;
   color: 'coral' | 'teal' | 'gold';
 }
 
+const FEATURE_ICONS: Record<FeatureIconVariant, typeof AgentIcon> = {
+  agent: AgentIcon,
+  mobile: MobileIcon,
+  security: SecurityIcon,
+  lightning: LightningIcon,
+};
+
 /** Feature icon component that renders the appropriate paint daube icon */
-function FeatureIcon({ variant, color }: { variant: IconVariant; color: Feature['color'] }) {
-  const iconProps = { size: 28, color, turbulence: 0.25 };
-
-  switch (variant) {
-    case 'agent':
-      return <AgentIcon {...iconProps} />;
-    case 'mobile':
-      return <MobileIcon {...iconProps} />;
-    case 'security':
-      return <SecurityIcon {...iconProps} />;
-    case 'lightning':
-      return <LightningIcon {...iconProps} />;
-    default:
-      return <AgentIcon {...iconProps} />;
-  }
+function FeatureIcon({ variant, color }: { variant: FeatureIconVariant; color: Feature['color'] }) {
+  const Icon = FEATURE_ICONS[variant];
+  return <Icon size={28} color={color} turbulence={0.25} />;
 }

Copy link
Copy Markdown
Contributor

@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 `@src/components/icons/PaintDaubeIcon.tsx`:
- Around line 22-32: BRAND_COLORS contains incorrect hex values for the brand
palette; update the coral, teal, and gold tokens inside the exported
BRAND_COLORS object so coral = "#FF7059", teal = "#0D9488", and gold =
"#F5D563", and ensure their corresponding dark variants (coralDark, tealDark,
goldDark) are adjusted to appropriate darker hexes consistent with the new base
colors (or regenerate them if your design system requires specific dark tokens)
while keeping the constant name BRAND_COLORS unchanged.
🧹 Nitpick comments (2)
src/components/icons/PaintDaubeIcon.tsx (2)

1044-1064: Clamp turbulence to the documented 0–1 range.

turbulence is documented as 0–1 but passed through unchecked. A negative or large value can produce invalid or extreme filters. Consider clamping once in PaintDaubeIcon.

♻️ Proposed fix
 export function PaintDaubeIcon({
   variant,
   color = 'coral',
   size = 24,
   turbulence = 0.3,
   seed = 42,
 }: PaintDaubeIconProps) {
   const filterId = `paint-daube-${variant}-${seed}`;
+  const clampedTurbulence = Math.max(0, Math.min(1, turbulence));
   const strokeColor = BRAND_COLORS[color];
   const pathData = ICON_PATHS[variant](seed);
@@
-        <PaintDaubeFilter id={filterId} turbulence={turbulence} />
+        <PaintDaubeFilter id={filterId} turbulence={clampedTurbulence} />

798-975: Reduce duplication across file icon paths.*

file, fileCode, fileData, fileDoc, fileStyle, fileWeb, fileMedia, fileConfig repeat the same outer file path. Consider extracting a shared base path builder to avoid drift and make edits cheaper.

Comment thread src/components/icons/PaintDaubeIcon.tsx Outdated
jbdevprimary and others added 4 commits January 18, 2026 22:54
- Add experiments.baseUrl: "/thumbcode" for GitHub Pages subdirectory
- Inject no-cache meta tags into HTML files for staging environment
- Fixes Expo app loading issue on GitHub Pages deployment

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Replace all emojis with brand-aligned procedural SVG icons using
feTurbulence filters for authentic paint texture effects.

- Add PaintDaubeIcon component with 30+ icon variants
- Create icon presets (AgentIcon, SecurityIcon, SuccessIcon, etc.)
- Update onboarding screens with brand icons
- Update tab navigation with consistent iconography
- Replace feedback component icons (Toast, Progress, Modal)
- Update form components (Checkbox, Select) with organic checkmarks
- Update settings screens with brand-aligned icons
- Add Icon component pattern for dynamic icon rendering

Closes #70

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Fixes linting warning about unused Circle import from react-native-svg.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove unused React imports (now using new JSX transform)
- Fix import type annotations for type-only imports
- Organize imports alphabetically per Biome rules
- Remove unused function parameters or prefix with underscore
- Fix formatting issues in tab layout component

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@jbdevprimary jbdevprimary force-pushed the feat/brand-paint-daube-icons branch from 41640f0 to 766eb9c Compare January 19, 2026 04:54
Updated icon color constants to match the documented brand palette:
- Coral: #F28B7D → #FF7059 (Thumb Coral)
- Teal: #51AFB9 → #0D9488 (Digital Teal)
- Gold: #F2CF79 → #F5D563 (Soft Gold)
- Charcoal: #1E1B18 → #151820 (Charcoal Navy)

Dark variants updated to match light mode specifications from CLAUDE.md.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@jbdevprimary
Copy link
Copy Markdown
Contributor Author

Fixed brand colors in commit 3145440 - Brand colors now align with CLAUDE.md P3 palette:

  • Coral: #FF7059
  • Teal: #0D9488
  • Gold: #F5D563
  • Charcoal: #151820

@sonarqubecloud
Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
0.0% Coverage on New Code (required ≥ 80%)
4.0% Duplication on New Code (required ≤ 3%)

See analysis details on SonarQube Cloud

@jbdevprimary jbdevprimary merged commit 17c22ac into main Jan 19, 2026
15 of 19 checks passed
@jbdevprimary jbdevprimary deleted the feat/brand-paint-daube-icons branch January 19, 2026 05:11
Copy link
Copy Markdown
Contributor

@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 @.github/workflows/deploy-gh-pages.yml:
- Around line 128-132: The "Inject no-cache headers for staging" step is
searching the wrong directory; change the find invocations that reference "dist"
to "docs-dist" so the sed injection and the file count (the find ... | wc -l in
the echo) operate on the built documentation; update both the find used for sed
and the find used in the echo to use "docs-dist" (preserve the existing sed
expression and step name).

In `@src/components/icons/PaintDaubeIcon.tsx`:
- Around line 21-31: BRAND_COLORS currently exposes charcoal and warmGray which
lets IconColor include neutrals; either remove those neutrals from BRAND_COLORS
and keep only coral/teal/gold, or move them into a separate NEUTRAL_COLORS
constant and update the IconColor type to only include the three brand keys.
Concretely: modify BRAND_COLORS to contain only coral, coralDark, teal,
tealDark, gold, goldDark; create a new NEUTRAL_COLORS with charcoal and
warmGray; and change the IconColor type/exports to be the union of only the
brand color keys (e.g., 'coral'|'coralDark'|'teal'|'tealDark'|'gold'|'goldDark')
so neutral colors cannot be used as IconColor.
🧹 Nitpick comments (4)
src/components/error/ErrorFallback.tsx (1)

61-61: Optional: drop redundant color prop.
ErrorIcon already defaults to coral; consider omitting color="coral" to reduce repetition unless you want the explicit override.

src/components/chat/ApprovalCard.tsx (1)

40-54: Optional: hoist the action map to avoid per-call allocations.

This keeps getActionInfo lightweight and avoids recreating the same object on each call.

♻️ Proposed refactor
- function getActionInfo(actionType: ApprovalMessage['metadata']['actionType']): ActionInfo {
-  const actionMap: Record<ApprovalMessage['metadata']['actionType'], ActionInfo> = {
-    commit: { Icon: EditIcon, iconColor: 'teal', label: 'Commit Changes', bgColor: 'bg-teal-500' },
-    push: { Icon: GitIcon, iconColor: 'coral', label: 'Push to Remote', bgColor: 'bg-coral-500' },
-    merge: { Icon: BranchIcon, iconColor: 'gold', label: 'Merge Branch', bgColor: 'bg-gold-500' },
-    deploy: { Icon: LightningIcon, iconColor: 'coral', label: 'Deploy', bgColor: 'bg-coral-600' },
-    file_change: {
-      Icon: FileIcon,
-      iconColor: 'teal',
-      label: 'File Changes',
-      bgColor: 'bg-teal-600',
-    },
-  };
-  return actionMap[actionType] || actionMap.commit;
-}
+const ACTION_INFO_MAP: Record<ApprovalMessage['metadata']['actionType'], ActionInfo> = {
+  commit: { Icon: EditIcon, iconColor: 'teal', label: 'Commit Changes', bgColor: 'bg-teal-500' },
+  push: { Icon: GitIcon, iconColor: 'coral', label: 'Push to Remote', bgColor: 'bg-coral-500' },
+  merge: { Icon: BranchIcon, iconColor: 'gold', label: 'Merge Branch', bgColor: 'bg-gold-500' },
+  deploy: { Icon: LightningIcon, iconColor: 'coral', label: 'Deploy', bgColor: 'bg-coral-600' },
+  file_change: {
+    Icon: FileIcon,
+    iconColor: 'teal',
+    label: 'File Changes',
+    bgColor: 'bg-teal-600',
+  },
+};
+
+function getActionInfo(actionType: ApprovalMessage['metadata']['actionType']): ActionInfo {
+  return ACTION_INFO_MAP[actionType] || ACTION_INFO_MAP.commit;
+}
app/(onboarding)/welcome.tsx (1)

56-71: Avoid silent fallback for unsupported feature icons

The default case returns AgentIcon, so a new or mistyped variant would render the wrong icon without any signal. Consider an explicit lookup map (or a guard) so unsupported variants fail loudly or render nothing.

🔧 Example adjustment
- function FeatureIcon({ variant, color }: { variant: IconVariant; color: Feature['color'] }) {
-   const iconProps = { size: 28, color, turbulence: 0.25 };
-
-   switch (variant) {
-     case 'agent':
-       return <AgentIcon {...iconProps} />;
-     case 'mobile':
-       return <MobileIcon {...iconProps} />;
-     case 'security':
-       return <SecurityIcon {...iconProps} />;
-     case 'lightning':
-       return <LightningIcon {...iconProps} />;
-     default:
-       return <AgentIcon {...iconProps} />;
-   }
- }
+const FEATURE_ICON_MAP = {
+  agent: AgentIcon,
+  mobile: MobileIcon,
+  security: SecurityIcon,
+  lightning: LightningIcon,
+} as const;
+
+function FeatureIcon({ variant, color }: { variant: IconVariant; color: Feature['color'] }) {
+  const iconProps = { size: 28, color, turbulence: 0.25 };
+  const Icon = FEATURE_ICON_MAP[variant];
+  return Icon ? <Icon {...iconProps} /> : null;
+}
app/(tabs)/agents.tsx (1)

27-28: Consider extracting the AgentAvatarIcon type to a shared location.

This type definition (React.FC<{ size?: number; color?: IconColor; turbulence?: number }>) is duplicated across multiple files (agents.tsx, chat.tsx, complete.tsx). Extracting it to @/components/icons would reduce duplication and ensure consistency.

♻️ Suggested refactor in src/components/icons/index.ts
// Add to the icons barrel export
export type IconComponentProps = {
  size?: number;
  color?: IconColor;
  turbulence?: number;
};
export type IconComponent = React.FC<IconComponentProps>;

Then import and use across consumer files:

-type AgentAvatarIcon = React.FC<{ size?: number; color?: IconColor; turbulence?: number }>;
+import { type IconComponent } from '@/components/icons';
+type AgentAvatarIcon = IconComponent;

Comment on lines +128 to +132
- name: Inject no-cache headers for staging
run: |
# Add no-cache meta tags to all HTML files for staging environment
find dist -name "*.html" -exec sed -i 's/<head>/<head>\n <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">\n <meta http-equiv="Pragma" content="no-cache">\n <meta http-equiv="Expires" content="0">/' {} \;
echo "Injected no-cache headers into $(find dist -name '*.html' | wc -l) HTML files"
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Wrong directory: dist should be docs-dist.

The documentation is built to docs-dist/ (see lines 52, 140), but this step searches in dist/. The find command will either fail or find zero files, so no cache headers will be injected.

🐛 Proposed fix
      - name: Inject no-cache headers for staging
        run: |
          # Add no-cache meta tags to all HTML files for staging environment
-          find dist -name "*.html" -exec sed -i 's/<head>/<head>\n  <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">\n  <meta http-equiv="Pragma" content="no-cache">\n  <meta http-equiv="Expires" content="0">/' {} \;
-          echo "Injected no-cache headers into $(find dist -name '*.html' | wc -l) HTML files"
+          find docs-dist -name "*.html" -exec sed -i 's/<head>/<head>\n  <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">\n  <meta http-equiv="Pragma" content="no-cache">\n  <meta http-equiv="Expires" content="0">/' {} \;
+          echo "Injected no-cache headers into $(find docs-dist -name '*.html' | wc -l) HTML files"
📝 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
- name: Inject no-cache headers for staging
run: |
# Add no-cache meta tags to all HTML files for staging environment
find dist -name "*.html" -exec sed -i 's/<head>/<head>\n <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">\n <meta http-equiv="Pragma" content="no-cache">\n <meta http-equiv="Expires" content="0">/' {} \;
echo "Injected no-cache headers into $(find dist -name '*.html' | wc -l) HTML files"
- name: Inject no-cache headers for staging
run: |
# Add no-cache meta tags to all HTML files for staging environment
find docs-dist -name "*.html" -exec sed -i 's/<head>/<head>\n <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate">\n <meta http-equiv="Pragma" content="no-cache">\n <meta http-equiv="Expires" content="0">/' {} \;
echo "Injected no-cache headers into $(find docs-dist -name '*.html' | wc -l) HTML files"
🤖 Prompt for AI Agents
In @.github/workflows/deploy-gh-pages.yml around lines 128 - 132, The "Inject
no-cache headers for staging" step is searching the wrong directory; change the
find invocations that reference "dist" to "docs-dist" so the sed injection and
the file count (the find ... | wc -l in the echo) operate on the built
documentation; update both the find used for sed and the find used in the echo
to use "docs-dist" (preserve the existing sed expression and step name).

Comment on lines +21 to +31
// Brand color hex values aligned with CLAUDE.md P3 "Warm Technical" palette
export const BRAND_COLORS = {
coral: '#FF7059', // Primary - Thumb Coral
coralDark: '#E85A4F', // Light mode variant
teal: '#0D9488', // Secondary - Digital Teal
tealDark: '#0F766E', // Light mode variant
gold: '#F5D563', // Accent - Soft Gold
goldDark: '#D4A84B', // Light mode variant
charcoal: '#151820', // Base Dark - Charcoal Navy
warmGray: '#696259',
} as const;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Brand palette mismatch: neutrals are exposed as IconColor

The header comment and PR objectives state icons should use only coral/teal/gold, but BRAND_COLORS (and thus IconColor) includes charcoal and warmGray, enabling non‑palette icon colors across the app. Either restrict IconColor to the three brand colors or explicitly update the guidelines to allow neutrals and keep them in a separate map/type to prevent accidental use.

💡 Possible direction
 export const BRAND_COLORS = {
   coral: '#FF7059',
-  coralDark: '#E85A4F',
   teal: '#0D9488',
-  tealDark: '#0F766E',
   gold: '#F5D563',
-  goldDark: '#D4A84B',
-  charcoal: '#151820',
-  warmGray: '#696259',
 } as const;

 export type IconColor = keyof typeof BRAND_COLORS;
📝 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
// Brand color hex values aligned with CLAUDE.md P3 "Warm Technical" palette
export const BRAND_COLORS = {
coral: '#FF7059', // Primary - Thumb Coral
coralDark: '#E85A4F', // Light mode variant
teal: '#0D9488', // Secondary - Digital Teal
tealDark: '#0F766E', // Light mode variant
gold: '#F5D563', // Accent - Soft Gold
goldDark: '#D4A84B', // Light mode variant
charcoal: '#151820', // Base Dark - Charcoal Navy
warmGray: '#696259',
} as const;
// Brand color hex values aligned with CLAUDE.md P3 "Warm Technical" palette
export const BRAND_COLORS = {
coral: '#FF7059', // Primary - Thumb Coral
teal: '#0D9488', // Secondary - Digital Teal
gold: '#F5D563', // Accent - Soft Gold
charcoal: '#151820', // Base Dark - Charcoal Navy
warmGray: '#696259',
} as const;
export type IconColor = keyof typeof BRAND_COLORS;
Suggested change
// Brand color hex values aligned with CLAUDE.md P3 "Warm Technical" palette
export const BRAND_COLORS = {
coral: '#FF7059', // Primary - Thumb Coral
coralDark: '#E85A4F', // Light mode variant
teal: '#0D9488', // Secondary - Digital Teal
tealDark: '#0F766E', // Light mode variant
gold: '#F5D563', // Accent - Soft Gold
goldDark: '#D4A84B', // Light mode variant
charcoal: '#151820', // Base Dark - Charcoal Navy
warmGray: '#696259',
} as const;
// Brand color hex values aligned with CLAUDE.md P3 "Warm Technical" palette
export const BRAND_COLORS = {
coral: '#FF7059', // Primary - Thumb Coral
teal: '#0D9488', // Secondary - Digital Teal
gold: '#F5D563', // Accent - Soft Gold
} as const;
export type IconColor = keyof typeof BRAND_COLORS;
🤖 Prompt for AI Agents
In `@src/components/icons/PaintDaubeIcon.tsx` around lines 21 - 31, BRAND_COLORS
currently exposes charcoal and warmGray which lets IconColor include neutrals;
either remove those neutrals from BRAND_COLORS and keep only coral/teal/gold, or
move them into a separate NEUTRAL_COLORS constant and update the IconColor type
to only include the three brand keys. Concretely: modify BRAND_COLORS to contain
only coral, coralDark, teal, tealDark, gold, goldDark; create a new
NEUTRAL_COLORS with charcoal and warmGray; and change the IconColor type/exports
to be the union of only the brand color keys (e.g.,
'coral'|'coralDark'|'teal'|'tealDark'|'gold'|'goldDark') so neutral colors
cannot be used as IconColor.

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.

[Brand] Replace emojis with procedural paint daube SVG icons

1 participant