@fpkit/acss 0.5.5 → 0.5.6

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.
Files changed (126) hide show
  1. package/libs/chunk-PWVRDQ3R.js +8 -0
  2. package/libs/chunk-PWVRDQ3R.js.map +1 -0
  3. package/libs/chunk-SVS4MX3U.cjs +31 -0
  4. package/libs/chunk-SVS4MX3U.cjs.map +1 -0
  5. package/libs/{icons-1f5afc0c.d.ts → icons-31ace3de.d.ts} +86 -49
  6. package/libs/icons.cjs +2 -2
  7. package/libs/icons.d.cts +1 -1
  8. package/libs/icons.d.ts +1 -1
  9. package/libs/icons.js +1 -1
  10. package/libs/index.cjs +34 -34
  11. package/libs/index.cjs.map +1 -1
  12. package/libs/index.d.cts +46 -15
  13. package/libs/index.d.ts +46 -15
  14. package/libs/index.js +7 -7
  15. package/libs/index.js.map +1 -1
  16. package/package.json +4 -3
  17. package/src/components/README.mdx +84 -0
  18. package/src/components/alert/README.mdx +86 -0
  19. package/src/components/alert/alert.mdx +74 -0
  20. package/src/components/alert/alert.scss +80 -0
  21. package/src/components/alert/alert.stories.tsx +132 -0
  22. package/src/components/alert/alert.tsx +154 -0
  23. package/src/components/alert/elements/README.mdx +77 -0
  24. package/src/components/alert/elements/dismiss-button.stories.tsx +31 -0
  25. package/src/components/alert/elements/dismiss-button.tsx +28 -0
  26. package/src/components/badge/badge.mdx +124 -0
  27. package/src/components/badge/badge.scss +4 -4
  28. package/src/components/buttons/button.scss +1 -0
  29. package/src/components/buttons/button.test.tsx +72 -72
  30. package/src/components/details/details.scss +20 -1
  31. package/src/components/dialog/README.mdx +187 -0
  32. package/src/components/dialog/dialog-modal.stories.tsx +113 -0
  33. package/src/components/dialog/dialog-modal.tsx +111 -0
  34. package/src/components/dialog/dialog.scss +28 -13
  35. package/src/components/dialog/dialog.stories.tsx +85 -30
  36. package/src/components/dialog/dialog.tsx +106 -61
  37. package/src/components/dialog/hooks/useClickOutside.ts +33 -0
  38. package/src/components/dialog/views/README.mdx +182 -0
  39. package/src/components/dialog/views/dialog-footer.tsx +45 -0
  40. package/src/components/dialog/{view → views}/dialog-header.stories.tsx +3 -4
  41. package/src/components/dialog/views/dialog-header.tsx +61 -0
  42. package/src/components/icons/components/add.tsx +14 -14
  43. package/src/components/icons/components/alert-solid.tsx +36 -0
  44. package/src/components/icons/components/alert-square-solid.tsx +36 -0
  45. package/src/components/icons/components/info-solid.tsx +40 -0
  46. package/src/components/icons/components/info.tsx +36 -0
  47. package/src/components/icons/components/question-solid.tsx +36 -0
  48. package/src/components/icons/components/success-solid.tsx +36 -0
  49. package/src/components/icons/components/warn-solid.tsx +36 -0
  50. package/src/components/icons/icon.stories.tsx +42 -0
  51. package/src/components/icons/icon.tsx +57 -41
  52. package/src/components/icons/index.ts +36 -29
  53. package/src/components/ui.tsx +28 -25
  54. package/src/decorators/instructions.tsx +44 -0
  55. package/src/hooks/useDialogClickHandler.ts +26 -0
  56. package/src/index.scss +23 -22
  57. package/src/sass/_globals.scss +7 -1
  58. package/src/styles/alert/alert.css +68 -0
  59. package/src/styles/alert/alert.css.map +1 -0
  60. package/src/styles/badge/badge.css +3 -3
  61. package/src/styles/details/details.css +14 -1
  62. package/src/styles/details/details.css.map +1 -1
  63. package/src/styles/dialog/dialog.css +28 -13
  64. package/src/styles/dialog/dialog.css.map +1 -1
  65. package/src/styles/index.css +121 -28
  66. package/src/styles/index.css.map +1 -1
  67. package/libs/chunk-QHIABQNQ.js +0 -8
  68. package/libs/chunk-QHIABQNQ.js.map +0 -1
  69. package/libs/chunk-ZOHIKF6I.cjs +0 -31
  70. package/libs/chunk-ZOHIKF6I.cjs.map +0 -1
  71. package/libs/components/badge/badge.css +0 -1
  72. package/libs/components/badge/badge.css.map +0 -1
  73. package/libs/components/badge/badge.min.css +0 -3
  74. package/libs/components/breadcrumbs/breadcrumb.css +0 -1
  75. package/libs/components/breadcrumbs/breadcrumb.css.map +0 -1
  76. package/libs/components/breadcrumbs/breadcrumb.min.css +0 -3
  77. package/libs/components/buttons/button.css +0 -1
  78. package/libs/components/buttons/button.css.map +0 -1
  79. package/libs/components/buttons/button.min.css +0 -3
  80. package/libs/components/cards/card-style.css +0 -1
  81. package/libs/components/cards/card-style.css.map +0 -1
  82. package/libs/components/cards/card-style.min.css +0 -3
  83. package/libs/components/cards/card.css +0 -1
  84. package/libs/components/cards/card.css.map +0 -1
  85. package/libs/components/cards/card.min.css +0 -3
  86. package/libs/components/details/details.css +0 -1
  87. package/libs/components/details/details.css.map +0 -1
  88. package/libs/components/details/details.min.css +0 -3
  89. package/libs/components/dialog/dialog.css +0 -1
  90. package/libs/components/dialog/dialog.css.map +0 -1
  91. package/libs/components/dialog/dialog.min.css +0 -3
  92. package/libs/components/form/form.css +0 -1
  93. package/libs/components/form/form.css.map +0 -1
  94. package/libs/components/form/form.min.css +0 -3
  95. package/libs/components/icons/icon.css +0 -1
  96. package/libs/components/icons/icon.css.map +0 -1
  97. package/libs/components/icons/icon.min.css +0 -3
  98. package/libs/components/images/img.css +0 -1
  99. package/libs/components/images/img.css.map +0 -1
  100. package/libs/components/images/img.min.css +0 -3
  101. package/libs/components/layout/landmarks.css +0 -1
  102. package/libs/components/layout/landmarks.css.map +0 -1
  103. package/libs/components/layout/landmarks.min.css +0 -3
  104. package/libs/components/link/link.css +0 -1
  105. package/libs/components/link/link.css.map +0 -1
  106. package/libs/components/link/link.min.css +0 -3
  107. package/libs/components/nav/nav.css +0 -1
  108. package/libs/components/nav/nav.css.map +0 -1
  109. package/libs/components/nav/nav.min.css +0 -3
  110. package/libs/components/progress/progress.css +0 -1
  111. package/libs/components/progress/progress.css.map +0 -1
  112. package/libs/components/progress/progress.min.css +0 -3
  113. package/libs/components/styles/index.css +0 -1
  114. package/libs/components/styles/index.css.map +0 -1
  115. package/libs/components/styles/index.min.css +0 -3
  116. package/libs/components/tag/tag.css +0 -1
  117. package/libs/components/tag/tag.css.map +0 -1
  118. package/libs/components/tag/tag.min.css +0 -3
  119. package/libs/components/text-to-speech/text-to-speech.css +0 -1
  120. package/libs/components/text-to-speech/text-to-speech.css.map +0 -1
  121. package/libs/components/text-to-speech/text-to-speech.min.css +0 -3
  122. package/libs/index.css +0 -1
  123. package/libs/index.css.map +0 -1
  124. package/src/components/alert-dialog/alert-dialog.stories.tsx +0 -35
  125. package/src/components/alert-dialog/alert-dialog.tsx +0 -76
  126. package/src/components/dialog/view/dialog-header.tsx +0 -32
