Rating
formcn/ratingFreeComponent
Rating component
Install it
npx shadcn@latest add https://formcn.dev/r/rating.jsonSource
1'use client'23import { useControllableState } from '@radix-ui/react-use-controllable-state'4import { type LucideProps, StarIcon } from 'lucide-react'5import type { KeyboardEvent, MouseEvent, ReactElement, ReactNode } from 'react'6import {7 Children,8 cloneElement,9 createContext,10 useCallback,11 useContext,12 useEffect,13 useRef,14 useState,15} from 'react'16import { cn } from '@/lib/utils'1718type RatingContextValue = {19 value: number20 readOnly: boolean21 hoverValue: number | null22 focusedStar: number | null23 handleValueChange: (24 event: MouseEvent<HTMLButtonElement> | KeyboardEvent<HTMLButtonElement>,25 value: number,26 ) => void27 handleKeyDown: (event: KeyboardEvent<HTMLButtonElement>) => void28 setHoverValue: (value: number | null) => void29 setFocusedStar: (value: number | null) => void30}3132const RatingContext = createContext<RatingContextValue | null>(null)3334const useRating = () => {35 const context = useContext(RatingContext)36 if (!context) {37 throw new Error('useRating must be used within a Rating component')38 }39 return context40}4142export type RatingButtonProps = LucideProps & {43 index?: number44 icon?: ReactElement<LucideProps>45}4647export const RatingButton = ({48 index: providedIndex,49 size = 20,50 className,51 icon = <StarIcon />,52}: RatingButtonProps) => {53 const {54 value,55 readOnly,56 hoverValue,57 focusedStar,58 handleValueChange,59 handleKeyDown,60 setHoverValue,61 setFocusedStar,62 } = useRating()6364 const index = providedIndex ?? 065 const isActive = index < (hoverValue ?? focusedStar ?? value ?? 0)66 let tabIndex = -16768 if (!readOnly) {69 tabIndex = value === index + 1 ? 0 : -170 }7172 const handleClick = useCallback(73 (event: MouseEvent<HTMLButtonElement>) => {74 handleValueChange(event, index + 1)75 },76 [handleValueChange, index],77 )7879 const handleMouseEnter = useCallback(() => {80 if (!readOnly) {81 setHoverValue(index + 1)82 }83 }, [readOnly, setHoverValue, index])8485 const handleFocus = useCallback(() => {86 setFocusedStar(index + 1)87 }, [setFocusedStar, index])8889 const handleBlur = useCallback(() => {90 setFocusedStar(null)91 }, [setFocusedStar])9293 return (94 <button95 className={cn(96 'rounded-full focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',97 'p-0.5',98 readOnly && 'cursor-not-allowed',99 className,100 )}101 disabled={readOnly}102 onBlur={handleBlur}103 onClick={handleClick}104 onFocus={handleFocus}105 onKeyDown={handleKeyDown}106 onMouseEnter={handleMouseEnter}107 tabIndex={tabIndex}108// … truncated
Files it writes
More from formcn
All 9 items| Component | Registry | Kind | Access | Installs | Command |
|---|---|---|---|---|---|
| File Inputfile-upload | formcn | Components | Free | no deps | |
| Multi-selectmulti-select | formcn | Components | Free | no deps | |
| Multi-step formmulti-step-viewer | formcn | Components | Free | 1 dep | |
| Passwordpassword | formcn | Components | Free | no deps | |
| Stepperstepper | formcn | Components | Free | no deps | |
| Tag Inputtag-input | formcn | Components | Free | 1 dep |
