Skip to content

Commit 44ab1da

Browse files
committed
fix: M3Ripple effect logic
1 parent 17237ca commit 44ab1da

File tree

12 files changed

+131
-78
lines changed

12 files changed

+131
-78
lines changed

m3-react/src/components/button/M3Button.tsx

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,10 @@ import {
2222
useRef,
2323
} from 'react'
2424

25-
import { useElementEffect } from '@/hooks'
25+
import {
26+
useElementEffect,
27+
useTarget,
28+
} from '@/hooks'
2629

2730
import { compose } from '@/utils/events'
2831
import { normalize } from '@/utils/content'
@@ -57,13 +60,16 @@ const M3Button: ForwardRefRenderFunction<
5760
const root = useRef<HTMLButtonElement | null>(null)
5861
const ripple = useRef<M3RippleMethods | null>(null)
5962

63+
const [rippleTarget, setRippleTarget] = useTarget<HTMLButtonElement>()
64+
6065
useImperativeHandle(ref, () => ({
6166
click: () => root.current?.click(),
6267
focus: () => root.current?.focus(),
6368
blur: () => root.current?.blur(),
6469
}))
6570

6671
useElementEffect(root, effects)
72+
useElementEffect(root, setRippleTarget)
6773

6874
const content = useMemo(() => normalize(children), [children])
6975

