Better UIBetter UI

Ripple Button


Preview

Usage

'use client'
 
import { RippleButton } from '@/components/button/ripple-button'
 
<RippleButton className="bg-orange-500">Click me for ripple</RippleButton>

Code

'use client'
 
import React, { useState } from 'react'
 
import { motion, MotionProps } from 'motion/react'
 
import { cn } from '@/lib/utils'
 
export interface RippleButtonProps
  extends Omit<React.HTMLAttributes<HTMLElement>, keyof MotionProps>,
    MotionProps {
  children: React.ReactNode
  className?: string
}
 
export function RippleButton({ children, className }: RippleButtonProps) {
  const [ripples, setRipples] = useState<
    { x: number; y: number; id: number }[]
  >([])
 
  const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
    const button = event.currentTarget.getBoundingClientRect()
    const x = event.clientX - button.left
    const y = event.clientY - button.top
 
    setRipples([...ripples, { x, y, id: Date.now() }])
  }
 
  return (
    <motion.button
      className={cn(
        `relative h-9 overflow-hidden whitespace-nowrap rounded-md bg-primary px-4 py-2
        text-center text-sm font-medium text-primary-foreground shadow transition-colors`,
        className
      )}
      whileTap={{ scale: 0.95 }}
      onClick={handleClick}
    >
      {ripples.map((ripple) => (
        <motion.span
          key={ripple.id}
          className="absolute rounded-full bg-white opacity-30"
          initial={{
            width: 0,
            height: 0,
            x: ripple.x,
            y: ripple.y,
            opacity: 0.5,
          }}
          animate={{
            width: 500,
            height: 500,
            x: ripple.x - 250,
            y: ripple.y - 250,
            opacity: 0,
          }}
          transition={{ duration: 0.5 }}
          onAnimationComplete={() =>
            setRipples(ripples.filter((r) => r.id !== ripple.id))
          }
        />
      ))}
      {children}
    </motion.button>
  )
}
 

Props

