Skip to content

style(theme): retint light theme to a cool neutral/slate palette - #462

Open
Brosski224 wants to merge 1 commit into
mainfrom
theme-retint
Open

style(theme): retint light theme to a cool neutral/slate palette#462
Brosski224 wants to merge 1 commit into
mainfrom
theme-retint

Conversation

@Brosski224

Copy link
Copy Markdown
Collaborator

Cherry-picked from local main. Retints the light theme to a cool neutral/slate palette.

Replace the near-white/near-black + periwinkle-purple light theme with
a calmer cool-slate system across the whole app: canvas/card/border/text
tokens, primary buttons, and the accent color in src/index.css's
[data-theme='light'] block, plus matching updates to the pricing/plan-tier
cards, badges, and hero promo cards ("Support development", "Link your
calendar") that previously used saturated per-tier brand colors or were
hardcoded outside the theme system entirely.

Left untouched: dark mode, genuinely semantic/status colors (errors,
success, warnings), external-brand colors (About page social buttons),
and a few theme-independent tokens (toggle track color, decorative mesh
gradients) that are hardcoded identically for both themes by design.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EtDAY24ssvKnCAjELnLpp2
@github-actions

Copy link
Copy Markdown
Contributor

React Doctor found 116 issues in 10 files · 26 errors & 90 warnings · score 60 / 100 (Needs work) · vs main

Errors

90 warnings

src/components/Cropper.tsx

  • ⚠️ L205 Interaction on static element no-static-element-interactions

src/components/FeatureSpotlight.tsx

  • ⚠️ L2 Full Framer Motion import use-lazy-motion
  • ⚠️ L49 Large component is hard to read and change no-giant-component
  • ⚠️ L95 window.open without noopener window-open-without-noopener
  • ⚠️ L102 Unversioned localStorage key client-localstorage-no-version
  • ⚠️ L175 transition: all animates everything no-transition-all
  • ⚠️ L213 Array index used as a key no-array-index-as-key
  • ⚠️ L297 AnimatePresence unmounts with its exiting child motion-animate-presence-must-outlive-child

src/components/GlobalChatOverlay.tsx

  • ⚠️ L4 Full Framer Motion import use-lazy-motion
  • ⚠️ L133 Large component is hard to read and change no-giant-component
  • ⚠️ L167 Missing effect dependencies exhaustive-deps
  • ⚠️ L175 Missing effect dependencies exhaustive-deps
  • ⚠️ L186 Effect re-subscribes on a changing callback prefer-use-effect-event
  • ⚠️ L433 Missing effect dependencies exhaustive-deps
  • ⚠️ L480 Control missing accessible label control-has-associated-label
  • ⚠️ L484 transition: all animates everything no-transition-all
  • ⚠️ L515 Field relies on placeholder text for its label no-placeholder-only-field
  • ⚠️ L515 transition: all animates everything no-transition-all
  • ⚠️ L523 Control missing accessible label control-has-associated-label

src/components/Launcher.tsx

  • ⚠️ L12 Full Framer Motion import use-lazy-motion
  • ⚠️ L83 Large component is hard to read and change no-giant-component
  • ⚠️ L323 State only used in handlers rerender-state-only-in-handlers
  • ⚠️ L340 Live state pushed to parent via effect no-pass-live-state-to-parent
  • ⚠️ L340 Parent kept in sync with a callback effect no-prop-callback-in-effect
  • ⚠️ L391 Pure function rebuilt every render prefer-module-scope-pure-function
  • ⚠️ L420 Control missing accessible label control-has-associated-label
  • ⚠️ L434 Control missing accessible label control-has-associated-label
  • ⚠️ L789 Overly precise SVG path values rendering-svg-precision
  • ⚠️ L852 transition: all animates everything no-transition-all
  • ⚠️ L1003 transition: all animates everything no-transition-all
  • ⚠️ L1014 transition: all animates everything no-transition-all
  • ⚠️ L1022 transition: all animates everything no-transition-all
  • ⚠️ L1023 Control missing accessible label control-has-associated-label

src/components/MeetingChatOverlay.tsx

  • ⚠️ L4 Full Framer Motion import use-lazy-motion
  • ⚠️ L203 Large component is hard to read and change no-giant-component
  • ⚠️ L225 State adjusted after a prop changes no-adjust-state-on-prop-change
  • ⚠️ L230 Missing effect dependencies exhaustive-deps
  • ⚠️ L238 Missing effect dependencies exhaustive-deps
  • ⚠️ L241 All state reset on prop change no-reset-all-state-on-prop-change
  • ⚠️ L243 State adjusted after a prop changes no-adjust-state-on-prop-change
  • ⚠️ L244 State adjusted after a prop changes no-adjust-state-on-prop-change
  • ⚠️ L245 State adjusted after a prop changes no-adjust-state-on-prop-change
  • ⚠️ L258 Missing effect dependencies exhaustive-deps
  • ⚠️ L265 Missing effect dependencies exhaustive-deps
  • ⚠️ L551 Missing effect dependencies exhaustive-deps
  • ⚠️ L594 Control missing accessible label control-has-associated-label
  • ⚠️ L598 transition: all animates everything no-transition-all

src/components/ModelSelectorWindow.tsx

  • ⚠️ L24 Large component is hard to read and change no-giant-component
  • ⚠️ L40 Hand-rolled external store subscription prefer-use-sync-external-store
  • ⚠️ L229 Unversioned localStorage key client-localstorage-no-version

40 more warnings not shown.

⚠️ Warning: .github/workflows/react-doctor.yml is configured incorrectly. See below to fix.

React Doctor compares against main to report only the issues this pull request introduces. This run couldn't complete that comparison (usually a shallow CI checkout with no merge base), so it listed every issue in the changed files, including ones that already existed on main.

Add fetch-depth: 0 to the actions/checkout step in .github/workflows/react-doctor.yml so the checkout includes the history React Doctor needs:

 jobs:
   react-doctor:
     steps:
       - uses: actions/checkout@v5
+        with:
+          fetch-depth: 0

       - uses: millionco/react-doctor@v2

To silence this warning, set silence-missing-baseline-warning: true on the React Doctor action.

Reviewed by React Doctor for commit 0c0f376. See inline comments for fixes.

@@ -212,7 +212,7 @@ export const FeatureSpotlight: React.FC = () => {
{currentFeature.bullets.map((bullet, idx) => (
<div key={idx} className={`flex items-center justify-center group/item transition-transform duration-200 px-2`}>

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.

React Doctor · react-doctor/no-array-index-as-key (warning)

Your users can see & submit the wrong data when this list reorders or filters, so use a stable id like key={item.id}, not the array index "idx".

Fix → Use a stable id from the item, like key={item.id} or key={item.slug}. Index keys break when the list reorders or filters.

Docs

@@ -787,7 +787,7 @@ const Launcher: React.FC<LauncherProps> = ({ onStartMeeting, onOpenSettings, onO
>
<path
d="M12 2C7.58172 2 4 5.58172 4 10V22L7 19L9.5 21.5L12 19L14.5 21.5L17 19L20 22V10C20 5.58172 16.4183 2 12 2Z"

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.

React Doctor · react-doctor/rendering-svg-precision (warning)

Your users download extra bytes for SVG d precision they can't see, so round it to 1 or 2 decimals.

Fix → Round path, points, and transform decimals to 1 or 2 digits. The extra precision adds bytes with no visible difference.

Docs

const chatWindowBg = isLightTheme ? '#FAFAFA' : '#111111';

// Submit initial query when overlay opens
useEffect(() => {

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.

React Doctor · react-doctor/effect-needs-cleanup (error)

setTimeout creates a timer in useEffect without guaranteed cleanup. Return a cleanup function that owns every allocation so it does not leak after unmount.

Fix → Return a cleanup function that stops the subscription or timer: return () => target.removeEventListener(name, handler) for listeners, return () => clearInterval(id) or clearTimeout(id) for timers, return () => observer.disconnect() for observers, return () => socket.close() for connections, or return unsubscribe if the subscribe call already gave you one.

Docs

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