Skip to content

Commit 2bd681d

Browse files
feat(VProgressCircular): add rounded prop (#22051)
1 parent 908e887 commit 2bd681d

File tree

3 files changed

+22
-3
lines changed

3 files changed

+22
-3
lines changed

packages/api-generator/src/locale/en/VProgressCircular.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"props": {
33
"indeterminate": "Constantly animates, use when loading progress is unknown. If set to the string `'disable-shrink'` it will use a simpler animation that does not run on the main thread.",
4+
"rounded": "Rounds the ends of the progress arc for a softer appearance. When enabled, the progress stroke will have rounded caps instead of square ends.",
45
"modelValue": "The percentage value for current progress.",
56
"query": "Animates like **indeterminate** prop but inverse.",
67
"rotate": "Rotates the circle start point in degrees.",

packages/docs/src/data/new-in.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,11 @@
191191
"hideTitle": "3.10.0"
192192
}
193193
},
194+
"VProgressCircular": {
195+
"props": {
196+
"rounded": "3.11.0"
197+
}
198+
},
194199
"VProgressLinear": {
195200
"props": {
196201
"chunkCount": "3.10.0",

packages/vuetify/src/components/VProgressCircular/VProgressCircular.tsx

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import { makeTagProps } from '@/composables/tag'
1111
import { makeThemeProps, provideTheme } from '@/composables/theme'
1212

1313
// Utilities
14-
import { ref, toRef, watchEffect } from 'vue'
14+
import { computed, ref, toRef, watchEffect } from 'vue'
1515
import { clamp, convertToUnit, genericComponent, PREFERS_REDUCED_MOTION, propsFactory, useRender } from '@/util'
1616

1717
// Types
@@ -21,6 +21,7 @@ export const makeVProgressCircularProps = propsFactory({
2121
bgColor: String,
2222
color: String,
2323
indeterminate: [Boolean, String] as PropType<boolean | 'disable-shrink'>,
24+
rounded: Boolean,
2425
modelValue: {
2526
type: [Number, String],
2627
default: 0,
@@ -74,7 +75,18 @@ export const VProgressCircular = genericComponent<VProgressCircularSlots>()({
7475
})
7576
const diameter = toRef(() => (MAGIC_RADIUS_CONSTANT / (1 - width.value / size.value)) * 2)
7677
const strokeWidth = toRef(() => width.value / size.value * diameter.value)
77-
const strokeDashOffset = toRef(() => convertToUnit(((100 - normalizedValue.value) / 100) * CIRCUMFERENCE))
78+
const strokeDashOffset = toRef(() => {
79+
const baseLength = ((100 - normalizedValue.value) / 100) * CIRCUMFERENCE
80+
return props.rounded && normalizedValue.value > 0 && normalizedValue.value < 100
81+
? convertToUnit(Math.min(CIRCUMFERENCE - 0.01, baseLength + strokeWidth.value))
82+
: convertToUnit(baseLength)
83+
})
84+
const startAngle = computed(() => {
85+
const baseAngle = Number(props.rotate)
86+
return props.rounded
87+
? baseAngle + (strokeWidth.value / 2) / CIRCUMFERENCE * 360
88+
: baseAngle
89+
})
7890

7991
watchEffect(() => {
8092
intersectionRef.value = root.value
@@ -109,7 +121,7 @@ export const VProgressCircular = genericComponent<VProgressCircularSlots>()({
109121
>
110122
<svg
111123
style={{
112-
transform: `rotate(calc(-90deg + ${Number(props.rotate)}deg))`,
124+
transform: `rotate(calc(-90deg + ${startAngle.value}deg))`,
113125
}}
114126
xmlns="http://www.w3.org/2000/svg"
115127
viewBox={ `0 0 ${diameter.value} ${diameter.value}` }
@@ -138,6 +150,7 @@ export const VProgressCircular = genericComponent<VProgressCircularSlots>()({
138150
stroke-width={ strokeWidth.value }
139151
stroke-dasharray={ CIRCUMFERENCE }
140152
stroke-dashoffset={ strokeDashOffset.value }
153+
stroke-linecap={ props.rounded ? 'round' : undefined }
141154
/>
142155
</svg>
143156

0 commit comments

Comments
 (0)