Skip to content

feat: add ProgressBar component #51

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
Jul 2, 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
1 change: 1 addition & 0 deletions js/react/lib/components/progress-bar/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./progress-bar.component";
41 changes: 41 additions & 0 deletions js/react/lib/components/progress-bar/progress-bar.component.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { Ferris } from "@/icons/ferris";
import { cn } from "@/utils/tw-merge";

type ProgressBarProps = {
percentage: number;
};
export const ProgressBar = (props: ProgressBarProps) => {
const percentage = Number(props.percentage ?? 0);
const isZeroProgress = percentage === 0;
const progressIsInLimit = isZeroProgress || percentage === 100;
const isInMinLimit = percentage < 25;

const position = {
right: isInMinLimit ? "auto" : `${100 - percentage}%`,
left: isInMinLimit ? `${percentage}%` : "auto",
};

return (
<div className="rustlanges-progress-bar__container">
<div className="rustlanges-progress-bar">
<span
className={cn([
"text-overline rustlanges-progress-bar__percentage",
isInMinLimit && "rustlanges-progress-bar__percentage--invert",
])}
style={position}
>
{percentage}%
<Ferris width={15} height={15} />
</span>
<div
className={cn([
"rustlanges-progress-bar__fill",
progressIsInLimit && "rustlanges-progress-bar__fill--limit",
])}
style={{ width: `${percentage}%` }}
/>
</div>
</div>
);
};
32 changes: 32 additions & 0 deletions js/react/lib/icons/ferris.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { SVGProps } from "react";
export const Ferris = (props: SVGProps<SVGSVGElement>) => (
<svg
width="1em"
height="1em"
viewBox="0 0 14 13"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M13.2682 6.41193C13.2127 6.1644 13.7349 5.75338 13.651 5.51418C13.5671 5.27498 12.9078 5.28028 12.7984 5.05319C12.689 4.82611 13.1048 4.30381 12.9715 4.09035C12.8381 3.87688 12.1945 4.03055 12.0372 3.83298C11.8799 3.63542 12.1728 3.03364 11.9952 2.85424C11.8177 2.67484 11.2243 2.9693 11.0287 2.81261C10.8332 2.65592 10.983 2.00266 10.774 1.8702C10.565 1.73773 10.0442 2.15405 9.82098 2.04505C9.59771 1.93605 9.59621 1.26615 9.3647 1.18137C9.13319 1.09659 8.71737 1.62419 8.47387 1.56817C8.23037 1.51216 8.08352 0.859662 7.83853 0.830898C7.59353 0.802133 7.30808 1.4077 7.05559 1.4077C6.8031 1.4077 6.51914 0.802134 6.27414 0.829384C6.02915 0.856634 5.8793 1.51064 5.63655 1.56666C5.3938 1.62267 4.98323 1.09886 4.74947 1.18061C4.51571 1.26236 4.51571 1.93378 4.29319 2.0443C4.07067 2.15481 3.55146 1.7347 3.34017 1.86944C3.12889 2.00418 3.28098 2.6544 3.08544 2.81185C2.88989 2.9693 2.29425 2.67635 2.11894 2.85348C1.94362 3.03061 2.23207 3.63466 2.07473 3.83222C1.91739 4.02979 1.27606 3.87613 1.14269 4.08959C1.00933 4.30305 1.42515 4.82308 1.31577 5.05244C1.20638 5.28179 0.544811 5.27347 0.463145 5.51342C0.38148 5.75338 0.899195 6.16365 0.843752 6.41117C0.78831 6.65869 0.142478 6.80176 0.114007 7.05534C0.094527 7.24836 0.669933 7.50421 1.1382 7.69194C1.15468 7.69951 1.17266 7.70556 1.1899 7.71389C1.11671 7.99336 1.10196 8.28517 1.14659 8.57072C1.19123 8.85627 1.29426 9.12929 1.44913 9.37238C1.26773 9.66668 1.19943 10.018 1.25714 10.3597C1.31485 10.7015 1.49458 11.01 1.7623 11.2269L2.52801 11.8537C2.80538 12.0809 3.1578 12.1931 3.51399 12.1678L3.47054 10.7447L4.82964 10.7023C4.82275 10.498 4.77233 10.2976 4.68183 10.1147C4.59132 9.9318 4.46285 9.77078 4.30518 9.64261L3.53572 9.01661C3.37628 8.88637 3.19067 8.79277 2.99181 8.74231C2.79295 8.69186 2.58559 8.68575 2.38416 8.72442C2.3482 8.67068 2.22308 8.45722 2.28077 8.08858C3.58367 8.45116 5.24546 8.66614 7.05334 8.66614C8.86122 8.66614 10.4998 8.45268 11.8019 8.09691C11.8551 8.461 11.7315 8.67219 11.6963 8.72442C11.4947 8.68584 11.2873 8.69199 11.0883 8.74244C10.8894 8.79289 10.7036 8.88644 10.544 9.01661L9.77678 9.64261C9.61921 9.77089 9.49082 9.93192 9.40033 10.1148C9.30983 10.2976 9.25935 10.498 9.25232 10.7023L10.6114 10.7447L10.5672 12.1678C10.9246 12.1938 11.2785 12.0815 11.5569 11.8537L12.3256 11.2277C12.592 11.0098 12.7707 10.7014 12.8283 10.3601C12.886 10.0187 12.8186 9.66791 12.6388 9.37313C12.7929 9.13154 12.8956 8.86026 12.9405 8.57646C12.9854 8.29267 12.9714 8.00255 12.8996 7.72449C12.9258 7.71464 12.9497 7.7048 12.9745 7.69269C13.4435 7.50497 14.0189 7.24912 13.9994 7.05609C13.9702 6.80251 13.3244 6.65945 13.2682 6.41193ZM8.71287 7.87588C8.2034 7.87588 7.79058 7.40884 7.79058 6.83052C7.79058 6.25221 8.2034 5.78592 8.71287 5.78592C9.22235 5.78592 9.63592 6.25297 9.63592 6.83052C9.63592 7.40808 9.2231 7.87588 8.71287 7.87588Z"
fill="#FF6711"
/>
<path
d="M8.71282 5.78589C8.20335 5.78589 7.79053 6.25293 7.79053 6.83049C7.79053 7.40804 8.20335 7.87584 8.71282 7.87584C9.2223 7.87584 9.63587 7.4088 9.63587 6.83049C9.63587 6.25217 9.22305 5.78589 8.71282 5.78589ZM8.61917 6.57312C8.45809 6.73587 8.23482 6.77599 8.11944 6.65942C8.00406 6.54284 8.04451 6.31727 8.20485 6.15453C8.36518 5.99178 8.59145 5.95318 8.70533 6.06748C8.81922 6.18178 8.781 6.40962 8.61917 6.57312Z"
fill="black"
/>
<path
d="M6.32288 6.83049C6.32288 7.4088 5.90856 7.87584 5.39984 7.87584C4.89111 7.87584 4.47754 7.4088 4.47754 6.83049C4.47754 6.25217 4.88961 5.78589 5.39984 5.78589C5.91006 5.78589 6.32288 6.25217 6.32288 6.83049Z"
fill="black"
/>
<path
d="M5.30565 6.57325C5.46745 6.40978 5.50588 6.18356 5.39147 6.06798C5.27707 5.9524 5.05316 5.99122 4.89136 6.15469C4.72956 6.31816 4.69113 6.54438 4.80553 6.65996C4.91994 6.77555 5.14385 6.73673 5.30565 6.57325Z"
fill="white"
/>
<path
d="M8.61922 6.57315C8.45814 6.73589 8.23487 6.77601 8.11949 6.65944C8.00411 6.54287 8.04457 6.3173 8.2049 6.15455C8.36524 5.9918 8.5915 5.9532 8.70538 6.0675C8.81927 6.1818 8.78106 6.40964 8.61922 6.57315Z"
fill="white"
/>
</svg>
);
1 change: 1 addition & 0 deletions js/react/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ export * from "./components/dropdown";
export * from "./components/calendar";
export * from "./components/dropdown-tree";
export * from "./components/input-search";
export * from "./components/progress-bar";
export * from "./icons";
12 changes: 12 additions & 0 deletions js/react/showcase/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
Calendar,
CalendarRangeDate,
DropdownTree,
ProgressBar,
InputSearch,
} from "@rustlanges/react";
import { ShowComponent } from "./ShowComponent";
Expand Down Expand Up @@ -512,6 +513,17 @@ export function App() {
<InputSearch className="max-w-80" />
</div>
</ShowComponent>
<ShowComponent
title="Progress Bar"
component={ProgressBar}
propsDef={{
percentage: {
type: "string",
default: 50,
optional: false,
},
}}
/>
</div>
);
}
1 change: 1 addition & 0 deletions styles/components.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,4 @@
@import "./components/dropdown-tree-subtopic.css";
@import "./components/dropdown-tree-end.css";
@import "./components/input-search.css";
@import "./components/progress-bar.css";
35 changes: 35 additions & 0 deletions styles/components/progress-bar.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
@layer components {
.rustlanges-progress-bar__container {
@apply h-[33px] w-full;
}

.rustlanges-progress-bar {
@apply relative h-2.5 w-full rounded-xl border border-black;
@apply bg-neutral-100 dark:bg-neutral-900;
}
.rustlanges-progress-bar__fill {
@apply absolute left-0 h-full;
@apply border-r border-r-black;
@apply rounded-l-xl;
@apply transition-all duration-1000;
@apply bg-primary-500;
}
.rustlanges-progress-bar__percentage {
@apply absolute -top-6;
@apply flex items-center gap-1;
@apply h-fit w-fit;
@apply px-1 py-0.5;
@apply text-primary-500;
@apply border border-black;
@apply rounded-l-xs rounded-tr-xs;
@apply transition-all duration-1000;
@apply bg-white dark:bg-neutral-900;
}

.rustlanges-progress-bar__fill--limit {
@apply rounded-r-xl border-none;
}
.rustlanges-progress-bar__percentage--invert {
@apply rounded-r-xs rounded-bl-none;
}
}
2 changes: 2 additions & 0 deletions styles/theme.css
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,8 @@
--font-monospace-body: monospace;

/* Border radiuses */

--radius-xs: 4px;
--radius-sm: 8px;
--radius-md: 16px;
--radius-DEFAULT: 16px;
Expand Down