Skip to content

feat: progressbar new way of handling classes #1607

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 11 additions & 15 deletions src/lib/progress/Progressbar.svelte
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
<script lang="ts">
import { twMerge } from "tailwind-merge";
import type { ProgressbarProps } from "$lib/types";
import clsx from "clsx";
import { cubicOut } from "svelte/easing";
import { Tween } from "svelte/motion";
import { progressbar } from ".";
import type { ProgressbarProps } from "$lib/types";

let { progress = "45", precision = 0, tweenDuration = 400, animate = false, size = "h-2.5", labelInside = false, labelOutside = "", easing = cubicOut, color = "primary", labelInsideClass, oustsideSpanClass, oustsideProgressClass, labeloutsidedivClass, divClass, ...restProps }: ProgressbarProps = $props();
let { progress = "45", precision = 0, tweenDuration = 400, animate = false, size = "h-2.5", labelInside = false, labelOutside = "", easing = cubicOut, color = "primary", class: className, classes, ...restProps }: ProgressbarProps = $props();

let _progress = new Tween(0, {
duration: animate ? tweenDuration : 0,
Expand All @@ -25,26 +24,26 @@
</script>

{#if labelOutside}
<div {...restProps} class={twMerge(outsideDiv(), clsx(labeloutsidedivClass))}>
<span class={twMerge(oustsideSpan(), clsx(oustsideSpanClass))}>{labelOutside}</span>
<span class={twMerge(outsideProgress(), clsx(oustsideProgressClass))}>{progress}%</span>
<div {...restProps} class={outsideDiv({ class: clsx(classes?.outsideDiv) })}>
<span class={oustsideSpan({ class: clsx(classes?.oustsideSpan) })}>{labelOutside}</span>
<span class={outsideProgress({ class: clsx(classes?.outsideProgress) })}>{progress}%</span>
</div>
{/if}
<div {...restProps} class={twMerge(base(), size, clsx(divClass))}>
<div {...restProps} class={base({ class: clsx(size, classes?.base, className) })}>
{#if labelInside}
<div class={twMerge(labelInsideDiv(), size, clsx(labelInsideClass))} style="width: {_progress.current}%">
<div class={labelInsideDiv({ class: clsx(classes?.labelInsideDiv, size) })} style="width: {_progress.current}%">
{_progress.current.toFixed(precision)}%
</div>
{:else}
<div class={twMerge(insideDiv(), size, clsx(labelInsideClass))} style="width: {_progress.current}%"></div>
<div class={insideDiv({ class: clsx(classes?.labelInsideDiv, size) })} style="width: {_progress.current}%"></div>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix incorrect class reference.

There's a copy-paste error where classes?.labelInsideDiv is used instead of classes?.insideDiv. This will apply the wrong styling to the inside div element.

Apply this fix:

-    <div class={insideDiv({ class: clsx(classes?.labelInsideDiv, size) })} style="width: {_progress.current}%"></div>
+    <div class={insideDiv({ class: clsx(classes?.insideDiv, size) })} style="width: {_progress.current}%"></div>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<div class={insideDiv({ class: clsx(classes?.labelInsideDiv, size) })} style="width: {_progress.current}%"></div>
<div class={insideDiv({ class: clsx(classes?.insideDiv, size) })} style="width: {_progress.current}%"></div>
🤖 Prompt for AI Agents
In src/lib/progress/Progressbar.svelte at line 38, the class reference uses
classes?.labelInsideDiv instead of the correct classes?.insideDiv, causing
incorrect styling. Replace classes?.labelInsideDiv with classes?.insideDiv in
the clsx function call to apply the proper styles to the inside div element.

{/if}
</div>

<!--
@component
[Go to docs](https://flowbite-svelte.com/)
## Type
[ProgressbarProps](https://github.com/themesberg/flowbite-svelte/blob/main/src/lib/types.ts#L1244)
[ProgressbarProps](https://github.com/themesberg/flowbite-svelte/blob/main/src/lib/types.ts#L1247)
## Props
@prop progress = "45"
@prop precision = 0
Expand All @@ -55,10 +54,7 @@
@prop labelOutside = ""
@prop easing = cubicOut
@prop color = "primary"
@prop labelInsideClass
@prop oustsideSpanClass
@prop oustsideProgressClass
@prop labeloutsidedivClass
@prop divClass
@prop class: className
@prop classes
@prop ...restProps
-->
30 changes: 13 additions & 17 deletions src/lib/progress/Progressradial.svelte
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
<script lang="ts">
import { twMerge } from "tailwind-merge";
import { progressradial } from "$lib/progress/theme";
import type { ProgressradialProps } from "$lib/types";
import clsx from "clsx";
import { cubicOut } from "svelte/easing";
import { Tween } from "svelte/motion";
import { progressradial } from "$lib/progress/theme";
import type { ProgressradialProps } from "$lib/types";

let { progress = 45, radius = 42, startingPosition = "top", precision = 0, tweenDuration = 400, animate = false, size = "h-24 w-24", thickness = 4, labelInside = false, labelOutside = "", easing = cubicOut, color = "primary", labelInsideClass, outsideSpanClass, outsideProgressClass, labelOutsideDivClass, divClass, ...restProps }: ProgressradialProps = $props();
let { progress = 45, radius = 42, startingPosition = "top", precision = 0, tweenDuration = 400, animate = false, size = "h-24 w-24", thickness = 4, labelInside = false, labelOutside = "", easing = cubicOut, color = "primary", class: className, classes, ...restProps }: ProgressradialProps = $props();

const _progress = new Tween(0, {
duration: animate ? tweenDuration : 0,
Expand Down Expand Up @@ -36,23 +35,23 @@

<div class="flex flex-col items-center">
{#if labelOutside}
<div class={twMerge(outsideDiv(), clsx(labelOutsideDivClass))}>
<span class={twMerge(outsideSpan(),clsx(outsideSpanClass))}>{labelOutside}</span>
<span class={twMerge(outsideProgress(),clsx(outsideProgressClass))}>{formattedProgress}%</span>
<div class={outsideDiv({ class: clsx(classes?.outsideDiv) })}>
<span class={outsideSpan({ class: clsx(classes?.outsideSpan) })}>{labelOutside}</span>
<span class={outsideProgress({ class: clsx(classes?.outsideProgress) })}>{formattedProgress}%</span>
</div>
{/if}

<div {...restProps} class={twMerge(base(), size, clsx(divClass))}>
<div {...restProps} class={base({ class: clsx(size, classes?.base, className) })}>
<svg viewBox="0 0 100 100" class="h-full w-full" style="transform: rotate({rotationAngle}deg)">
<!-- Background circle -->
<circle cx="50" cy="50" r={radius} class={circleBackground()} fill="none" stroke-width={thickness} />
<circle cx="50" cy="50" r={radius} class={circleBackground({ class: clsx(classes?.circleBackground) })} fill="none" stroke-width={thickness} />

<!-- Foreground circle (progress indicator) -->
<circle cx="50" cy="50" r={radius} class={circleForeground()} fill="none" stroke-width={thickness} stroke-dasharray={circumference} stroke-dashoffset={strokeDashoffset} stroke-linecap="round" />
<circle cx="50" cy="50" r={radius} class={circleForeground({ class: clsx(classes?.circleForeground) })} fill="none" stroke-width={thickness} stroke-dasharray={circumference} stroke-dashoffset={strokeDashoffset} stroke-linecap="round" />
</svg>

{#if labelInside}
<div class={twMerge(labelInsideDiv(), clsx(labelInsideClass))}>
<div class={labelInsideDiv({ class: clsx(classes?.labelInsideDiv) })}>
{formattedProgress}%
</div>
{/if}
Expand All @@ -63,7 +62,7 @@
@component
[Go to docs](https://flowbite-svelte.com/)
## Type
[ProgressradialProps](https://github.com/themesberg/flowbite-svelte/blob/main/src/lib/types.ts#L1261)
[ProgressradialProps](https://github.com/themesberg/flowbite-svelte/blob/main/src/lib/types.ts#L1259)
## Props
@prop progress = 45
@prop radius = 42
Expand All @@ -77,10 +76,7 @@
@prop labelOutside = ""
@prop easing = cubicOut
@prop color = "primary"
@prop labelInsideClass
@prop outsideSpanClass
@prop outsideProgressClass
@prop labelOutsideDivClass
@prop divClass
@prop class: className
@prop classes
@prop ...restProps
-->
14 changes: 13 additions & 1 deletion src/lib/progress/theme.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
import { tv } from "tailwind-variants";
import type { ClassValue } from "svelte/elements";
import { tv, type VariantProps } from "tailwind-variants";

// export type ProgressbarClasses = Partial<typeof progressbar>["slots"];
export type ProgressbarClasses = Partial<{
[K in keyof typeof progressbar["slots"]]: ClassValue;
}>;
export type ProgressbarVariants = VariantProps<typeof progressbar> & { classes: ProgressbarClasses };

export const progressbar = tv({
slots: {
Expand Down Expand Up @@ -116,6 +123,11 @@ export const progressbar = tv({
}
});

export type ProgressradialClasses = Partial<{
[K in keyof typeof progressradial["slots"]]: ClassValue;
}>;
export type ProgressradialVariants = VariantProps<typeof progressradial> & { classes?: ProgressradialClasses };

export const progressradial = tv({
slots: {
base: "relative inline-flex",
Expand Down
59 changes: 25 additions & 34 deletions src/lib/types.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,19 @@
import type { HTMLButtonAttributes, HTMLAnchorAttributes, HTMLAttributes, HTMLLiAttributes, HTMLImgAttributes, HTMLInputAttributes, HTMLLabelAttributes, HTMLSelectAttributes, HTMLTextareaAttributes, HTMLDialogAttributes, SVGAttributes, HTMLTableAttributes, HTMLTdAttributes, HTMLThAttributes, HTMLOlAttributes, HTMLBlockquoteAttributes, HTMLSourceAttributes, HTMLTrackAttributes, HTMLVideoAttributes, ChangeEventHandler, DragEventHandler } from "svelte/elements";
import type { TransitionConfig, FadeParams, BlurParams, FlyParams, SlideParams, ScaleParams, EasingFunction } from "svelte/transition";
import { type Writable } from "svelte/store";
import type { Snippet, Component } from "svelte";
import { tv, type VariantProps } from "tailwind-variants";
import type { Coords, Middleware, Placement, Strategy } from "@floating-ui/dom";
import type { ClassValue } from "clsx";
import type { Component, Snippet } from "svelte";
import type { HTMLAnchorAttributes, HTMLAttributes, HTMLBlockquoteAttributes, HTMLButtonAttributes, HTMLDialogAttributes, HTMLImgAttributes, HTMLInputAttributes, HTMLLabelAttributes, HTMLLiAttributes, HTMLOlAttributes, HTMLProgressAttributes, HTMLSelectAttributes, HTMLSourceAttributes, HTMLTableAttributes, HTMLTdAttributes, HTMLTextareaAttributes, HTMLThAttributes, HTMLTrackAttributes, HTMLVideoAttributes, SVGAttributes } from "svelte/elements";
import { type Writable } from "svelte/store";
import type { BlurParams, EasingFunction, FadeParams, FlyParams, ScaleParams, SlideParams, TransitionConfig } from "svelte/transition";
import { tv, type VariantProps } from "tailwind-variants";

// component variants
import type { AlertVariants } from "./alert/theme";
import type { BadgeVariants } from "./badge/theme";
import type { BannerVariants } from "./banner/theme";
import type { ButtonVariants, GradientButtonVariantes, button, gradientButton } from "./buttons/theme";
import type { CarouselVariants } from "./carousel/theme";
import type { closeButtonVariants } from "./utils/theme";
import type Slide from "./carousel/Slide.svelte";
import type { ApexOptions } from "apexcharts";
import type { DrawerVariants } from "./drawer/theme";
import type { FileuploadViariants } from "$lib/forms/fileupload/theme";
import type { FloatingLabelInputVaratiants } from "$lib/forms/floating-label/theme";
import type { HelperVariants } from "$lib/forms/helper/theme";
import type { InputVariants } from "$lib/forms/input-field/theme";
import type { LabelVariants } from "$lib/forms/label/theme";
import type { RadioVariants } from "$lib/forms/radio/theme";

import type { RangeVariants } from "$lib/forms/range/theme";
import type { SearchVariants } from "$lib/forms/search/theme";
import type { MultiSelectVariants, SelectVariants } from "$lib/forms/select/theme";
Expand All @@ -40,7 +32,17 @@ import { timeline } from "$lib/timeline/theme";
import type { ToastVaraints } from "$lib/toast/theme";
import type { ToolbarButtonVariants, ToolbarGroupVariants, ToolbarVariants } from "$lib/toolbar/theme";
import type { TooltipVariants } from "$lib/tooltip/theme";
import type { ApexOptions } from "apexcharts";
import type { AlertVariants } from "./alert/theme";
import type { BadgeVariants } from "./badge/theme";
import type { BannerVariants } from "./banner/theme";
import type { ButtonVariants, GradientButtonVariantes, button, gradientButton } from "./buttons/theme";
import type Slide from "./carousel/Slide.svelte";
import type { CarouselVariants } from "./carousel/theme";
import type { DrawerVariants } from "./drawer/theme";
import type { closeButtonVariants } from "./utils/theme";
// typography component variants
import type { ButtonToggleVariants } from "$lib/forms/button-toggle/theme";
import type { AnchorVariants } from "$lib/typography/anchor/theme";
import type { BlockquoteVariants } from "$lib/typography/blockquote/theme";
import type { DescriptionListVariants } from "$lib/typography/descriptionlist/theme";
Expand All @@ -49,7 +51,6 @@ import type { ImgVariants } from "$lib/typography/img/theme";
import type { ListVariants } from "$lib/typography/list/theme";
import type { ParagraphVariants } from "$lib/typography/paragraph/theme";
import type { SpanVariants } from "$lib/typography/span/theme";
import type { ButtonToggleVariants, ButtonToggleContentVariants, ButtonToggleTextVariants } from "$lib/forms/button-toggle/theme";

// end of component variants

Expand Down Expand Up @@ -720,9 +721,9 @@ export interface CheckboxProps extends Omit<HTMLInputAttributes, "children" | "c
children?: Snippet<
[
| {
value?: string | number;
checked: boolean;
}
value?: string | number;
checked: boolean;
}
| CheckboxItem
]
>;
Expand Down Expand Up @@ -963,7 +964,7 @@ export interface TimepickerProps {
timeIntervals?: string[];
columns?: ColumnCount;
// Callback props instead of events
onselect?: (data: { time: string; endTime: string; [key: string]: string }) => void;
onselect?: (data: { time: string; endTime: string;[key: string]: string }) => void;
}

// textarea
Expand Down Expand Up @@ -1161,7 +1162,7 @@ export interface ToolbarProps extends ToolbarVariants, Omit<HTMLAttributes<HTMLD
end?: Snippet;
}

export interface ToolbarGroupProps extends ToolbarGroupVariants, HTMLAttributes<HTMLDivElement> {}
export interface ToolbarGroupProps extends ToolbarGroupVariants, HTMLAttributes<HTMLDivElement> { }

export type ToolbarButtonProps = ToolbarButtonVariants &
AnchorButtonAttributes & {
Expand All @@ -1170,6 +1171,7 @@ export type ToolbarButtonProps = ToolbarButtonVariants &

// pagination
import type { PaginationItemVariants, PaginationVariants } from "$lib/pagination/theme";
import type { ProgressbarVariants, ProgressradialVariants } from "./progress/theme";

export type PaginationItemType = {
size?: "default" | "large";
Expand Down Expand Up @@ -1242,7 +1244,7 @@ export interface PopoverProps extends Omit<PopperProps, "title"> {
}

// progress
export interface ProgressbarProps extends HTMLAttributes<HTMLDivElement> {
export interface ProgressbarProps extends ProgressbarVariants, HTMLAttributes<HTMLDivElement> {
progress?: string | number;
precision?: number;
tweenDuration?: number;
Expand All @@ -1252,14 +1254,9 @@ export interface ProgressbarProps extends HTMLAttributes<HTMLDivElement> {
labelOutside?: string;
easing?: EasingFunction;
color?: ColorType;
oustsideSpanClass?: ClassValue;
oustsideProgressClass?: ClassValue;
labeloutsidedivClass?: ClassValue;
labelInsideClass?: ClassValue;
divClass?: ClassValue;
}

export interface ProgressradialProps {
export interface ProgressradialProps extends ProgressradialVariants, HTMLAttributes<HTMLDivElement> {
progress?: number | string;
radius?: number;
startingPosition?: "top" | "right" | "bottom" | "left";
Expand All @@ -1272,12 +1269,6 @@ export interface ProgressradialProps {
labelOutside?: string;
easing?: (t: number) => number;
color?: ColorType;
labelInsideClass?: ClassValue;
outsideSpanClass?: ClassValue;
outsideProgressClass?: ClassValue;
labelOutsideDivClass?: ClassValue;
divClass?: ClassValue;
[key: string]: any;
}

// rating
Expand Down Expand Up @@ -1499,7 +1490,7 @@ export interface SkeletonProps extends Omit<HTMLAttributes<HTMLDivElement>, "cla
class?: ClassValue;
}

export interface TestimonialPlaceholderProps extends Omit<HTMLAttributes<HTMLDivElement>, "class">{
export interface TestimonialPlaceholderProps extends Omit<HTMLAttributes<HTMLDivElement>, "class"> {
class?: ClassValue;
}

Expand Down
62 changes: 46 additions & 16 deletions src/routes/component-data/Progressbar.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,52 @@
"name": "Progressbar",
"type": {
"name": "ProgressbarProps",
"link": "https://github.com/themesberg/flowbite-svelte/blob/main/src/lib/types.ts#L1244"
"link": "https://github.com/themesberg/flowbite-svelte/blob/main/src/lib/types.ts#L1247"
},
"props": [
["progress", "\"45\""],
["precision", "0"],
["tweenDuration", "400"],
["animate", "false"],
["size", "\"h-2.5\""],
["labelInside", "false"],
["labelOutside", "\"\""],
["easing", "cubicOut"],
["color", "\"primary\""],
["labelInsideClass", ""],
["oustsideSpanClass", ""],
["oustsideProgressClass", ""],
["labeloutsidedivClass", ""],
["divClass", ""]
[
"progress",
"\"45\""
],
[
"precision",
"0"
],
[
"tweenDuration",
"400"
],
[
"animate",
"false"
],
[
"size",
"\"h-2.5\""
],
[
"labelInside",
"false"
],
[
"labelOutside",
"\"\""
],
[
"easing",
"cubicOut"
],
[
"color",
"\"primary\""
],
[
"class: className",
""
],
[
"classes",
""
]
]
}
}
Loading