@@ -84,12 +90,12 @@ const M3Button: ForwardRefRenderFunction<
8490
disabled={disabled}
8591
onKeyUp={compose(event => {
8692
if (event.code === 'Enter') {
87-
ripple.current?.activate(event)
93+
ripple.current?.activate(event.nativeEvent)
8894
}
8995
}, onKeyUp)}
9096
{...attrs}
9197
>
92-
<M3Ripple ref={ripple} owner={root} />
98+
<M3Ripple ref={ripple} owner={rippleTarget} />
9399
<span className="m3-button__state">
94100
{content.map(([child, isIcon], index) => (
95101
<span

m3-react/src/components/card/M3Card.tsx

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type {
1+
import {
22
FC,
33
HTMLAttributes,
44
ReactNode,
@@ -12,7 +12,11 @@ import { M3Ripple } from '@/components/ripple'
1212

1313
import { useRef } from 'react'
1414

15-
import makeId from '@/utils/id'
15+
import {
16+
useElementEffect,
17+
useId,
18+
useTarget,
19+
} from '@/hooks'
1620

1721
import { compose } from '@/utils/events'
1822
import {
@@ -62,7 +66,7 @@ const Subheading: FC<HTMLAttributes<HTMLElement>> = ({
6266
)
6367

6468
const M3Card: FC<M3CardProps> = ({
65-
id = makeId('m3-card'),
69+
id,
6670
appearance = 'filled',
6771
heading = '',
6872
subheading = '',
@@ -74,8 +78,10 @@ const M3Card: FC<M3CardProps> = ({
7478
onClick = (_) => {},
7579
...attrs
7680
}) => {
81+
const _id = useId(id ,'m3-card')
7782
const state = useRef<HTMLDivElement | null>(null)
7883
const ripple = useRef<M3RippleMethods | null>(null)
84+
const [rippleTarget, setRippleTarget] = useTarget<HTMLDivElement>()
7985

8086
const [slots, content, hasSlot] = distinct(children, {
8187
content: Content,
@@ -84,18 +90,20 @@ const M3Card: FC<M3CardProps> = ({
8490
subheading: Subheading,
8591
})
8692

93+
useElementEffect(state, setRippleTarget)
94+
8795
const hasHeading = hasSlot('heading') || heading.length > 0
8896
const hasSubheading = hasSlot('subheading') || subheading.length > 0
8997

9098
const headingId = slots.heading?.props.id ?? null
9199
const headingEl = slots.heading
92-
? headingId ? slots.heading : augment(slots.heading, { id: id + '-heading' })
100+
? headingId ? slots.heading : augment(slots.heading, { id: _id + '-heading' })
93101
: heading.length
94-
? <Heading id={id + '-heading'} children={heading} />
102+
? <Heading id={_id + '-heading'} children={heading} />
95103
: null
96104

97105
const aria = !('aria-label' in attrs) && !hasSlot('content') && hasHeading ? {
98-
'aria-labelledby': headingId ?? id + '-heading',
106+
'aria-labelledby': headingId ?? _id + '-heading',
99107
} : {}
100108

101109
return (
@@ -109,18 +117,18 @@ const M3Card: FC<M3CardProps> = ({
109117
role={role}
110118
onClick={compose(event => {
111119
if (interactive) {
112-
ripple.current?.activate(event)
120+
ripple.current?.activate(event.nativeEvent)
113121
}
114122
}, onClick)}
115123
{...{
116-
...(interactive ? { tabindex: 0 } : {}),
124+
...(interactive ? { tabIndex: 0 } : {}),
117125
...aria,
118126
...attrs,
119127
}}
120128
>
121129
{interactive ? (
122130
<div ref={state} className="m3-card__state">
123-
<M3Ripple ref={ripple} owner={state}/>
131+
<M3Ripple ref={ripple} owner={rippleTarget} />
124132
</div>
125133
) : null}
126134
{slots.content ?? (<>

m3-react/src/components/checkbox/M3Checkbox.tsx

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,11 @@ import {
2323
useRef,
2424
} from 'react'
2525

26-
import useId from '@/hooks/useId'
26+
import {
27+
useElementEffect,
28+
useId,
29+
useTarget,
30+
} from '@/hooks'
2731

2832
import { toClassName } from '@/utils/styling'
2933

@@ -64,13 +68,16 @@ const M3Checkbox: ForwardRefRenderFunction<
6468
const root = useRef<HTMLElement | null>(null)
6569
const input = useRef<HTMLInputElement | null>(null)
6670
const ripple = useRef<M3RippleMethods | null>(null)
71+
const [rippleTarget, setRippleTarget] = useTarget<HTMLElement>()
6772

6873
useImperativeHandle(ref, () => ({
6974
click: () => input.current?.click(),
7075
focus: () => input.current?.focus(),
7176
blur: () => input.current?.blur(),
7277
}))
7378

79+
useElementEffect(root, setRippleTarget)
80+
7481
const contains = useCallback((array: unknown[], value: unknown) => {
7582
return array.some(v => equalsFn(v, value))
7683
}, [equalsFn])
@@ -101,7 +108,7 @@ const M3Checkbox: ForwardRefRenderFunction<
101108
}])}
102109
{...args}
103110
>
104-
<M3Ripple ref={ripple} owner={root} />
111+
<M3Ripple ref={ripple} owner={rippleTarget} />
105112

106113
<input
107114
id={useId(id, 'm3-checkbox')}

m3-react/src/components/fab-button/M3FabButton.tsx

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ import {
2323
useRef,
2424
} from 'react'
2525

26+
import {
27+
useElementEffect,
28+
useTarget,
29+
} from '@/hooks'
30+
2631
import { compose } from '@/utils/events'
2732
import { normalize } from '@/utils/content'
2833
import { toClassName } from '@/utils/styling'
@@ -55,13 +60,16 @@ const M3FabButton: ForwardRefRenderFunction<
5560
}, ref) => {
5661
const root = useRef<HTMLButtonElement | null>(null)
5762
const ripple = useRef<M3RippleMethods | null>(null)
63+
const [rippleTarget, setRippleTarget] = useTarget<HTMLElement>()
5864

5965
useImperativeHandle(ref, () => ({
6066
click: () => root.current?.click(),
6167
focus: () => root.current?.focus(),
6268
blur: () => root.current?.blur(),
6369
}))
6470

71+
useElementEffect(root, setRippleTarget)
72+
6573
const content = normalize(children)
6674

6775
const hasText = content.some(([, isIcon]) => !isIcon)
@@ -83,12 +91,12 @@ const M3FabButton: ForwardRefRenderFunction<
8391
disabled={disabled}
8492
onKeyUp={compose(event => {
8593
if (event.code === 'Enter') {
86-
ripple.current?.activate(event)
94+
ripple.current?.activate(event.nativeEvent)
8795
}
8896
}, onKeyUp)}
8997
{...attrs}
9098
>
91-
<M3Ripple ref={ripple} owner={root} />
99+
<M3Ripple ref={ripple} owner={rippleTarget} />
92100
<span className="m3-fab-button__state">
93101
{content.map(([child, isIcon], index) => (
94102
<span

m3-react/src/components/icon-button/M3IconButton.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type {
1+
import {
22
ForwardRefRenderFunction,
33
HTMLAttributes,
44
} from 'react'
@@ -20,6 +20,11 @@ import {
2020
useRef,
2121
} from 'react'
2222

23+
import {
24+
useElementEffect,
25+
useTarget,
26+
} from '@/hooks'
27+
2328
import { compose } from '@/utils/events'
2429
import { toClassName } from '@/utils/styling'
2530

@@ -49,13 +54,16 @@ const M3IconButton: ForwardRefRenderFunction<
4954
}, ref) => {
5055
const root = useRef<HTMLButtonElement | null>(null)
5156
const ripple = useRef<M3RippleMethods | null>(null)
57+
const [rippleTarget, setRippleTarget] = useTarget<HTMLButtonElement>()
5258

5359
useImperativeHandle(ref, () => ({
5460
click: () => root.current?.click(),
5561
focus: () => root.current?.focus(),
5662
blur: () => root.current?.blur(),
5763
}))
5864

65+
useElementEffect(root, setRippleTarget)
66+
5967
return (
6068
<button
6169
ref={root}
@@ -69,12 +77,12 @@ const M3IconButton: ForwardRefRenderFunction<
6977
disabled={disabled}
7078
onKeyUp={compose(event => {
7179
if (event.code === 'Enter') {
72-
ripple.current?.activate(event)
80+
ripple.current?.activate(event.nativeEvent)
7381
}
7482
}, onKeyUp)}
7583
{...attrs}
7684
>
77-
<M3Ripple ref={ripple} owner={root}/>
85+
<M3Ripple ref={ripple} owner={rippleTarget} />
7886
<span className="m3-icon-button__state">
7987
<M3IconAppearance.Provider value={toggleable && selected ? 'filled' : 'outlined'}>
8088
{children}

m3-react/src/components/navigation/M3NavigationTab.tsx

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,15 @@ import { M3Ripple } from '@/components/ripple'
1919
import {
2020
forwardRef,
2121
useImperativeHandle,
22+
useMemo,
2223
useRef,
2324
} from 'react'
2425

2526
import {
2627
useBreakpoint,
28+
useElementEffect,
2729
useId,
30+
useTarget,
2831
} from '@/hooks'
2932

3033
import { compose } from '@/utils/events'
@@ -74,12 +77,15 @@ const M3NavigationTab: ForwardRefRenderFunction<
7477
}, ref) => {
7578
const button = useRef<HTMLButtonElement | null>(null)
7679
const ripple = useRef<M3RippleMethods | null>(null)
80+
const [rippleTarget, setRippleTarget] = useTarget<HTMLElement>()
7781

78-
const [slots, content, hasSlot] = distinct(children, {
82+
useElementEffect(button, setRippleTarget)
83+
84+
const [slots, content, hasSlot] = useMemo(() => distinct(children, {
7985
icon: Icon,
8086
label: Label,
8187
badge: Badge,
82-
})
88+
}), [children])
8389

8490
const appearance = useM3NavigationAppearance()
8591
const breakpoint = useBreakpoint()
@@ -126,11 +132,11 @@ const M3NavigationTab: ForwardRefRenderFunction<
126132
}}
127133
onKeyUp={compose(event => {
128134
if (event.code === 'Enter') {
129-
ripple.current?.activate(event)
135+
ripple.current?.activate(event.nativeEvent)
130136
}
131137
}, onKeyUp)}
132138
>
133-
<M3Ripple ref={ripple} owner={button} />
139+
<M3Ripple ref={ripple} owner={rippleTarget} />
134140

135141
<span className="m3-navigation-tab__state">
136142
<M3IconAppearance.Provider value={active ? 'filled' : 'outlined'}>

m3-react/src/components/popper/index.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,3 @@ export type {
1010
export { default as M3Popper } from './M3Popper'
1111

1212
export { default as useM3PopperCloserEffect } from './closer'
13-
export { default as useM3PopperTarget } from './target'

0 commit comments

Comments
 (0)