diff --git a/packages/surveys/src/components/v5/progress/index.tsx b/packages/surveys/src/components/v5/progress/index.tsx new file mode 100644 index 0000000000..ab2e4b98d4 --- /dev/null +++ b/packages/surveys/src/components/v5/progress/index.tsx @@ -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 ( +
+
+
+ ); +} diff --git a/packages/surveys/src/components/v5/progress/progress.stories.tsx b/packages/surveys/src/components/v5/progress/progress.stories.tsx new file mode 100644 index 0000000000..322d181ffa --- /dev/null +++ b/packages/surveys/src/components/v5/progress/progress.stories.tsx @@ -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; + +const meta: Meta = { + 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) => ( +
+ +
+ ), + ], + 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; + +/** + * 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", + }, + }, +}; diff --git a/packages/surveys/tsconfig.json b/packages/surveys/tsconfig.json index a86d9f8dc9..17fea3f7ba 100644 --- a/packages/surveys/tsconfig.json +++ b/packages/surveys/tsconfig.json @@ -6,6 +6,7 @@ "isolatedModules": true, "jsx": "react-jsx", "jsxImportSource": "preact", + "moduleResolution": "bundler", "paths": { "@/*": ["./src/*"] },