-
Notifications
You must be signed in to change notification settings - Fork 19
feat(rating): add RatingStars, RatingModal; integrate maintainer rati… #75
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
feat(rating): add RatingStars, RatingModal; integrate maintainer rati… #75
Conversation
📝 WalkthroughWalkthroughAdds a maintainer-driven bounty completion and contributor rating flow: new RatingModal and RatingStars components, sidebar handlers to mark completion and submit ratings, mock bounty timestamp updates, Jest localStorage test setup, TypeScript shims for motion/icons, and small hook & navbar typing/behavior adjustments. Changes
Sequence DiagramsequenceDiagram
participant Maintainer as Maintainer
participant Sidebar as Bounty Sidebar
participant Modal as Rating Modal
participant Stars as Rating Stars
participant Toast as UI Toast
Maintainer->>Sidebar: Click "Mark as Completed"
Sidebar->>Sidebar: set completed = true\nset showRating = true
Sidebar->>Modal: open RatingModal(bounty, contributor)
Maintainer->>Stars: Hover/Select stars (1–5)
Stars-->>Modal: onChange(rating)
Maintainer->>Modal: Enter feedback
Maintainer->>Modal: Click Submit
Modal->>Sidebar: onSubmit(rating, feedback)
Sidebar->>Sidebar: set lastRating, reputationGain, hasRated = true
Sidebar->>Toast: show success toast
Modal-->>Maintainer: show success view
Maintainer->>Modal: Close
Modal->>Sidebar: onClose
Sidebar->>Maintainer: show post-rating summary (rating, points)
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 3❌ Failed checks (2 warnings, 1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
🧪 Generate unit tests (beta)
Comment |
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: 3
🤖 Fix all issues with AI agents
In `@components/bounty/bounty-sidebar.tsx`:
- Around line 24-27: The maintainer flag is hard-coded (CURRENT_USER_ID and
IS_MAINTAINER) and must be replaced with real auth and server-side
authorization: remove the constants in bounty-sidebar.tsx and read the current
user and roles from your auth provider (e.g., useAuth() / session hook) to set
currentUserId and isMaintainer in the component, then ensure all sensitive
actions (bounty completion, rating) call backend endpoints that validate the
caller is the maintainer (e.g., in your markBountyComplete or rateSubmission API
handlers) before performing changes; update UI to rely only on auth-derived
flags and treat client checks as purely UX, not security.
- Around line 101-113: The early-return guards in handleSubmitRating (checks for
hasRated, IS_MAINTAINER, completed) currently call alert() then return, which
resolves the RatingModal onSubmit Promise and shows success; change each guard
to instead throw an Error or return a rejected Promise with a clear message
(e.g., "Already rated", "Only maintainers can rate", "Bounty not completed") so
the modal treats the outcome as a failure and stays in the error state; keep the
existing alert if you want UI feedback but ensure the function subsequently
throws/rejects using those same messages.
In `@components/rating/rating-stars.tsx`:
- Around line 10-41: The component allows interactions when disabled because
mouse handlers only check displayOnly; update all interaction checks to consider
disabled as well (e.g., onMouseEnter/onMouseLeave/onClick and handleKeyDown
should early-return if disabled || displayOnly || !onChange) and use the
disabled flag to set pointerEvents and cursor; also only apply slider ARIA
attributes (aria-valuenow, aria-valuemin, aria-valuemax and role="slider") when
not displayOnly (i.e., when role is slider) and when not disabled ensure
tabIndex is 0 otherwise -1 so the DOM reflects the true interactive state; touch
up references in RatingStars, handleKeyDown, hovered/setHovered, and the span
handlers to implement these conditional checks and ARIA changes.
🧹 Nitpick comments (1)
components/rating/rating-modal.tsx (1)
52-55: Add dialog semantics for accessibility.If the
.modalclass isn’t providing dialog semantics, consider adding explicitrole/ariaattributes.♿ Suggested update
- return ( - <div className="modal"> - <h2>Rate Contributor</h2> + return ( + <div className="modal" role="dialog" aria-modal="true" aria-labelledby="rating-modal-title"> + <h2 id="rating-modal-title">Rate Contributor</h2>
| const handleSubmitRating = async (rating: number, feedback: string) => { | ||
| if (hasRated) { | ||
| alert('You have already rated this contributor.'); | ||
| return; | ||
| } | ||
| if (!IS_MAINTAINER) { | ||
| alert('Only maintainers can rate contributors.'); | ||
| return; | ||
| } | ||
| if (!completed) { | ||
| alert('Bounty must be marked as completed before rating.'); | ||
| return; | ||
| } |
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.
🧩 Analysis chain
🏁 Script executed:
find . -name "bounty-sidebar.tsx" -type fRepository: boundlessfi/bounties
Length of output: 102
🏁 Script executed:
find . -name "*rating*modal*" -o -name "*RatingModal*" | grep -E "\.(tsx?|jsx?)$"Repository: boundlessfi/bounties
Length of output: 100
🏁 Script executed:
find . -type f -name "*.tsx" | xargs grep -l "RatingModal" | head -20Repository: boundlessfi/bounties
Length of output: 139
🏁 Script executed:
wc -l ./components/bounty/bounty-sidebar.tsxRepository: boundlessfi/bounties
Length of output: 106
🏁 Script executed:
cat -n ./components/bounty/bounty-sidebar.tsx | grep -A 50 "handleSubmitRating"Repository: boundlessfi/bounties
Length of output: 4539
🏁 Script executed:
wc -l ./components/rating/rating-modal.tsxRepository: boundlessfi/bounties
Length of output: 103
🏁 Script executed:
cat -n ./components/rating/rating-modal.tsxRepository: boundlessfi/bounties
Length of output: 2888
Guard failures should reject so the modal doesn't show success.
RatingModal treats any resolved onSubmit as success. Returning early after alert() still resolves the Promise and will show the success view. Reject/throw to keep the modal in an error state.
🛠️ Suggested fix
if (hasRated) {
alert('You have already rated this contributor.');
- return;
+ throw new Error('You have already rated this contributor.');
}
if (!IS_MAINTAINER) {
alert('Only maintainers can rate contributors.');
- return;
+ throw new Error('Only maintainers can rate contributors.');
}
if (!completed) {
alert('Bounty must be marked as completed before rating.');
- return;
+ throw new Error('Bounty must be marked as completed before rating.');
}📝 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.
| const handleSubmitRating = async (rating: number, feedback: string) => { | |
| if (hasRated) { | |
| alert('You have already rated this contributor.'); | |
| return; | |
| } | |
| if (!IS_MAINTAINER) { | |
| alert('Only maintainers can rate contributors.'); | |
| return; | |
| } | |
| if (!completed) { | |
| alert('Bounty must be marked as completed before rating.'); | |
| return; | |
| } | |
| const handleSubmitRating = async (rating: number, feedback: string) => { | |
| if (hasRated) { | |
| alert('You have already rated this contributor.'); | |
| throw new Error('You have already rated this contributor.'); | |
| } | |
| if (!IS_MAINTAINER) { | |
| alert('Only maintainers can rate contributors.'); | |
| throw new Error('Only maintainers can rate contributors.'); | |
| } | |
| if (!completed) { | |
| alert('Bounty must be marked as completed before rating.'); | |
| throw new Error('Bounty must be marked as completed before rating.'); | |
| } |
🤖 Prompt for AI Agents
In `@components/bounty/bounty-sidebar.tsx` around lines 101 - 113, The
early-return guards in handleSubmitRating (checks for hasRated, IS_MAINTAINER,
completed) currently call alert() then return, which resolves the RatingModal
onSubmit Promise and shows success; change each guard to instead throw an Error
or return a rejected Promise with a clear message (e.g., "Already rated", "Only
maintainers can rate", "Bounty not completed") so the modal treats the outcome
as a failure and stays in the error state; keep the existing alert if you want
UI feedback but ensure the function subsequently throws/rejects using those same
messages.
| export const RatingStars: React.FC<RatingStarsProps> = ({ value, onChange, disabled, displayOnly }) => { | ||
| const [hovered, setHovered] = useState<number | null>(null); | ||
|
|
||
| const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => { | ||
| if (!onChange || disabled || displayOnly) return; | ||
| if (e.key === 'ArrowLeft' && value > 1) onChange(value - 1); | ||
| if (e.key === 'ArrowRight' && value < 5) onChange(value + 1); | ||
| }; | ||
|
|
||
| return ( | ||
| <div | ||
| tabIndex={displayOnly ? -1 : 0} | ||
| role={displayOnly ? 'img' : 'slider'} | ||
| aria-valuenow={value} | ||
| aria-valuemin={1} | ||
| aria-valuemax={5} | ||
| onKeyDown={handleKeyDown} | ||
| style={{ display: 'flex', gap: 4, outline: 'none', cursor: displayOnly ? 'default' : 'pointer' }} | ||
| > | ||
| {[1, 2, 3, 4, 5].map((star) => ( | ||
| <span | ||
| key={star} | ||
| onMouseEnter={() => !displayOnly && setHovered(star)} | ||
| onMouseLeave={() => !displayOnly && setHovered(null)} | ||
| onClick={() => onChange && !disabled && !displayOnly && onChange(star)} | ||
| style={{ | ||
| color: (hovered ?? value) >= star ? '#FFD700' : '#CCC', | ||
| fontSize: 28, | ||
| transition: 'color 0.2s', | ||
| pointerEvents: displayOnly ? 'none' : 'auto', | ||
| userSelect: '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.
🧩 Analysis chain
🏁 Script executed:
find . -type f -name "rating-stars.tsx" | head -20Repository: boundlessfi/bounties
Length of output: 100
🏁 Script executed:
cat -n ./components/rating/rating-stars.tsxRepository: boundlessfi/bounties
Length of output: 1975
Ensure disabled state prevents all interactions and align ARIA props with role.
When disabled=true but displayOnly=false, hover effects still fire because the handlers check !displayOnly only (lines 32-33, 39). Additionally, ARIA slider attributes (aria-valuenow, aria-valuemin, aria-valuemax) are always present even when role="img", which is semantically incorrect. Consolidate interaction state logic and conditionally apply ARIA slider attributes only when appropriate.
Suggested fix
export const RatingStars: React.FC<RatingStarsProps> = ({ value, onChange, disabled, displayOnly }) => {
const [hovered, setHovered] = useState<number | null>(null);
+ const isDisplayOnly = displayOnly || !onChange;
+ const isInteractive = !isDisplayOnly && !disabled;
const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
- if (!onChange || disabled || displayOnly) return;
+ if (!isInteractive) return;
if (e.key === 'ArrowLeft' && value > 1) onChange(value - 1);
if (e.key === 'ArrowRight' && value < 5) onChange(value + 1);
};
return (
<div
- tabIndex={displayOnly ? -1 : 0}
- role={displayOnly ? 'img' : 'slider'}
- aria-valuenow={value}
- aria-valuemin={1}
- aria-valuemax={5}
+ tabIndex={isInteractive ? 0 : -1}
+ role={isDisplayOnly ? 'img' : 'slider'}
+ aria-label={isDisplayOnly ? `${value} out of 5 stars` : 'Rating'}
+ aria-valuenow={isDisplayOnly ? undefined : value}
+ aria-valuemin={isDisplayOnly ? undefined : 0}
+ aria-valuemax={isDisplayOnly ? undefined : 5}
+ aria-disabled={isDisplayOnly ? undefined : disabled}
onKeyDown={handleKeyDown}
- style={{ display: 'flex', gap: 4, outline: 'none', cursor: displayOnly ? 'default' : 'pointer' }}
+ style={{ display: 'flex', gap: 4, outline: 'none', cursor: isInteractive ? 'pointer' : 'default' }}
>
{[1, 2, 3, 4, 5].map((star) => (
<span
key={star}
- onMouseEnter={() => !displayOnly && setHovered(star)}
- onMouseLeave={() => !displayOnly && setHovered(null)}
- onClick={() => onChange && !disabled && !displayOnly && onChange(star)}
+ onMouseEnter={() => isInteractive && setHovered(star)}
+ onMouseLeave={() => isInteractive && setHovered(null)}
+ onClick={() => isInteractive && onChange?.(star)}
style={{
color: (hovered ?? value) >= star ? '#FFD700' : '#CCC',
fontSize: 28,
transition: 'color 0.2s',
- pointerEvents: displayOnly ? 'none' : 'auto',
+ pointerEvents: isInteractive ? 'auto' : 'none',
userSelect: 'none',
}}
aria-label={star + ' star'}🤖 Prompt for AI Agents
In `@components/rating/rating-stars.tsx` around lines 10 - 41, The component
allows interactions when disabled because mouse handlers only check displayOnly;
update all interaction checks to consider disabled as well (e.g.,
onMouseEnter/onMouseLeave/onClick and handleKeyDown should early-return if
disabled || displayOnly || !onChange) and use the disabled flag to set
pointerEvents and cursor; also only apply slider ARIA attributes (aria-valuenow,
aria-valuemin, aria-valuemax and role="slider") when not displayOnly (i.e., when
role is slider) and when not disabled ensure tabIndex is 0 otherwise -1 so the
DOM reflects the true interactive state; touch up references in RatingStars,
handleKeyDown, hovered/setHovered, and the span handlers to implement these
conditional checks and ARIA changes.
git rm pnpm-lock.yaml ls -la pnpm-lock.yaml || true git status --porcelain -b git rm pnpm-lock.yaml || true && git add -A && git rebase --continue || true git rm pnpm-lock.yaml git update-index --remove pnpm-lock.yaml && git add -A && git status --porcelain -b feat(rating): add RatingStars, RatingModal; integrate maintainer rating flow; remove debug banner
ed411d9 to
09e49c6
Compare
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: 4
🤖 Fix all issues with AI agents
In `@components/bounty/bounty-sidebar.tsx`:
- Around line 101-124: The handler handleSubmitRating currently accepts a
feedback parameter but never uses it, causing a lint no-unused-vars error;
either remove the feedback parameter or surface it—e.g., include feedback in the
success toast (toast.success) by appending the feedback to the description or
message, or store it via a new state setter (e.g., setLastFeedback) alongside
setLastRating/setReputationGain; update the function signature and any UI that
calls handleSubmitRating accordingly so feedback is consumed and the lint error
is resolved.
- Around line 126-134: The current renderActionButton hides the maintainer
rating flow after completion; update renderActionButton to show a persistent
"Rate Contributor" action when the bounty is completed and the viewer is a
maintainer by adding a new button rendered for the case bounty.status ===
'claimed' && IS_MAINTAINER && completed; wire its onClick to open the rating
modal (create or reuse a handler like handleOpenRating or openRatingModal) and
ensure the rating modal state/handler (e.g., isRatingOpen, setIsRatingOpen,
handleSubmitRating) exists and is used so the maintainer can re-open the rating
UI after dismissing it; keep the existing handleMarkCompleted behavior unchanged
for marking completion.
In `@components/rating/rating-modal.tsx`:
- Around line 25-39: The catch block in handleSubmit currently declares an
unused binding "e", triggering the no-unused-vars lint error; remove the unused
binding by changing "catch (e)" to an unbound catch ("catch") in the
handleSubmit function where onSubmit(rating, feedback) is awaited, leaving the
existing error handling body (setError('Failed to submit rating. Please try
again.')) intact so lint passes without losing the catch behavior.
- Around line 42-47: The JSX string "Contributor's" triggers
react/no-unescaped-entities; inside the success branch of the RatingModal
component (the conditional return when success is truthy) update the text to
escape the apostrophe by using a JS string expression or an HTML entity (e.g.,
replace the raw "Contributor's reputation updated." with {"Contributor's
reputation updated."} or use ') so the lint rule is satisfied; keep the
surrounding JSX (h2, p, button with onClose) unchanged.
| const renderActionButton = () => { | ||
| if (bounty.status === 'claimed' && IS_MAINTAINER && !completed) { | ||
| return ( | ||
| <Button onClick={handleMarkCompleted} disabled={loading} className="w-full gap-2 bg-green-600 text-white hover:bg-green-700"> | ||
| {loading ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : <Check className="mr-2 h-4 w-4" />} | ||
| Mark as Completed | ||
| </Button> | ||
| ) | ||
| } |
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.
Allow reopening the rating flow after completion.
Once the modal is dismissed, there’s no way to rate later because the “Mark as Completed” button disappears and no “Rate Contributor” action is shown. This blocks a core flow if the maintainer closes the modal accidentally.
🛠️ Suggested fix (add a “Rate Contributor” action)
const renderActionButton = () => {
if (bounty.status === 'claimed' && IS_MAINTAINER && !completed) {
return (
<Button onClick={handleMarkCompleted} disabled={loading} className="w-full gap-2 bg-green-600 text-white hover:bg-green-700">
{loading ? <Loader2 className="mr-2 h-4 w-4 animate-spin" /> : <Check className="mr-2 h-4 w-4" />}
Mark as Completed
</Button>
)
}
+ if (bounty.status === 'claimed' && IS_MAINTAINER && completed && !hasRated) {
+ return (
+ <Button onClick={() => setShowRating(true)} className="w-full gap-2 bg-primary text-primary-foreground hover:bg-primary/90">
+ Rate Contributor
+ </Button>
+ )
+ }🤖 Prompt for AI Agents
In `@components/bounty/bounty-sidebar.tsx` around lines 126 - 134, The current
renderActionButton hides the maintainer rating flow after completion; update
renderActionButton to show a persistent "Rate Contributor" action when the
bounty is completed and the viewer is a maintainer by adding a new button
rendered for the case bounty.status === 'claimed' && IS_MAINTAINER && completed;
wire its onClick to open the rating modal (create or reuse a handler like
handleOpenRating or openRatingModal) and ensure the rating modal state/handler
(e.g., isRatingOpen, setIsRatingOpen, handleSubmitRating) exists and is used so
the maintainer can re-open the rating UI after dismissing it; keep the existing
handleMarkCompleted behavior unchanged for marking completion.
|
@0xdevcollins Pls can u merge my code please ser... And compliments too thank you |
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
🤖 Fix all issues with AI agents
In `@types/shims.d.ts`:
- Around line 1-12: The ambient shims declare overly-broad any types for
"@tabler/icons-react" (IconMenu2, IconX) and "motion/react" (motion,
AnimatePresence, useScroll, useMotionValueEvent); remove this shim file entirely
so TypeScript uses the packages' built-in types, or replace the declarations by
re-exporting the actual package types (e.g., export { IconMenu2, IconX } from
"@tabler/icons-react" and export { motion, AnimatePresence, useScroll,
useMotionValueEvent } from "motion/react") to eliminate the use of any and
satisfy strict:true.
🧹 Nitpick comments (1)
components/bounty/bounty-sidebar.tsx (1)
87-99: Consider cleanup for thesetTimeoutto avoid state updates on unmounted components.If the user navigates away before the 1-second timeout completes,
setCompleted(true)andsetShowRating(true)will fire on an unmounted component, causing React warnings.🛠️ Proposed fix with cleanup
const handleMarkCompleted = async () => { if (!IS_MAINTAINER) { alert('Only maintainers can mark as completed.'); return; } setLoading(true) - // Simulate completion API call - setTimeout(() => { - setLoading(false) - setCompleted(true) - setShowRating(true) - }, 1000) + // Simulate completion API call + try { + await new Promise((resolve) => setTimeout(resolve, 1000)) + setCompleted(true) + setShowRating(true) + } finally { + setLoading(false) + } }Using
awaitwith a Promise-wrapped timeout keeps the async flow sequential and avoids the unmount race. Alternatively, store the timeout ID in a ref and clear it in a cleanup effect.
| declare module "@tabler/icons-react" { | ||
| import * as React from 'react' | ||
| export const IconMenu2: React.FC<any> | ||
| export const IconX: React.FC<any> | ||
| } | ||
|
|
||
| declare module "motion/react" { | ||
| export const motion: any | ||
| export const AnimatePresence: any | ||
| export const useScroll: any | ||
| export const useMotionValueEvent: any | ||
| } |
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.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check if the file exists and show its content
echo "=== Checking types/shims.d.ts ==="
if [ -f "types/shims.d.ts" ]; then
echo "File exists, content:"
cat -n types/shims.d.ts
else
echo "File not found at types/shims.d.ts"
# Search for it
find . -name "shims.d.ts" -type f 2>/dev/null
fi
echo ""
echo "=== Looking for package.json in root ==="
if [ -f "package.json" ]; then
echo "Found package.json, checking dependencies:"
jq '.dependencies // {} | keys' package.json 2>/dev/null || cat package.json | head -30
fi
echo ""
echo "=== Checking for tsconfig.json ==="
if [ -f "tsconfig.json" ]; then
echo "Found tsconfig.json:"
cat tsconfig.json
fiRepository: boundlessfi/bounties
Length of output: 2679
🏁 Script executed:
#!/bin/bash
# Search for references to `@tabler/icons-react` and motion/react in the codebase
echo "=== References to `@tabler/icons-react` ==="
rg "@tabler/icons-react" --type ts --type tsx --type js --type jsx -B 2 -A 2
echo ""
echo "=== References to motion/react ==="
rg "motion/react" --type ts --type tsx --type js --type jsx -B 2 -A 2
echo ""
echo "=== References to framer-motion ==="
rg "framer-motion" --type ts --type tsx --type js --type jsx -B 2 -A 2Repository: boundlessfi/bounties
Length of output: 279
🏁 Script executed:
#!/bin/bash
# Try to find build or lint configuration files that might show errors
echo "=== Looking for build configuration ==="
find . -maxdepth 2 -type f \( -name ".eslintrc*" -o -name "eslint.config.*" -o -name "next.config.*" -o -name "tsconfig.*.json" -o -name ".github" \) 2>/dev/null | head -20
echo ""
echo "=== Checking for CI configuration ==="
if [ -d ".github/workflows" ]; then
echo "GitHub workflows found:"
ls -la .github/workflows/
echo ""
echo "Build/lint workflow content:"
cat .github/workflows/*.yml 2>/dev/null | grep -A 20 "typescript\|build\|lint\|tsc" || echo "No explicit build commands found"
fi
echo ""
echo "=== Checking package.json for devDependencies with `@types` or TypeScript ==="
cat package.json | jq '.devDependencies // empty | to_entries[] | select(.key | contains("typescript") or contains("@types") or contains("eslint"))' 2>/dev/null | head -30Repository: boundlessfi/bounties
Length of output: 1647
🌐 Web query:
@tabler/icons-react TypeScript types definitions built-in
💡 Result:
Yes — @tabler/icons-react ships TypeScript typings built-in (you don’t need a separate @types/... package).
- The package’s
package.jsonincludes atypesentry pointing to its bundled.d.tsfile (e.g../dist/esm/tabler-icons-react.d.ts). (app.unpkg.com) - The Tabler Icons repo README also states that
@tabler/icons-reactexports its own type declarations for React + TypeScript. (github.com)
Citations:
- 1: https://app.unpkg.com/%40tabler/icons-react%403.0.1/files/package.json?utm_source=openai
- 2: https://github.com/tabler/tabler-icons
🌐 Web query:
motion react framer-motion TypeScript types built-in v12
💡 Result:
In Motion/Framer Motion v12, the TypeScript types are built-in (the packages ship their own .d.ts files), so you generally do not install any @types/... package.
- Install / import (Motion for React): install
motion, then import from"motion/react". (motion.dev) - Built-in typings are published with the package:
motion@12.xexports atypesentry (./dist/index.d.ts) and the React entrypoint also points at../dist/react.d.ts. (app.unpkg.com) - Framer Motion v12 also ships its own types:
framer-motion@12.xexportstypes(./dist/types/index.d.ts) viaexportsandtypesfields. (app.unpkg.com)
Common v12 React types you can import/use
(Names as exposed in the library’s docs/types)
MotionProps(base animation/gesture/layout props)HTMLMotionProps<Tag>(props formotion.div,motion.button, etc.)SVGMotionProps<T>MotionValue<T>and related helpers
The motion namespace is typed so each intrinsic element is a ForwardRefExoticComponent<HTMLMotionProps<K>>, and motion.create returns a component typed as MotionProps & Props. (tessl.io)
Typical TypeScript patterns
import { motion, type MotionProps } from "motion/react";
type MyMotionDivProps = MotionProps & React.ComponentPropsWithoutRef<"div">;
export function MyMotionDiv(props: MyMotionDivProps) {
return <motion.div {...props} />;
}import { motion } from "motion/react";
type CardProps = { title: string };
const Card = (props: CardProps) => <div>{props.title}</div>;
export const MotionCard = motion.create(Card); // typed as MotionProps & CardPropsCitations:
- 1: https://motion.dev/docs/react-installation?utm_source=openai
- 2: https://app.unpkg.com/motion%4012.26.1/files/package.json?utm_source=openai
- 3: https://app.unpkg.com/framer-motion%4012.27.1/files/package.json?utm_source=openai
- 4: https://tessl.io/registry/tessl/npm-framer-motion/12.23.0/files/docs/motion-components.md?utm_source=openai
Remove unnecessary any type shims — both packages include built-in TypeScript definitions.
The any types in this file conflict with your strict: true TypeScript configuration and are unnecessary. Both @tabler/icons-react and motion (v12+) ship with their own complete type definitions, so these ambient declarations should not be needed.
Either remove the shim file entirely and rely on the packages' built-in types, or if you must keep ambient declarations, re-export the actual package exports:
🛠️ Recommended fixes
Option 1: Remove the shim entirely (preferred if packages' types resolve correctly)
- Delete
types/shims.d.tsand ensure TypeScript can resolve the packages' built-in types.
Option 2: Re-export actual types from the packages
declare module "@tabler/icons-react" {
- import * as React from 'react'
- export const IconMenu2: React.FC<any>
- export const IconX: React.FC<any>
+ export * from "@tabler/icons-react";
}
declare module "motion/react" {
- export const motion: any
- export const AnimatePresence: any
- export const useScroll: any
- export const useMotionValueEvent: any
+ export * from "motion/react";
}📝 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.
| declare module "@tabler/icons-react" { | |
| import * as React from 'react' | |
| export const IconMenu2: React.FC<any> | |
| export const IconX: React.FC<any> | |
| } | |
| declare module "motion/react" { | |
| export const motion: any | |
| export const AnimatePresence: any | |
| export const useScroll: any | |
| export const useMotionValueEvent: any | |
| } | |
| declare module "@tabler/icons-react" { | |
| export * from "@tabler/icons-react"; | |
| } | |
| declare module "motion/react" { | |
| export * from "motion/react"; | |
| } |
🧰 Tools
🪛 GitHub Check: build-and-lint (24.x)
[failure] 11-11:
Unexpected any. Specify a different type
[failure] 10-10:
Unexpected any. Specify a different type
[failure] 9-9:
Unexpected any. Specify a different type
[failure] 8-8:
Unexpected any. Specify a different type
[failure] 4-4:
Unexpected any. Specify a different type
[failure] 3-3:
Unexpected any. Specify a different type
🤖 Prompt for AI Agents
In `@types/shims.d.ts` around lines 1 - 12, The ambient shims declare overly-broad
any types for "@tabler/icons-react" (IconMenu2, IconX) and "motion/react"
(motion, AnimatePresence, useScroll, useMotionValueEvent); remove this shim file
entirely so TypeScript uses the packages' built-in types, or replace the
declarations by re-exporting the actual package types (e.g., export { IconMenu2,
IconX } from "@tabler/icons-react" and export { motion, AnimatePresence,
useScroll, useMotionValueEvent } from "motion/react") to eliminate the use of
any and satisfy strict:true.
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
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
components/ui/resizable-navbar.tsx (1)
69-70:⚠️ Potential issue | 🔴 CriticalFix shims.d.ts:
motionmust be typed with JSX component factories, notunknown.The shim at
types/shims.d.ts(line 4) declaresexport const motion: unknown, which blocks the type check. When the code tries to use<motion.div>at line 69, TypeScript rejects it becausemotionhas no accessible properties or methods.Update the shim to properly declare
motionwith its JSX component factory types:Example fix for shims.d.ts
declare module "motion/react" { import { RefObject } from 'react' export const motion: { div: React.FC<React.HTMLAttributes<HTMLDivElement> & any> // ... other component factories } export const AnimatePresence: unknown export function useScroll(options?: { target?: RefObject<Element | null>; offset?: string[] }): { scrollY: { get(): number } } export function useMotionValueEvent<T = number>( motionValue: { get(): T }, eventName: string, handler: (latest: T) => void ): void }Alternatively, ensure
@types/framer-motionis installed or usemotion/react's own type definitions rather than custom shims.
🧹 Nitpick comments (1)
components/ui/resizable-navbar.tsx (1)
54-55: Double type assertion is a code smell; prefer a proper type guard or updated shim.The
as unknown as React.RefObject<Element | null>pattern bypasses TypeScript's type checking entirely. While this may silence the compiler foruseScroll, it can mask legitimate type mismatches at runtime.Consider updating the
types/shims.d.tsto properly declare theuseScrolloverload that acceptsReact.RefObject<HTMLDivElement | null>, or use a type predicate/assertion function that validates the ref.
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
🤖 Fix all issues with AI agents
In `@types/shims.d.ts`:
- Around line 8-10: Remove the unused duplicate import of React by deleting the
import line that brings in "React" so only the needed type import "RefObject"
from 'react' remains; update the top of the declaration (where RefObject is
imported) to ensure there are no other unused React symbols referenced (e.g.,
remove any lone "import * as React from 'react'" statement).
|
Hello @0xdevcollins Pls all checks have passsed pls can u merge... Thank you ser! |
|
I have made the changes to fix the review |
|
@codderrabbit re-review |
…ck user id override
|
@0xdevcollins Hello pls can u merge I have done it according to how it saying but it is telling me to write a full code base for authenication when what we are dealing with is mock plssss |
Video showing what was done
Maintainer Rating System — Summary
Status: Prototype implemented (UI + mocked flow)
Branch:
implement-maintainer-rating-systemWhat was added
components/rating/RatingStarsInteractive 1–5 star input (supports hover + keyboard navigation)
components/rating/RatingModalModal with star rating, optional feedback textarea, loading/success/error states
bounty-sidebar.tsxmock-bounty.tsTest data adjusted to include claimed-state entries for easier testing
Key behavior
How to run locally
implement-maintainer-rating-systemnpm run dev/yarn dev/ etc.)Quick test checklist
/bounty/6(or any claimed bounty ID frommock-bounty.ts)IS_MAINTAINERinbounty-sidebar.tsxtofalse→ verify non-maintainers cannot see/complete the flowCloses #66
Summary by CodeRabbit
New Features
Chores
✏️ Tip: You can customize this high-level summary in your review settings.