Skip to content

Commit

Permalink
feat: add ripple effect on button click
Browse files Browse the repository at this point in the history
  • Loading branch information
claudaniloxavier committed Nov 22, 2023
1 parent bbe3073 commit 86d212c
Show file tree
Hide file tree
Showing 6 changed files with 115 additions and 15 deletions.
17 changes: 13 additions & 4 deletions lib/components/Button/index.tsx
@@ -1,12 +1,15 @@
import { FC } from 'react'
import { FC, useRef } from 'react'

// STYLES
import classNames from 'classnames'
import styles from './styles.module.scss'
// HOOKS
import useRipple from '../../hooks/useRipple'

// TYPES
import { ButtonProps as Props } from './types'

// STYLES
import classNames from 'classnames'
import styles from './styles.module.scss'

const Button: FC<Props> = ({
className,
children,
Expand All @@ -21,8 +24,12 @@ const Button: FC<Props> = ({
onClick,
...rest
}: Props) => {
const buttonRef = useRef<HTMLButtonElement>(null)
const ripples = useRipple(buttonRef)

return (
<button
ref={buttonRef}
onClick={disabled ? undefined : onClick}
disabled={disabled}
className={classNames(className, styles.button, {
Expand Down Expand Up @@ -51,6 +58,8 @@ const Button: FC<Props> = ({
})}
{...rest}
>
{ripples}

{icon && (
<span className={styles.icon}>
{icon}
Expand Down
2 changes: 2 additions & 0 deletions lib/components/Button/styles.module.scss
Expand Up @@ -7,6 +7,7 @@
$disabled-opacity: 0.42;

.button {
position: relative;
display: inline-flex;
align-items: center;
justify-content: center;
Expand All @@ -19,6 +20,7 @@ $disabled-opacity: 0.42;
border: border.$width-thin solid transparent;
transition: all 180ms ease-in-out;
user-select: none;
overflow: hidden;

&:disabled {
cursor: not-allowed;
Expand Down
17 changes: 17 additions & 0 deletions lib/hooks/useDebounce.ts
@@ -0,0 +1,17 @@
import { useEffect, useState } from 'react'

const useDebounce = <T>(value: T, delay?: number): T => {
const [debouncedValue, setDebouncedValue] = useState<T>(value)

useEffect(() => {
const timer = setTimeout(() => setDebouncedValue(value), delay || 500)

return () => {
clearTimeout(timer)
}
}, [value, delay])

return debouncedValue
}

export default useDebounce
65 changes: 65 additions & 0 deletions lib/hooks/useRipple.tsx
@@ -0,0 +1,65 @@
import { useEffect, useState, RefObject, CSSProperties } from 'react'

import useDebounce from './useDebounce'

const useRipple = <T extends HTMLElement>(ref: RefObject<T>) => {
const [ripples, setRipples] = useState<CSSProperties[]>([])

useEffect(() => {
if (ref.current) {
const element = ref.current

const clickHandler = (e: MouseEvent) => {
var rect = element.getBoundingClientRect()
var left = e.clientX - rect.left
var top = e.clientY - rect.top

const height = element.clientHeight
const width = element.clientWidth
const diameter = Math.max(width, height)

setRipples([
...ripples,
{
top: top - diameter / 2,
left: left - diameter /2,
height: Math.max(width, height),
width: Math.max(width, height)
}
])
}

element.addEventListener('click', clickHandler)

return () => {
element.removeEventListener('click', clickHandler)
}
}
}, [ref, ripples])

const debounced = useDebounce(ripples, 1000)
useEffect(() => {
if (debounced.length) {
setRipples([])
}
}, [debounced.length])

return ripples.map((style, i) => {
return (
<span
key={i}
style={{
...style,
position: 'absolute',
backgroundColor: '#FFFFFF',
opacity: "25%",
transform: "scale(0)",
animation: "rippleAnimation 600ms linear",
borderRadius: "50%"
}}
/>
)
})
}

export default useRipple
9 changes: 8 additions & 1 deletion lib/theme/main.scss
Expand Up @@ -2,4 +2,11 @@

// body {
// background-color: red;
// }
// }

@keyframes rippleAnimation {
to {
transform: scale(4);
opacity: 0;
}
}
20 changes: 10 additions & 10 deletions lib/theme/variables/_color.scss
Expand Up @@ -53,16 +53,16 @@ $warning-700: #F59F00;
$warning-800: #F08C00;
$warning-900: #E67700;

$default-50: #E7F5FF;
$default-100: #D0EBFF;
$default-200: #A5D8FF;
$default-300: #74C0FC;
$default-400: #4DABF7;
$default-500: #339AF0;
$default-600: #228BE6;
$default-700: #1C7ED6;
$default-800: #1971C2;
$default-900: #1864AB;
$default-50: #f8f9fa;
$default-100: #f1f3f5;
$default-200: #e9ecef;
$default-300: #dee2e6;
$default-400: #ced4da;
$default-500: #adb5bd;
$default-600: #868e96;
$default-700: #495057;
$default-800: #343a40;
$default-900: #212529;

$light-transparent-4: rgba(255, 255, 255, 0.04);
$light-transparent-8: rgba(255, 255, 255, 0.08);
Expand Down

0 comments on commit 86d212c

Please sign in to comment.