diff --git a/docs/content/1.getting-started/3.theme.md b/docs/content/1.getting-started/3.theme.md index 391bad0216..561e8f9280 100644 --- a/docs/content/1.getting-started/3.theme.md +++ b/docs/content/1.getting-started/3.theme.md @@ -750,8 +750,12 @@ This is how the `@theme` is generated for each design token: --outline-color-default: var(--ui-border); --outline-color-inverted: var(--ui-border-inverted); --stroke-color-default: var(--ui-border); + --stroke-color-muted: var(--ui-border-muted); + --stroke-color-accented: var(--ui-border-accented); --stroke-color-inverted: var(--ui-border-inverted); --fill-color-default: var(--ui-border); + --fill-color-muted: var(--ui-border-muted); + --fill-color-accented: var(--ui-border-accented); --fill-color-inverted: var(--ui-border-inverted); } ``` diff --git a/docs/content/3.components/progress.md b/docs/content/3.components/progress.md index 5156735bb7..a14f48a4cb 100644 --- a/docs/content/3.components/progress.md +++ b/docs/content/3.components/progress.md @@ -57,6 +57,20 @@ props: --- :: +### Variant + +Use the `variant` prop to change the style of the Progress. Defaults to `linear`. + +::component-code +--- +external: + - modelValue +props: + modelValue: 50 + variant: linear +--- +:: + ### Status Use the `status` prop to display the current Progress value above the bar. @@ -71,6 +85,22 @@ props: --- :: +### Status Position + +Use the `status-position` prop to define where the status text is displayed. Defaults to `outside`. + +::component-code +--- +external: + - modelValue +props: + modelValue: 50 + variant: circular + status: true + statusPosition: 'inside' +--- +:: + ### Indeterminate When no `v-model` is set or the value is `null`, the Progress becomes _indeterminate_. The progress bar is animated as a `carousel`, but you can change it using the [`animation`](#animation) prop. diff --git a/playground/app/pages/components/progress.vue b/playground/app/pages/components/progress.vue index 46a4a5d444..88d4f907d8 100644 --- a/playground/app/pages/components/progress.vue +++ b/playground/app/pages/components/progress.vue @@ -58,6 +58,7 @@ onMounted(() => { :max="max" status inverted + color="warning" class="w-48 justify-start" /> @@ -65,5 +66,70 @@ onMounted(() => {
+ +
+ + + + + + + + + + + + + + + +
diff --git a/src/runtime/components/Progress.vue b/src/runtime/components/Progress.vue index 51541ac156..c751eae762 100644 --- a/src/runtime/components/Progress.vue +++ b/src/runtime/components/Progress.vue @@ -17,6 +17,11 @@ export interface ProgressProps extends Pick /** Display the current progress value. */ status?: boolean + /** + * The position of the status text. + * @defaultValue 'outside' + */ + statusPosition?: 'inside' | 'outside' /** Whether the progress is visually inverted. */ inverted?: boolean /** @@ -37,6 +42,11 @@ export interface ProgressProps extends Pick(), { inverted: false, modelValue: null, - orientation: 'horizontal' + orientation: 'horizontal', + variant: 'linear', + statusPosition: 'outside' }) const emits = defineEmits() const slots = defineSlots() @@ -72,6 +84,9 @@ const appConfig = useAppConfig() as Progress['AppConfig'] const rootProps = useForwardPropsEmits(reactivePick(props, 'getValueLabel', 'modelValue'), emits) +const RADIUS = 40 +const circumference = 2 * Math.PI * RADIUS + const isIndeterminate = computed(() => rootProps.value.modelValue === null) const hasSteps = computed(() => Array.isArray(props.max)) @@ -99,7 +114,23 @@ const percent = computed(() => { } }) +const dashOffset = computed(() => + ((percent.value || 0) / 100) * circumference +) +const trackPath = computed(() => { + const r = RADIUS + return ` + M 50 50 + m 0 -${r} + a ${r} ${r} 0 1 1 0 ${r * 2} + a ${r} ${r} 0 1 1 0 -${r * 2} + ` +}) + const indicatorStyle = computed(() => { + if (props.variant === 'circular') { + return + } if (percent.value === undefined) { return } @@ -123,7 +154,7 @@ const indicatorStyle = computed(() => { const statusStyle = computed(() => { return { - [props.orientation === 'vertical' ? 'height' : 'width']: percent.value ? `${percent.value}%` : 'fit-content' + [props.orientation === 'vertical' ? 'height' : 'width']: percent.value && (props.variant === 'linear') ? `${percent.value}%` : 'fit-content' } }) @@ -162,20 +193,50 @@ const ui = computed(() => tv({ extend: tv(theme), ...(appConfig.ui?.progress || size: props.size, color: props.color, orientation: props.orientation, - inverted: props.inverted + inverted: props.inverted, + variant: props.variant, + statusPosition: props.statusPosition }))