Skip to content

Commit e31eb68

Browse files
authored
Merge pull request #141 from motiondivision/fix/svg-attr
fix(motion): rm svg stroke-width style
2 parents f92adc3 + 36a1e05 commit e31eb68

File tree

5 files changed

+122
-122
lines changed

5 files changed

+122
-122
lines changed

packages/motion/src/components/__tests__/svg.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,26 @@ describe('row-value', () => {
3535
expect(path.getAttribute('stroke')).toBe('blue')
3636
expect(path.getAttribute('opacity')).toBe('1')
3737
})
38+
it('should update stroke-width through attributes instead of style', async () => {
39+
const strokeWidth = motionValue(2)
40+
const wrapper = render(Motion, {
41+
props: {
42+
as: 'path',
43+
style: {
44+
strokeWidth,
45+
},
46+
},
47+
attrs: {
48+
'data-testid': 'path',
49+
},
50+
})
51+
await nextTick()
52+
const path = wrapper.getByTestId('path')
53+
expect(path.style.strokeWidth).toBeFalsy()
54+
expect(path.getAttribute('stroke-width')).toBe('2')
55+
strokeWidth.set(4)
56+
await delay(100)
57+
expect(path.style.strokeWidth).toBeFalsy()
58+
expect(path.getAttribute('stroke-width')).toBe('4')
59+
})
3860
})

