feat: progress component + storybook setup for surveys package

This commit is contained in:
Dhruwang
2025-11-24 16:44:46 +05:30
parent a2897a242c
commit 7304f45b22
3 changed files with 156 additions and 0 deletions

View File

@@ -0,0 +1,49 @@
import type { JSX } from "preact";
interface ProgressProps {
value?: number;
max?: number;
containerStyling?: JSX.CSSProperties;
indicatorStyling?: JSX.CSSProperties;
"aria-label"?: string;
}
/**
* Progress component displays an indicator showing the completion progress of a task.
* Typically displayed as a progress bar.
*
* @param value - Current progress value (0-100 by default)
* @param max - Maximum value (default: 100)
* @param containerStyling - Custom styling object for the container
* @param indicatorStyling - Custom styling object for the indicator
* @param aria-label - Accessible label for the progress bar
*/
export function Progress({
value = 0,
max = 100,
containerStyling = {},
indicatorStyling = {},
"aria-label": ariaLabel = "Progress",
}: ProgressProps) {
// Calculate percentage, ensuring it stays within 0-100 range
const percentage = Math.min(Math.max((value / max) * 100, 0), 100);
return (
<div
role="progressbar"
aria-valuemin={0}
aria-valuemax={max}
aria-valuenow={value}
aria-label={ariaLabel}
className="fb-relative fb-h-2 fb-w-full fb-overflow-hidden fb-rounded-full fb-bg-accent-bg"
style={containerStyling}>
<div
className="fb-h-full fb-w-full fb-flex-1 fb-bg-brand fb-transition-all fb-duration-500 fb-ease-in-out"
style={{
transform: `translateX(-${100 - percentage}%)`,
...indicatorStyling,
}}
/>
</div>
);
}

View File

@@ -0,0 +1,106 @@
import type { Meta, StoryObj } from "@storybook/preact-vite";
import type { ComponentProps } from "preact";
import { useEffect, useState } from "preact/hooks";
import "../../../styles/global.css";
import { Progress } from "./index";
type ProgressProps = ComponentProps<typeof Progress>;
const meta: Meta<ProgressProps> = {
title: "v5/Progress",
component: Progress,
parameters: {
layout: "centered",
docs: {
description: {
component:
"Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.",
},
},
},
tags: ["autodocs"],
decorators: [
(Story: any) => (
<div id="fbjs" style={{ width: "400px", padding: "20px" }}>
<Story />
</div>
),
],
argTypes: {
value: {
control: { type: "range", min: 0, max: 100, step: 1 },
description: "Current progress value",
table: {
type: { summary: "number" },
defaultValue: { summary: "0" },
},
},
max: {
control: { type: "number" },
description: "Maximum value",
table: {
type: { summary: "number" },
defaultValue: { summary: "100" },
},
},
containerStyling: {
control: "object",
description: "Custom styling object for the container",
table: {
type: { summary: "CSSProperties" },
defaultValue: { summary: "{}" },
},
},
indicatorStyling: {
control: "object",
description: "Custom styling object for the indicator",
table: {
type: { summary: "CSSProperties" },
defaultValue: { summary: "{}" },
},
},
},
};
export default meta;
type Story = StoryObj<ProgressProps>;
/**
* Default progress bar with 50% completion
*/
export const Default: Story = {
args: {
value: 50,
},
};
/**
* Progress bar with no progress (0%)
*/
export const Empty: Story = {
args: {
value: 0,
},
};
/**
* Progress bar with full progress (100%)
*/
export const Complete: Story = {
args: {
value: 100,
},
};
/**
* Progress bar with gradient indicator
*/
export const customStyling: Story = {
args: {
value: 70,
indicatorStyling: {
background: "linear-gradient(90deg, #3b82f6 0%, #8b5cf6 100%)",
height: "2rem",
},
},
};

View File

@@ -6,6 +6,7 @@
"isolatedModules": true,
"jsx": "react-jsx",
"jsxImportSource": "preact",
"moduleResolution": "bundler",
"paths": {
"@/*": ["./src/*"]
},