-
Notifications
You must be signed in to change notification settings - Fork 26
Major UI Overhaul #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@plyght is attempting to deploy a commit to the exon Team on Vercel. A member of the Team first needs to authorize it. |
Important Review skippedMore than 25% of the files skipped due to max files limit. The review is being skipped to prevent a low-quality review. 39 files out of 146 files are above the max files limit of 100. Please upgrade to Pro plan to get higher limits. You can disable this status message by setting the """ WalkthroughThis update introduces a comprehensive UI and UX overhaul focused on the todo input experience, visual theming, and responsive design. A modal input dialog for adding todos is now available, triggered by keyboard shortcuts and a floating button, with stateful control for visibility. The todo addition logic now prepends new items, and layouts are reorganized for mobile and desktop, including conditional rendering and centering. The visual design is enhanced with new animated border and shadow components, a custom font, refined color theming, and dark mode improvements. Several new UI utility components and CSS utilities are added to support these features. Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant UI (HomeClient)
participant ModalInput
participant TodoList
User->>UI (HomeClient): Press 'n' or click '+'
UI (HomeClient)->>ModalInput: Show input modal
User->>ModalInput: Enter todo, submit
ModalInput->>UI (HomeClient): onAddTodo(newTodo)
UI (HomeClient)->>TodoList: Prepend new todo
User->>UI (HomeClient): Press Escape or click backdrop
UI (HomeClient)->>ModalInput: Hide input modal
Possibly related PRs
Poem
""" ✨ Finishing Touches
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. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this 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
🔭 Outside diff range comments (2)
app/HomeClient.tsx (2)
110-147
: 🛠️ Refactor suggestionStabilise the
keydown
handler to avoid unnecessary re-registrations
handleKeyDown
is re-created on every render because it’s defined insideuseEffect
without a stable reference, causing the listener to be removed/re-added on every state change listed in the dependency array (workspaces
,currentWorkspace
,isInputVisible
, …).
This is not harmful, but it is needless work and can produce subtle timing bugs if the cleanup fails.- useEffect(() => { - const handleKeyDown = (e: KeyboardEvent) => { + const handleKeyDown = useCallback((e: KeyboardEvent) => { … - } - document.addEventListener('keydown', handleKeyDown) - return () => { - document.removeEventListener('keydown', handleKeyDown) - } - }, [workspaces, setCurrentWorkspace, currentWorkspace, isInputVisible]) + }, [workspaces, currentWorkspace, isInputVisible]) + + useEffect(() => { + document.addEventListener('keydown', handleKeyDown, { passive: true }) + return () => document.removeEventListener('keydown', handleKeyDown) + }, [handleKeyDown])Benefits
• Only one listener lives for the component’s lifetime.
• Dependency list becomes minimal and easier to reason about.
• Using{ passive: true }
(nopreventDefault
for workspace shortcut) helps scrolling performance.
If you need to callpreventDefault
, you can conditionally switch to a non-passive listener.
287-304
:⚠️ Potential issueGenerate a temporary client-side id for optimistic todos
newTodo
is pushed into state without anid
. Until the server responds, React keys inTodoList
will beundefined
, and subsequent optimistic creations will all share that same key, risking list reconciliation glitches and duplicate map hits.- const newTodo = { + const newTodo = { + id: crypto.randomUUID(), // fallback id; replace when server responds ...todo,After the POST succeeds you already replace the placeholder with the server object, so no extra work is needed.
🧹 Nitpick comments (6)
app/layout.tsx (1)
29-31
: Consider accessibility implications of preventing zoomThe added viewport meta tag disables user zooming with
maximum-scale=1.0
anduser-scalable=no
, which improves the app-like experience on mobile but may create accessibility issues for users with visual impairments who rely on zooming to read content.Consider either:
- Allowing zooming for accessibility while maintaining your layout with:
-<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover" /> +<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=5.0, viewport-fit=cover" />
- If zoom must be disabled for the UI to function properly, ensure text sizes are sufficiently large and contrast meets WCAG standards.
components/ai-todo-input.tsx (1)
325-329
: Text centering and removal of problematic focus handlerThe input is now center-aligned which creates a more balanced appearance, and the removal of the onFocus handler addresses the issues mentioned in the comment.
Consider adding more detail to the comment about what specific issues the onFocus handler was causing to help future developers understand this decision.
components/ui/border-beam-mask.tsx (1)
20-22
: Consider using CSS custom properties for more flexible theming.While the inline style approach works, consider using CSS custom properties for the border color to better integrate with potential theme switching.
- style={{ - boxShadow: `inset 0 0 0 1px ${borderColor}`, - }} + style={{ + "--border-color": borderColor, + boxShadow: "inset 0 0 0 1px var(--border-color)", + } as React.CSSProperties}components/ui/border-beam.tsx (1)
38-39
: Long, complex class string could impact readability and maintenance.The pseudo-element styling is contained in a very long, complex class string that could be difficult to maintain. Consider breaking it into smaller, more manageable parts or using a dedicated CSS module.
- "before:absolute before:inset-0 before:rounded-[inherit] before:p-[var(--border-width)px] before:bg-[linear-gradient(to_right,var(--color-from),var(--color-to),var(--color-from))] before:animate-border-beam before:content-['']", + // Break into multiple lines for better readability + [ + "before:absolute before:inset-0 before:rounded-[inherit]", + "before:p-[var(--border-width)px]", + "before:bg-[linear-gradient(to_right,var(--color-from),var(--color-to),var(--color-from))]", + "before:animate-border-beam before:content-['']", + ].join(" "),app/HomeClient.tsx (1)
678-710
: Escape key should not close the modal while the input has unsaved textBecause the input dialog closes instantly on every
Escape
press, users lose the typed text by accident (e.g. trying to dismiss an autocomplete list).
Consider either:• Detect
e.target
insideAI-TodoInput
and ignoreEscape
if the event originated there, or
• Ask the user for confirmation whentitle
/description
fields are non-empty.No code diff provided since UX decision is needed.
app/globals.css (1)
5-39
: Verify that custom font files are shipped and served efficientlyFour
@font-face
blocks point at/fonts/OpenRunde-*.woff{,2}
.
Please confirm that:
- These files are included in the deployed
public/fonts
folder.woff2
is listed first so modern browsers pick the smaller file (✅ done).- Unused weights (e.g. 800) are not shipped to keep bundle size lean.
Minor but worth double-checking.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (8)
public/fonts/OpenRunde-Bold.woff
is excluded by!**/*.woff
public/fonts/OpenRunde-Bold.woff2
is excluded by!**/*.woff2
public/fonts/OpenRunde-Medium.woff
is excluded by!**/*.woff
public/fonts/OpenRunde-Medium.woff2
is excluded by!**/*.woff2
public/fonts/OpenRunde-Regular.woff
is excluded by!**/*.woff
public/fonts/OpenRunde-Regular.woff2
is excluded by!**/*.woff2
public/fonts/OpenRunde-Semibold.woff
is excluded by!**/*.woff
public/fonts/OpenRunde-Semibold.woff2
is excluded by!**/*.woff2
📒 Files selected for processing (14)
app/HomeClient.tsx
(5 hunks)app/globals.css
(4 hunks)app/layout.tsx
(1 hunks)components/ai-todo-input.tsx
(3 hunks)components/theme-toggle.tsx
(1 hunks)components/todo-input.tsx
(2 hunks)components/todo-item.tsx
(3 hunks)components/ui/animated-border.tsx
(1 hunks)components/ui/border-beam-interactive.tsx
(1 hunks)components/ui/border-beam-mask.tsx
(1 hunks)components/ui/border-beam.tsx
(1 hunks)components/ui/button.tsx
(1 hunks)components/ui/card.tsx
(1 hunks)tailwind.config.ts
(2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (7)
components/ui/card.tsx (1)
lib/utils.ts (1)
cn
(5-7)
components/ai-todo-input.tsx (1)
components/ui/animated-border.tsx (1)
AnimatedBorder
(11-46)
components/todo-input.tsx (1)
components/ui/animated-border.tsx (1)
AnimatedBorder
(11-46)
components/ui/border-beam-interactive.tsx (1)
lib/utils.ts (1)
cn
(5-7)
components/ui/animated-border.tsx (1)
lib/utils.ts (1)
cn
(5-7)
components/ui/border-beam-mask.tsx (1)
lib/utils.ts (1)
cn
(5-7)
components/ui/border-beam.tsx (1)
lib/utils.ts (1)
cn
(5-7)
🔇 Additional comments (20)
components/ui/card.tsx (1)
6-13
: Clean formatting and improved visual feedbackThe Card component now uses a more maintainable multi-line format and implements the new shadow system with hover effects, creating a more polished interactive experience.
components/ai-todo-input.tsx (1)
297-301
: Nice implementation of the AnimatedBorder componentThe container has been simplified and enhanced with the new AnimatedBorder component, which provides a more cohesive visual experience with the rest of the UI overhaul.
components/theme-toggle.tsx (2)
21-21
: Enhanced button styling with improved transitionsThe theme toggle button now incorporates the new shadow system with hover effects and a subtle upward animation, making it more engaging and visually consistent with other interactive elements in the UI.
24-28
: Improved icon rendering with better color semanticsThe multiline conditional rendering improves code readability, and the yellow Sun icon in dark mode provides better visual semantics than the previous implementation.
components/ui/button.tsx (2)
7-7
: Enhancement to the button base styles with shadow utility.The addition of the
shadow-button
class to the base button styles integrates with the broader shadow utility enhancements mentioned in the PR. This provides consistent shadow styling across button variants.
11-16
: Improved dark mode support and visual consistency.The button variants have been enhanced with:
- Refined gradient colors with proper dark mode alternatives
- Improved hover and active states for better interaction feedback
- Dark mode specific shadows and border colors
- More consistent text coloring with foreground variable usage
These changes align well with the UI overhaul objectives and provide better visual consistency across different color schemes.
components/ui/border-beam-mask.tsx (1)
1-25
: Well-structured border mask component with good customization options.This new component provides a simple but effective way to create a solid border mask with customizable color. The implementation:
- Follows React best practices with clearly defined props interface
- Uses absolute positioning to avoid affecting layout
- Properly inherits border radius from parent elements
- Disables pointer events to avoid interfering with underlying interactive elements
The inset box shadow approach for creating the border is an elegant solution that doesn't affect the element's dimensions.
components/todo-input.tsx (3)
11-11
: Added AnimatedBorder component import.Good addition that supports the visual enhancements to the input component.
125-130
: Enhanced input container with animated border effect.The addition of the
AnimatedBorder
component improves the visual feedback of the input container. The implementation:
- Uses consistent styling with the overall UI theme
- Maintains appropriate shadow and background styling for light/dark modes
- Sets proper border radius and overflow handling
- Uses the group utility for hover/focus state management
This change aligns well with the UI overhaul objectives mentioned in the PR.
131-139
: Improved text input alignment and styling.The changes to center-align the input text and justify the container content create a more balanced and visually appealing input experience. This complements the animated border and creates a more cohesive design.
components/ui/border-beam.tsx (2)
1-45
: Well-structured animated border beam component with extensive customization options.This new component creates a visually appealing animated gradient border effect with excellent customization options. The implementation:
- Provides sensible defaults for all props
- Uses CSS custom properties for dynamic styling
- Leverages pseudo-elements for efficient animation rendering
- Properly handles border-radius inheritance
- Includes clear code comments for different sections of the implementation
The component is well-structured and follows React best practices.
24-31
:✅ Verification successful
Ensure border-beam animation is properly defined in Tailwind config.
The component uses
animate-border-beam
class which requires a corresponding animation definition in your Tailwind configuration.
🏁 Script executed:
#!/bin/bash # Check if the border-beam animation is defined in the Tailwind config echo "Checking for border-beam animation in Tailwind config..." if grep -r "border-beam" --include="tailwind.config.*" .; then echo "✅ Found border-beam animation definition" else echo "❌ Missing border-beam animation definition in Tailwind config" echo "You need to add the animation to your Tailwind config:" echo "extend: { animation: { 'border-beam': '...' } }" fiLength of output: 413
animate-border-beam is already configured
✅ Verified thattailwind.config.ts
defines theborder-beam
animation underextend.animation
, so theanimate-border-beam
class is available.tailwind.config.ts (3)
14-14
: LGTM: Good addition of border-beam animation.The animation uses a CSS variable for duration control, making it flexible for different use cases.
21-25
: LGTM: Well-structured keyframes for border-beam animation.The keyframes for the border-beam animation create a smooth horizontal gradient animation by transitioning the background position from 0% to 100% and back.
70-83
: LGTM: Good implementation of safe area utilities for mobile devices.The custom plugin adds utilities for handling safe areas on mobile devices, particularly useful for iOS devices with notches or home indicators. The
.mb-safe-keyboard
class will help with keyboard display on iOS, and.pt-safe
handles top insets.components/todo-item.tsx (3)
29-38
: LGTM: Enhanced color contrast for different urgency levels.The updated text colors for time indicators provide better contrast in both light and dark modes, improving readability and accessibility.
47-56
: LGTM: Improved gradient styling for status indicators.Adding the
via
color stop creates smoother gradients, and the adjusted opacity values enhance visual hierarchy while maintaining readability.
240-240
: LGTM: Enhanced card styling with consistent shadow system.The updated card styling now uses semantic utility classes (
shadow-card
,hover:shadow-card-hover
) and adds a subtle hover animation effect withtranslate-y-[-1px]
, creating a polished and interactive experience.components/ui/animated-border.tsx (1)
1-46
: LGTM: Well-implemented animated border component.This new
AnimatedBorder
component creates an elegant animated gradient border effect that appears on hover and transitions to a solid border on focus. The implementation:
- Uses CSS variables for flexible color customization
- Properly handles transitions between states
- Uses CSS masking for the border-only effect
- Maintains accessibility by changing styles on focus
The component is a good addition to the UI library and will enhance the visual feedback of interactive elements.
components/ui/border-beam-interactive.tsx (1)
1-55
: LGTM: Well-structured interactive border component with client-side rendering.The
BorderBeamInteractive
component is well-implemented with:
- Client-side rendering protection using the
mounted
state pattern- Flexible prop customization for different visual needs
- Clear separation of hover and focus states with appropriate transitions
- Good use of pseudo-elements for layered visual effects
- Well-commented code explaining the purpose of different CSS rules
The component enhances the UI library and complements the
AnimatedBorder
component for interactive elements.
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
There was a problem hiding this 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
♻️ Duplicate comments (1)
app/globals.css (1)
68-71
: Preserve keyboard-accessible focus states
Removing the native focus outline globally will break keyboard navigation visibility. Please revert and replace with a:focus-visible
rule:-input:focus { - outline: none !important; -} +input:focus { + /* keep default for assistive tech */ +} +input:focus-visible { + outline: 2px solid hsl(var(--sidebar-ring)); + outline-offset: 2px; +}
🧹 Nitpick comments (7)
app/globals.css (7)
54-64
: Remove or reference unusedgradient-rotate
keyframes
I don't see any class or component usinganimation: gradient-rotate
. If this keyframe is dead code, please remove it to reduce bundle size. Otherwise, link it to the correct utility or component.To find references, run:
rg --ignore-case "gradient-rotate" -n .
66-66
: Eliminate placeholder comment
The line/* Empty space where removed keyframes were */
can be removed to clean up the stylesheet.
74-81
: EnhanceanimatedGradient
keyframes for smoother transitions
Currently the animation jumps from 0% to 100%. Consider adding intermediate stops (e.g., 50%) for a more gradual effect:@keyframes animatedGradient { 0% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } 100% { background-position: 200% 50%; } }
84-88
: Extend safe-area handling and font fallback
Good addition ofenv(safe-area-inset-bottom)
. To support notches at the top, consider addingpadding-top: env(safe-area-inset-top)
. Also ensure"OpenRunde"
falls back gracefully—validate that your font stack covers all expected platforms.
90-98
: Improve iOS keyboard-safe area support
The.ios-keyboard-support
class is helpful. For wider iOS compatibility, you may add the legacyconstant()
fallback:@supports (-webkit-touch-callout: none) { .ios-keyboard-support { bottom: constant(safe-area-inset-bottom); bottom: env(safe-area-inset-bottom); } }
105-166
: Review shadow utility definitions and Tailwind integration
The custom shadow utilities (.shadow-, .dark .shadow-) look consistent and map to your new CSS variables. To leverage Tailwind’s JIT and purge capabilities, consider defining these intailwind.config.ts
undertheme.extend.boxShadow
instead of raw CSS utilities.
217-266
: Review dark-mode variables and glow effects
The dark-mode counterparts and glow variables mirror the light mode and extend the theme appropriately. Ensure that glow intensities do not hinder text readability or cause eye strain. A quick visual check in dark mode across components is recommended.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
app/globals.css
(4 hunks)components/ui/animated-border.tsx
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- components/ui/animated-border.tsx
🔇 Additional comments (5)
app/globals.css (5)
14-21
: Validate the Medium weight@font-face
declaration
The Medium variant mirrors the Regular pattern—please confirm the/fonts/OpenRunde-Medium.*woff*
files are available. You may also include alocal('OpenRunde Medium')
fallback to improve load times.
23-30
: Validate the Semibold weight@font-face
declaration
Semibold is defined correctly. Double-check that both WOFF2/WOFF files exist and consider addingunicode-range
if you plan to subset or improve loading performance for specific character sets.
32-39
: Validate the Bold weight@font-face
declaration
Confirm the/fonts/OpenRunde-Bold.*woff*
files are present. If you support italic or other styles in the future, plan to add corresponding@font-face
blocks to maintain consistency.
171-206
: Validate new CSS custom properties for light and sidebar colors
A large block of new--*
variables was introduced. Please verify contrast ratios (WCAG AA/AAA) for your primary/secondary text on backgrounds, especially in the sidebar. Running an automated audit (e.g., axe-core) can catch any accessibility regressions.
208-214
: Approve light-mode shadow value additions
The light-mode shadow definitions align with design specs and use consistent RGBA values. These appear ready for use.
There was a problem hiding this 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
♻️ Duplicate comments (1)
app/globals.css (1)
69-72
: Accessible focus styles implemented
Good catch replacing the removed outline withinput:focus-visible
to maintain keyboard accessibility. This addresses earlier accessibility feedback.
🧹 Nitpick comments (5)
app/globals.css (5)
5-39
: Enhance font-face declarations with local fallbacks and unicode-range
Consider addinglocal('OpenRunde')
sources for each weight to leverage system‐installed fonts and specifying aunicode-range
to limit glyph loading for performance.
66-66
: Remove placeholder comment and extra whitespace
The comment/* Empty space where removed keyframes were */
and surrounding empty lines can be cleaned up to keep the stylesheet concise.
75-82
: Standardize animation naming and definitions
Consider aligning naming conventions (e.g.,gradient-rotate
vs.animatedGradient
) and grouping animation keyframes for better maintainability and clarity.
106-143
: Consolidate shadow utility classes
The shadow utilities follow a consistent pattern. If you’re using a preprocessor or a Tailwind plugin, consider generating these classes programmatically or centralizing the variable definitions to reduce duplication.
171-216
: Organize and document CSS variables
Grouping related custom properties (e.g., base colors, sidebar colors, shadows) with headers or comments will improve readability and maintenance. Consider referencing your design tokens documentation.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
app/globals.css
(2 hunks)
🔇 Additional comments (4)
app/globals.css (4)
85-89
: Confirm safe-area and overscroll behaviors
Usingenv(safe-area-inset-bottom)
andoverscroll-behavior-y: none
is appropriate for mobile layouts. Verify that disabling overscroll won’t conflict with desired bounce behavior on iOS.
102-104
: Evaluate browser support fortext-wrap: balance
text-wrap: balance
is still experimental in many browsers. Consider providing a fallback or verifying it meets your target browser support matrix.
273-293
: Verify inline themeshine
keyframe usage
Theshine
keyframe defined under@theme inline
may overlap with other animations. Confirm that this theme block is actually applied and that there’s no duplication with other keyframes.
91-99
:✅ Verification successful
Ensure
.ios-keyboard-support
is applied
The iOS support rule is well-defined, but search for its usage in relevant components to confirm it’s leveraged where needed.
🏁 Script executed:
#!/bin/bash # Find where .ios-keyboard-support is used rg -n "ios-keyboard-support"Length of output: 403
Verified
.ios-keyboard-support
is in use
Theios-keyboard-support
class is applied in the following locations, so no further updates to its usage are needed:
- app/HomeClient.tsx:738
- app/HomeClient.tsx:745
There was a problem hiding this 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
♻️ Duplicate comments (1)
app/globals.css (1)
65-69
: Accessible focus-visible stylesGreat use of
:focus-visible
and exclusion of.no-inner-border
. This restores the keyboard focus ring in an accessible way.
🧹 Nitpick comments (4)
app/globals.css (4)
63-63
: Remove placeholder commentThe empty comment block marking removed keyframes is no longer needed—please delete it to keep the stylesheet lean.
80-84
: Scope form input overridesTargeting
form input
globally removes borders and shadows from all form controls. Consider narrowing this to a more specific class (e.g.,.ai-todo-input input
) to avoid unintended side effects in other forms.
86-92
: Consolidate duplicate input rulesThe rules in this block overlap with the previous override. You can simplify by merging selectors or refining class usage to eliminate redundancy.
123-124
: Text wrap balancingIntroducing
text-wrap: balance
for better typographic balance is a nice enhancement. Note browser support is still emerging—consider a fallback comment for older browsers.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
app/globals.css
(2 hunks)components/ai-todo-input.tsx
(4 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- components/ai-todo-input.tsx
🔇 Additional comments (22)
app/globals.css (22)
5-14
: Font-face Regular declaration looks goodThe
@font-face
for weight 400 includes local fallbacks,font-display: swap
, and a comprehensiveunicode-range
—all aligning with best practices.
16-25
: Font-face Medium declaration looks goodThe weight 500 declaration mirrors the regular style and correctly specifies local sources, formats, and unicode coverage.
27-36
: Font-face Semibold declaration looks goodWeight 600 is set up consistently with the other weights, ensuring a seamless typographic scale.
38-47
: Font-face Bold declaration looks goodThe bold (700) variant is declared correctly; all four weights follow the same pattern for consistency.
71-78
: Validate the complex:not()
selectorThe selector
input:focus-visible:not(.group input, .no-inner-border)
includes a descendant combinator inside:not()
, which may not be valid CSS in all browsers. Please verify in your build output that it behaves as intended or refactor into separate:not()
clauses.
95-102
: Animated gradient keyframesThe
@keyframes animatedGradient
provides a smooth border animation and aligns with your Framer Motion enhancements. Looks solid.
108-109
: Safe-area padding onbody
Adding
padding-bottom: env(safe-area-inset-bottom)
correctly supports notch and keyboard safe areas on modern devices.
112-118
: iOS keyboard supportThe
@supports (-webkit-touch-callout: none)
block and.ios-keyboard-support
class appropriately fix the UI at the bottom for iOS, matching the new Tailwind utilities.
126-149
: Shadow utility classesThe new
.shadow-*
utilities map cleanly to your custom properties, providing a clear semantic API for shadows at multiple intensities. This will promote consistency across components.
151-161
: Dark mode glow utilitiesThe
.dark .shadow-glow-sm|md|accent
classes are well constructed, offering cohesive glow effects in dark mode.
163-170
: Combined card shadow variantsYour
.shadow-card
and.dark .shadow-card
rules layer custom shadows and glows effectively. Using@apply
for the base variant and explicitbox-shadow
for dark mode is both performant and clear.
172-179
: Hover state transitions for cardsThe transition settings on
.shadow-card-hover
(and its dark counterpart) will deliver smooth interactive feedback.
181-187
: Button shadow utilities
.shadow-button
and its dark variant maintain consistency with card shadows, ensuring buttons integrate visually with the overall design system.
192-218
: Base theme custom propertiesUpdates to
--foreground
,--card-foreground
,--popover-foreground
,--primary-foreground
, etc., sharpen the color palette and maintain semantic naming. These align with accessibility guidelines.
219-228
: Sidebar custom propertiesThe sidebar-specific variables (
--sidebar-background
,--sidebar-primary
, etc.) reflect your updated layout design and integrate cleanly with both light and dark modes.
229-236
: Light mode shadow valuesCentralizing your light-mode shadow tokens in custom properties simplifies future tweaks and promotes consistency.
240-247
: Dark mode base colorsThe inverted values for dark mode base colors maintain adequate contrast and mirror the light-mode mappings effectively.
248-255
: Dark mode accent and alertsYour
--secondary
,--muted
,--accent
, and--destructive
tokens in dark mode offer clear hierarchy and maintain readability.
256-264
: Dark mode border and chart colorsAdjustments to the dark-mode border, input, ring, and chart variables complement the rest of the palette nicely.
266-274
: Dark mode sidebar colorsThe sidebar variables under
.dark
correctly adapt for a darker theme, preserving visual hierarchy and accessibility.
276-282
: Dark mode shadow tokensThe darker shadow opacities and spreads are well-tuned for visibility against dark backgrounds and enhance depth.
284-286
: Dark mode glow effectsDefining
--glow-sm
,--glow-md
, and--glow-accent
completes your dark mode shadow/glow toolkit for interactive elements.
There was a problem hiding this 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
🧹 Nitpick comments (8)
app/globals.css (8)
63-64
: Remove Placeholder CommentThe comment
/* Empty space where removed keyframes were */
no longer adds value. Please remove this line to keep the CSS clean.
87-92
: Targeted Todo-Input StylingThe
.group input[type="text"]
and.no-inner-border
rules effectively remove inner borders, but the repeated use of!important
can make future overrides difficult. Where possible, replace!important
with a more specific selector or utility class.
95-145
: Consolidate & Prefix KeyframesYou’ve added several new animations (
animatedGradient
,shine
,simplePulse
,borderRotate
,backgroundMove
).
- Consider prefixing names (e.g.,
todo-animatedGradient
) to avoid collisions with other global styles or repeated declarations.- There’s another
@keyframes shine
defined later in an@theme inline
block—ensure you don’t inadvertently overwrite one or the other.- Verify each animation is actually used in the components; remove any unused keyframes to reduce payload.
147-215
: Review .todo-input-container Visual StylingThe light and dark mode styles for
.todo-input-container
provide a compelling animated border effect. A few thoughts:
mask-composite: exclude
and-webkit-mask-composite: xor
have uneven browser support—please verify behavior across all target browsers (especially Safari & iOS).- Ensure custom focus styles remain visible inside this container—double-check that focus rings aren’t clipped by the
isolation: isolate
setting.- You could DRY up duplicate transition and hover properties by extracting them into a shared utility.
218-222
: Confirm Safe Area Insets on BodyApplying
padding-bottom: env(safe-area-inset-bottom)
improves iOS keyboard handling. However,overscroll-behavior-y: none
can suppress native scroll bounce—verify that this doesn’t negatively impact UX on other platforms.
264-274
: Dark Mode Glow UtilitiesThe
.shadow-glow-*
classes extend shadows for dark mode nicely. Consider documenting these in your style guide so team members know when to use them.
304-312
: Border Animation VariablesDefining
--border-color-custom
and--hover-gradient-custom
at root and.dark
is clear. If more variants arise, consider centralizing these in a shared partial or utility file.
315-360
: Revisit CSS Variable OrganizationThe comprehensive set of base colors, radii, and shadow values provides full theming coverage. For future maintainability:
- Group related variables (e.g., colors, shadows, radii) into clearly commented subsections.
- Sort variables alphabetically within each category.
This will help contributors quickly locate and update values.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (6)
app/globals.css
(2 hunks)components/ai-todo-input.tsx
(7 hunks)components/todo-input.tsx
(3 hunks)components/ui/animated-border.tsx
(1 hunks)components/ui/border-beam-interactive.tsx
(1 hunks)components/ui/border-beam.tsx
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
- components/ui/border-beam-interactive.tsx
- components/ui/animated-border.tsx
- components/ai-todo-input.tsx
- components/ui/border-beam.tsx
- components/todo-input.tsx
🔇 Additional comments (8)
app/globals.css (8)
5-47
: Well-Configured @font-face DeclarationsThe four
@font-face
blocks correctly include local fallbacks, multiple weights,woff2
andwoff
formats,font-display: swap
, and a comprehensiveunicode-range
. This addresses previous performance and loading concerns around custom fonts.
224-231
: Validate iOS Keyboard Support BlockThe
@supports (-webkit-touch-callout: none)
rule correctly targets iOS. Ensure this only applies to devices needing the fix and doesn’t inadvertently affect desktop/mobile browsers that support this feature.
235-262
: Shadow Utility ClassesThe new utilities (
.shadow-sm
through.shadow-accent
) neatly centralize your design system shadows via CSS variables. This is a solid pattern for maintainability and theme consistency.
276-283
: Combined Shadow Effects for CardsUsing
@apply shadow-md
in.shadow-card
and layering glows in dark mode follows Tailwind best practices. Looks good.
285-292
: Shadow Hover Transitions
.shadow-card-hover
and its dark variant provide smooth hover feedback. The transition settings are clear and performant.
294-300
: Button Shadow StylesThe
.shadow-button
definitions align with your other utilities and maintain consistency.
362-411
: Dark Theme Variable OverridesThe dark-mode variable overrides mirror the light theme cleanly and support a cohesive dark UI. Great work.
417-424
: Apply Base Styles via @layer baseBootstrapping global border and background/text utilities in
@layer base
ensures consistent styling from the ground up. This setup aligns well with Tailwind’s layering model.
/* Accessible focus styles that work with BorderBeam */ | ||
input:focus-visible:not(.no-inner-border) { | ||
outline: 2px solid hsl(var(--sidebar-ring)); | ||
outline-offset: 2px; | ||
} | ||
|
||
/* Override Tailwind's ring utilities for most inputs */ | ||
input:focus-visible:not(.group input, .no-inner-border) { | ||
--tw-ring-offset-width 6D40 : 0 !important; | ||
--tw-ring-offset-color: transparent !important; | ||
--tw-ring-color: transparent !important; | ||
--tw-ring-offset-shadow: none !important; | ||
--tw-ring-shadow: none !important; | ||
} | ||
|
||
/* Remove any inner borders from AITodoInput */ | ||
form input { | ||
border: 0 !important; | ||
box-shadow: none !important; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
❓ Verification inconclusive
Refine Input Focus & Border Overrides
- The focus outline is set to
2px
, but WCAG 2.1 recommends a minimum of3px
for visibility. Consider increasing tooutline: 3px solid …
. - Avoid complex selectors inside
:not()
(e.g.,:not(.group input)
) for broader compatibility—refactor to simpler selectors or add utility classes. - The global
form input { border:0!important; }
rule is very broad and may strip borders from unintended inputs. Scope it specifically to your AITodoInput (e.g.,.ai-todo-input input
) to prevent collateral styling issues.
Refine Input Focus Styling & Scope Border Overrides
- WCAG 2.1 requires a visible focus indicator (minimum 2 CSS px thick) but doesn’t mandate a 3 px outline—raising to 3 px can improve visibility without violating WCAG.
- Complex selectors inside
:not()
(e.g.:not(.group input)
) rely on Selectors Level 4 support, which isn’t universal. Refactor to simpler selectors or add a utility class to exclude grouped inputs. - The rule
applies to every form field. Limit its scope to your AITodoInput component—e.g.
form input { border: 0 !important; box-shadow: none !important; }
.ai-todo-input input { border: 0; box-shadow: none; }
There was a problem hiding this 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
♻️ Duplicate comments (2)
app/globals.css (2)
71-78
: **Scope Tailwind Ring Overrides to Specific Components **Global overrides via
input:focus-visible:not(.group input, .no-inner-border) { … }with
!important
may strip ring utilities from unintended inputs app-wide. Refactor to target only your custom input (e.g.,.todo-input-container input:focus-visible
) to avoid collateral styling issues.
81-84
: **Avoid Globalform input
Border Removal **The rule
form input { border:0!important; box-shadow:none!important; }applies to all form fields, including third-party and system components. Scope it to your AITodoInput (e.g.,
.ai-todo-input input
) to prevent unintended side effects in other forms.
🧹 Nitpick comments (7)
app/globals.css (7)
5-47
: Font-face Declarations Are Well-Structured, Consider Performance OptimizationsThe
@font-face
blocks for Regular, Medium, Semibold, and Bold weights correctly includefont-display: swap
andunicode-range
. Paths and local fallbacks look valid (per past verification).
Optional enhancements:
- Add
local('OpenRunde')
as an extra fallback in case the family is installed under a more generic name.- Split the
unicode-range
into smaller subsets (e.g., Latin, extended) to defer loading heavier glyph sets and improve initial page load.
63-64
: Remove Placeholder CommentThe comment
/* Empty space where removed keyframes were */
appears to be a leftover placeholder. Removing it (or documenting its purpose) will keep the stylesheet cleaner.
65-70
: Enhance Focus Outline for WCAG ComplianceUsing
outline: 2px solid
improves visibility over the default, but WCAG 2.1 recommends a minimum of 3px for high-contrast focus indicators. Consider updating to:input:focus-visible:not(.no-inner-border) { outline: 3px solid hsl(var(--sidebar-ring)); outline-offset: 2px; }
87-92
: Refine Input Selector SpecificityThe selectors
.group input[type="text"], .no-inner-border { … }are still very broad. For clarity and maintainability, consider scoping to the container, for example:
.todo-input-container .group input[type="text"] { … }or a dedicated utility class on your input wrapper.
95-105
: Prune Unused KeyframesThe
@keyframes animatedGradient
declaration isn’t referenced anywhere else in this file or in components. Removing it (or wiring it up where intended) will eliminate dead code and reduce bundle size.
146-153
: Validate Container Styling for Hardware AccelerationUsing
transform: translateZ(0)
to force GPU acceleration is a smart optimization but can create a new stacking context. Verify it doesn’t inadvertently affect z-index ordering elsewhere. Alternatively, you could usewill-change: transform
for a more declarative hint.
307-374
: Consolidate Shadow Utility ClassesYou’ve introduced many new
.shadow-*
utilities mapping to CSS variables. There's some duplication between light and dark mode definitions—consider abstracting the color/glow component into a single custom property (e.g.--shadow-color
) and reusing a single mixin to reduce repetition.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
app/globals.css
(2 hunks)components/ai-todo-input.tsx
(7 hunks)components/todo-input.tsx
(3 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
- components/ai-todo-input.tsx
- components/todo-input.tsx
🔇 Additional comments (2)
app/globals.css (2)
297-305
: Check iOS Keyboard Safe-Area SupportThe
@supports (-webkit-touch-callout: none)
block correctly targets iOS for.ios-keyboard-support
. Please verify on devices (or simulator) that the fixed footer/input container honorsenv(safe-area-inset-bottom)
and doesn’t get hidden by the keyboard on different iOS versions.
490-511
: Verify Custom@theme inline
At-RuleThe
@theme inline
block and nested@keyframes shine
likely rely on a custom Tailwind plugin. Confirm that your build pipeline supports this at-rule and that the animation is actually applied; otherwise it may be silently dropped.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🔭 Outside diff range comments (1)
styles/animations.css (1)
1-8
: 🛠️ Refactor suggestionDuplicate
@keyframes shine
name risks collision
The@keyframes shine
definition here may conflict with othershine
keyframes inapp/globals.css
. Keyframe names are global; consider namespacing this (e.g.,animations-shine
) to avoid unexpected overrides.
♻️ Duplicate F438 comments (1)
app/globals.css (1)
65-78
: 🛠️ Refactor suggestionSimplify complex
:not()
selectors for compatibility
Usinginput:focus-visible:not(.group input, .no-inner-border)
includes a combinator inside:not()
, which is not universally supported. Split this into separate selectors, e.g.:input:focus-visible:not(.no-inner-border):not([class~="group"]) { … } .group input:focus-visible { /* custom override */ }This ensures consistent parsing across browsers.
🧹 Nitpick comments (8)
styles/animations.css (3)
10-19
: Optimize chevron rotation animation
The.chevron-rotate
transition is well-scoped totransform
, butwill-change: transform
should be used sparingly. Ensure this element actually benefits from GPU acceleration and consider removingwill-change
once the animation completes to avoid long-term memory usage.
46-54
: Avoid initial collapse animation flicker
Applying the collapse animation to.expand-content:not(.open)
will run on initial load, potentially causing a flash. Consider adding ananimatable
flag after mount to gate these animations, or useanimation-delay
andanimation-fill-mode
to suppress the first playback.
56-60
: Use more targeted GPU acceleration
Forcing GPU acceleration withtransform: translateZ(0)
on each child may be heavy. Instead, applywill-change: transform
orbackface-visibility: hidden
on the container to achieve smoother animations without per-child transforms.app/globals.css (5)
5-47
: Centralize font-face declarations and validate fallbacks
The four@font-face
rules correctly declare weights 400–700 with local and webfont sources and a unicode-range for optimization. To further improve performance, consider specifyingfont-stretch
if any variants differ, and verify that thelocal()
names match the actual installed font names on users’ systems.
147-165
: Optimize.todo-input-container
pseudo-elements
Applyingtransition: all 0.5s ease
can trigger expensive repaints. Narrow the transition to only the properties you animate (e.g.,opacity
,background
,border-color
). You can also DRY up the double-pseudo technique by abstracting shared styles into a mixin or utility class.
169-214
: Refine hover and focus state animations
The hover (simpleSlide
) and focus interactions are functional, but the use of!important
onbackground
andtransition
may complicate future overrides. Evaluate if!important
is strictly necessary, and consider consolidating these rules to reduce specificity wars.
261-283
: Consolidate light/dark interactive state styles
The hover and focus styles for light and dark modes share much of their logic. Extract common declarations into a shared class or Tailwind utility to reduce duplication and make future tweaks easier.
316-383
: Evaluate necessity of extensive shadow utilities
While the new.shadow-*
utilities provide granular control, consider leveraging Tailwind’s built-in shadow tokens or consolidating overlapping variants to keep your utility CSS bundle lean.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
app/globals.css
(2 hunks)components/todo-item.tsx
(15 hunks)styles/animations.css
(1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
- components/todo-item.tsx
🔇 Additional comments (2)
styles/animations.css (1)
21-30
:❓ Verification inconclusive
Ensure smoothExpand/smoothCollapse height var covers content size
Usingvar(--auto-height, 500px)
requires the JS hook to set--auto-height
dynamically; otherwise content taller than 500px will be clipped. Verify that--auto-height
always reflects the element’s scrollHeight. Optionally, switch tomax-height
transitions for simpler auto-sizing.Run:
🏁 Script executed:
#!/bin/bash # Confirm dynamic setting of --auto-height in JS rg -n "setProperty('--auto-height'" -A3 .Length of output: 139
🏁 Script executed:
#!/bin/bash # Search for dynamic setting of --auto-height in JS/TS files rg -n "style\\.setProperty" -A3 --glob "*.js" --glob "*.ts" rg -n "\"--auto-height\"" -A3 --glob "*.js" --glob "*.ts" rg -n "scrollHeight" -A3 --glob "*.js" --glob "*.ts"Length of output: 171
Ensure
--auto-height
Is Set Dynamically
I wasn’t able to find any JS/TS code that callselement.style.setProperty('--auto-height', …)
or reads an element’sscrollHeight
. Without this, content taller than the 500 px fallback will be clipped.• Verify your JS hook computes each section’s
scrollHeight
and does something like:
el.style.setProperty('--auto-height', el.scrollHeight + 'px')
• As an alternative, you can switch to animatingmax-height
(e.g. from0
to9999px
) for true auto-sizing without needing a CSS variable.app/globals.css (1)
299-314
: Improve iOS keyboard safe-area support
The.ios-keyboard-support
class correctly addresses the safe-area inset. Ensure this class is applied to the correct container and test on real iOS devices (hardware and software keyboards) to validate no layout jumps occur when the keyboard appears.
overflow: hidden; | ||
height: 0; | ||
opacity: 0; | ||
border-top: 1px solid #e5e7eb; /* Default gray border */ | ||
display: block; | ||
pointer-events: none; | ||
transition: opacity 250ms ease-out; | ||
} | ||
|
||
.dark .expand-content { | ||
border-top-color: rgba(255, 255, 255, 0.1); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Border persists when collapsed—consider hiding on collapse
.expand-content
applies a top border even when height is 0
, leading to a stray line when collapsed. You may want to toggle border-top: none
on collapse or set border-color: transparent
for .expand-content:not(.open)
.
@keyframes animatedGradient { | ||
0% { | ||
background-position: 0% 50%; | ||
} | ||
50% { | ||
background-position: 100% 50%; | ||
} | ||
100% { | ||
background-position: 0% 50%; | ||
} | ||
} | ||
|
||
@keyframes shine { | ||
0% { | ||
background-position: -100% 0; | ||
} | ||
100% { | ||
background-position: 200% 0; | ||
} | ||
} | ||
|
||
/* Add a simple pulsing animation instead */ | ||
@keyframes simplePulse { | ||
0% { | ||
opacity: 0.7; | ||
} | ||
50% { | ||
opacity: 0.9; | ||
} | ||
100% { | ||
opacity: 0.7; | ||
} | ||
} | ||
|
||
@keyframes borderRotate { | ||
0% { | ||
transform: rotate(0deg); | ||
} | ||
100% { | ||
transform: rotate(360deg); | ||
} | ||
} | ||
|
||
@keyframes backgroundMove { | ||
to { | ||
background-position: 200% center; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Resolve duplicate and unused keyframe names
This block defines multiple animations—including a second shine
(see above), animatedGradient
, simplePulse
, borderRotate
, and backgroundMove
. Duplicate keyframe names will override one another unpredictably. Additionally, verify whether gradientSlide
(defined later) is used; if not, remove it to eliminate dead code.
Would you like a script to scan for references to these keyframes?
app/globals.css
Outdated
form input { | ||
border: 0 !important; | ||
box-shadow: none !important; | ||
} | ||
|
||
/* Target the todo input field specifically, but allow container border */ | ||
.group input[type="text"], | ||
.no-inner-border { | ||
border: none !important; | ||
outline: none !important; | ||
box-shadow: none !important; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Scope global input border resets to specific components
The rule form input { border:0!important; box-shadow:none!important; }
is overly broad and may strip styling from unrelated form fields. Likewise, .group input[type="text"], .no-inner-border
is too generic. Limit these selectors to your todo-input component, e.g.:
.ai-todo-input input { border: 0; box-shadow: none; }
This prevents unintended style removal elsewhere.
app/globals.css
Outdated
@keyframes simpleSlide { | ||
from { | ||
background-position: 0% 50%; | ||
} | ||
to { | ||
background-position: 100% 50%; | ||
} | ||
} | ||
|
||
@keyframes gradientSlide { | ||
to { background-position: 200% center; } | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Verification agent
🧩 Analysis chain
Clean up unused gradientSlide
keyframe
The gradientSlide
keyframe appears to be defined but never referenced. Run the following to confirm usage and remove it if unused:
🏁 Script executed:
#!/bin/bash
rg -n "gradientSlide" -A2 .
Length of output: 165
Remove unused gradientSlide
keyframe
I ran rg -n "gradientSlide" -A2 .
and only found its definition in app/globals.css
(lines 295–297) with no usages elsewhere. It’s safe to delete.
Locations to update:
- app/globals.css: lines 295–297
Suggested diff:
@@ app/globals.css
- @keyframes gradientSlide {
- to { background-position: 200% center; }
- }
📝 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.
@keyframes simpleSlide { | |
from { | |
background-position: 0% 50%; | |
} | |
to { | |
background-position: 100% 50%; | |
} | |
} | |
@keyframes gradientSlide { | |
to { background-position: 200% center; } | |
} | |
@keyframes simpleSlide { | |
from { | |
background-position: 0% 50%; | |
} | |
to { | |
background-position: 100% 50%; | |
} | |
} |
Plyght the goat |
@Xoni30 ty king lmao |
This pull request introduces several improvements and updates across the codebase, focusing on linting and formatting configurations, code style consistency, and minor refactors for better readability and maintainability. Below is a breakdown of the most significant changes:
Linting and Formatting Configuration:
@typescript-eslint
and Prettier integration in.eslintrc.json
, enforcing rules like no unused variables (with exceptions for_
-prefixed variables) and Prettier formatting (prettier/prettier
set to "error")..prettierrc
for Prettier formatting preferences (e.g., single quotes, trailing commas, and a print width of 100) and.prettierignore
to exclude directories likenode_modules
and.next
from formatting. [1] [2].lintstagedrc
to run Prettier and ESLint on staged files, ensuring code quality before commits.Code Style Improvements:
route.ts
files inapp/api
). (app/api/auth/[...all]/route.tsL1-R2, app/api/parse-todo/route.tsL1-R126)app/api
files, improving readability and aligning with Prettier rules. [1] [2] [3]Minor Refactors:
_session
instead ofsession
) to suppress warnings while maintaining clarity.Documentation Update:
README.md
to include installation steps withbun
as an alternative package manager, enhancing developer setup instructions.