packages/motion/src/state/style.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ const SVG_STYLE_TO_ATTRIBUTES = {
7676
'fill': true,
7777
'stroke': true,
7878
'opacity': true,
79+
'stroke-width': true,
7980
'fill-opacity': true,
8081
'stroke-opacity': true,
8182
'stroke-linecap': true,

playground/nuxt/pages/layout.vue

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
<script setup lang="ts">
2-
import { LazyMotion, m, motion } from 'motion-v'
2+
import { motion } from 'motion-v'
33
import { ref } from 'vue'
44
5-
const allFeatures = import('./test').then(res => res.default)
65
const isExpanded = ref(false)
76
87
function handleAnimationComplete() {
@@ -19,22 +18,6 @@ function handleAnimationStart() {
1918
<button @click="isExpanded = !isExpanded">
2019
{{ isExpanded ? 'Shrink' : 'Expand' }}
2120
</button>
22-
<LazyMotion :features="allFeatures">
23-
<m.button
24-
:layout="true"
25-
:initial="{ borderRadius: '12px' }"
26-
class="bg-purple-500 h-20"
27-
:style="{ width: isExpanded ? '300px' : '100px' }"
28-
tabindex="-1"
29-
:transition="{
30-
layout: {
31-
type: 'spring',
32-
stiffness: 100,
33-
damping: 10,
34-
},
35-
}"
36-
/>
37-
</LazyMotion>
3821

3922
<motion.button
4023
:layout="true"

playground/nuxt/pages/test.ts

Lines changed: 0 additions & 3 deletions
This file was deleted.

playground/nuxt/pages/test.vue

Lines changed: 98 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -1,88 +1,73 @@
1-
<script setup lang="tsx">
2-
/** @jsxImportSource vue */
3-
import { AnimateNumber } from 'motion-number-vue'
4-
import { motion } from 'motion-v'
5-
import { ref } from 'vue'
1+
<script setup lang="ts">
2+
import { animate, motion, useMotionValue, useTransform } from 'motion-v'
63
7-
const isCompact = ref(true)
8-
const isCurrency = ref(false)
4+
const progress = useMotionValue(0)
95
10-
function Switch({ isOn, toggle }: { isOn: boolean, toggle: () => void }) {
11-
return (
12-
<motion.button
13-
class="switch-container"
14-
style={{
15-
justifyContent: `flex-${isOn ? 'end' : 'start'}`,
16-
}}
17-
initial={false}
18-
animate={{
19-
backgroundColor: isOn
20-
? 'var(--hue-6-transparent)'
21-
: '#586d8c33',
22-
}}
23-
onClick={toggle}
24-
focus={{
25-
outline: '2px solid #4ff0b7',
26-
}}
27-
>
28-
<motion.div
29-
class="switch-handle"
30-
layout
31-
data-is-on={isOn}
32-
transition={{
33-
type: 'spring',
34-
visualDuration: 0.2,
35-
bounce: 0.2,
36-
}}
37-
/>
38-
</motion.button>
39-
)
6+
const circleStrokeWidth = useTransform(progress, [0, 1], [0, 20])
7+
const circleRotation = useTransform(progress, [0, 1], ['-90deg', '-90deg'])
8+
const circleColor = useTransform(progress, [0, 1], ['#ffffff', '#8df0cc'])
9+
10+
const buttonScale = useTransform(progress, [0, 1], [1, 0.85])
11+
const buttonProgressX = useTransform(progress, [0, 1], ['-200%', '0%'])
12+
13+
function handlePointerDown() {
14+
progress.set(0)
15+
animate(progress, 1, {
16+
duration: 2,
17+
ease: 'easeOut',
18+
})
4019
}
41-
const value = ref(5385)
42-
function changeCurrency() {
43-
// value.value = 58
44-
value.value = Math.random() * 1000 * (Math.random() > 0.5 ? 1 : -1) * 10 ** Math.floor(Math.random() * 3)
20+
21+
function handlePointerUp() {
22+
animate(progress, 0, { duration: 0.3 })
4523
}
4624
</script>
4725

4826
<template>
49-
<div
50-
class="container"
51-
@click="changeCurrency"
52-
>
53-
<AnimateNumber
54-
:format="{
55-
notation: isCompact ? 'compact' : undefined,
56-
compactDisplay: isCompact ? 'short' : undefined,
57-
roundingMode: isCompact ? 'trunc' : undefined,
58-
style: isCurrency ? 'currency' : undefined,
59-
currency: isCurrency ? 'USD' : undefined,
60-
}"
61-
locales="en-US"
62-
class="number"
63-
:transition="{
64-
visualDuration: 0.6,
65-
type: 'spring',
66-
bounce: 0.25,
67-
opacity: { duration: 0.3, ease: 'linear' },
68-
}"
69-
:value="value"
70-
/>
71-
<div class="controls">
72-
<div>
73-
Currency:
74-
<Switch
75-
:is-on="isCurrency"
76-
:toggle="() => isCurrency = !isCurrency"
27+
<div class="container">
28+
<div class="button-wrapper">
29+
<motion.button
30+
class="button"
31+
:style="{
32+
scale: buttonScale,
33+
}"
34+
@pointerdown="handlePointerDown"
35+
@pointerup="handlePointerUp"
36+
@pointerleave="handlePointerUp"
37+
>
38+
<motion.div
39+
class="button-background"
40+
:style="{
41+
x: buttonProgressX,
42+
}"
7743
/>
78-
</div>
79-
<div>
80-
Compact:
81-
<Switch
82-
:is-on="isCompact"
83-
:toggle="() => isCompact = !isCompact"
44+
Hold to confirm
45+
</motion.button>
46+
47+
<motion.svg
48+
class="progress-ring"
49+
width="320"
50+
height="320"
51+
viewBox="0 0 320 320"
52+
>
53+
<motion.circle
54+
cx="160"
55+
cy="160"
56+
r="120"
57+
fill="none"
58+
stroke="var(--white-feint)"
59+
stroke-width="24"
60+
stroke-linecap="round"
61+
:style="{
62+
rotate: circleRotation,
63+
transformOrigin: 'center',
64+
opacity: progress,
65+
stroke: circleColor,
66+
strokeWidth: circleStrokeWidth,
67+
pathLength: progress,
68+
}"
8469
/>
85-
</div>
70+
</motion.svg>
8671
</div>
8772
</div>
8873
</template>
@@ -91,40 +76,52 @@ function changeCurrency() {
9176
.container {
9277
display: flex;
9378
flex-direction: column;
79+
gap: 16px;
9480
align-items: center;
95-
gap: 20px;
96-
}
97-
98-
.number {
99-
font-size: 78px;
81+
justify-content: center;
82+
padding: 16px;
83+
height: 80px;
10084
}
10185
102-
.controls {
86+
.button-wrapper {
87+
position: relative;
10388
display: flex;
104-
gap: 20px;
105-
border-radius: 50px;
89+
align-items: center;
90+
justify-content: center;
10691
}
10792
108-
.controls > div {
109-
display: flex;
110-
align-items: center;
111-
gap: 10px;
112-
font-size: 18px;
93+
.progress-ring {
94+
position: absolute;
95+
top: 50%;
96+
left: 50%;
97+
transform: translate(-50%, -50%);
98+
pointer-events: none;
11399
}
114100
115-
.switch-container {
116-
width: 40px;
117-
height: 20px;
118-
border-radius: 25px;
119-
cursor: pointer;
120-
display: flex;
121-
padding: 5px;
101+
.button {
102+
color: var(--black);
103+
background-color: var(--white);
104+
border-radius: 999px;
105+
padding: 12px 20px;
106+
position: relative;
107+
isolation: isolate;
108+
overflow: hidden;
109+
will-change: transform;
110+
user-select: none;
111+
-webkit-user-select: none;
112+
-webkit-touch-callout: none;
122113
}
123114
124-
.switch-handle {
125-
width: 20px;
126-
height: 20px;
127-
background-color: #4ff0b7;
128-
border-radius: 50%;
115+
.button-background {
116+
position: absolute;
117+
top: 0;
118+
left: 0;
119+
width: 100%;
120+
height: 100%;
121+
background-color: var(--green);
122+
border-radius: 999px;
123+
z-index: -1;
124+
filter: blur(20px);
125+
scale: 2;
129126
}
130127
</style>

0 commit comments

Comments
 (0)