PropTypeDefault
children
ReactNode
-
className
string
-
defaultChecked
boolean
-
defaultValue
string | number | readonly string[]
-
suppressContentEditableWarning
boolean
-
suppressHydrationWarning
boolean
-
accessKey
string
-
autoCapitalize
"off" | "none" | "on" | "sentences" | "words" | "characters" | (string & {})
-
autoFocus
boolean
-
contentEditable
"inherit" | Booleanish | "plaintext-only"
-
contextMenu
string
-
dir
string
-
draggable
Booleanish
-
enterKeyHint
"enter" | "done" | "go" | "next" | "previous" | "search" | "send"
-
hidden
boolean
-
id
string
-
lang
string
-
nonce
string
-
slot
string
-
spellCheck
Booleanish
-
tabIndex
number
-
title
string
-
translate
"yes" | "no"
-
radioGroup
string
-
role
AriaRole
-
about
string
-
content
string
-
datatype
string
-
inlist
any
-
prefix
string
-
property
string
-
rel
string
-
resource
string
-
rev
string
-
typeof
string
-
vocab
string
-
autoCorrect
string
-
autoSave
string
-
color
string
-
itemProp
string
-
itemScope
boolean
-
itemType
string
-
itemID
string
-
itemRef
string
-
results
number
-
security
string
-
unselectable
"off" | "on"
-
popover
"" | "auto" | "manual"
-
popoverTargetAction
"toggle" | "show" | "hide"
-
popoverTarget
string
-
inert
boolean
-
inputMode
"none" | "search" | "text" | "tel" | "url" | "email" | "numeric" | "decimal"
-
is
string
-
aria-activedescendant
string
-
aria-atomic
Booleanish
-
aria-autocomplete
"none" | "list" | "inline" | "both"
-
aria-braillelabel
string
-
aria-brailleroledescription
string
-
aria-busy
Booleanish
-
aria-checked
boolean | "true" | "false" | "mixed"
-
aria-colcount
number
-
aria-colindex
number
-
aria-colindextext
string
-
aria-colspan
number
-
aria-controls
string
-
aria-current
boolean | "true" | "false" | "page" | "step" | "location" | "date" | "time"
-
aria-describedby
string
-
aria-description
string
-
aria-details
string
-
aria-disabled
Booleanish
-
aria-dropeffect
"none" | "link" | "copy" | "execute" | "move" | "popup"
-
aria-errormessage
string
-
aria-expanded
Booleanish
-
aria-flowto
string
-
aria-grabbed
Booleanish
-
aria-haspopup
boolean | "true" | "false" | "dialog" | "grid" | "listbox" | "menu" | "tree"
-
aria-hidden
Booleanish
-
aria-invalid
boolean | "true" | "false" | "grammar" | "spelling"
-
aria-keyshortcuts
string
-
aria-label
string
-
aria-labelledby
string
-
aria-level
number
-
aria-live
"off" | "assertive" | "polite"
-
aria-modal
Booleanish
-
aria-multiline
Booleanish
-
aria-multiselectable
Booleanish
-
aria-orientation
"horizontal" | "vertical"
-
aria-owns
string
-
aria-placeholder
string
-
aria-posinset
number
-
aria-pressed
boolean | "true" | "false" | "mixed"
-
aria-readonly
Booleanish
-
aria-relevant
"text" | "additions" | "additions removals" | "additions text" | "all" | "removals" | "removals additions" | "removals text" | "text additions" | "text removals"
-
aria-required
Booleanish
-
aria-roledescription
string
-
aria-rowcount
number
-
aria-rowindex
number
-
aria-rowindextext
string
-
aria-rowspan
number
-
aria-selected
Booleanish
-
aria-setsize
number
-
aria-sort
"none" | "ascending" | "descending" | "other"
-
aria-valuemax
number
-
aria-valuemin
number
-
aria-valuenow
number
-
aria-valuetext
string
-
dangerouslySetInnerHTML
{ __html: string | TrustedHTML; }
-
onCopy
ClipboardEventHandler<HTMLElement>
-
onCopyCapture
ClipboardEventHandler<HTMLElement>
-
onCut
ClipboardEventHandler<HTMLElement>
-
onCutCapture
ClipboardEventHandler<HTMLElement>
-
onPaste
ClipboardEventHandler<HTMLElement>
-
onPasteCapture
ClipboardEventHandler<HTMLElement>
-
onCompositionEnd
CompositionEventHandler<HTMLElement>
-
onCompositionEndCapture
CompositionEventHandler<HTMLElement>
-
onCompositionStart
CompositionEventHandler<HTMLElement>
-
onCompositionStartCapture
CompositionEventHandler<HTMLElement>
-
onCompositionUpdate
CompositionEventHandler<HTMLElement>
-
onCompositionUpdateCapture
CompositionEventHandler<HTMLElement>
-
onFocus
FocusEventHandler<HTMLElement>
-
onFocusCapture
FocusEventHandler<HTMLElement>
-
onBlur
FocusEventHandler<HTMLElement>
-
onBlurCapture
FocusEventHandler<HTMLElement>
-
onChange
FormEventHandler<HTMLElement>
-
onChangeCapture
FormEventHandler<HTMLElement>
-
onBeforeInput
FormEventHandler<HTMLElement>
-
onBeforeInputCapture
FormEventHandler<HTMLElement>
-
onInput
FormEventHandler<HTMLElement>
-
onInputCapture
FormEventHandler<HTMLElement>
-
onReset
FormEventHandler<HTMLElement>
-
onResetCapture
FormEventHandler<HTMLElement>
-
onSubmit
FormEventHandler<HTMLElement>
-
onSubmitCapture
FormEventHandler<HTMLElement>
-
onInvalid
FormEventHandler<HTMLElement>
-
onInvalidCapture
FormEventHandler<HTMLElement>
-
onLoad
ReactEventHandler<HTMLElement>
-
onLoadCapture
ReactEventHandler<HTMLElement>
-
onError
ReactEventHandler<HTMLElement>
-
onErrorCapture
ReactEventHandler<HTMLElement>
-
onKeyDown
KeyboardEventHandler<HTMLElement>
-
onKeyDownCapture
KeyboardEventHandler<HTMLElement>
-
onKeyPress
KeyboardEventHandler<HTMLElement>
-
onKeyPressCapture
KeyboardEventHandler<HTMLElement>
-
onKeyUp
KeyboardEventHandler<HTMLElement>
-
onKeyUpCapture
KeyboardEventHandler<HTMLElement>
-
onAbort
ReactEventHandler<HTMLElement>
-
onAbortCapture
ReactEventHandler<HTMLElement>
-
onCanPlay
ReactEventHandler<HTMLElement>
-
onCanPlayCapture
ReactEventHandler<HTMLElement>
-
onCanPlayThrough
ReactEventHandler<HTMLElement>
-
onCanPlayThroughCapture
ReactEventHandler<HTMLElement>
-
onDurationChange
ReactEventHandler<HTMLElement>
-
onDurationChangeCapture
ReactEventHandler<HTMLElement>
-
onEmptied
ReactEventHandler<HTMLElement>
-
onEmptiedCapture
ReactEventHandler<HTMLElement>
-
onEncrypted
ReactEventHandler<HTMLElement>
-
onEncryptedCapture
ReactEventHandler<HTMLElement>
-
onEnded
ReactEventHandler<HTMLElement>
-
onEndedCapture
ReactEventHandler<HTMLElement>
-
onLoadedData
ReactEventHandler<HTMLElement>
-
onLoadedDataCapture
ReactEventHandler<HTMLElement>
-
onLoadedMetadata
ReactEventHandler<HTMLElement>
-
onLoadedMetadataCapture
ReactEventHandler<HTMLElement>
-
onLoadStart
ReactEventHandler<HTMLElement>
-
onLoadStartCapture
ReactEventHandler<HTMLElement>
-
onPause
ReactEventHandler<HTMLElement>
-
onPauseCapture
ReactEventHandler<HTMLElement>
-
onPlay
ReactEventHandler<HTMLElement>
-
onPlayCapture
ReactEventHandler<HTMLElement>
-
onPlaying
ReactEventHandler<HTMLElement>
-
onPlayingCapture
ReactEventHandler<HTMLElement>
-
onProgress
ReactEventHandler<HTMLElement>
-
onProgressCapture
ReactEventHandler<HTMLElement>
-
onRateChange
ReactEventHandler<HTMLElement>
-
onRateChangeCapture
ReactEventHandler<HTMLElement>
-
onResize
ReactEventHandler<HTMLElement>
-
onResizeCapture
ReactEventHandler<HTMLElement>
-
onSeeked
ReactEventHandler<HTMLElement>
-
onSeekedCapture
ReactEventHandler<HTMLElement>
-
onSeeking
ReactEventHandler<HTMLElement>
-
onSeekingCapture
ReactEventHandler<HTMLElement>
-
onStalled
ReactEventHandler<HTMLElement>
-
onStalledCapture
ReactEventHandler<HTMLElement>
-
onSuspend
ReactEventHandler<HTMLElement>
-
onSuspendCapture
ReactEventHandler<HTMLElement>
-
onTimeUpdate
ReactEventHandler<HTMLElement>
-
onTimeUpdateCapture
ReactEventHandler<HTMLElement>
-
onVolumeChange
ReactEventHandler<HTMLElement>
-
onVolumeChangeCapture
ReactEventHandler<HTMLElement>
-
onWaiting
ReactEventHandler<HTMLElement>
-
onWaitingCapture
ReactEventHandler<HTMLElement>
-
onAuxClick
MouseEventHandler<HTMLElement>
-
onAuxClickCapture
MouseEventHandler<HTMLElement>
-
onClick
MouseEventHandler<HTMLElement>
-
onClickCapture
MouseEventHandler<HTMLElement>
-
onContextMenu
MouseEventHandler<HTMLElement>
-
onContextMenuCapture
MouseEventHandler<HTMLElement>
-
onDoubleClick
MouseEventHandler<HTMLElement>
-
onDoubleClickCapture
MouseEventHandler<HTMLElement>
-
onDragCapture
DragEventHandler<HTMLElement>
-
onDragEndCapture
DragEventHandler<HTMLElement>
-
onDragEnter
DragEventHandler<HTMLElement>
-
onDragEnterCapture
DragEventHandler<HTMLElement>
-
onDragExit
DragEventHandler<HTMLElement>
-
onDragExitCapture
DragEventHandler<HTMLElement>
-
onDragLeave
DragEventHandler<HTMLElement>
-
onDragLeaveCapture
DragEventHandler<HTMLElement>
-
onDragOver
DragEventHandler<HTMLElement>
-
onDragOverCapture
DragEventHandler<HTMLElement>
-
onDragStartCapture
DragEventHandler<HTMLElement>
-
onDrop
DragEventHandler<HTMLElement>
-
onDropCapture
DragEventHandler<HTMLElement>
-
onMouseDown
MouseEventHandler<HTMLElement>
-
onMouseDownCapture
MouseEventHandler<HTMLElement>
-
onMouseEnter
MouseEventHandler<HTMLElement>
-
onMouseLeave
MouseEventHandler<HTMLElement>
-
onMouseMove
MouseEventHandler<HTMLElement>
-
onMouseMoveCapture
MouseEventHandler<HTMLElement>
-
onMouseOut
MouseEventHandler<HTMLElement>
-
onMouseOutCapture
MouseEventHandler<HTMLElement>
-
onMouseOver
MouseEventHandler<HTMLElement>
-
onMouseOverCapture
MouseEventHandler<HTMLElement>
-
onMouseUp
MouseEventHandler<HTMLElement>
-
onMouseUpCapture
MouseEventHandler<HTMLElement>
-
onSelect
ReactEventHandler<HTMLElement>
-
onSelectCapture
ReactEventHandler<HTMLElement>
-
onTouchCancel
TouchEventHandler<HTMLElement>
-
onTouchCancelCapture
TouchEventHandler<HTMLElement>
-
onTouchEnd
TouchEventHandler<HTMLElement>
-
onTouchEndCapture
TouchEventHandler<HTMLElement>
-
onTouchMove
TouchEventHandler<HTMLElement>
-
onTouchMoveCapture
TouchEventHandler<HTMLElement>
-
onTouchStart
TouchEventHandler<HTMLElement>
-
onTouchStartCapture
TouchEventHandler<HTMLElement>
-
onPointerDown
PointerEventHandler<HTMLElement>
-
onPointerDownCapture
PointerEventHandler<HTMLElement>
-
onPointerMove
PointerEventHandler<HTMLElement>
-
onPointerMoveCapture
PointerEventHandler<HTMLElement>
-
onPointerUp
PointerEventHandler<HTMLElement>
-
onPointerUpCapture
PointerEventHandler<HTMLElement>
-
onPointerCancel
PointerEventHandler<HTMLElement>
-
onPointerCancelCapture
PointerEventHandler<HTMLElement>
-
onPointerEnter
PointerEventHandler<HTMLElement>
-
onPointerLeave
PointerEventHandler<HTMLElement>
-
onPointerOver
PointerEventHandler<HTMLElement>
-
onPointerOverCapture
PointerEventHandler<HTMLElement>
-
onPointerOut
PointerEventHandler<HTMLElement>
-
onPointerOutCapture
PointerEventHandler<HTMLElement>
-
onGotPointerCapture
PointerEventHandler<HTMLElement>
-
onGotPointerCaptureCapture
PointerEventHandler<HTMLElement>
-
onLostPointerCapture
PointerEventHandler<HTMLElement>
-
onLostPointerCaptureCapture
PointerEventHandler<HTMLElement>
-
onScroll
UIEventHandler<HTMLElement>
-
onScrollCapture
UIEventHandler<HTMLElement>
-
onWheel
WheelEventHandler<HTMLElement>
-
onWheelCapture
WheelEventHandler<HTMLElement>
-
onAnimationStartCapture
AnimationEventHandler<HTMLElement>
-
onAnimationEnd
AnimationEventHandler<HTMLElement>
-
onAnimationEndCapture
AnimationEventHandler<HTMLElement>
-
onAnimationIteration
AnimationEventHandler<HTMLElement>
-
onAnimationIterationCapture
AnimationEventHandler<HTMLElement>
-
onToggle
ToggleEventHandler<HTMLElement>
-
onBeforeToggle
ToggleEventHandler<HTMLElement>
-
onTransitionCancel
TransitionEventHandler<HTMLElement>
-
onTransitionCancelCapture
TransitionEventHandler<HTMLElement>
-
onTransitionEnd
TransitionEventHandler<HTMLElement>
-
onTransitionEndCapture
TransitionEventHandler<HTMLElement>
-
onTransitionRun
TransitionEventHandler<HTMLElement>
-
onTransitionRunCapture
TransitionEventHandler<HTMLElement>
-
onTransitionStart
TransitionEventHandler<HTMLElement>
-
onTransitionStartCapture
TransitionEventHandler<HTMLElement>
-
style
MotionStyle
-
transformTemplate
(transform: TransformProperties, generatedTransform: string) => string
-
data-framer-appear-id
string
-
initial
boolean | TargetAndTransition | VariantLabels
-
animate
boolean | TargetAndTransition | VariantLabels | AnimationControls
-
exit
TargetAndTransition | VariantLabels
-
variants
Variants
-
transition
Transition
-
onBeforeLayoutMeasure
(box: Box) => void
-
onLayoutMeasure
(box: Box, prevBox: Box) => void
-
onUpdate
(latest: ResolvedValues) => void
-
onAnimationStart
(definition: AnimationDefinition) => void
-
onAnimationComplete
(definition: AnimationDefinition) => void
-
onPan
(event: PointerEvent, info: PanInfo) => void
-
onPanStart
(event: PointerEvent, info: PanInfo) => void
-
onPanSessionStart
(event: PointerEvent, info: EventInfo) => void
-
onPanEnd
(event: PointerEvent, info: PanInfo) => void
-
onTap
(event: PointerEvent | MouseEvent | TouchEvent, info: TapInfo) => void
-
onTapStart
(event: PointerEvent | MouseEvent | TouchEvent, info: TapInfo) => void
-
onTapCancel
(event: PointerEvent | MouseEvent | TouchEvent, info: TapInfo) => void
-
whileTap
TargetAndTransition | VariantLabels
-
globalTapTarget
boolean
-
whileHover
TargetAndTransition | VariantLabels
-
onHoverStart
(event: MouseEvent, info: EventInfo) => void
-
onHoverEnd
(event: MouseEvent, info: EventInfo) => void
-
whileFocus
TargetAndTransition | VariantLabels
-
whileInView
TargetAndTransition | VariantLabels
-
onViewportEnter
ViewportEventHandler
-
onViewportLeave
ViewportEventHandler
-
viewport
ViewportOptions
-
drag
boolean | "x" | "y"
-
whileDrag
TargetAndTransition | VariantLabels
-
dragDirectionLock
boolean
-
dragPropagation
boolean
-
dragConstraints
false | Partial<BoundingBox> | RefObject<Element | null>
-
dragElastic
DragElastic
-
dragMomentum
boolean
-
dragTransition
Partial<Omit<Inertia, "type" | "velocity">>
-
dragControls
DragControls
-
dragSnapToOrigin
boolean
-
dragListener
boolean
-
onMeasureDragConstraints
(constraints: BoundingBox) => void | BoundingBox
-
_dragX
MotionValue<number>
-
_dragY
MotionValue<number>
-
onDragStart
(event: PointerEvent | MouseEvent | TouchEvent, info: PanInfo) => void
-
onDragEnd
(event: PointerEvent | MouseEvent | TouchEvent, info: PanInfo) => void
-
onDrag
(event: PointerEvent | MouseEvent | TouchEvent, info: PanInfo) => void
-
onDirectionLock
(axis: "x" | "y") => void
-
onDragTransitionEnd
() => void
-
layout
boolean | "position" | "size" | "preserve-aspect"
-
layoutId
string
-
onLayoutAnimationStart
() => void
-
onLayoutAnimationComplete
() => void
-
layoutDependency
any
-
layoutScroll
boolean
-
layoutRoot
boolean
-
data-framer-portal-id
string
-
custom
any
-
inherit
boolean
-
ignoreStrict
boolean
-

On this page