Update proportion bar component
This commit is contained in:
@@ -1,23 +0,0 @@
|
|||||||
"use client";
|
|
||||||
|
|
||||||
import { memo } from "react";
|
|
||||||
import { ProgressView } from "./Progress.view";
|
|
||||||
import type { ProgressProps } from "./Progress.types";
|
|
||||||
|
|
||||||
const ProgressContainer = memo<ProgressProps>(
|
|
||||||
({ progress = "3-2", className = "" }) => {
|
|
||||||
const barClasses = `h-[8px] relative w-full`;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ProgressView
|
|
||||||
progress={progress}
|
|
||||||
className={className}
|
|
||||||
barClasses={barClasses}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
ProgressContainer.displayName = "Progress";
|
|
||||||
|
|
||||||
export default ProgressContainer;
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
export { default } from "./Progress.container";
|
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { memo } from "react";
|
||||||
|
import { ProportionBarView } from "./ProportionBar.view";
|
||||||
|
import type { ProportionBarProps } from "./ProportionBar.types";
|
||||||
|
|
||||||
|
const ProportionBarContainer = memo<ProportionBarProps>(
|
||||||
|
({ progress = "3-2", className = "" }) => {
|
||||||
|
const barClasses = `h-[8px] relative w-full`;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<ProportionBarView
|
||||||
|
progress={progress}
|
||||||
|
className={className}
|
||||||
|
barClasses={barClasses}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
ProportionBarContainer.displayName = "ProportionBar";
|
||||||
|
|
||||||
|
export default ProportionBarContainer;
|
||||||
+5
-5
@@ -1,4 +1,4 @@
|
|||||||
export type ProgressBarState =
|
export type ProportionBarState =
|
||||||
| "1-0"
|
| "1-0"
|
||||||
| "1-1"
|
| "1-1"
|
||||||
| "1-2"
|
| "1-2"
|
||||||
@@ -12,13 +12,13 @@ export type ProgressBarState =
|
|||||||
| "3-1"
|
| "3-1"
|
||||||
| "3-2";
|
| "3-2";
|
||||||
|
|
||||||
export interface ProgressProps {
|
export interface ProportionBarProps {
|
||||||
progress?: ProgressBarState;
|
progress?: ProportionBarState;
|
||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProgressViewProps {
|
export interface ProportionBarViewProps {
|
||||||
progress: ProgressBarState;
|
progress: ProportionBarState;
|
||||||
className: string;
|
className: string;
|
||||||
barClasses: string;
|
barClasses: string;
|
||||||
}
|
}
|
||||||
+4
-4
@@ -1,11 +1,11 @@
|
|||||||
import type { ProgressViewProps } from "./Progress.types";
|
import type { ProportionBarViewProps } from "./ProportionBar.types";
|
||||||
|
|
||||||
export function ProgressView({
|
export function ProportionBarView({
|
||||||
progress,
|
progress,
|
||||||
className,
|
className,
|
||||||
barClasses,
|
barClasses,
|
||||||
}: ProgressViewProps) {
|
}: ProportionBarViewProps) {
|
||||||
// Progress bar type
|
// Proportion bar type
|
||||||
const [fullSegments, partialSegment] = progress.split("-").map(Number);
|
const [fullSegments, partialSegment] = progress.split("-").map(Number);
|
||||||
// Calculate total progress:
|
// Calculate total progress:
|
||||||
// - For 1-X: first section is (X+1)/6 filled
|
// - For 1-X: first section is (X+1)/6 filled
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
export { default } from "./ProportionBar.container";
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
import { useTranslation } from "../../../contexts/MessagesContext";
|
import { useTranslation } from "../../../contexts/MessagesContext";
|
||||||
import Button from "../../buttons/Button";
|
import Button from "../../buttons/Button";
|
||||||
import Stepper from "../../progress/Progress/Stepper";
|
import Stepper from "../../progress/Stepper";
|
||||||
import type { ModalFooterProps } from "./ModalFooter.types";
|
import type { ModalFooterProps } from "./ModalFooter.types";
|
||||||
|
|
||||||
export function ModalFooterView({
|
export function ModalFooterView({
|
||||||
|
|||||||
@@ -1,110 +0,0 @@
|
|||||||
import Progress from "../../app/components/progress/Progress";
|
|
||||||
|
|
||||||
export default {
|
|
||||||
title: "Components/Progress",
|
|
||||||
component: Progress,
|
|
||||||
parameters: {
|
|
||||||
layout: "centered",
|
|
||||||
docs: {
|
|
||||||
description: {
|
|
||||||
component:
|
|
||||||
"Progress bar component for showing completion percentage. Displays a 3-segment progress bar with support for partial fills.",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
argTypes: {
|
|
||||||
progress: {
|
|
||||||
control: { type: "select" },
|
|
||||||
options: [
|
|
||||||
"1-0",
|
|
||||||
"1-1",
|
|
||||||
"1-2",
|
|
||||||
"1-3",
|
|
||||||
"1-4",
|
|
||||||
"1-5",
|
|
||||||
"2-0",
|
|
||||||
"2-1",
|
|
||||||
"2-2",
|
|
||||||
"3-0",
|
|
||||||
"3-1",
|
|
||||||
"3-2",
|
|
||||||
],
|
|
||||||
description: "Progress state (format: segments-partial)",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
tags: ["autodocs"],
|
|
||||||
};
|
|
||||||
|
|
||||||
export const Default = {
|
|
||||||
args: {
|
|
||||||
progress: "3-2",
|
|
||||||
},
|
|
||||||
render: (args) => (
|
|
||||||
<div className="w-full max-w-[600px]">
|
|
||||||
<Progress {...args} />
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
};
|
|
||||||
|
|
||||||
export const AllStates = {
|
|
||||||
args: {},
|
|
||||||
render: (_args) => (
|
|
||||||
<div className="space-y-4 w-full max-w-[600px]">
|
|
||||||
<div className="w-full">
|
|
||||||
<p className="text-white mb-2">1-0</p>
|
|
||||||
<Progress {..._args} progress="1-0" />
|
|
||||||
</div>
|
|
||||||
<div className="w-full">
|
|
||||||
<p className="text-white mb-2">1-1</p>
|
|
||||||
<Progress {..._args} progress="1-1" />
|
|
||||||
</div>
|
|
||||||
<div className="w-full">
|
|
||||||
<p className="text-white mb-2">1-2</p>
|
|
||||||
<Progress {..._args} progress="1-2" />
|
|
||||||
</div>
|
|
||||||
<div className="w-full">
|
|
||||||
<p className="text-white mb-2">1-3</p>
|
|
||||||
<Progress {..._args} progress="1-3" />
|
|
||||||
</div>
|
|
||||||
<div className="w-full">
|
|
||||||
<p className="text-white mb-2">1-4</p>
|
|
||||||
<Progress {..._args} progress="1-4" />
|
|
||||||
</div>
|
|
||||||
<div className="w-full">
|
|
||||||
<p className="text-white mb-2">1-5</p>
|
|
||||||
<Progress {..._args} progress="1-5" />
|
|
||||||
</div>
|
|
||||||
<div className="w-full">
|
|
||||||
<p className="text-white mb-2">2-0</p>
|
|
||||||
<Progress {..._args} progress="2-0" />
|
|
||||||
</div>
|
|
||||||
<div className="w-full">
|
|
||||||
<p className="text-white mb-2">2-1</p>
|
|
||||||
<Progress {..._args} progress="2-1" />
|
|
||||||
</div>
|
|
||||||
<div className="w-full">
|
|
||||||
<p className="text-white mb-2">2-2</p>
|
|
||||||
<Progress {..._args} progress="2-2" />
|
|
||||||
</div>
|
|
||||||
<div className="w-full">
|
|
||||||
<p className="text-white mb-2">3-0</p>
|
|
||||||
<Progress {..._args} progress="3-0" />
|
|
||||||
</div>
|
|
||||||
<div className="w-full">
|
|
||||||
<p className="text-white mb-2">3-1</p>
|
|
||||||
<Progress {..._args} progress="3-1" />
|
|
||||||
</div>
|
|
||||||
<div className="w-full">
|
|
||||||
<p className="text-white mb-2">3-2</p>
|
|
||||||
<Progress {..._args} progress="3-2" />
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
),
|
|
||||||
parameters: {
|
|
||||||
docs: {
|
|
||||||
description: {
|
|
||||||
story: "Different progress states of the progress bar component.",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
import ProportionBar from "../../app/components/progress/ProportionBar";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
title: "Components/Progress/ProportionBar",
|
||||||
|
component: ProportionBar,
|
||||||
|
parameters: {
|
||||||
|
layout: "centered",
|
||||||
|
docs: {
|
||||||
|
description: {
|
||||||
|
component:
|
||||||
|
"Proportion bar component for showing completion percentage. Displays a 3-segment proportion bar with support for partial fills.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
argTypes: {
|
||||||
|
progress: {
|
||||||
|
control: { type: "select" },
|
||||||
|
options: [
|
||||||
|
"1-0",
|
||||||
|
"1-1",
|
||||||
|
"1-2",
|
||||||
|
"1-3",
|
||||||
|
"1-4",
|
||||||
|
"1-5",
|
||||||
|
"2-0",
|
||||||
|
"2-1",
|
||||||
|
"2-2",
|
||||||
|
"3-0",
|
||||||
|
"3-1",
|
||||||
|
"3-2",
|
||||||
|
],
|
||||||
|
description: "Proportion state (format: segments-partial)",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
tags: ["autodocs"],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Default = {
|
||||||
|
args: {
|
||||||
|
progress: "3-2",
|
||||||
|
},
|
||||||
|
render: (args) => (
|
||||||
|
<div className="w-[300px]">
|
||||||
|
<ProportionBar {...args} />
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
export const AllStates = {
|
||||||
|
args: {},
|
||||||
|
render: (_args) => (
|
||||||
|
<div className="space-y-4 w-[300px]">
|
||||||
|
<ProportionBar {..._args} progress="1-0" />
|
||||||
|
<ProportionBar {..._args} progress="1-1" />
|
||||||
|
<ProportionBar {..._args} progress="1-2" />
|
||||||
|
<ProportionBar {..._args} progress="1-3" />
|
||||||
|
<ProportionBar {..._args} progress="1-4" />
|
||||||
|
<ProportionBar {..._args} progress="1-5" />
|
||||||
|
<ProportionBar {..._args} progress="2-0" />
|
||||||
|
<ProportionBar {..._args} progress="2-1" />
|
||||||
|
<ProportionBar {..._args} progress="2-2" />
|
||||||
|
<ProportionBar {..._args} progress="3-0" />
|
||||||
|
<ProportionBar {..._args} progress="3-1" />
|
||||||
|
<ProportionBar {..._args} progress="3-2" />
|
||||||
|
</div>
|
||||||
|
),
|
||||||
|
parameters: {
|
||||||
|
docs: {
|
||||||
|
description: {
|
||||||
|
story: "Different proportion states of the proportion bar component.",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -2,21 +2,21 @@ import React from "react";
|
|||||||
import { describe, it, expect } from "vitest";
|
import { describe, it, expect } from "vitest";
|
||||||
import { render, screen } from "@testing-library/react";
|
import { render, screen } from "@testing-library/react";
|
||||||
import "@testing-library/jest-dom/vitest";
|
import "@testing-library/jest-dom/vitest";
|
||||||
import Progress from "../../app/components/progress/Progress";
|
import ProportionBar from "../../app/components/progress/ProportionBar";
|
||||||
import {
|
import {
|
||||||
componentTestSuite,
|
componentTestSuite,
|
||||||
ComponentTestSuiteConfig,
|
ComponentTestSuiteConfig,
|
||||||
} from "../utils/componentTestSuite";
|
} from "../utils/componentTestSuite";
|
||||||
|
|
||||||
type ProgressProps = React.ComponentProps<typeof Progress>;
|
type ProportionBarProps = React.ComponentProps<typeof ProportionBar>;
|
||||||
|
|
||||||
const baseProps: ProgressProps = {
|
const baseProps: ProportionBarProps = {
|
||||||
progress: "2-1",
|
progress: "2-1",
|
||||||
};
|
};
|
||||||
|
|
||||||
const config: ComponentTestSuiteConfig<ProgressProps> = {
|
const config: ComponentTestSuiteConfig<ProportionBarProps> = {
|
||||||
component: Progress,
|
component: ProportionBar,
|
||||||
name: "Progress",
|
name: "ProportionBar",
|
||||||
props: baseProps,
|
props: baseProps,
|
||||||
requiredProps: [],
|
requiredProps: [],
|
||||||
optionalProps: {
|
optionalProps: {
|
||||||
@@ -27,17 +27,17 @@ const config: ComponentTestSuiteConfig<ProgressProps> = {
|
|||||||
testCases: {
|
testCases: {
|
||||||
renders: true,
|
renders: true,
|
||||||
accessibility: true,
|
accessibility: true,
|
||||||
keyboardNavigation: false, // Progress is not keyboard navigable
|
keyboardNavigation: false, // ProportionBar is not keyboard navigable
|
||||||
disabledState: false, // Progress doesn't have disabled state
|
disabledState: false, // ProportionBar doesn't have disabled state
|
||||||
errorState: false,
|
errorState: false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
componentTestSuite<ProgressProps>(config);
|
componentTestSuite<ProportionBarProps>(config);
|
||||||
|
|
||||||
describe("Progress (behavioral tests)", () => {
|
describe("ProportionBar (behavioral tests)", () => {
|
||||||
it("renders progress bar with correct progress value", () => {
|
it("renders proportion bar with correct progress value", () => {
|
||||||
render(<Progress progress="2-1" />);
|
render(<ProportionBar progress="2-1" />);
|
||||||
const progressbar = screen.getByRole("progressbar");
|
const progressbar = screen.getByRole("progressbar");
|
||||||
// 2-1: First section full (1) + second section 1/3 filled = 1 + 1/3 ≈ 1.333
|
// 2-1: First section full (1) + second section 1/3 filled = 1 + 1/3 ≈ 1.333
|
||||||
expect(progressbar).toHaveAttribute("aria-valuenow", "1.3333333333333333");
|
expect(progressbar).toHaveAttribute("aria-valuenow", "1.3333333333333333");
|
||||||
@@ -46,18 +46,18 @@ describe("Progress (behavioral tests)", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("applies custom className", () => {
|
it("applies custom className", () => {
|
||||||
const { container } = render(<Progress className="custom-class" />);
|
const { container } = render(<ProportionBar className="custom-class" />);
|
||||||
expect(container.firstChild).toHaveClass("custom-class");
|
expect(container.firstChild).toHaveClass("custom-class");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("defaults to progress 3-2 when progress is not specified", () => {
|
it("defaults to progress 3-2 when progress is not specified", () => {
|
||||||
render(<Progress />);
|
render(<ProportionBar />);
|
||||||
const progressbar = screen.getByRole("progressbar");
|
const progressbar = screen.getByRole("progressbar");
|
||||||
// 3-2: First two sections full (2) + third section 2/3 filled = 2 + 2/3 ≈ 2.667
|
// 3-2: First two sections full (2) + third section 2/3 filled = 2 + 2/3 ≈ 2.667
|
||||||
expect(progressbar).toHaveAttribute("aria-valuenow", "2.6666666666666665");
|
expect(progressbar).toHaveAttribute("aria-valuenow", "2.6666666666666665");
|
||||||
});
|
});
|
||||||
|
|
||||||
it("handles all progress states correctly", () => {
|
it("handles all proportion states correctly", () => {
|
||||||
const testCases = [
|
const testCases = [
|
||||||
{ progress: "1-0" as const, expected: 1 / 6 }, // First section 1/6 filled
|
{ progress: "1-0" as const, expected: 1 / 6 }, // First section 1/6 filled
|
||||||
{ progress: "1-5" as const, expected: 1 }, // First section 6/6 filled (fully filled)
|
{ progress: "1-5" as const, expected: 1 }, // First section 6/6 filled (fully filled)
|
||||||
@@ -68,7 +68,7 @@ describe("Progress (behavioral tests)", () => {
|
|||||||
];
|
];
|
||||||
|
|
||||||
testCases.forEach(({ progress, expected }) => {
|
testCases.forEach(({ progress, expected }) => {
|
||||||
const { unmount } = render(<Progress progress={progress} />);
|
const { unmount } = render(<ProportionBar progress={progress} />);
|
||||||
const progressbar = screen.getByRole("progressbar");
|
const progressbar = screen.getByRole("progressbar");
|
||||||
expect(progressbar).toHaveAttribute("aria-valuenow", String(expected));
|
expect(progressbar).toHaveAttribute("aria-valuenow", String(expected));
|
||||||
unmount();
|
unmount();
|
||||||
@@ -2,7 +2,7 @@ import React from "react";
|
|||||||
import { describe, it, expect } from "vitest";
|
import { describe, it, expect } from "vitest";
|
||||||
import { render, screen } from "@testing-library/react";
|
import { render, screen } from "@testing-library/react";
|
||||||
import "@testing-library/jest-dom/vitest";
|
import "@testing-library/jest-dom/vitest";
|
||||||
import Stepper from "../../app/components/progress/Progress/Stepper";
|
import Stepper from "../../app/components/progress/Stepper";
|
||||||
import {
|
import {
|
||||||
componentTestSuite,
|
componentTestSuite,
|
||||||
ComponentTestSuiteConfig,
|
ComponentTestSuiteConfig,
|
||||||
|
|||||||
Reference in New Issue
Block a user