@stackshift-ui/accordion 1.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +373 -0
- package/README.md +24 -0
- package/dist/accordion.d.ts +19 -0
- package/dist/accordion.js +2 -0
- package/dist/accordion.mjs +2 -0
- package/dist/chunk-3EYN2AKU.mjs +1 -0
- package/dist/chunk-Y5BC66KM.mjs +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/index.mjs +2 -0
- package/dist/setupTests.d.ts +2 -0
- package/dist/setupTests.js +51 -0
- package/dist/setupTests.mjs +51 -0
- package/package.json +63 -0
- package/src/accordion.test.tsx +80 -0
- package/src/accordion.tsx +87 -0
- package/src/index.ts +4 -0
- package/src/setupTests.ts +4 -0
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@stackshift-ui/accordion",
|
|
3
|
+
"description": "A vertically stacked set of interactive headings that each reveal a section of content.",
|
|
4
|
+
"version": "1.0.0-beta.1",
|
|
5
|
+
"private": false,
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"module": "./dist/index.mjs",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist/**",
|
|
12
|
+
"src"
|
|
13
|
+
],
|
|
14
|
+
"author": "WebriQ <info@webriq.com>",
|
|
15
|
+
"devDependencies": {
|
|
16
|
+
"@testing-library/react": "^16.0.1",
|
|
17
|
+
"@testing-library/jest-dom": "^6.5.0",
|
|
18
|
+
"@testing-library/user-event": "^14.6.1",
|
|
19
|
+
"@types/react": "^18.3.9",
|
|
20
|
+
"@types/react-dom": "^18.3.0",
|
|
21
|
+
"@vitejs/plugin-react": "^4.3.1",
|
|
22
|
+
"@vitest/coverage-v8": "^2.1.1",
|
|
23
|
+
"esbuild-plugin-rdi": "^0.0.0",
|
|
24
|
+
"esbuild-plugin-react18": "^0.2.5",
|
|
25
|
+
"esbuild-plugin-react18-css": "^0.0.4",
|
|
26
|
+
"jsdom": "^25.0.1",
|
|
27
|
+
"react": "^18.3.1",
|
|
28
|
+
"react-dom": "^18.3.1",
|
|
29
|
+
"tsup": "^8.3.0",
|
|
30
|
+
"typescript": "^5.6.2",
|
|
31
|
+
"vite-tsconfig-paths": "^5.0.1",
|
|
32
|
+
"vitest": "^2.1.1",
|
|
33
|
+
"@stackshift-ui/eslint-config": "6.0.10",
|
|
34
|
+
"@stackshift-ui/typescript-config": "6.0.10"
|
|
35
|
+
},
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@radix-ui/react-accordion": "^1.2.11",
|
|
38
|
+
"classnames": "^2.5.1",
|
|
39
|
+
"lucide-react": "^0.468.0",
|
|
40
|
+
"@stackshift-ui/scripts": "6.1.0-beta.0",
|
|
41
|
+
"@stackshift-ui/system": "6.1.0-beta.0"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"@stackshift-ui/system": ">=6.1.0-beta.0",
|
|
45
|
+
"@types/react": "16.8 - 19",
|
|
46
|
+
"next": "10 - 14",
|
|
47
|
+
"react": "16.8 - 19",
|
|
48
|
+
"react-dom": "16.8 - 19"
|
|
49
|
+
},
|
|
50
|
+
"peerDependenciesMeta": {
|
|
51
|
+
"next": {
|
|
52
|
+
"optional": true
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"scripts": {
|
|
56
|
+
"build": "tsup && tsc -p tsconfig-build.json",
|
|
57
|
+
"clean": "rm -rf dist",
|
|
58
|
+
"dev": "tsup --watch && tsc -p tsconfig-build.json -w",
|
|
59
|
+
"typecheck": "tsc --noEmit",
|
|
60
|
+
"lint": "eslint src/",
|
|
61
|
+
"test": "vitest run --coverage"
|
|
62
|
+
}
|
|
63
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { render, screen } from "@testing-library/react";
|
|
2
|
+
import userEvent from "@testing-library/user-event";
|
|
3
|
+
import { describe, expect, test } from "vitest";
|
|
4
|
+
import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "./accordion";
|
|
5
|
+
|
|
6
|
+
describe("accordion", () => {
|
|
7
|
+
test("Common: Accordion - test if renders without errors", async () => {
|
|
8
|
+
const clx = "accordion-class";
|
|
9
|
+
|
|
10
|
+
const { unmount } = render(
|
|
11
|
+
<Accordion data-testid="accordion" type="single" className={clx} collapsible>
|
|
12
|
+
<AccordionItem value="item-1">
|
|
13
|
+
<AccordionTrigger data-testid="accordion-trigger">First item</AccordionTrigger>
|
|
14
|
+
<AccordionContent>This is the first accordion item content.</AccordionContent>
|
|
15
|
+
</AccordionItem>
|
|
16
|
+
</Accordion>,
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
const accordion = screen.getByTestId("accordion");
|
|
20
|
+
|
|
21
|
+
expect(accordion.classList).toContain(clx);
|
|
22
|
+
|
|
23
|
+
const firstItem = accordion.querySelector("[data-slot=accordion-item]");
|
|
24
|
+
expect(firstItem).toBeDefined();
|
|
25
|
+
|
|
26
|
+
const trigger = screen.getByTestId("accordion-trigger");
|
|
27
|
+
expect(trigger).toBeDefined();
|
|
28
|
+
|
|
29
|
+
expect(screen.queryByText("This is the first accordion item content.")).toBeNull();
|
|
30
|
+
|
|
31
|
+
const user = userEvent.setup();
|
|
32
|
+
await user.click(trigger);
|
|
33
|
+
|
|
34
|
+
expect(await screen.findByText("This is the first accordion item content.")).toBeDefined();
|
|
35
|
+
unmount();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
test("Common: Accordion - test if renders with multiple items", async () => {
|
|
39
|
+
const clx = "accordion-class";
|
|
40
|
+
|
|
41
|
+
const { unmount } = render(
|
|
42
|
+
<Accordion data-testid="accordion-multiple" type="multiple" className={clx}>
|
|
43
|
+
<AccordionItem value="item-1">
|
|
44
|
+
<AccordionTrigger data-testid="accordion-trigger">First item</AccordionTrigger>
|
|
45
|
+
<AccordionContent>This is the first accordion item content.</AccordionContent>
|
|
46
|
+
</AccordionItem>
|
|
47
|
+
<AccordionItem value="item-2">
|
|
48
|
+
<AccordionTrigger data-testid="accordion-trigger">Second item</AccordionTrigger>
|
|
49
|
+
<AccordionContent>This is the second accordion item content.</AccordionContent>
|
|
50
|
+
</AccordionItem>
|
|
51
|
+
<AccordionItem value="item-3">
|
|
52
|
+
<AccordionTrigger data-testid="accordion-trigger">Third item</AccordionTrigger>
|
|
53
|
+
<AccordionContent>This is the third accordion item content.</AccordionContent>
|
|
54
|
+
</AccordionItem>
|
|
55
|
+
</Accordion>,
|
|
56
|
+
);
|
|
57
|
+
|
|
58
|
+
const accordion = screen.getByTestId("accordion-multiple");
|
|
59
|
+
expect(accordion.classList).toContain(clx);
|
|
60
|
+
|
|
61
|
+
const items = accordion.querySelectorAll("[data-slot=accordion-item]");
|
|
62
|
+
expect(items.length).toBe(3);
|
|
63
|
+
|
|
64
|
+
const triggers = screen.getAllByTestId("accordion-trigger");
|
|
65
|
+
expect(triggers.length).toBe(3);
|
|
66
|
+
|
|
67
|
+
const user = userEvent.setup();
|
|
68
|
+
|
|
69
|
+
await user.click(triggers[0]);
|
|
70
|
+
expect(
|
|
71
|
+
await screen.findByText("This is the first accordion item content."),
|
|
72
|
+
).toBeInTheDocument();
|
|
73
|
+
|
|
74
|
+
await user.click(triggers[1]);
|
|
75
|
+
expect(
|
|
76
|
+
await screen.findByText("This is the second accordion item content."),
|
|
77
|
+
).toBeInTheDocument();
|
|
78
|
+
unmount();
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as AccordionPrimitive from "@radix-ui/react-accordion";
|
|
4
|
+
import { ChevronDownIcon } from "lucide-react";
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
|
|
7
|
+
import { cn, DefaultComponent, useStackShiftUIComponents } from "@stackshift-ui/system";
|
|
8
|
+
|
|
9
|
+
const displayNameAccordion = "Accordion";
|
|
10
|
+
const displayNameAccordionItem = "AccordionItem";
|
|
11
|
+
const displayNameAccordionHeader = "AccordionHeader";
|
|
12
|
+
const displayNameAccordionTrigger = "AccordionTrigger";
|
|
13
|
+
const displayNameAccordionContent = "AccordionContent";
|
|
14
|
+
|
|
15
|
+
function Accordion({ ...props }: React.ComponentProps<typeof AccordionPrimitive.Root>) {
|
|
16
|
+
const { [displayNameAccordion]: Component = DefaultComponent } = useStackShiftUIComponents();
|
|
17
|
+
return <Component as={AccordionPrimitive.Root} data-slot="accordion" {...props} />;
|
|
18
|
+
}
|
|
19
|
+
Accordion.displayName = displayNameAccordion;
|
|
20
|
+
|
|
21
|
+
function AccordionItem({
|
|
22
|
+
className,
|
|
23
|
+
...props
|
|
24
|
+
}: React.ComponentProps<typeof AccordionPrimitive.Item>) {
|
|
25
|
+
const { [displayNameAccordionItem]: Component = DefaultComponent } = useStackShiftUIComponents();
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<Component
|
|
29
|
+
as={AccordionPrimitive.Item}
|
|
30
|
+
data-slot="accordion-item"
|
|
31
|
+
className={cn("border-b last:border-b-0", className)}
|
|
32
|
+
{...props}
|
|
33
|
+
/>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
AccordionItem.displayName = displayNameAccordionItem;
|
|
37
|
+
|
|
38
|
+
function AccordionTrigger({
|
|
39
|
+
className,
|
|
40
|
+
children,
|
|
41
|
+
...props
|
|
42
|
+
}: React.ComponentProps<typeof AccordionPrimitive.Trigger>) {
|
|
43
|
+
const { [displayNameAccordionHeader]: HeaderComponent = DefaultComponent } =
|
|
44
|
+
useStackShiftUIComponents();
|
|
45
|
+
|
|
46
|
+
const { [displayNameAccordionTrigger]: Component = DefaultComponent } =
|
|
47
|
+
useStackShiftUIComponents();
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<HeaderComponent as={AccordionPrimitive.Header} className="flex">
|
|
51
|
+
<Component
|
|
52
|
+
as={AccordionPrimitive.Trigger}
|
|
53
|
+
data-slot="accordion-trigger"
|
|
54
|
+
className={cn(
|
|
55
|
+
"focus-visible:border-ring focus-visible:ring-ring/50 flex flex-1 items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180",
|
|
56
|
+
className,
|
|
57
|
+
)}
|
|
58
|
+
{...props}>
|
|
59
|
+
{children}
|
|
60
|
+
<ChevronDownIcon className="text-muted-foreground pointer-events-none size-4 shrink-0 translate-y-0.5 transition-transform duration-200" />
|
|
61
|
+
</Component>
|
|
62
|
+
</HeaderComponent>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
AccordionTrigger.displayName = displayNameAccordionTrigger;
|
|
66
|
+
|
|
67
|
+
function AccordionContent({
|
|
68
|
+
className,
|
|
69
|
+
children,
|
|
70
|
+
...props
|
|
71
|
+
}: React.ComponentProps<typeof AccordionPrimitive.Content>) {
|
|
72
|
+
const { [displayNameAccordionContent]: Component = DefaultComponent } =
|
|
73
|
+
useStackShiftUIComponents();
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<Component
|
|
77
|
+
as={AccordionPrimitive.Content}
|
|
78
|
+
data-slot="accordion-content"
|
|
79
|
+
className="data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm"
|
|
80
|
+
{...props}>
|
|
81
|
+
<div className={cn("pt-0 pb-4", className)}>{children}</div>
|
|
82
|
+
</Component>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
AccordionContent.displayName = displayNameAccordionContent;
|
|
86
|
+
|
|
87
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger };
|
package/src/index.ts
ADDED