@zentauri-ui/zentauri-components 1.3.1 → 1.4.0
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/README.md +78 -0
- package/cli/cli.integration.test.ts +51 -0
- package/cli/index.mjs +664 -0
- package/cli/registry.json +36 -0
- package/cli/rewrite-imports.mjs +57 -0
- package/cli/rewrite-imports.test.ts +71 -0
- package/dist/ui/slider/slider.d.ts +18 -0
- package/dist/ui/slider/slider.d.ts.map +1 -1
- package/dist/ui/slider.js +21 -25
- package/dist/ui/slider.js.map +1 -1
- package/dist/ui/slider.mjs +21 -25
- package/dist/ui/slider.mjs.map +1 -1
- package/package.json +8 -2
- package/src/hooks/index.ts +48 -0
- package/src/hooks/useBodyScrollLock/index.ts +1 -0
- package/src/hooks/useBodyScrollLock/useBodyScrollLock.test.ts +51 -0
- package/src/hooks/useBodyScrollLock/useBodyScrollLock.ts +48 -0
- package/src/hooks/useClickOutside/index.ts +5 -0
- package/src/hooks/useClickOutside/useClickOutside.test.tsx +60 -0
- package/src/hooks/useClickOutside/useClickOutside.ts +52 -0
- package/src/hooks/useClipboard/index.ts +1 -0
- package/src/hooks/useClipboard/useClipboard.test.ts +101 -0
- package/src/hooks/useClipboard/useClipboard.ts +69 -0
- package/src/hooks/useControllableState/index.ts +4 -0
- package/src/hooks/useControllableState/useControllableState.test.ts +59 -0
- package/src/hooks/useControllableState/useControllableState.ts +49 -0
- package/src/hooks/useDebouncedValue/index.ts +1 -0
- package/src/hooks/useDebouncedValue/useDebouncedValue.test.ts +74 -0
- package/src/hooks/useDebouncedValue/useDebouncedValue.ts +29 -0
- package/src/hooks/useDisclosure/index.ts +5 -0
- package/src/hooks/useDisclosure/useDisclosure.test.ts +64 -0
- package/src/hooks/useDisclosure/useDisclosure.ts +62 -0
- package/src/hooks/useDocumentTitle/index.ts +4 -0
- package/src/hooks/useDocumentTitle/useDocumentTitle.test.ts +40 -0
- package/src/hooks/useDocumentTitle/useDocumentTitle.ts +58 -0
- package/src/hooks/useFocusManagement/index.ts +1 -0
- package/src/hooks/useFocusManagement/useFocusManagement.test.tsx +45 -0
- package/src/hooks/useFocusManagement/useFocusManagement.ts +77 -0
- package/src/hooks/useHover/index.ts +1 -0
- package/src/hooks/useHover/useHover.test.ts +45 -0
- package/src/hooks/useHover/useHover.ts +45 -0
- package/src/hooks/useInView/index.ts +1 -0
- package/src/hooks/useInView/useInView.test.ts +43 -0
- package/src/hooks/useInView/useInView.ts +28 -0
- package/src/hooks/useIntersectionObserver/index.ts +4 -0
- package/src/hooks/useIntersectionObserver/useIntersectionObserver.test.ts +75 -0
- package/src/hooks/useIntersectionObserver/useIntersectionObserver.ts +54 -0
- package/src/hooks/useIsMounted/index.ts +1 -0
- package/src/hooks/useIsMounted/useIsMounted.test.ts +25 -0
- package/src/hooks/useIsMounted/useIsMounted.ts +22 -0
- package/src/hooks/useIsomorphicLayoutEffect/index.ts +1 -0
- package/src/hooks/useIsomorphicLayoutEffect/useIsomorphicLayoutEffect.test.ts +19 -0
- package/src/hooks/useIsomorphicLayoutEffect/useIsomorphicLayoutEffect.ts +12 -0
- package/src/hooks/useLocalStorage/index.ts +4 -0
- package/src/hooks/useLocalStorage/useLocalStorage.test.ts +99 -0
- package/src/hooks/useLocalStorage/useLocalStorage.ts +109 -0
- package/src/hooks/useMediaQuery/index.ts +1 -0
- package/src/hooks/useMediaQuery/useMediaQuery.test.ts +63 -0
- package/src/hooks/useMediaQuery/useMediaQuery.ts +37 -0
- package/src/hooks/useNetworkStatus/index.ts +1 -0
- package/src/hooks/useNetworkStatus/useNetworkStatus.test.ts +53 -0
- package/src/hooks/useNetworkStatus/useNetworkStatus.ts +33 -0
- package/src/hooks/usePageVisibility/index.ts +1 -0
- package/src/hooks/usePageVisibility/usePageVisibility.test.ts +21 -0
- package/src/hooks/usePageVisibility/usePageVisibility.ts +31 -0
- package/src/hooks/usePagination/index.ts +6 -0
- package/src/hooks/usePagination/usePagination.test.ts +139 -0
- package/src/hooks/usePagination/usePagination.ts +153 -0
- package/src/hooks/usePrefersColorScheme/index.ts +4 -0
- package/src/hooks/usePrefersColorScheme/usePrefersColorScheme.test.ts +53 -0
- package/src/hooks/usePrefersColorScheme/usePrefersColorScheme.ts +21 -0
- package/src/hooks/usePrefersReducedMotion/index.ts +1 -0
- package/src/hooks/usePrefersReducedMotion/usePrefersReducedMotion.test.ts +27 -0
- package/src/hooks/usePrefersReducedMotion/usePrefersReducedMotion.ts +14 -0
- package/src/hooks/useResizeObserver/index.ts +4 -0
- package/src/hooks/useResizeObserver/useResizeObserver.test.ts +68 -0
- package/src/hooks/useResizeObserver/useResizeObserver.ts +58 -0
- package/src/hooks/useSessionStorage/index.ts +4 -0
- package/src/hooks/useSessionStorage/useSessionStorage.test.ts +54 -0
- package/src/hooks/useSessionStorage/useSessionStorage.ts +84 -0
- package/src/hooks/useThrottledCallback/index.ts +1 -0
- package/src/hooks/useThrottledCallback/useThrottledCallback.test.ts +75 -0
- package/src/hooks/useThrottledCallback/useThrottledCallback.ts +36 -0
- package/src/hooks/useToggle/index.ts +1 -0
- package/src/hooks/useToggle/useToggle.test.ts +40 -0
- package/src/hooks/useToggle/useToggle.ts +22 -0
- package/src/hooks/useWindowSize/index.ts +1 -0
- package/src/hooks/useWindowSize/useWindowSize.test.ts +23 -0
- package/src/hooks/useWindowSize/useWindowSize.ts +39 -0
- package/src/lib/utils.ts +25 -0
- package/src/ui/accordion/accordion-base.tsx +223 -0
- package/src/ui/accordion/accordion.test.tsx +146 -0
- package/src/ui/accordion/accordion.tsx +11 -0
- package/src/ui/accordion/animated/accordion-content-animated.tsx +46 -0
- package/src/ui/accordion/animated/accordion-root-animated.tsx +10 -0
- package/src/ui/accordion/animated/animations.ts +16 -0
- package/src/ui/accordion/animated/index.ts +7 -0
- package/src/ui/accordion/animated/types.ts +7 -0
- package/src/ui/accordion/index.ts +23 -0
- package/src/ui/accordion/types.ts +48 -0
- package/src/ui/accordion/variants.ts +115 -0
- package/src/ui/alert/alert-base.tsx +157 -0
- package/src/ui/alert/alert.test.tsx +150 -0
- package/src/ui/alert/alert.tsx +9 -0
- package/src/ui/alert/animated/alert-animated.tsx +20 -0
- package/src/ui/alert/animated/animations.ts +20 -0
- package/src/ui/alert/animated/index.ts +3 -0
- package/src/ui/alert/animated/types.ts +16 -0
- package/src/ui/alert/index.ts +22 -0
- package/src/ui/alert/types.ts +28 -0
- package/src/ui/alert/variants.ts +74 -0
- package/src/ui/avatar/animated/animations.ts +11 -0
- package/src/ui/avatar/animated/avatar-animated.tsx +25 -0
- package/src/ui/avatar/animated/index.ts +6 -0
- package/src/ui/avatar/animated/types.ts +16 -0
- package/src/ui/avatar/avatar-base.tsx +184 -0
- package/src/ui/avatar/avatar.test.tsx +51 -0
- package/src/ui/avatar/avatar.tsx +11 -0
- package/src/ui/avatar/index.ts +16 -0
- package/src/ui/avatar/types.ts +36 -0
- package/src/ui/avatar/variants.ts +52 -0
- package/src/ui/badge/animated/animations.ts +20 -0
- package/src/ui/badge/animated/badge-animated.tsx +28 -0
- package/src/ui/badge/animated/index.ts +5 -0
- package/src/ui/badge/animated/types.ts +18 -0
- package/src/ui/badge/badge-base.tsx +53 -0
- package/src/ui/badge/badge.test.tsx +48 -0
- package/src/ui/badge/badge.tsx +9 -0
- package/src/ui/badge/index.ts +5 -0
- package/src/ui/badge/types.ts +25 -0
- package/src/ui/badge/variants.ts +85 -0
- package/src/ui/breadcrumb/breadcrumb.test.tsx +62 -0
- package/src/ui/breadcrumb/breadcrumb.tsx +135 -0
- package/src/ui/breadcrumb/index.ts +28 -0
- package/src/ui/breadcrumb/types.ts +29 -0
- package/src/ui/breadcrumb/variants.ts +53 -0
- package/src/ui/buttons/animated/animations.ts +34 -0
- package/src/ui/buttons/animated/button-animated.tsx +70 -0
- package/src/ui/buttons/animated/index.ts +5 -0
- package/src/ui/buttons/animated/types.ts +29 -0
- package/src/ui/buttons/button-base.tsx +59 -0
- package/src/ui/buttons/button.test.tsx +480 -0
- package/src/ui/buttons/button.tsx +9 -0
- package/src/ui/buttons/index.ts +5 -0
- package/src/ui/buttons/types.ts +14 -0
- package/src/ui/buttons/variants.ts +77 -0
- package/src/ui/card/animated/animations.ts +32 -0
- package/src/ui/card/animated/card-animated.tsx +28 -0
- package/src/ui/card/animated/index.ts +12 -0
- package/src/ui/card/animated/types.ts +8 -0
- package/src/ui/card/card-base.tsx +146 -0
- package/src/ui/card/card.test.tsx +79 -0
- package/src/ui/card/card.tsx +11 -0
- package/src/ui/card/index.ts +21 -0
- package/src/ui/card/types.ts +42 -0
- package/src/ui/card/variants.ts +122 -0
- package/src/ui/divider/animated/animations.ts +27 -0
- package/src/ui/divider/animated/divider-animated.tsx +24 -0
- package/src/ui/divider/animated/index.ts +4 -0
- package/src/ui/divider/animated/types.ts +18 -0
- package/src/ui/divider/divider-base.tsx +80 -0
- package/src/ui/divider/divider.tsx +9 -0
- package/src/ui/divider/index.ts +14 -0
- package/src/ui/divider/types.ts +18 -0
- package/src/ui/divider/variants.ts +98 -0
- package/src/ui/drawer/animated/animations.ts +39 -0
- package/src/ui/drawer/animated/drawer-content-animated.tsx +101 -0
- package/src/ui/drawer/animated/index.ts +14 -0
- package/src/ui/drawer/animated/types.ts +18 -0
- package/src/ui/drawer/drawer-base.tsx +259 -0
- package/src/ui/drawer/drawer.test.tsx +132 -0
- package/src/ui/drawer/drawer.tsx +11 -0
- package/src/ui/drawer/index.ts +21 -0
- package/src/ui/drawer/types.ts +39 -0
- package/src/ui/drawer/variants.ts +122 -0
- package/src/ui/dropdown/dropdown.test.tsx +114 -0
- package/src/ui/dropdown/dropdown.tsx +179 -0
- package/src/ui/dropdown/index.ts +15 -0
- package/src/ui/dropdown/types.ts +68 -0
- package/src/ui/dropdown/variants.ts +138 -0
- package/src/ui/empty-state/animated/animations.ts +19 -0
- package/src/ui/empty-state/animated/empty-state-animated.tsx +23 -0
- package/src/ui/empty-state/animated/index.ts +7 -0
- package/src/ui/empty-state/animated/types.ts +26 -0
- package/src/ui/empty-state/empty-state-base.tsx +114 -0
- package/src/ui/empty-state/empty-state.tsx +9 -0
- package/src/ui/empty-state/index.ts +10 -0
- package/src/ui/empty-state/types.ts +19 -0
- package/src/ui/empty-state/variants.ts +51 -0
- package/src/ui/file-upload/file-upload.test.tsx +36 -0
- package/src/ui/file-upload/file-upload.tsx +119 -0
- package/src/ui/file-upload/index.ts +5 -0
- package/src/ui/file-upload/types.ts +21 -0
- package/src/ui/file-upload/variants.ts +29 -0
- package/src/ui/inputs/animated/animations.ts +36 -0
- package/src/ui/inputs/animated/index.ts +5 -0
- package/src/ui/inputs/animated/input-animated.tsx +124 -0
- package/src/ui/inputs/animated/types.ts +40 -0
- package/src/ui/inputs/index.ts +5 -0
- package/src/ui/inputs/input-base.tsx +114 -0
- package/src/ui/inputs/input.test.tsx +414 -0
- package/src/ui/inputs/input.tsx +8 -0
- package/src/ui/inputs/types.ts +18 -0
- package/src/ui/inputs/variants.ts +316 -0
- package/src/ui/modal/animated/animations.ts +29 -0
- package/src/ui/modal/animated/index.ts +5 -0
- package/src/ui/modal/animated/modal-content-animated.tsx +96 -0
- package/src/ui/modal/animated/types.ts +23 -0
- package/src/ui/modal/index.ts +21 -0
- package/src/ui/modal/modal-base.tsx +279 -0
- package/src/ui/modal/modal.test.tsx +129 -0
- package/src/ui/modal/modal.tsx +8 -0
- package/src/ui/modal/types.ts +31 -0
- package/src/ui/modal/variants.ts +109 -0
- package/src/ui/pagination/index.ts +13 -0
- package/src/ui/pagination/pagination.test.tsx +165 -0
- package/src/ui/pagination/pagination.tsx +237 -0
- package/src/ui/pagination/types.ts +66 -0
- package/src/ui/pagination/variants.ts +97 -0
- package/src/ui/progress/animated/animations.ts +9 -0
- package/src/ui/progress/animated/index.ts +17 -0
- package/src/ui/progress/animated/progress-animated.tsx +133 -0
- package/src/ui/progress/animated/types.ts +35 -0
- package/src/ui/progress/index.ts +10 -0
- package/src/ui/progress/progress-base.tsx +151 -0
- package/src/ui/progress/progress.test.tsx +84 -0
- package/src/ui/progress/progress.tsx +12 -0
- package/src/ui/progress/types.ts +33 -0
- package/src/ui/progress/variants.ts +105 -0
- package/src/ui/select/index.ts +25 -0
- package/src/ui/select/select.test.tsx +128 -0
- package/src/ui/select/select.tsx +221 -0
- package/src/ui/select/types.ts +77 -0
- package/src/ui/select/variants.ts +163 -0
- package/src/ui/skeleton/animated/animations.ts +15 -0
- package/src/ui/skeleton/animated/index.ts +20 -0
- package/src/ui/skeleton/animated/skeleton-animated.tsx +119 -0
- package/src/ui/skeleton/animated/types.ts +49 -0
- package/src/ui/skeleton/index.ts +24 -0
- package/src/ui/skeleton/skeleton-base.tsx +288 -0
- package/src/ui/skeleton/skeleton.tsx +8 -0
- package/src/ui/skeleton/types.ts +31 -0
- package/src/ui/skeleton/variants.ts +254 -0
- package/src/ui/slider/index.ts +22 -0
- package/src/ui/slider/slider.test.tsx +94 -0
- package/src/ui/slider/slider.tsx +728 -0
- package/src/ui/slider/types.ts +66 -0
- package/src/ui/slider/variants.ts +81 -0
- package/src/ui/spinner/animated/index.ts +5 -0
- package/src/ui/spinner/animated/spinner.test.tsx +41 -0
- package/src/ui/spinner/animated/spinner.tsx +143 -0
- package/src/ui/spinner/animated/types.ts +11 -0
- package/src/ui/spinner/animated/variants.ts +50 -0
- package/src/ui/stepper/index.ts +22 -0
- package/src/ui/stepper/stepper.test.tsx +183 -0
- package/src/ui/stepper/stepper.tsx +172 -0
- package/src/ui/stepper/types.ts +32 -0
- package/src/ui/stepper/variants.ts +69 -0
- package/src/ui/table/animated/animations.ts +9 -0
- package/src/ui/table/animated/index.ts +15 -0
- package/src/ui/table/animated/table-animated.tsx +15 -0
- package/src/ui/table/animated/types.ts +16 -0
- package/src/ui/table/index.ts +22 -0
- package/src/ui/table/table-base.tsx +197 -0
- package/src/ui/table/table.tsx +13 -0
- package/src/ui/table/types.ts +47 -0
- package/src/ui/table/variants.ts +105 -0
- package/src/ui/tabs/animated/animations.ts +48 -0
- package/src/ui/tabs/animated/index.ts +8 -0
- package/src/ui/tabs/animated/tabs-content-animated.tsx +46 -0
- package/src/ui/tabs/animated/types.ts +24 -0
- package/src/ui/tabs/index.ts +10 -0
- package/src/ui/tabs/tabs-base.tsx +185 -0
- package/src/ui/tabs/tabs.test.tsx +53 -0
- package/src/ui/tabs/tabs.tsx +2 -0
- package/src/ui/tabs/types.ts +88 -0
- package/src/ui/tabs/variants.ts +70 -0
- package/src/ui/toast/animated/animations.ts +17 -0
- package/src/ui/toast/animated/index.ts +9 -0
- package/src/ui/toast/animated/toast-animated.tsx +96 -0
- package/src/ui/toast/animated/types.ts +13 -0
- package/src/ui/toast/index.ts +26 -0
- package/src/ui/toast/toast-base.tsx +231 -0
- package/src/ui/toast/toast.test.tsx +102 -0
- package/src/ui/toast/toast.tsx +13 -0
- package/src/ui/toast/types.ts +57 -0
- package/src/ui/toast/variants.ts +73 -0
- package/src/ui/toggle/animated/animations.ts +9 -0
- package/src/ui/toggle/animated/index.ts +7 -0
- package/src/ui/toggle/animated/toggle-animated.tsx +76 -0
- package/src/ui/toggle/animated/types.ts +13 -0
- package/src/ui/toggle/index.ts +5 -0
- package/src/ui/toggle/toggle-base.tsx +70 -0
- package/src/ui/toggle/toggle.test.tsx +44 -0
- package/src/ui/toggle/toggle.tsx +9 -0
- package/src/ui/toggle/types.ts +18 -0
- package/src/ui/toggle/variants.ts +84 -0
- package/src/ui/tooltip/animated/animations.ts +16 -0
- package/src/ui/tooltip/animated/index.ts +10 -0
- package/src/ui/tooltip/animated/tooltip-content-animated.tsx +47 -0
- package/src/ui/tooltip/animated/types.ts +19 -0
- package/src/ui/tooltip/index.ts +17 -0
- package/src/ui/tooltip/tooltip-base.tsx +152 -0
- package/src/ui/tooltip/tooltip.test.tsx +84 -0
- package/src/ui/tooltip/tooltip.tsx +8 -0
- package/src/ui/tooltip/types.ts +57 -0
- package/src/ui/tooltip/variants.ts +61 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { useState } from "react";
|
|
2
|
+
import { render, screen } from "@testing-library/react";
|
|
3
|
+
import userEvent from "@testing-library/user-event";
|
|
4
|
+
import { describe, expect, it } from "vitest";
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
Accordion,
|
|
8
|
+
AccordionContent,
|
|
9
|
+
AccordionItem,
|
|
10
|
+
AccordionTrigger,
|
|
11
|
+
} from "./accordion";
|
|
12
|
+
|
|
13
|
+
describe("Accordion", () => {
|
|
14
|
+
describe("public contract and metadata", () => {
|
|
15
|
+
it("should expose displayName on compound parts", () => {
|
|
16
|
+
expect(Accordion.displayName).toBe("Accordion");
|
|
17
|
+
expect(AccordionItem.displayName).toBe("AccordionItem");
|
|
18
|
+
expect(AccordionTrigger.displayName).toBe("AccordionTrigger");
|
|
19
|
+
expect(AccordionContent.displayName).toBe("AccordionContent");
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("should stamp data-slot on the root container", () => {
|
|
23
|
+
render(
|
|
24
|
+
<Accordion defaultValue="one">
|
|
25
|
+
<AccordionItem value="one">
|
|
26
|
+
<AccordionTrigger>One</AccordionTrigger>
|
|
27
|
+
<AccordionContent>Panel one</AccordionContent>
|
|
28
|
+
</AccordionItem>
|
|
29
|
+
</Accordion>,
|
|
30
|
+
);
|
|
31
|
+
const root = document.querySelector('[data-slot="accordion"]');
|
|
32
|
+
expect(root).toBeTruthy();
|
|
33
|
+
expect(root?.getAttribute("data-slot")).toBe("accordion");
|
|
34
|
+
});
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
describe("single mode", () => {
|
|
38
|
+
it("should show panel content when defaultValue matches", () => {
|
|
39
|
+
render(
|
|
40
|
+
<Accordion defaultValue="a">
|
|
41
|
+
<AccordionItem value="a">
|
|
42
|
+
<AccordionTrigger>Item A</AccordionTrigger>
|
|
43
|
+
<AccordionContent>Content A</AccordionContent>
|
|
44
|
+
</AccordionItem>
|
|
45
|
+
</Accordion>,
|
|
46
|
+
);
|
|
47
|
+
expect(screen.getByRole("region")).toHaveTextContent("Content A");
|
|
48
|
+
expect(screen.getByRole("button", { name: "Item A" })).toHaveAttribute(
|
|
49
|
+
"aria-expanded",
|
|
50
|
+
"true",
|
|
51
|
+
);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("should toggle aria-expanded and panel visibility when the trigger is clicked", async () => {
|
|
55
|
+
const user = userEvent.setup();
|
|
56
|
+
render(
|
|
57
|
+
<Accordion defaultValue="a">
|
|
58
|
+
<AccordionItem value="a">
|
|
59
|
+
<AccordionTrigger>Item A</AccordionTrigger>
|
|
60
|
+
<AccordionContent>Content A</AccordionContent>
|
|
61
|
+
</AccordionItem>
|
|
62
|
+
</Accordion>,
|
|
63
|
+
);
|
|
64
|
+
await user.click(screen.getByRole("button", { name: "Item A" }));
|
|
65
|
+
expect(screen.getByRole("button", { name: "Item A" })).toHaveAttribute(
|
|
66
|
+
"aria-expanded",
|
|
67
|
+
"false",
|
|
68
|
+
);
|
|
69
|
+
expect(screen.queryByRole("region")).not.toBeInTheDocument();
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it("should wire aria-controls to the panel id", () => {
|
|
73
|
+
render(
|
|
74
|
+
<Accordion defaultValue="x">
|
|
75
|
+
<AccordionItem value="x">
|
|
76
|
+
<AccordionTrigger>Open</AccordionTrigger>
|
|
77
|
+
<AccordionContent>Inside</AccordionContent>
|
|
78
|
+
</AccordionItem>
|
|
79
|
+
</Accordion>,
|
|
80
|
+
);
|
|
81
|
+
const trigger = screen.getByRole("button", { name: "Open" });
|
|
82
|
+
const controls = trigger.getAttribute("aria-controls");
|
|
83
|
+
expect(controls).toBe("x-panel");
|
|
84
|
+
expect(document.getElementById("x-panel")).toBe(
|
|
85
|
+
screen.getByRole("region"),
|
|
86
|
+
);
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
describe("multiple mode", () => {
|
|
91
|
+
it("should allow more than one panel open when type is multiple", async () => {
|
|
92
|
+
const user = userEvent.setup();
|
|
93
|
+
render(
|
|
94
|
+
<Accordion type="multiple" defaultValues={["a"]}>
|
|
95
|
+
<AccordionItem value="a">
|
|
96
|
+
<AccordionTrigger>A</AccordionTrigger>
|
|
97
|
+
<AccordionContent>Panel A</AccordionContent>
|
|
98
|
+
</AccordionItem>
|
|
99
|
+
<AccordionItem value="b">
|
|
100
|
+
<AccordionTrigger>B</AccordionTrigger>
|
|
101
|
+
<AccordionContent>Panel B</AccordionContent>
|
|
102
|
+
</AccordionItem>
|
|
103
|
+
</Accordion>,
|
|
104
|
+
);
|
|
105
|
+
await user.click(screen.getByRole("button", { name: "B" }));
|
|
106
|
+
expect(screen.getByRole("button", { name: "A" })).toHaveAttribute(
|
|
107
|
+
"aria-expanded",
|
|
108
|
+
"true",
|
|
109
|
+
);
|
|
110
|
+
expect(screen.getByRole("button", { name: "B" })).toHaveAttribute(
|
|
111
|
+
"aria-expanded",
|
|
112
|
+
"true",
|
|
113
|
+
);
|
|
114
|
+
expect(screen.getByText("Panel A")).toBeInTheDocument();
|
|
115
|
+
expect(screen.getByText("Panel B")).toBeInTheDocument();
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
describe("controlled single mode", () => {
|
|
120
|
+
it("should reflect external value changes and invoke onValueChange", async () => {
|
|
121
|
+
const user = userEvent.setup();
|
|
122
|
+
function Controlled() {
|
|
123
|
+
const [value, setValue] = useState<string | undefined>("a");
|
|
124
|
+
return (
|
|
125
|
+
<Accordion type="single" value={value} onValueChange={setValue}>
|
|
126
|
+
<AccordionItem value="a">
|
|
127
|
+
<AccordionTrigger>A</AccordionTrigger>
|
|
128
|
+
<AccordionContent>Panel A</AccordionContent>
|
|
129
|
+
</AccordionItem>
|
|
130
|
+
<AccordionItem value="b">
|
|
131
|
+
<AccordionTrigger>B</AccordionTrigger>
|
|
132
|
+
<AccordionContent>Panel B</AccordionContent>
|
|
133
|
+
</AccordionItem>
|
|
134
|
+
</Accordion>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
render(<Controlled />);
|
|
138
|
+
await user.click(screen.getByRole("button", { name: "B" }));
|
|
139
|
+
expect(screen.getByRole("button", { name: "B" })).toHaveAttribute(
|
|
140
|
+
"aria-expanded",
|
|
141
|
+
"true",
|
|
142
|
+
);
|
|
143
|
+
expect(screen.getByText("Panel B")).toBeInTheDocument();
|
|
144
|
+
});
|
|
145
|
+
});
|
|
146
|
+
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// accordion.tsx — default static entry (no framer-motion on content)
|
|
2
|
+
import { AccordionBase, AccordionContent, AccordionItem, AccordionTrigger } from "./accordion-base";
|
|
3
|
+
import type { AccordionProps } from "./types";
|
|
4
|
+
|
|
5
|
+
export function Accordion(props: AccordionProps) {
|
|
6
|
+
return <AccordionBase {...props} />;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
Accordion.displayName = "Accordion";
|
|
10
|
+
|
|
11
|
+
export { AccordionContent, AccordionItem, AccordionTrigger };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { motion } from "framer-motion";
|
|
4
|
+
|
|
5
|
+
import { cn } from "../../../lib/utils";
|
|
6
|
+
|
|
7
|
+
import { accordionContentTransitionPresets } from "./animations";
|
|
8
|
+
import { useAccordionContext, useAccordionItemValue } from "../accordion-base";
|
|
9
|
+
import { accordionContentVariants } from "../variants";
|
|
10
|
+
import { AccordionContentAnimatedProps } from "./types";
|
|
11
|
+
|
|
12
|
+
export function AccordionContentAnimated({
|
|
13
|
+
className,
|
|
14
|
+
children,
|
|
15
|
+
transitionVariant = "default",
|
|
16
|
+
ref,
|
|
17
|
+
}: AccordionContentAnimatedProps) {
|
|
18
|
+
const itemValue = useAccordionItemValue("AccordionContent");
|
|
19
|
+
const {
|
|
20
|
+
isOpen,
|
|
21
|
+
size,
|
|
22
|
+
} = useAccordionContext("AccordionContent");
|
|
23
|
+
const open = isOpen(itemValue);
|
|
24
|
+
const panelId = `${itemValue}-panel`;
|
|
25
|
+
const transitionConfig = accordionContentTransitionPresets[transitionVariant];
|
|
26
|
+
const motionless = transitionVariant === "none";
|
|
27
|
+
|
|
28
|
+
return open ? (
|
|
29
|
+
<motion.div
|
|
30
|
+
key={itemValue}
|
|
31
|
+
ref={ref}
|
|
32
|
+
id={panelId}
|
|
33
|
+
role="region"
|
|
34
|
+
data-slot="accordion-content"
|
|
35
|
+
className={cn(accordionContentVariants({ size }), className)}
|
|
36
|
+
initial={motionless ? false : { opacity: 0 }}
|
|
37
|
+
animate={motionless ? undefined : { opacity: 1 }}
|
|
38
|
+
exit={motionless ? undefined : { opacity: 0 }}
|
|
39
|
+
transition={transitionConfig}
|
|
40
|
+
>
|
|
41
|
+
{children}
|
|
42
|
+
</motion.div>
|
|
43
|
+
) : null;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
AccordionContentAnimated.displayName = "AccordionContentAnimated";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { AccordionBase } from "../accordion-base";
|
|
4
|
+
import type { AccordionAnimatedProps } from "./types";
|
|
5
|
+
|
|
6
|
+
export function Accordion(props: AccordionAnimatedProps) {
|
|
7
|
+
return <AccordionBase {...props} />;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
Accordion.displayName = "Accordion";
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Transition } from "framer-motion";
|
|
2
|
+
|
|
3
|
+
/** Easing and duration presets for accordion panel open/close (opacity only). */
|
|
4
|
+
export type AccordionTransition = "none" | "default" | "smooth" | "slow";
|
|
5
|
+
|
|
6
|
+
export type AccordionTransitionPresets = Record<
|
|
7
|
+
AccordionTransition,
|
|
8
|
+
Transition
|
|
9
|
+
>;
|
|
10
|
+
|
|
11
|
+
export const accordionContentTransitionPresets: AccordionTransitionPresets = {
|
|
12
|
+
none: { duration: 0 },
|
|
13
|
+
default: { duration: 0.2, ease: [0.4, 0, 0.2, 1] },
|
|
14
|
+
smooth: { duration: 0.28, ease: [0.22, 1, 0.36, 1] },
|
|
15
|
+
slow: { duration: 0.38, ease: [0.4, 0, 0.2, 1] },
|
|
16
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
export { Accordion } from "./accordion-root-animated";
|
|
4
|
+
export { AccordionItem, AccordionTrigger } from "../accordion-base";
|
|
5
|
+
export { AccordionContentAnimated } from "./accordion-content-animated";
|
|
6
|
+
export type { AccordionAnimatedProps, AccordionContentAnimatedProps } from "./types";
|
|
7
|
+
export { accordionContentTransitionPresets } from "./animations";
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { AccordionBaseProps, AccordionContentProps, AccordionTransition } from "../types";
|
|
2
|
+
|
|
3
|
+
export type AccordionAnimatedProps = AccordionBaseProps;
|
|
4
|
+
|
|
5
|
+
export type AccordionContentAnimatedProps = AccordionContentProps & {
|
|
6
|
+
transitionVariant?: AccordionTransition;
|
|
7
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
export {
|
|
4
|
+
Accordion,
|
|
5
|
+
AccordionContent,
|
|
6
|
+
AccordionItem,
|
|
7
|
+
AccordionTrigger,
|
|
8
|
+
} from "./accordion";
|
|
9
|
+
export type { AccordionBaseProps } from "./types";
|
|
10
|
+
export type {
|
|
11
|
+
AccordionContentProps,
|
|
12
|
+
AccordionItemProps,
|
|
13
|
+
AccordionProps,
|
|
14
|
+
AccordionTransition,
|
|
15
|
+
AccordionTriggerProps,
|
|
16
|
+
AccordionType,
|
|
17
|
+
} from "./types";
|
|
18
|
+
export {
|
|
19
|
+
accordionVariants,
|
|
20
|
+
accordionItemVariants,
|
|
21
|
+
accordionTriggerVariants,
|
|
22
|
+
accordionContentVariants,
|
|
23
|
+
} from "./variants";
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { VariantProps } from "class-variance-authority";
|
|
2
|
+
import type { HTMLAttributes, ReactNode, Ref } from "react";
|
|
3
|
+
|
|
4
|
+
import type { AccordionTransition } from "./animated/animations";
|
|
5
|
+
import type { accordionVariants } from "./variants";
|
|
6
|
+
|
|
7
|
+
export type { AccordionTransition };
|
|
8
|
+
|
|
9
|
+
type AccordionVariantProps = VariantProps<typeof accordionVariants>;
|
|
10
|
+
|
|
11
|
+
export type AccordionType = "single" | "multiple";
|
|
12
|
+
|
|
13
|
+
export type AccordionBaseProps = AccordionVariantProps & {
|
|
14
|
+
type?: AccordionType;
|
|
15
|
+
/** Controlled value for `single` mode. */
|
|
16
|
+
value?: string;
|
|
17
|
+
/** Controlled values for `multiple` mode. */
|
|
18
|
+
values?: string[];
|
|
19
|
+
defaultValue?: string;
|
|
20
|
+
defaultValues?: string[];
|
|
21
|
+
onValueChange?: (value: string | undefined) => void;
|
|
22
|
+
onValuesChange?: (values: string[]) => void;
|
|
23
|
+
className?: string;
|
|
24
|
+
children?: ReactNode;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export type AccordionProps = AccordionBaseProps;
|
|
28
|
+
|
|
29
|
+
export type AccordionItemProps = HTMLAttributes<HTMLDivElement> & {
|
|
30
|
+
value: string;
|
|
31
|
+
ref?: Ref<HTMLDivElement>;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
export type AccordionTriggerProps = HTMLAttributes<HTMLButtonElement> & {
|
|
35
|
+
ref?: Ref<HTMLButtonElement>;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export type AccordionContentProps = HTMLAttributes<HTMLDivElement> & {
|
|
39
|
+
ref?: Ref<HTMLDivElement>;
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export type AccordionCtx = {
|
|
43
|
+
type: NonNullable<AccordionProps["type"]>;
|
|
44
|
+
appearance: NonNullable<AccordionProps["appearance"]>;
|
|
45
|
+
size: NonNullable<AccordionProps["size"]>;
|
|
46
|
+
isOpen: (value: string) => boolean;
|
|
47
|
+
toggle: (value: string) => void;
|
|
48
|
+
};
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { cva } from "class-variance-authority";
|
|
2
|
+
|
|
3
|
+
export const accordionVariants = cva("w-full", {
|
|
4
|
+
variants: {
|
|
5
|
+
appearance: {
|
|
6
|
+
default: "divide-y divide-white/10 rounded-xl border border-white/10",
|
|
7
|
+
outline: "divide-y divide-white/10 rounded-xl border border-white/15",
|
|
8
|
+
ghost: "divide-y divide-white/5",
|
|
9
|
+
card: "space-y-2",
|
|
10
|
+
separated: "space-y-3",
|
|
11
|
+
sky: "divide-y divide-sky-600 rounded-xl border border-sky-600",
|
|
12
|
+
rose: "divide-y divide-rose-600 rounded-xl border border-rose-600",
|
|
13
|
+
purple: "divide-y divide-purple-600 rounded-xl border border-purple-600",
|
|
14
|
+
pink: "divide-y divide-pink-600 rounded-xl border border-pink-600",
|
|
15
|
+
orange: "divide-y divide-orange-600 rounded-xl border border-orange-600",
|
|
16
|
+
yellow: "divide-y divide-yellow-600 rounded-xl border border-yellow-600",
|
|
17
|
+
teal: "divide-y divide-teal-600 rounded-xl border border-teal-600",
|
|
18
|
+
indigo: "divide-y divide-indigo-600 rounded-xl border border-indigo-600",
|
|
19
|
+
emerald:
|
|
20
|
+
"divide-y divide-emerald-600 rounded-xl border border-emerald-600",
|
|
21
|
+
"gradient-blue":
|
|
22
|
+
"divide-y divide-gradient-to-r from-blue-600 to-purple-600 rounded-xl border border-gradient-to-r from-blue-600 to-purple-600",
|
|
23
|
+
"gradient-green":
|
|
24
|
+
"divide-y divide-gradient-to-r from-green-600 to-lime-600 rounded-xl border border-gradient-to-r from-green-600 to-lime-600",
|
|
25
|
+
"gradient-red":
|
|
26
|
+
"divide-y divide-gradient-to-r from-red-600 to-pink-600 rounded-xl border border-gradient-to-r from-red-600 to-pink-600",
|
|
27
|
+
"gradient-yellow":
|
|
28
|
+
"divide-y divide-gradient-to-r from-yellow-600 to-orange-600 rounded-xl border border-gradient-to-r from-yellow-600 to-orange-600",
|
|
29
|
+
"gradient-purple":
|
|
30
|
+
"divide-y divide-gradient-to-r from-purple-600 to-pink-600 rounded-xl border border-gradient-to-r from-purple-600 to-pink-600",
|
|
31
|
+
"gradient-teal":
|
|
32
|
+
"divide-y divide-gradient-to-r from-teal-600 to-cyan-600 rounded-xl border border-gradient-to-r from-teal-600 to-cyan-600",
|
|
33
|
+
"gradient-indigo":
|
|
34
|
+
"divide-y divide-gradient-to-r from-indigo-600 to-purple-600 rounded-xl border border-gradient-to-r from-indigo-600 to-purple-600",
|
|
35
|
+
"gradient-pink":
|
|
36
|
+
"divide-y divide-gradient-to-r from-pink-600 to-rose-600 rounded-xl border border-gradient-to-r from-pink-600 to-rose-600",
|
|
37
|
+
"gradient-orange":
|
|
38
|
+
"divide-y divide-gradient-to-r from-orange-600 to-red-600 rounded-xl border border-gradient-to-r from-orange-600 to-red-600",
|
|
39
|
+
},
|
|
40
|
+
size: {
|
|
41
|
+
sm: "px-3 py-2 text-sm",
|
|
42
|
+
md: "px-4 py-3 text-sm",
|
|
43
|
+
lg: "px-5 py-4 text-base",
|
|
44
|
+
},
|
|
45
|
+
},
|
|
46
|
+
defaultVariants: {
|
|
47
|
+
appearance: "default",
|
|
48
|
+
size: "md",
|
|
49
|
+
},
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
export const accordionItemVariants = cva("", {
|
|
53
|
+
variants: {
|
|
54
|
+
appearance: {
|
|
55
|
+
default: "",
|
|
56
|
+
outline: "",
|
|
57
|
+
ghost: "",
|
|
58
|
+
card: "rounded-xl border border-white/10 bg-white/[0.03] p-2",
|
|
59
|
+
separated: "rounded-xl border border-white/10 bg-slate-950/40 p-2",
|
|
60
|
+
sky: "rounded-xl border border-sky-600 bg-sky-600/[0.03] p-2",
|
|
61
|
+
rose: "rounded-xl border border-rose-600 bg-rose-600/[0.03] p-2",
|
|
62
|
+
purple: "rounded-xl border border-purple-600 bg-purple-600/[0.03] p-2",
|
|
63
|
+
pink: "rounded-xl border border-pink-600 bg-pink-600/[0.03] p-2",
|
|
64
|
+
orange: "rounded-xl border border-orange-600 bg-orange-600/[0.03] p-2",
|
|
65
|
+
yellow: "rounded-xl border border-yellow-600 bg-yellow-600/[0.03] p-2",
|
|
66
|
+
teal: "rounded-xl border border-teal-600 bg-teal-600/[0.03] p-2",
|
|
67
|
+
indigo: "rounded-xl border border-indigo-600 bg-indigo-600/[0.03] p-2",
|
|
68
|
+
emerald: "rounded-xl border border-emerald-600 bg-emerald-600/[0.03] p-2",
|
|
69
|
+
"gradient-blue":
|
|
70
|
+
"rounded-xl bg-linear-to-r from-blue-600 to-purple-600/[0.03] p-2 text-white",
|
|
71
|
+
"gradient-green":
|
|
72
|
+
"rounded-xl bg-linear-to-r from-green-600 to-lime-600/[0.03] p-2 text-white",
|
|
73
|
+
"gradient-red":
|
|
74
|
+
"rounded-xl bg-linear-to-r from-red-600 to-pink-600/[0.03] p-2 text-white",
|
|
75
|
+
"gradient-yellow":
|
|
76
|
+
"rounded-xl bg-linear-to-r from-yellow-600 to-orange-600/[0.03] p-2 text-white",
|
|
77
|
+
"gradient-purple":
|
|
78
|
+
"rounded-xl bg-linear-to-r from-purple-600 to-pink-600/[0.03] p-2 text-white",
|
|
79
|
+
"gradient-teal":
|
|
80
|
+
"rounded-xl bg-linear-to-r from-teal-600 to-cyan-600/[0.03] p-2 text-white",
|
|
81
|
+
"gradient-indigo":
|
|
82
|
+
"rounded-xl bg-linear-to-r from-indigo-600 to-purple-600/[0.03] p-2 text-white",
|
|
83
|
+
"gradient-pink":
|
|
84
|
+
"rounded-xl bg-linear-to-r from-pink-600 to-rose-600/[0.03] p-2 text-white",
|
|
85
|
+
"gradient-orange":
|
|
86
|
+
"rounded-xl bg-linear-to-r from-orange-600 to-red-600/[0.03] p-2 text-white",
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
defaultVariants: { appearance: "default" },
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
export const accordionTriggerVariants = cva(
|
|
93
|
+
"flex w-full items-center justify-between gap-3 py-3 text-left font-medium text-slate-50 outline-none transition hover:text-white focus-visible:ring-2 focus-visible:ring-white/30",
|
|
94
|
+
{
|
|
95
|
+
variants: {
|
|
96
|
+
size: {
|
|
97
|
+
sm: "py-2 text-sm",
|
|
98
|
+
md: "py-3 text-sm",
|
|
99
|
+
lg: "py-4 text-base",
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
defaultVariants: { size: "md" },
|
|
103
|
+
},
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
export const accordionContentVariants = cva("pb-3 text-sm", {
|
|
107
|
+
variants: {
|
|
108
|
+
size: {
|
|
109
|
+
sm: "pb-2 text-xs",
|
|
110
|
+
md: "pb-3 text-sm",
|
|
111
|
+
lg: "pb-4 text-base",
|
|
112
|
+
},
|
|
113
|
+
},
|
|
114
|
+
defaultVariants: { size: "md" },
|
|
115
|
+
});
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { createContext, useContext, useMemo } from "react";
|
|
4
|
+
import {
|
|
5
|
+
HiExclamationTriangle,
|
|
6
|
+
HiInformationCircle,
|
|
7
|
+
HiXMark,
|
|
8
|
+
} from "react-icons/hi2";
|
|
9
|
+
|
|
10
|
+
import { cn } from "../../lib/utils";
|
|
11
|
+
|
|
12
|
+
import type { AlertBaseProps, AlertProps, AlertSectionProps, AlertSize } from "./types";
|
|
13
|
+
import {
|
|
14
|
+
alertDescriptionVariants,
|
|
15
|
+
alertTitleVariants,
|
|
16
|
+
alertVariants,
|
|
17
|
+
} from "./variants";
|
|
18
|
+
|
|
19
|
+
const AlertSizeContext = createContext<AlertSize>("md");
|
|
20
|
+
|
|
21
|
+
function useAlertSize(): AlertSize {
|
|
22
|
+
const ctx = useContext(AlertSizeContext);
|
|
23
|
+
if (!ctx) {
|
|
24
|
+
throw new Error("useAlertSize must be used within an Alert");
|
|
25
|
+
}
|
|
26
|
+
return ctx;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function AlertBase(props: AlertBaseProps) {
|
|
30
|
+
const {
|
|
31
|
+
className,
|
|
32
|
+
triggerClassName,
|
|
33
|
+
appearance = "default",
|
|
34
|
+
size = "md",
|
|
35
|
+
closable = false,
|
|
36
|
+
onClose,
|
|
37
|
+
closeLabel = "Dismiss alert",
|
|
38
|
+
children,
|
|
39
|
+
ref,
|
|
40
|
+
as: Wrapper = "div",
|
|
41
|
+
...rest
|
|
42
|
+
} = props;
|
|
43
|
+
|
|
44
|
+
const live = appearance === "error" ? "assertive" : "polite";
|
|
45
|
+
const ctx = useMemo(() => size ?? "md", [size]);
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<AlertSizeContext.Provider value={ctx}>
|
|
49
|
+
<Wrapper
|
|
50
|
+
ref={ref}
|
|
51
|
+
data-slot="alert"
|
|
52
|
+
role="alert"
|
|
53
|
+
aria-live={live}
|
|
54
|
+
className={cn(
|
|
55
|
+
alertVariants({ appearance, size }),
|
|
56
|
+
closable ? "pr-12" : "",
|
|
57
|
+
className,
|
|
58
|
+
)}
|
|
59
|
+
{...rest}
|
|
60
|
+
>
|
|
61
|
+
{children}
|
|
62
|
+
{closable ? (
|
|
63
|
+
<button
|
|
64
|
+
type="button"
|
|
65
|
+
data-slot="alert-close"
|
|
66
|
+
aria-label={closeLabel}
|
|
67
|
+
onClick={onClose}
|
|
68
|
+
className={cn(
|
|
69
|
+
"absolute right-3 top-3 inline-flex size-8 items-center justify-center rounded-md text-slate-200 transition hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/30",
|
|
70
|
+
triggerClassName,
|
|
71
|
+
)}
|
|
72
|
+
>
|
|
73
|
+
<HiXMark className="size-4" aria-hidden />
|
|
74
|
+
</button>
|
|
75
|
+
) : null}
|
|
76
|
+
</Wrapper>
|
|
77
|
+
</AlertSizeContext.Provider>
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
AlertBase.displayName = "AlertBase";
|
|
82
|
+
|
|
83
|
+
export function AlertIcon({ className, children }: AlertSectionProps) {
|
|
84
|
+
return (
|
|
85
|
+
<span
|
|
86
|
+
data-slot="alert-icon"
|
|
87
|
+
className={cn("mt-0.5 shrink-0 text-current", className)}
|
|
88
|
+
>
|
|
89
|
+
{children}
|
|
90
|
+
</span>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
AlertIcon.displayName = "AlertIcon";
|
|
95
|
+
|
|
96
|
+
export function AlertTitle({ className, children }: AlertSectionProps) {
|
|
97
|
+
const size = useAlertSize();
|
|
98
|
+
return (
|
|
99
|
+
<div
|
|
100
|
+
data-slot="alert-title"
|
|
101
|
+
className={cn(alertTitleVariants({ size }), className)}
|
|
102
|
+
>
|
|
103
|
+
{children}
|
|
104
|
+
</div>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
AlertTitle.displayName = "AlertTitle";
|
|
109
|
+
|
|
110
|
+
export function AlertDescription({ className, children }: AlertSectionProps) {
|
|
111
|
+
const size = useAlertSize();
|
|
112
|
+
return (
|
|
113
|
+
<div
|
|
114
|
+
data-slot="alert-description"
|
|
115
|
+
className={cn(alertDescriptionVariants({ size }), className)}
|
|
116
|
+
>
|
|
117
|
+
{children}
|
|
118
|
+
</div>
|
|
119
|
+
);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
AlertDescription.displayName = "AlertDescription";
|
|
123
|
+
|
|
124
|
+
export function AlertClose({
|
|
125
|
+
className,
|
|
126
|
+
children,
|
|
127
|
+
"aria-label": ariaLabel = "Dismiss alert",
|
|
128
|
+
onClick,
|
|
129
|
+
}: AlertSectionProps & { onClick?: () => void; "aria-label"?: string }) {
|
|
130
|
+
return (
|
|
131
|
+
<button
|
|
132
|
+
type="button"
|
|
133
|
+
data-slot="alert-close"
|
|
134
|
+
aria-label={ariaLabel}
|
|
135
|
+
onClick={onClick}
|
|
136
|
+
className={cn(
|
|
137
|
+
"inline-flex size-8 items-center justify-center rounded-md text-slate-200 transition hover:bg-white/10 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/30",
|
|
138
|
+
className,
|
|
139
|
+
)}
|
|
140
|
+
>
|
|
141
|
+
{children ?? <HiXMark className="size-4" aria-hidden />}
|
|
142
|
+
</button>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
AlertClose.displayName = "AlertClose";
|
|
147
|
+
|
|
148
|
+
export function AlertDefaultIcon({
|
|
149
|
+
appearance,
|
|
150
|
+
}: {
|
|
151
|
+
appearance?: AlertProps["appearance"];
|
|
152
|
+
}) {
|
|
153
|
+
if (appearance === "error") {
|
|
154
|
+
return <HiExclamationTriangle className="size-5" aria-hidden />;
|
|
155
|
+
}
|
|
156
|
+
return <HiInformationCircle className="size-5" aria-hidden />;
|
|
157
|
+
}
|