@@ -0,0 +1,84 @@
1
+ import { Meta } from "@storybook/blocks";
2
+
3
+ <Meta title="ACSS UI" />
4
+
5
+ # UI Component
6
+
7
+ A lightweight polymorphic component that serves as a foundation for building
8
+ flexible UI elements.
9
+
10
+ ## Features
11
+
12
+ - Polymorphic component that can render as any HTML element
13
+ - Type-safe props with TypeScript
14
+ - Supports custom styling through CSS properties and classes
15
+ - Forward ref support
16
+ - Lightweight and performant
17
+
18
+ ## Props
19
+
20
+ | Prop | Type | Description |
21
+ | -------- | ------------------- | ------------------------------------- |
22
+ | as | React.ElementType | HTML element to render (default: div) |
23
+ | styles | React.CSSProperties | Inline styles object |
24
+ | classes | string | CSS class names |
25
+ | children | React.ReactNode | Child elements |
26
+ | ...props | any | All valid HTML attributes |
27
+
28
+ ## Technical Details
29
+
30
+ The component uses advanced TypeScript features to ensure type safety:
31
+
32
+ - Polymorphic refs
33
+ - Component props with proper type inference
34
+ - Props omission to avoid conflicts
35
+
36
+ ## Usage Examples
37
+
38
+ ### Basic Usage
39
+
40
+ ```tsx
41
+ import UI from '#components/ui'
42
+
43
+ // Render as a div (default)
44
+ <UI classes="my-class">Content</UI>
45
+
46
+ // Render as a button
47
+ <UI as="button" classes="btn">Click me</UI>
48
+
49
+ // With custom styles
50
+ <UI
51
+ as="section"
52
+ styles={{ padding: "1rem", background: "#f0f0f0" }}
53
+ >
54
+ Section content
55
+ </UI>
56
+ ```
57
+
58
+ ### Advanced Usage
59
+
60
+ ```tsx
61
+ import UI from "#components/ui";
62
+
63
+ // With ref forwarding
64
+ const MyComponent = () => {
65
+ const ref = useRef<HTMLDivElement>(null);
66
+
67
+ return (
68
+ <UI
69
+ ref={ref}
70
+ as="div"
71
+ styles={{ position: "relative" }}
72
+ classes="container"
73
+ >
74
+ Custom component
75
+ </UI>
76
+ );
77
+ };
78
+ ```
79
+
80
+ ## Additional Notes
81
+
82
+ - The component automatically merges default styles with custom styles
83
+ - TypeScript will provide proper type hints for element-specific props
84
+ - Use the `as` prop to change the rendered element while maintaining type safety
@@ -0,0 +1,86 @@
1
+ import { Meta } from "@storybook/blocks";
2
+
3
+ # Alert Component
4
+
5
+ ## Summary
6
+
7
+ The Alert component is used to display important messages to users. It can be
8
+ dismissible and supports various interaction tests.
9
+
10
+ ## Features
11
+
12
+ - Display alert messages
13
+ - Dismissible option
14
+ - Customizable title and content
15
+ - Interaction testing support
16
+
17
+ ## Props
18
+
19
+ | Prop | Type | Description |
20
+ | ------------- | ----------- | ----------------------------------------- |
21
+ | `title` | `string` | The title of the alert |
22
+ | `children` | `ReactNode` | The content of the alert |
23
+ | `dismissible` | `boolean` | Whether the alert can be dismissed |
24
+ | `onDismiss` | `function` | Callback function when alert is dismissed |
25
+ | `open` | `boolean` | Whether the alert is visible |
26
+ | `className` | `string` | Additional CSS classes for the alert |
27
+
28
+ ## Technical Details
29
+
30
+ The Alert component is built using React functional components and hooks. It
31
+ supports interaction testing using Storybook.
32
+
33
+ ## Usage Example
34
+
35
+ ### Basic Usage
36
+
37
+ ```tsx
38
+ import React from "react";
39
+ import Alert from "./alert";
40
+
41
+ const App = () => (
42
+ <Alert
43
+ title="Alert Title"
44
+ dismissible={true}
45
+ onDismiss={() => console.log("Alert dismissed")}
46
+ >
47
+ This is an alert message
48
+ </Alert>
49
+ );
50
+
51
+ export default App;
52
+ ```
53
+
54
+ ### Advanced Usage
55
+
56
+ ```tsx
57
+ import React, { useState } from "react";
58
+ import Alert from "./alert";
59
+
60
+ const App = () => {
61
+ const [isOpen, setIsOpen] = useState(true);
62
+
63
+ return (
64
+ <div>
65
+ <button onClick={() => setIsOpen(!isOpen)}>Toggle Alert</button>
66
+ {isOpen && (
67
+ <Alert
68
+ title="Advanced Alert"
69
+ dismissible={true}
70
+ onDismiss={() => setIsOpen(false)}
71
+ >
72
+ This is an advanced alert message
73
+ </Alert>
74
+ )}
75
+ </div>
76
+ );
77
+ };
78
+
79
+ export default App;
80
+ ```
81
+
82
+ ### Additional Notes
83
+
84
+ - Ensure to handle the `onDismiss` callback to manage the alert's visibility
85
+ state.
86
+ - Customize the alert's appearance using the `className` prop.
@@ -0,0 +1,74 @@
1
+ import { Meta } from "@storybook/blocks";
2
+
3
+ <Meta title="FP.REACT Components/Alert/Readme" />
4
+
5
+ # Alert Component
6
+
7
+ ## Summary
8
+
9
+ The `Alert` component is a customizable component for displaying status messages
10
+ with different severity levels. It supports multiple severity types (default,
11
+ info, success, warning, error) and can include optional titles and dismissal
12
+ functionality.
13
+
14
+ ## Features
15
+
16
+ - Multiple severity levels with matching visual indicators
17
+ - Optional title and dismissible states
18
+ - Accessible by default with appropriate ARIA attributes
19
+ - Customizable icons through `iconProps`
20
+
21
+ ## Props
22
+
23
+ ```tsx
24
+ export type AlertProps = {
25
+ open: boolean;
26
+ severity?: "default" | "info" | "success" | "warning" | "error";
27
+ children: React.ReactNode;
28
+ title?: string;
29
+ dismissible?: boolean;
30
+ onDismiss?: () => void;
31
+ iconProps?: IconProps;
32
+ } & React.ComponentProps<typeof UI>;
33
+ ```
34
+
35
+ ## Technical Details
36
+
37
+ The `Alert` component uses the `UI` component for rendering and supports various
38
+ severity levels with corresponding ARIA attributes for accessibility. It also
39
+ allows for custom icons through the `iconProps` prop.
40
+
41
+ ## Usage Example
42
+
43
+ ### Basic Usage
44
+
45
+ ```tsx
46
+ import Alert from "#components/alert";
47
+
48
+ <Alert open={true} severity="info">
49
+ This is an info alert.
50
+ </Alert>;
51
+ ```
52
+
53
+ ### Advanced Usage
54
+
55
+ ```tsx
56
+ import Alert from "#components/alert";
57
+
58
+ <Alert
59
+ open={true}
60
+ severity="error"
61
+ title="Error"
62
+ dismissible={true}
63
+ onDismiss={() => console.log("Alert dismissed")}
64
+ iconProps={{ fill: "#000", size: 24 }}
65
+ >
66
+ This is an error alert with a custom icon.
67
+ </Alert>;
68
+ ```
69
+
70
+ ### Additional Notes
71
+
72
+ - The `Alert` component is designed to be accessible by default.
73
+ - The `dismissible` prop allows the alert to be dismissed by the user.
74
+ - Custom icons can be provided through the `iconProps` prop.
@@ -0,0 +1,80 @@
1
+ [role="alert"] {
2
+ /* Success colors */
3
+ --alert-success-bg: #e6f4ea;
4
+ --alert-success-border: #34a853;
5
+ --alert-success-text: #1e4620;
6
+
7
+ /* Error colors */
8
+ --alert-error-bg: #fdeded;
9
+ --alert-error-border: #d32f2f;
10
+ --alert-error-text: #5f2120;
11
+
12
+ /* Warning colors */
13
+ --alert-warning-bg: #fff4e5;
14
+ --alert-warning-border: #ff9800;
15
+ --alert-warning-text: #663c00;
16
+
17
+ /* Info colors */
18
+ --alert-info-bg: #e5f6fd;
19
+ --alert-info-border: #0288d1;
20
+ --alert-info-text: #084154;
21
+
22
+ --alert-border: thin solid currentColor;
23
+
24
+ background-color: var(--alert-bg, whitesmoke);
25
+ border: var(--alert-border, currentColor);
26
+ color: var(--alert-color, currentColor);
27
+ padding: var(--alert-padding, var(--spc-4));
28
+ margin-block-end: var(--alert-margin-block-end);
29
+ font-size: var(--fs-0);
30
+ line-height: 1.6;
31
+ display: flex;
32
+ flex-direction: row;
33
+ // align-items: center;
34
+ border-radius: var(--alert-border-radius, var(--border-radius));
35
+ border: var(--alert-border);
36
+ gap: var(--alert-gap, var(--spc-4));
37
+ div {
38
+ margin-block-start: 0;
39
+ align-items: center;
40
+ }
41
+
42
+ .alert-message {
43
+ flex: 2;
44
+ margin-block-start: 0;
45
+ h3 {
46
+ margin-block-end: 0;
47
+ }
48
+ }
49
+
50
+ &[data-alert~="info"] {
51
+ --alert-bg: var(--alert-info-bg);
52
+ --alert-color: var(--alert-info-text);
53
+ border-color: var(--alert-info-border);
54
+ }
55
+
56
+ &[data-alert~="warning"] {
57
+ --alert-bg: var(--alert-warning-bg);
58
+ --alert-color: var(--alert-warning-text);
59
+ border-color: var(--alert-warning-border);
60
+ }
61
+
62
+ &[data-alert~="error"] {
63
+ --alert-bg: var(--alert-error-bg);
64
+ --alert-color: var(--alert-error-text);
65
+ border-color: var(--alert-error-border);
66
+ }
67
+
68
+ &[data-alert~="success"] {
69
+ --alert-bg: var(--alert-success-bg);
70
+ --alert-color: var(--alert-success-text);
71
+ border-color: var(--alert-success-border);
72
+ }
73
+
74
+ button {
75
+ &[data-btn~="icon"] {
76
+ --btn-bg: transparent;
77
+ max-height: fit-content;
78
+ }
79
+ }
80
+ }
@@ -0,0 +1,132 @@
1
+ import { StoryObj, Meta, StoryFn } from "@storybook/react";
2
+ import { within, expect, userEvent, fn } from "@storybook/test";
3
+
4
+ import Alert from "./alert";
5
+ import WithInstructions from "#decorators/instructions.jsx";
6
+ import React from "react";
7
+
8
+ const ButtonDecorator = (Story: StoryFn) => {
9
+ const [isOpen, setIsOpen] = React.useState(false);
10
+ return (
11
+ <div>
12
+ <button onClick={() => setIsOpen(!isOpen)}>Open Alert</button>
13
+ <Story
14
+ args={{
15
+ open: isOpen,
16
+ title: "Alert Title",
17
+ children: "This is an alert message",
18
+ dismissible: false,
19
+ }}
20
+ />
21
+ </div>
22
+ );
23
+ };
24
+
25
+ const instructions = (
26
+ <>
27
+ <p>We are testing the following interactions on the alert:</p>
28
+ <ul>
29
+ <li>Tab through the alert.</li>
30
+ <li>Check if the button gets focused.</li>
31
+ <li>Click the button to dismiss the alert.</li>
32
+ <li>Check that the alert is no longer in the document.</li>
33
+ </ul>
34
+ </>
35
+ );
36
+
37
+ const meta: Meta<typeof Alert> = {
38
+ title: "FP.REACT Components/Alert",
39
+ component: Alert,
40
+ tags: ["beta"],
41
+ parameters: {
42
+ docs: {
43
+ description: {
44
+ component:
45
+ "The Alert component is used to display important messages to users. It can be dismissible and supports various interaction tests",
46
+ },
47
+ },
48
+ },
49
+ args: {
50
+ title: "Alert Title",
51
+ children:
52
+ "The Alert component is used to display important messages to users.",
53
+ dismissible: true,
54
+ onDismiss: () => fn(),
55
+ },
56
+ } as Meta;
57
+
58
+ export default meta;
59
+ type Story = StoryObj<typeof Alert>;
60
+
61
+ export const DefaultAlert: Story = {
62
+ args: {
63
+ open: true,
64
+ },
65
+ play: async ({ canvasElement }) => {
66
+ const canvas = within(canvasElement);
67
+ expect(canvas.getByText(/this is an alert message/i)).toBeInTheDocument();
68
+ },
69
+ } as Story;
70
+
71
+ export const SuccessAlert: Story = {
72
+ args: {
73
+ open: true,
74
+ severity: "success",
75
+ },
76
+ } as Story;
77
+
78
+ export const WarningAlert: Story = {
79
+ args: {
80
+ open: true,
81
+ severity: "warning",
82
+ },
83
+ } as Story;
84
+
85
+ export const ErrorAlert: Story = {
86
+ args: {
87
+ open: true,
88
+ severity: "error",
89
+ },
90
+ } as Story;
91
+
92
+ export const InfoAlert: Story = {
93
+ args: {
94
+ open: true,
95
+ severity: "info",
96
+ },
97
+ } as Story;
98
+
99
+ export const OpenAlert: Story = {
100
+ decorators: [ButtonDecorator],
101
+ } as Story;
102
+
103
+ export const InteractionTest: Story = {
104
+ args: {
105
+ open: true,
106
+ className: "my alert",
107
+ },
108
+ decorators: [WithInstructions(instructions, "Alert interactions test:")],
109
+ play: async ({ canvasElement, step }) => {
110
+ const canvas = within(canvasElement);
111
+ const alert = canvas.getByRole("alert");
112
+ const dismissButton = canvas.getByRole("button", { name: /close alert/i });
113
+ await step(
114
+ "Check that the alert and button are in the document",
115
+ async () => {
116
+ expect(alert).toBeInTheDocument();
117
+ expect(dismissButton).toBeInTheDocument();
118
+ }
119
+ );
120
+ // await step(
121
+ // "Tab through the alert and check if the button gets focused",
122
+ // async () => {
123
+ // userEvent.tab({ delay: 500 });
124
+ // expect(dismissButton).toHaveFocus();
125
+ // }
126
+ // );
127
+ await step("Click the button to dismiss the alert", async () => {
128
+ await userEvent.click(dismissButton, { delay: 500 });
129
+ expect(alert).not.toBeInTheDocument();
130
+ });
131
+ },
132
+ } as Story;
@@ -0,0 +1,154 @@
1
+ import React from "react";
2
+ import UI from "#components/ui";
3
+ import Icon from "#components/icons/icon";
4
+ import { IconProps } from "#components/icons/types";
5
+ import DismissButton from "./elements/dismiss-button";
6
+
7
+ // First, define a type for the valid severity values
8
+ type Severity = "default" | "info" | "success" | "warning" | "error";
9
+
10
+ /**
11
+ * Props for the Alert component.
12
+ */
13
+ export type AlertProps = {
14
+ /**
15
+ * Whether the alert is open.
16
+ */
17
+ open: boolean;
18
+ /**
19
+ * The severity level of the alert.
20
+ * @default "default"
21
+ */
22
+ severity?: Severity;
23
+ /**
24
+ * The main message content.
25
+ */
26
+ children: React.ReactNode;
27
+ /**
28
+ * Optional title for the alert.
29
+ */
30
+ title?: string;
31
+ /**
32
+ * Whether the alert can be dismissed.
33
+ * @default false
34
+ */
35
+ dismissible?: boolean;
36
+ /**
37
+ * Callback when alert is dismissed.
38
+ */
39
+ onDismiss?: () => void;
40
+
41
+ /**
42
+ * Size of the icon in pixels.
43
+ * @default 32
44
+ */
45
+ iconSize?: number;
46
+
47
+ /**
48
+ * Additional props to pass to the Icon component.
49
+ */
50
+ iconProps?: IconProps;
51
+ } & React.ComponentProps<typeof UI>;
52
+
53
+ /**
54
+ * Alert is a customizable component for displaying status messages with different severity levels.
55
+ * It supports multiple severity types (default, info, success, warning, error) and can include
56
+ * optional titles and dismissal functionality.
57
+ *
58
+ * Features:
59
+ * - Multiple severity levels with matching visual indicators
60
+ * - Optional title and dismissible states
61
+ * - Accessible by default with appropriate ARIA attributes
62
+ * - Customizable icons through iconProps
63
+ *
64
+ * @example
65
+ * ```tsx
66
+ * <Alert
67
+ * open={true}
68
+ * severity="info"
69
+ * title="Optional Title"
70
+ * dismissible={true}
71
+ * onDismiss={() => console.log('Alert dismissed')}
72
+ * >
73
+ * Alert message content
74
+ * </Alert>
75
+ * ```
76
+ *
77
+ * @see {@link AlertProps} for available configuration options
78
+ */ const Alert: React.FC<AlertProps> = ({
79
+ open,
80
+ severity = "default",
81
+ children,
82
+ title,
83
+ dismissible = false,
84
+ onDismiss,
85
+ iconSize,
86
+ iconProps,
87
+ ...props
88
+ }) => {
89
+ const [isVisible, setIsVisible] = React.useState(open);
90
+
91
+ React.useEffect(() => {
92
+ setIsVisible(open);
93
+ }, [open]);
94
+
95
+ if (!isVisible) return null;
96
+
97
+ const handleDismiss = (): void => {
98
+ setIsVisible(false);
99
+ onDismiss?.();
100
+ };
101
+
102
+ /**
103
+ * Default props for the Icon component used in the Alert component.
104
+ * These props set the fill color to white and the size to 32 pixels.
105
+ */
106
+ const defaultIconProps: IconProps = {
107
+ size: iconSize || 32,
108
+ };
109
+
110
+ // Update the severityType object with the type
111
+ const severityType: Record<Severity, "polite" | "assertive"> = {
112
+ default: "polite",
113
+ info: "polite",
114
+ success: "polite",
115
+ warning: "polite",
116
+ error: "assertive",
117
+ } as const;
118
+
119
+ const mergedIconProps = { ...defaultIconProps, ...iconProps };
120
+
121
+ // Update the severityIcons object with the type
122
+ const severityIcons: Record<Severity, JSX.Element> = {
123
+ info: <Icon.InfoSolid {...mergedIconProps} />,
124
+ success: <Icon.SuccessSolid {...mergedIconProps} />,
125
+ warning: <Icon.WarnSolid {...mergedIconProps} />,
126
+ error: <Icon.AlertSolid {...mergedIconProps} />,
127
+ default: <Icon.AlertSquareSolid {...mergedIconProps} />,
128
+ };
129
+
130
+ return (
131
+ <UI
132
+ as="div"
133
+ role="alert"
134
+ aria-live={severityType[severity]}
135
+ aria-atomic="true"
136
+ className={`alert alert-${severity}`}
137
+ data-alert={severity}
138
+ {...props}
139
+ >
140
+ <UI aria-hidden="true">{severityIcons[severity]}</UI>
141
+ <UI as="div" className="alert-message">
142
+ {title && (
143
+ <UI as="h3" className="alert-title">
144
+ {title}
145
+ </UI>
146
+ )}
147
+ <UI as="div">{children}</UI>
148
+ </UI>
149
+ {dismissible && <DismissButton onDismiss={handleDismiss} />}
150
+ </UI>
151
+ );
152
+ };
153
+ export default Alert;
154
+ Alert.displayName = "Alert";
@@ -0,0 +1,77 @@
1
+ import { Meta } from "@storybook/blocks";
2
+
3
+ <Meta title="FP.REACT Elements/DismissButton/Readme" />
4
+
5
+ # DismissButton
6
+
7
+ ## Summary
8
+
9
+ The `DismissButton` component is a reusable button designed to dismiss alerts.
10
+ It includes an icon and an optional callback function for handling dismiss
11
+ actions.
12
+
13
+ ## Features
14
+
15
+ - Customizable icon size
16
+ - Callback function for dismiss actions
17
+ - Accessible with `aria-label`
18
+
19
+ ## Props
20
+
21
+ | Name | Type | Default | Description |
22
+ | ----------- | ------------ | ------- | ------------------------------------------------ |
23
+ | `onDismiss` | `() => void` | - | Callback function when dismiss button is clicked |
24
+ | `iconSize` | `number` | `16` | Size of the close icon in pixels |
25
+
26
+ ## Technical Details
27
+
28
+ The `DismissButton` component uses the `Button` and `Icon` components from the
29
+ `#components` library. It is memoized using `React.memo` for performance
30
+ optimization.
31
+
32
+ ## Usage Example
33
+
34
+ ### Basic Usage
35
+
36
+ ```tsx
37
+ import React from "react";
38
+ import DismissButton from "#components/alert/elements/dismiss-button";
39
+
40
+ const handleDismiss = () => {
41
+ console.log("Alert dismissed");
42
+ };
43
+
44
+ const AlertComponent = () => (
45
+ <div className="alert">
46
+ <span>Alert message</span>
47
+ <DismissButton onDismiss={handleDismiss} />
48
+ </div>
49
+ );
50
+
51
+ export default AlertComponent;
52
+ ```
53
+
54
+ ### Advanced Usage
55
+
56
+ ```tsx
57
+ import React from "react";
58
+ import DismissButton from "#components/alert/elements/dismiss-button";
59
+
60
+ const handleDismiss = () => {
61
+ // Custom logic for dismissing the alert
62
+ };
63
+
64
+ const CustomAlert = () => (
65
+ <div className="custom-alert">
66
+ <span>Custom alert message</span>
67
+ <DismissButton onDismiss={handleDismiss} iconSize={24} />
68
+ </div>
69
+ );
70
+
71
+ export default CustomAlert;
72
+ ```
73
+
74
+ ## Additional Notes
75
+
76
+ - Ensure the `onDismiss` callback is provided to handle the dismiss action.
77
+ - The `iconSize` prop can be adjusted to fit the design requirements.