-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Alert component #3982
Alert component #3982
Conversation
…per, adding isCloseable prop
🦋 Changeset detectedLatest commit: 740e07d The changes in this PR will be included in the next version bump. This PR includes changesets to release 3 packages
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
WalkthroughThis pull request introduces a new Changes
Possibly related PRs
Suggested labels
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 19
🧹 Outside diff range and nitpick comments (35)
.changeset/poor-sheep-repair.md (1)
1-6
: LGTM with a suggestion for the commit message.The patch version bumps are appropriate for introducing a new component. However, consider enhancing the commit message to be more descriptive about the changes.
Consider this format for the commit message:
-introduced Alert component (#2250) +feat: introduce Alert component with various styles and controlled visibility (#2250) + +- Add new Alert component with multiple variants (solid, bordered, flat) +- Support custom styling and icon integration +- Include comprehensive documentation and testsapps/docs/content/components/alert/usage.ts (1)
1-12
: Consider enhancing the example to showcase more Alert features.The current example is quite basic. Consider demonstrating more Alert capabilities such as:
- Different variants (success, warning, error)
- Custom icons
- Dismissible alerts
- Different sizes
Example enhancement:
const App = `import {Alert} from "@nextui-org/react"; export default function App() { - const title = "This is an alert"; - const description = "Thanks for subscribing to our newsletter!"; - return ( <div className="flex items-center justify-center w-full"> - <Alert title={title} description={description} /> + <Alert + variant="success" + title="Success!" + description="Thanks for subscribing to our newsletter!" + icon={<CheckCircleIcon />} + isCloseable + /> </div> ); }`;apps/docs/content/components/alert/variants.ts (1)
1-17
: Enhance Alert examples with more meaningful content and variations.While the current examples demonstrate the different variants well, consider enhancing them with:
- Real-world content that shows typical use cases
- Different colors/types (success, warning, error)
- Icons or actions to showcase full component capabilities
const App = `import {Alert} from "@nextui-org/react"; export default function App() { return ( <div className="flex flex-col gap-4 w-full"> - <Alert variant="solid"> - A solid variant alert + <Alert variant="solid" color="success"> + Your profile has been successfully updated! </Alert> - <Alert variant="bordered"> - A bordered variant alert + <Alert variant="bordered" color="warning"> + Your session is about to expire in 5 minutes. </Alert> - <Alert variant="flat"> - A flat variant alert + <Alert variant="flat" color="error"> + Failed to save changes. Please try again. </Alert> </div> ); }`;apps/docs/content/components/alert/radius.ts (2)
1-18
: Enhance the example's type safety and accessibility.Consider the following improvements:
- Add type safety by explicitly typing the radius values
- Enhance accessibility with ARIA labels
- Include more meaningful content in the alerts
-const App = `import {Alert} from "@nextui-org/react"; +const App = `import {Alert} from "@nextui-org/react"; +type RadiusType = "none" | "sm" | "md" | "lg" | "full"; export default function App() { return ( <div className="flex items-center justify-center w-full"> <div className="flex flex-col w-full"> - {["none", "sm", "md", "lg", "full"].map((radius) => ( + {["none", "sm", "md", "lg", "full"].map((radius: RadiusType) => ( <div key={radius} className="w-full flex items-center my-3"> <Alert radius={radius} - title={\`This is a \${radius} radius alert\`} + title={\`Alert with \${radius} radius\`} + description="This is a description of what the alert is about." + aria-label={\`Alert example with \${radius} border radius\`} /> </div> ))} </div> </div> ); }`;
20-26
: Update file extension and simplify exports.The file extension in the key should match the TypeScript code, and the export structure can be simplified.
const react = { - "/App.jsx": App, + "/App.tsx": App, }; -export default { - ...react, -}; +export default react;apps/docs/content/components/alert/colors.ts (1)
7-14
: Consider extracting the colors array as a constant.The colors array could be extracted as a named constant for better maintainability and reusability. This would also make it easier to document the available color options.
- {["default", "primary", "secondary", "success", "warning", "danger"].map((color) => ( + const ALERT_COLORS = ["default", "primary", "secondary", "success", "warning", "danger"] as const; + {ALERT_COLORS.map((color) => (packages/utilities/shared-icons/src/success.tsx (2)
3-16
: Consider memoizing the component for performance optimization.While the current implementation is correct, consider memoizing the component using React.memo since it's a purely presentational component that renders the same output given the same props.
-export const SuccessIcon = ( +export const SuccessIcon = React.memo(( props: IconSvgProps & { className?: string; }, -) => { +)) => {
9-25
: Consider making the fill attribute configurable.The SVG currently has a hardcoded
fill="none"
attribute. Consider making this configurable through props to allow for different styling needs in various contexts (e.g., dark mode, different color schemes).<svg - fill="none" + fill={props.fill || "none"} height="24" viewBox="0 0 24 24" width="24"Also, consider adding aria-label for better accessibility:
<svg fill="none" height="24" viewBox="0 0 24 24" width="24" + aria-label="success icon" xmlns="http://www.w3.org/2000/svg"
apps/docs/content/components/alert/custom-styles.ts (1)
8-25
: Consider accessibility and interaction improvements.While the styling looks good, there are a few suggestions for improvement:
- Add appropriate ARIA attributes for better accessibility
- Either remove the
cursor-pointer
or add an interaction handler- Consider using a more specific shadow class (e.g.,
shadow-sm
,shadow-md
)<Alert title={title} description={description} + role="alert" classNames={{ base: [ "bg-background", "border", "border-foreground-400", - "shadow", + "shadow-md", "hover:bg-slate-200", - "cursor-pointer", ], title: ["text-base", "text-foreground", "font-semibold"], description: ["text-base", "text-foreground-600"], }} />apps/docs/content/components/alert/controlled.ts (2)
1-2
: Add missing React import statementThe code uses React (useState) but doesn't import it. While this might work in certain environments, it's better to be explicit about dependencies.
-const App = `import {Alert, Button} from "@nextui-org/react"; +const App = `import React from "react"; +import {Alert, Button} from "@nextui-org/react";
3-8
: Consider moving constants outside the componentThe title and description constants are recreated on each render. For better performance, consider moving them outside the component since they don't depend on component state or props.
+const ALERT_TITLE = "Success Notification"; +const ALERT_DESCRIPTION = "Your action has been completed successfully. We'll notify you when updates are available."; export default function App() { const [isVisible, setIsVisible] = React.useState(true); - - const title = "Success Notification"; - const description = "Your action has been completed successfully. We'll notify you when updates are available.";packages/core/theme/src/components/index.ts (1)
41-41
: Consider maintaining alphabetical order of exportsThe new alert export should be placed between "accordion" and "autocomplete" exports to maintain the alphabetical ordering pattern used in this file.
export * from "./accordion"; +export * from "./alert"; export * from "./autocomplete"; -export * from "./alert";packages/utilities/shared-icons/src/info-circle.tsx (1)
3-16
: Consider making dimensions configurable.The height and width are hardcoded to 24 units. Consider making these configurable through props while maintaining the aspect ratio.
export const InfoCircleIcon = ( props: IconSvgProps & { className?: string; + size?: number; }, ) => { + const size = props.size || 24; return ( <svg fill="none" - height="24" + height={size} viewBox="0 0 24 24" - width="24" + width={size} xmlns="http://www.w3.org/2000/svg" {...props} >packages/utilities/shared-icons/src/danger.tsx (1)
9-16
: Add accessibility attributes and consider flexible dimensionsThe SVG implementation could be improved for accessibility and flexibility:
- Add aria-label for screen readers
- Consider making dimensions configurable via props
Consider applying these changes:
<svg fill="none" - height="20" - width="20" + height={props.height || "20"} + width={props.width || "20"} viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg" + aria-label="danger icon" + role="img" {...props} >apps/docs/content/components/alert/with-icon.ts (1)
42-46
: Consider enhancing the example to showcase more Alert features.While the example effectively demonstrates icon usage, it could be more educational by showing additional Alert properties.
Consider expanding the example:
export default function App() { return ( - <Alert icon={<UserIcon />}>An alert with a custom icon</Alert> + <Alert + icon={<UserIcon />} + variant="bordered" + className="max-w-md" + > + An alert with a custom icon and additional styling + </Alert> ); }packages/components/alert/package.json (2)
40-45
: Verify peer dependency version constraintsThe peer dependencies specify minimum versions but don't set upper bounds. This could lead to compatibility issues with future major versions. Consider adding upper bounds using the
^
or~
version range syntax."peerDependencies": { - "react": ">=18", - "react-dom": ">=18", - "@nextui-org/theme": ">=2.1.0", - "@nextui-org/system": ">=2.0.0" + "react": "^18.0.0", + "react-dom": "^18.0.0", + "@nextui-org/theme": "^2.1.0", + "@nextui-org/system": "^2.0.0" },
16-19
: Consider adding source maps to distributionThe files array only includes the "dist" directory. Consider adding source maps to help with debugging in development environments.
"files": [ - "dist" + "dist", + "dist/*.map" ],packages/components/alert/src/alert.tsx (3)
17-23
: Consider enhancing type safety for iconMapThe iconMap could benefit from stricter typing to ensure type safety across the component.
Consider this improvement:
-const iconMap = { +const iconMap: Record<AlertColor, React.FC<React.SVGProps<SVGSVGElement>>> = { primary: InfoCircleIcon, secondary: InfoCircleIcon, success: SuccessIcon, warning: WarningIcon, danger: DangerIcon, } as const;
27-29
: Document the reason for omitting hasDescriptionThe interface omits 'hasDescription' from UseAlertProps, but the reasoning isn't clear.
Consider adding a JSDoc comment explaining why this property is omitted:
+/** + * Props for the Alert component. + * Extends UseAlertProps but omits hasDescription as it's handled internally + * based on the description prop. + */ export interface AlertProps extends Omit<UseAlertProps, "hasDescription"> { color: AlertColor; }
64-75
: Improve close button accessibility and error handlingThe close button implementation could be enhanced in several ways:
- More descriptive aria-label
- Add error boundary for custom icon rendering
- Make icon dimensions customizable
{(isClosable || onClose) && ( <Button isIconOnly - aria-label="Close" + aria-label={`Close ${title || 'alert'}`} radius="full" variant="light" onClick={handleClose} {...(getCloseButtonProps() as ButtonProps)} > - <CloseIcon height={20} width={20} /> + <CloseIcon + height={getCloseButtonProps()?.iconSize ?? 20} + width={getCloseButtonProps()?.iconSize ?? 20} + /> </Button> )}packages/components/alert/__tests__/alert.test.tsx (2)
1-8
: Consider using @testing-library/user-event for button interactionsWhile using
click()
works,@testing-library/user-event
provides a more comprehensive simulation of user interactions, including keyboard events and focus handling.import * as React from "react"; -import {act, render} from "@testing-library/react"; +import {act, render} from "@testing-library/react"; +import userEvent from "@testing-library/user-event";
16-22
: Strengthen ref test with specific element assertionsConsider adding assertions to verify the correct element type and attributes are forwarded to the ref.
it("ref should be forwarded", () => { const ref = React.createRef<HTMLDivElement>(); render(<Alert ref={ref} description={description} title={title} />); expect(ref.current).not.toBeNull(); + expect(ref.current).toBeInstanceOf(HTMLDivElement); + expect(ref.current).toHaveAttribute("role", "alert"); });apps/docs/content/docs/components/alert.mdx (3)
23-23
: Consider removing the CLI version tagThe
@latest
tag in the CLI command might become outdated. Consider removing it or documenting version compatibility requirements.- cli: "npx nextui-cli@latest add alert", + cli: "npx nextui-cli add alert",
76-80
: Consider adding a preview for custom implementationThe custom implementation section has
showPreview={false}
. Consider adding a preview to help users understand the expected outcome of using theuseAlert
hook.
95-99
: Enhance accessibility documentationConsider adding more detailed accessibility information:
- Keyboard interaction patterns
- Screen reader announcements
- ARIA attributes behavior
- Focus management
packages/components/alert/stories/alert.stories.tsx (6)
8-45
: Add TypeScript types to improve type safety.The Storybook configuration would benefit from proper TypeScript types for the
args
parameter and control options.- argTypes: { + type AlertStoryArgs = { + color: "default" | "primary" | "secondary" | "success" | "warning" | "danger"; + variant: "solid" | "flat" | "bordered"; + radius: "none" | "sm" | "md" | "lg" | "full"; + isClosable: boolean; + }; + + argTypes: {Also, consider adding accessibility-related controls such as
role
andaria-live
to match common alert component patterns.
36-44
: Reconsider the full-screen decorator layout.The current decorator uses
w-screen h-screen
which might cause layout issues in the documentation. Consider using relative units or a more contained layout.- <div className="flex items-center justify-center w-screen h-screen"> + <div className="flex items-center justify-center min-h-[400px] w-full">
54-88
: Reduce code duplication in template components.The ColorTemplate and RadiusTemplate share similar structure. Consider creating a reusable higher-order component.
+ const createVariationTemplate = (variations: string[], getProps: (variation: string) => object) => { + return (args: any) => ( + <div className="flex flex-col w-full"> + {variations.map((variation) => ( + <div key={variation} className="w-full flex items-center my-3"> + <Alert {...args} {...getProps(variation)} /> + </div> + ))} + </div> + ); + }; + + const ColorTemplate = createVariationTemplate( + ["default", "primary", "secondary", "success", "warning", "danger"], + (color) => ({ color, title: `This is a ${color} alert` }) + );
90-104
: Enhance state management in CloseableTemplate.Consider using a more robust state management approach and add error boundaries.
const CloseableTemplate = (args) => { const [isVisible, setIsVisible] = React.useState(true); + const [error, setError] = React.useState<Error | null>(null); + + const handleClose = React.useCallback(() => { + try { + setIsVisible(false); + } catch (err) { + setError(err as Error); + } + }, []); + + if (error) { + return <div>Error: {error.message}</div>; + } return ( <div className="flex flex-col items-center justify-center gap-4"> {isVisible ? ( - <Alert {...args} isClosable isVisible={isVisible} onClose={() => setIsVisible(false)} /> + <Alert {...args} isClosable isVisible={isVisible} onClose={handleClose} />
106-173
: Add documentation to story exports.Consider adding parameters to document each story's purpose and usage.
export const Default = { render: Template, args: { ...defaultProps, }, + parameters: { + docs: { + description: { + story: 'Basic usage of the Alert component with default configuration.', + }, + }, + }, };
175-192
: Use theme tokens instead of hardcoded values.The CustomWithClassNames story uses hardcoded color values. Consider using theme tokens for better maintainability.
base: [ "bg-background", "border", "border-foreground-400", "shadow", - "hover:bg-slate-200", + "hover:bg-default-200", "cursor-pointer", ],apps/docs/config/routes.json (2)
147-153
: LGTM! Consider enhancing keywords for better searchability.The Alert component route is correctly positioned and well-structured. The configuration follows the established patterns.
Consider expanding keywords to include more search terms:
- "keywords": "alert, notification, message", + "keywords": "alert, notification, message, banner, toast, warning, error, success, info",
Documentation files need update indicators for marked components
The documentation files exist but lack clear update indicators or recent change markers for components marked as "updated" in routes.json. This inconsistency should be addressed:
- None of the examined MDX files contain visible update dates, changelog entries, or version indicators in their frontmatter
- The "updated" flag in routes.json suggests recent changes, but the documentation content doesn't reflect this status
- Documentation readers have no way to identify what has changed in these supposedly updated components
🔗 Analysis chain
Line range hint
1-720
: Verify documentation synchronization for updated components.The configuration shows a coordinated update pattern, particularly for date-related components. Please ensure that all "updated" components have corresponding documentation changes reflected in their MDX files.
Run this script to verify documentation updates:
Let me try another verification approach to check if the documentation files exist and their content has been updated.
Let me try one final verification to check the content of these files directly.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify that MDX files for updated components have recent changes # Test: Check if MDX files for updated components have been modified echo "Checking documentation updates for modified components..." rg -l 'updated": true' | while read -r config_file; do # Extract paths of updated components from the config paths=$(cat "$config_file" | jq -r '.. | objects | select(.updated == true) | .path // empty') # Check if each MDX file exists and has recent changes echo "$paths" | while read -r path; do if [[ -n "$path" ]]; then # Convert /docs/ path to actual file path mdx_file="apps/docs/content/${path#/docs/}" echo "Checking: $mdx_file" git log -1 --pretty=format:"%h - %an, %ar : %s" "$mdx_file" || echo "No recent changes found for $mdx_file" fi done doneLength of output: 6361
Script:
#!/bin/bash # Check if the MDX files exist and look for recent content changes echo "Checking for documentation files and their content..." # First, verify if the files exist fd -e mdx -p "layout|badge|checkbox|skeleton|tabs|tooltip|cli-api|nextui-provider" apps/docs/content # Then check content of existing files for recent updates echo -e "\nChecking file contents for update indicators..." rg -l "updated:|last.*updated|changelog|update" --type mdx -g "*{layout,badge,checkbox,skeleton,tabs,tooltip,cli-api,nextui-provider}*"Length of output: 932
Script:
#!/bin/bash # Check content of the identified documentation files echo "Examining content of documentation files..." for file in \ apps/docs/content/docs/api-references/cli-api.mdx \ apps/docs/content/docs/api-references/nextui-provider.mdx \ apps/docs/content/docs/components/badge.mdx \ apps/docs/content/docs/components/checkbox.mdx \ apps/docs/content/docs/components/skeleton.mdx \ apps/docs/content/docs/components/tabs.mdx \ apps/docs/content/docs/components/tooltip.mdx \ apps/docs/content/docs/customization/layout.mdx do echo "=== $file ===" # Look for update-related content in the frontmatter or first few lines head -n 20 "$file" 2>/dev/null || echo "File not found" doneLength of output: 8052
apps/docs/content/components/alert/custom-impl.ts (1)
134-142
: Remove the unnecessaryreact
object and directly export the components.The
react
object is not needed since the components are already defined and exported individually. Remove the object and update the default export to only include theMyAlert
component.Apply this diff to remove the unnecessary object:
-const react = { - "/App.jsx": App, - "/InfoCircleIcon": InfoCircleIcon, - "/CloseIcon": CloseIcon, -}; - -export default { - ...react, -}; +export default MyAlert;packages/components/alert/src/use-alert.ts (1)
112-115
: Consider adding a null check for onClose.To prevent potential null pointer exceptions, consider adding a null check before invoking the
onClose
callback in thehandleClose
function.const handleClose = useCallback(() => { setIsVisible(false); - onClose?.(); + if (onClose) { + onClose(); + } }, [setIsVisible, onClose]);
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
⛔ Files ignored due to path filters (1)
pnpm-lock.yaml
is excluded by!**/pnpm-lock.yaml
📒 Files selected for processing (31)
.changeset/poor-sheep-repair.md
(1 hunks)apps/docs/config/routes.json
(1 hunks)apps/docs/content/components/alert/colors.ts
(1 hunks)apps/docs/content/components/alert/controlled.ts
(1 hunks)apps/docs/content/components/alert/custom-impl.ts
(1 hunks)apps/docs/content/components/alert/custom-styles.ts
(1 hunks)apps/docs/content/components/alert/index.ts
(1 hunks)apps/docs/content/components/alert/radius.ts
(1 hunks)apps/docs/content/components/alert/usage.ts
(1 hunks)apps/docs/content/components/alert/variants.ts
(1 hunks)apps/docs/content/components/alert/with-icon.ts
(1 hunks)apps/docs/content/components/index.ts
(1 hunks)apps/docs/content/docs/components/alert.mdx
(1 hunks)packages/components/alert/README.md
(1 hunks)packages/components/alert/__tests__/alert.test.tsx
(1 hunks)packages/components/alert/package.json
(1 hunks)packages/components/alert/src/alert.tsx
(1 hunks)packages/components/alert/src/index.ts
(1 hunks)packages/components/alert/src/use-alert.ts
(1 hunks)packages/components/alert/stories/alert.stories.tsx
(1 hunks)packages/components/alert/tsconfig.json
(1 hunks)packages/components/alert/tsup.config.ts
(1 hunks)packages/core/react/package.json
(1 hunks)packages/core/react/src/index.ts
(1 hunks)packages/core/theme/src/components/alert.ts
(1 hunks)packages/core/theme/src/components/index.ts
(1 hunks)packages/utilities/shared-icons/src/danger.tsx
(1 hunks)packages/utilities/shared-icons/src/index.ts
(1 hunks)packages/utilities/shared-icons/src/info-circle.tsx
(1 hunks)packages/utilities/shared-icons/src/success.tsx
(1 hunks)packages/utilities/shared-icons/src/warning.tsx
(1 hunks)
✅ Files skipped from review due to trivial changes (3)
- apps/docs/content/components/alert/index.ts
- packages/components/alert/tsconfig.json
- packages/components/alert/tsup.config.ts
🧰 Additional context used
🪛 LanguageTool
packages/components/alert/README.md
[typographical] ~17-~17: Usually, a comma is necessary before ‘Yes’ at the end of a sentence. Did you mean “, please”?
Context: ...xtui-org/alert ``` ## Contribution Yes please! See the [contributing guidelines](http...
(COMMA_BEFORE_PLEASE)
🔇 Additional comments (42)
packages/components/alert/src/index.ts (4)
1-1
: LGTM! Clean import statement.
The import follows standard practices for React components.
3-4
: LGTM! Clean type export.
Good practice using type-only export for component props.
9-10
: LGTM! Clean component export.
The export is well-organized and follows standard practices.
6-7
: LGTM! Hook export follows React conventions.
The hook export follows React naming conventions and is properly modularized.
Let's verify the hook implementation and usage:
✅ Verification successful
Hook implementation and usage are properly structured and follow React conventions
The verification confirms that:
- The
useAlert
hook follows React composition patterns by utilizing standard React hooks (useCallback
,useMemo
,useControlledState
) - It's properly integrated in the Alert component with correct prop handling
- The hook is well-organized with clear separation of concerns, providing various getter methods for different parts of the alert
- It has proper exports and is being used across documentation and component files
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the useAlert hook implementation and its usage pattern
# Expected: The hook should follow React hooks rules and be used in components
# Check hook implementation
ast-grep --pattern 'export function useAlert() {
$$$
}'
# Check hook usage in components
rg -l 'useAlert'
Length of output: 292
Script:
#!/bin/bash
# Let's check the implementation of useAlert hook and its usage pattern
ast-grep --pattern 'export function useAlert() {
$$$
}'
# Check usage pattern in alert.tsx
rg -A 5 'useAlert' packages/components/alert/src/alert.tsx
# Check if hook follows React rules by using other hooks
rg 'use[A-Z]' packages/components/alert/src/use-alert.ts
Length of output: 1253
apps/docs/content/components/alert/usage.ts (1)
14-20
: LGTM!
The route configuration is well-structured and follows standard practices.
apps/docs/content/components/alert/variants.ts (1)
19-25
: LGTM! Export structure follows documentation system conventions.
The export structure is clean and follows the pattern used for interactive code examples in documentation.
apps/docs/content/components/alert/colors.ts (2)
1-2
: LGTM! Import statement is correct.
The import statement correctly references the Alert component from the main package entry point.
20-26
: LGTM! Export configuration is correct.
The export structure properly maps the component to its documentation path.
packages/utilities/shared-icons/src/success.tsx (1)
1-6
: LGTM! Clean type definition and import.
The component properly imports and extends the IconSvgProps type with an optional className property, following TypeScript best practices.
apps/docs/content/components/alert/custom-styles.ts (2)
1-6
: LGTM! Clear and well-structured component setup.
The component follows React naming conventions and has clear prop definitions.
29-35
: LGTM! Clean export configuration.
The export structure follows the documentation platform's conventions correctly.
apps/docs/content/components/alert/controlled.ts (1)
30-36
: LGTM!
The export configuration is well-structured and follows the documentation example pattern correctly.
packages/utilities/shared-icons/src/info-circle.tsx (1)
1-20
: LGTM! Clean and well-structured implementation.
The component follows React best practices and properly implements an SVG icon with:
- Correct SVG attributes (viewBox, xmlns)
- Proper prop spreading for customization
- Clean and semantic markup
packages/utilities/shared-icons/src/danger.tsx (2)
1-6
: LGTM: Clean type definitions and imports
The type definitions are well-structured, properly extending IconSvgProps with an optional className property.
17-17
: LGTM: SVG path implementation
The path data correctly defines a danger icon shape, and the lack of fill attribute allows for color customization via CSS.
packages/utilities/shared-icons/src/index.ts (1)
36-39
: LGTM! The new icon exports follow consistent patterns.
The new exports for alert-related icons (info-circle, warning, danger, success) are logically grouped together and follow the established export pattern.
Let's verify the existence of the referenced icon files:
✅ Verification successful
Let me verify if these files exist with a different approach using fd
command to ensure we're not missing any file extensions.
✓ All referenced icon files exist and are properly exported
All new icon files (info-circle.tsx, warning.tsx, danger.tsx, success.tsx) are present in the shared-icons source directory, confirming that the exports in index.ts are valid and properly reference existing implementations.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify that all new icon files exist
# Expected: All files should exist in the same directory
cd packages/utilities/shared-icons/src
for icon in info-circle warning danger success; do
echo "Checking for $icon.tsx..."
if ! [ -f "$icon.tsx" ]; then
echo "Error: $icon.tsx is missing"
exit 1
fi
done
Length of output: 605
Script:
#!/bin/bash
# Search for icon files with any extension in the icons directory
cd packages/utilities/shared-icons/src
echo "Searching for info-circle files:"
fd "^info-circle\." --max-depth 1
echo -e "\nSearching for warning files:"
fd "^warning\." --max-depth 1
echo -e "\nSearching for danger files:"
fd "^danger\." --max-depth 1
echo -e "\nSearching for success files:"
fd "^success\." --max-depth 1
Length of output: 514
apps/docs/content/components/alert/with-icon.ts (2)
1-2
: LGTM! Template string approach is appropriate for documentation.
The code example is properly structured as a template string, making it suitable for documentation purposes.
48-54
: LGTM! Export configuration is correct.
The export structure properly follows the documentation system's requirements.
packages/utilities/shared-icons/src/warning.tsx (1)
1-6
: LGTM! Clean and well-typed props interface.
The component's props are properly typed by extending IconSvgProps with an optional className, following TypeScript best practices.
packages/core/react/src/index.ts (1)
46-46
: LGTM! The export follows the established patterns.
The new Alert component export is correctly placed in alphabetical order among other NextUI component exports.
Let's verify that the package dependency is properly configured:
✅ Verification successful
The package dependency is properly configured
The @nextui-org/alert
package is correctly listed in the dependencies section of packages/core/react/package.json
with the workspace reference "workspace:*"
, following the same pattern as other NextUI component packages.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify @nextui-org/alert package dependency
# Test: Check if the package is listed in dependencies
rg -A 5 '"@nextui-org/alert"' package.json
Length of output: 44
Script:
#!/bin/bash
# Let's check the package.json in the core/react directory since that's where the export is being added
cat packages/core/react/package.json
Length of output: 3264
packages/components/alert/package.json (2)
31-39
: LGTM: Build scripts configuration
The scripts section is well-configured with all necessary commands for building, development, and type checking. The use of clean-package for prepack and postpack is a good practice.
2-4
: 🛠️ Refactor suggestion
Consider starting with version 1.0.0
The package is being introduced with version 2.0.0, which typically implies breaking changes from a previous version. However, since this is a new package, it would be more appropriate to start with version 1.0.0 to follow semantic versioning conventions.
- "version": "2.0.0",
+ "version": "1.0.0",
packages/components/alert/src/alert.tsx (2)
1-14
: LGTM! Well-organized imports
The imports are properly structured and all dependencies seem necessary for the component's functionality.
31-82
: Verify component integration with design system
The Alert component implementation looks solid overall. Consider verifying the following:
- Color tokens match the design system
- Animation transitions align with other components
- Responsive behavior works as expected
✅ Verification successful
The search results show consistent color token usage across the components library, including the Alert component. The color tokens (primary
, secondary
, success
, warning
, danger
) are used consistently in various components like Button, Badge, MenuItem, etc. Let's verify the animation transitions:
Color tokens and animations are properly integrated with the design system
The verification shows that:
- Color tokens are consistently used across components, including the Alert component's color prop options (
primary
,secondary
,success
,warning
,danger
) - Transitions and animations follow a consistent pattern:
- Standard duration values (0.2s - 0.3s for most UI transitions)
- Common animation properties (opacity, transform)
- Consistent easing functions (easeInOut, easeOut)
The Alert component's implementation aligns well with the design system's patterns for both color tokens and animations.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Check for consistent color token usage across the design system
rg -g '*.{ts,tsx}' --no-filename 'primary|secondary|success|warning|danger' packages/components/
Length of output: 20214
Script:
#!/bin/bash
# Check for animation/transition related styles and configurations
rg -g '*.{ts,tsx,css}' --no-filename 'transition|animation|duration' packages/components/
Length of output: 4902
packages/core/react/package.json (1)
87-87
: LGTM! Addition of Alert component dependency follows established patterns.
The new @nextui-org/alert
dependency is correctly added using workspace notation and maintains consistent ordering with other NextUI component dependencies.
Let's verify the package size impact:
✅ Verification successful
Alert package structure and size appear consistent with other components
Based on the repository structure analysis, the Alert component follows the same implementation pattern as other UI components like Modal:
- Standard package structure with tests, stories, and source files
- Similar number of implementation files (alert.tsx, use-alert.ts, etc.)
- Proper integration with the theme system
- Comparable file organization to other established components
The dependency addition to core/react/package.json is appropriate and follows the project's conventions.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check the size of the new alert package
# Expected: Package size should be comparable to similar components
# Get the package.json of the alert package
fd -t f "package.json" -x cat {} \; | grep -A 5 "@nextui-org/alert"
# List files in the alert package to understand its footprint
fd . -t f --full-path "*packages/*alert*"
Length of output: 576
Script:
#!/bin/bash
# Let's try a different approach to check the alert package structure and size
# Find all files related to the alert component
fd -t f . "packages/alert"
# Check the implementation details
rg -t ts -t tsx "Alert" "packages/alert" -l
# Look for similar component packages for size comparison
fd -t f . "packages/(toast|modal)"
Length of output: 345
Script:
#!/bin/bash
# Let's try one more approach with more generic searches
# Find all package.json files in the packages directory
fd package.json packages/
# Look for alert-related files across the repository
rg -t ts -t typescript "Alert" -l
# Get size information of similar component packages
find . -type f -path "*/packages/*" -name "*.ts" -o -name "*.tsx" | grep -i "alert\|modal\|toast"
Length of output: 4655
apps/docs/content/docs/components/alert.mdx (1)
6-6
: Verify the alert content import path
Please ensure that the @/content/components/alert
import path is correct and the file exists.
✅ Verification successful
The import path is correct and the file exists
The import statement import {alertContent} from "@/content/components/alert"
is valid. The alert content is properly exported from apps/docs/content/components/alert/index.ts
and the import is correctly used in the alert documentation file. The @/
alias in the import path is a common Next.js convention that maps to the appropriate directory.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the existence of the alert content file
fd --type f "alert\.(ts|js|tsx|jsx)" content/components/
Length of output: 165
Script:
#!/bin/bash
# Let's first find all alert-related files in the repository
fd --type f "alert"
# Also search for any imports of alert content
rg -l "@/content.*alert"
Length of output: 364
Script:
#!/bin/bash
# Let's check the apps/docs directory structure for content organization
fd --type d "content" apps/docs/
# And look for any content-related files in the docs app
fd --type f . apps/docs/content/
Length of output: 35860
Script:
#!/bin/bash
# Let's check the content of the alert content file
cat apps/docs/content/components/alert/index.ts
# And also check if this file is imported in the alert.mdx
rg -A 5 "import.*alert.*content" apps/docs/content/docs/components/alert.mdx
Length of output: 703
packages/components/alert/src/use-alert.ts (8)
1-11
: LGTM!
The imports are well-organized and follow a logical order. The imported types, functions, and modules are relevant to the implementation of the useAlert
hook.
13-75
: Comprehensive and well-documented Props interface.
The Props
interface is thoroughly defined, with clear JSDoc comments explaining each property. It covers essential aspects of the alert component, such as title, description, icon, visibility control, event handlers, and customization options.
The classNames
property allows for granular styling of individual alert slots, enhancing flexibility.
79-188
: Well-structured and optimized useAlert hook implementation.
The useAlert
hook follows a clear and logical structure:
- It separates variant-specific props using
mapPropsVariants
. - It utilizes
useControlledState
for managing the alert's visibility state. - It memoizes the
slots
object for optimized rendering. - It provides a set of memoized getter functions for each alert slot's props.
- It returns an object with all necessary properties and functions for the alert component.
The hook efficiently handles the alert's state, styling, and behavior while ensuring optimal performance through memoization and controlled state management.
99-103
: Verify the default value for isDefaultVisible.
The isDefaultVisible
prop is used as the default value for the isVisible
state when isVisibleProp
is not provided. However, the default value is set to true
, which might not align with the JSDoc comment in the Props
interface that states @default false
.
Please confirm if the default value should be true
or false
and update the code or documentation accordingly to maintain consistency.
117-120
: Efficient memoization of the slots object.
The slots
object is memoized using useMemo
, with dependencies on the description
and variantProps
. This ensures that the object is only recreated when necessary, optimizing performance.
The use of objectToDeps
is a nice touch to convert the variantProps
object into a dependency array for the memoization.
122-136
: Comprehensive base props composition.
The getBaseProps
function composes the base props for the alert component by merging:
- Data attributes for visibility, closeability, and presence of title/description.
- Filtered DOM props from
otherProps
andprops
. - Base slot className from the
slots
object.
This approach ensures that all relevant props are included and filtered appropriately.
138-169
: Consistent and memoized slot prop getters.
The prop getter functions for each alert slot (mainWrapper
, description
, title
, closeButton
, alertIcon
) follow a consistent pattern:
- They are memoized using
useCallback
to optimize performance. - They return an object with the
className
property derived from the corresponding slot in theslots
object. - They merge the
classNames
prop for the specific slot, allowing for custom styling.
This approach provides a clean and efficient way to manage the props for each slot of the alert component.
171-188
: Comprehensive return object for the useAlert hook.
The useAlert
hook returns an object containing all the necessary properties and functions for the alert component to consume, including:
- State variables (
title
,icon
,description
,isClosable
,isVisible
). - Ref (
domRef
). - Prop getter functions (
getBaseProps
,getMainWrapperProps
,getDescriptionProps
,getTitleProps
,getCloseButtonProps
,getAlertIconProps
). - Event handlers (
handleClose
,onClose
). - Variant prop (
color
).
This return object provides a clean and organized interface for the alert component to utilize the hook's functionality.
packages/core/theme/src/components/alert.ts (8)
1-3
: LGTM!
The imports are correctly specified and follow the necessary conventions.
4-23
: Excellent documentation!
The JSDoc comment provides a clear and concise explanation of the alert
component, including a helpful code example demonstrating its usage. This level of documentation greatly enhances the usability and maintainability of the code.
24-32
: Well-structured component definition.
The alert
component is defined using the tv
utility, with a clear separation of concerns into slots. Each slot is appropriately styled using Tailwind CSS classes, ensuring a consistent and visually appealing design.
33-111
: Comprehensive variant support.
The alert
component offers extensive customization options through its variant system. It supports multiple color schemes, styles (solid, flat, bordered), and border radius options. The variant definitions are well-organized and follow a consistent pattern, making it easy to understand and extend.
112-116
: Appropriate default variants.
The component specifies sensible default variants for color, style, and border radius. This ensures that the alert component has a consistent appearance out of the box, while still allowing for customization when needed.
117-322
: Extensive compound variants for fine-grained control.
The compoundVariants
section defines a wide range of combinations for color schemes and styles. This allows for precise control over the appearance of the alert component in various scenarios. The class definitions are comprehensive and cover all relevant slots, ensuring a cohesive design.
324-327
: Proper type definitions and exports.
The file exports the necessary type definitions (AlertVariantProps
and AlertSlots
) and the alert
component itself. This enables strong typing and facilitates the usage of the component in a TypeScript environment.
1-327
: Verify the integration with the @nextui-org/alert
package.
Ensure that the alert
component is properly integrated into the @nextui-org/alert
package and that the package's README and documentation are updated to reflect the new functionality.
Run the following script to verify the integration:
✅ Verification successful
The alert component is properly integrated with @nextui-org/alert package
The verification shows that:
- The theme's alert component is correctly imported and used in
use-alert.ts
- The Alert component is fully implemented with proper integration of theme variants
- Comprehensive test coverage exists in
alert.test.tsx
- Package dependencies are correctly configured in
package.json
The only missing element appears to be documentation, but this is likely part of the website docs rather than the package itself.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the integration of the `alert` component with the `@nextui-org/alert` package.
# Test 1: Check if the `alert` component is exported from the package's entry point.
rg -A 5 $'export .* from .*/alert' packages/components/alert/src/index.ts
# Test 2: Check if the `Alert` component is imported and used in the package's README.
rg -A 5 $'import .* Alert' packages/components/alert/README.md
# Test 3: Check if the `Alert` component is documented in the package's documentation.
fd alert.mdx packages/components/alert/docs
Length of output: 419
Script:
#!/bin/bash
# Let's verify the integration more thoroughly
# Check if the alert component is imported and used in the Alert component
rg -l "import.*alert.*from.*theme" packages/components/alert/src/
# Check the actual Alert component implementation
cat packages/components/alert/src/alert.tsx
# Check if there's a test file
fd "alert.test" packages/components/alert/
# Check package.json dependencies
cat packages/components/alert/package.json
# Check if there's documentation in other locations
fd -e mdx -e md -H alert packages/docs/content/
Length of output: 4174
Script:
#!/bin/bash
# Let's check the use-alert.ts file to verify the theme integration
cat packages/components/alert/src/use-alert.ts
# Check if there's documentation in the docs directory
fd -e mdx -e md alert docs/
# Check the test file content
cat packages/components/alert/__tests__/alert.test.tsx
Length of output: 7670
<Alert | ||
color={color} | ||
title={\`This is a \${color} alert\`} | ||
/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add type safety for the color prop.
The color prop should be properly typed to ensure only valid color values are used.
- <Alert
- color={color}
- title={`This is a ${color} alert`}
- />
+ <Alert
+ color={color as "default" | "primary" | "secondary" | "success" | "warning" | "danger"}
+ title={`This is a ${color} alert`}
+ />
Committable suggestion skipped: line range outside the PR's diff.
@@ -31,3 +31,4 @@ export * from "./dropdown"; | |||
export * from "./navbar"; | |||
export * from "./table"; | |||
export * from "./autocomplete"; | |||
export * from "./alert"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
The alert component export needs to be fixed
The current implementation has issues:
- The alert directory only exports
alertContent
object with examples - The main Alert component is not properly exported from
custom-impl.ts
- The barrel file's
export * from "./alert"
won't work as expected
To fix this:
- Create a proper export of the Alert component in
alert/index.ts
- Or update the barrel file to use the correct path:
export { default as Alert } from "./alert/custom-impl"
🔗 Analysis chain
LGTM! The export follows the established pattern.
The new alert component export maintains consistency with other component exports in the barrel file.
Let's verify that the alert component exists:
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Verify the existence of the alert component
# Expected: Find the alert component implementation
# Check for the alert component directory/file
fd --type f "alert" apps/docs/content/components
# Verify the component's implementation
rg -l "export.*Alert" apps/docs/content/components/alert
Length of output: 157
Script:
#!/bin/bash
# Let's check the actual implementation to verify the export
rg -A 5 "export.*Alert" apps/docs/content/components/alert/custom-impl.ts
Length of output: 201
Script:
#!/bin/bash
# Let's check the entire content of the alert implementation file
cat apps/docs/content/components/alert/custom-impl.ts
Length of output: 3724
Script:
#!/bin/bash
# Let's check if there's an index file in the alert directory that re-exports the component
cat apps/docs/content/components/alert/index.ts 2>/dev/null || echo "File not found"
Length of output: 465
base: [ | ||
"bg-background", | ||
"border", | ||
"border-foreground-400", | ||
"shadow", | ||
"hover:bg-slate-200", | ||
"cursor-pointer", | ||
], |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💡 Codebase verification
Consider using a semantic color token instead of slate-200
The hover state using hover:bg-slate-200
should be replaced with a semantic color token from the NextUI theme system to ensure proper contrast ratios and consistent theming across light and dark modes. Consider using hover:bg-default-200
or hover:bg-content2
which are designed to maintain appropriate contrast with text colors.
🔗 Analysis chain
Verify color contrast for hover state.
The hover:bg-slate-200
might not provide sufficient contrast with the text colors. Consider testing with a color contrast checker.
Let me gather more information about the color scheme and theme configuration to better understand the contrast situation.
Let me do one final check to understand the alert component's color scheme implementation.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for any defined color schemes or theme configurations
rg -g '*.{ts,tsx,js,jsx}' --no-heading 'slate-200|text-foreground' ./packages/core/theme/
Length of output: 6802
Script:
#!/bin/bash
# Search for theme configuration related to background colors and slate colors
rg -g '*.{ts,tsx,js,jsx}' --no-heading 'colors.*slate|colors.*background|darkMode|theme\.extend\.colors' .
# Search for any alert component styling or theme configuration
ast-grep --pattern 'export const alert = {
$$$
}'
Length of output: 840
Script:
#!/bin/bash
# Check for any tailwind configuration files that might define custom colors
fd -e js -e ts "tailwind.config" -x cat {}
# Look for any theme tokens or design system color definitions
rg -g '*.{ts,tsx,js,jsx}' --no-heading 'colors.*= {|semanticTokens|theme\.extend' .
Length of output: 16464
{isVisible ? ( | ||
<Alert | ||
title={title} | ||
description={description} | ||
isVisible={isVisible} | ||
onClose={() => setIsVisible(false)} | ||
/> | ||
) : ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Remove redundant isVisible prop
The Alert component is already conditionally rendered based on the isVisible
state. Passing isVisible
as a prop is redundant since the component won't render when isVisible
is false.
{isVisible ? (
<Alert
title={title}
description={description}
- isVisible={isVisible}
onClose={() => setIsVisible(false)}
/>
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
{isVisible ? ( | |
<Alert | |
title={title} | |
description={description} | |
isVisible={isVisible} | |
onClose={() => setIsVisible(false)} | |
/> | |
) : ( | |
{isVisible ? ( | |
<Alert | |
title={title} | |
description={description} | |
onClose={() => setIsVisible(false)} | |
/> | |
) : ( |
<svg | ||
fill="none" | ||
height="24" | ||
viewBox="0 0 24 24" | ||
width="24" | ||
xmlns="http://www.w3.org/2000/svg" | ||
{...props} | ||
> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add ARIA attributes for better accessibility.
The SVG icon should include appropriate ARIA attributes to improve accessibility for screen readers.
<svg
fill="none"
height="24"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
+ aria-hidden="true"
+ role="img"
+ aria-label="Information circle icon"
{...props}
>
Committable suggestion skipped: line range outside the PR's diff.
### Alert Props | ||
|
||
| Attribute | Type | Description | Default | | ||
| ---------------- | --------------------------------------------------------------------------- | ------------------------------------------- | --------- | | ||
| title | `string` | The alert title | - | | ||
| icon | `ReactNode` | The alert icon - overrides the default icon | - | | ||
| description | `ReactNode` | The alert description | - | | ||
| color | `default` \| `primary` \| `secondary` \| `success` \| `warning` \| `danger` | The alert color theme | `default` | | ||
| variant | `solid` \| `bordered` \| `flat` | The alert variant | `flat` | | ||
| radius | `none` \| `sm` \| `md` \| `lg` \| `full` | The alert border radius | `md` | | ||
| isVisible | `boolean` | Whether the alert is visible | - | | ||
| isClosable | `boolean` | Whether the alert can be closed | `false` | | ||
| closeButtonProps | `ButtonProps` | Props for the close button | - | | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Enhance API documentation
Consider adding:
- The
className
prop documentation for custom styling - TypeScript interface exports
- CSS variables or design tokens that can be customized
export const WithIcon = { | ||
render: Template, | ||
args: { | ||
...defaultProps, | ||
title: "This is an alert with a custom icon", | ||
icon: ( | ||
<svg height={24} viewBox="0 0 24 24" width={24}> | ||
<g | ||
fill="none" | ||
stroke="currentColor" | ||
strokeLinecap="round" | ||
strokeLinejoin="round" | ||
strokeMiterlimit={10} | ||
strokeWidth={1.5} | ||
> | ||
<path | ||
d="M11.845 21.662C8.153 21.662 5 21.088 5 18.787s3.133-4.425 6.845-4.425c3.692 0 6.845 2.1 6.845 4.4s-3.134 2.9-6.845 2.9z" | ||
data-name="Stroke 1" | ||
/> | ||
<path d="M11.837 11.174a4.372 4.372 0 10-.031 0z" data-name="Stroke 3" /> | ||
</g> | ||
</svg> | ||
), | ||
}, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Enhance accessibility of the WithIcon story.
The SVG icon should include proper ARIA attributes for accessibility.
icon: (
- <svg height={24} viewBox="0 0 24 24" width={24}>
+ <svg
+ height={24}
+ viewBox="0 0 24 24"
+ width={24}
+ role="img"
+ aria-label="User profile icon"
+ aria-hidden="false"
+ >
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
export const WithIcon = { | |
render: Template, | |
args: { | |
...defaultProps, | |
title: "This is an alert with a custom icon", | |
icon: ( | |
<svg height={24} viewBox="0 0 24 24" width={24}> | |
<g | |
fill="none" | |
stroke="currentColor" | |
strokeLinecap="round" | |
strokeLinejoin="round" | |
strokeMiterlimit={10} | |
strokeWidth={1.5} | |
> | |
<path | |
d="M11.845 21.662C8.153 21.662 5 21.088 5 18.787s3.133-4.425 6.845-4.425c3.692 0 6.845 2.1 6.845 4.4s-3.134 2.9-6.845 2.9z" | |
data-name="Stroke 1" | |
/> | |
<path d="M11.837 11.174a4.372 4.372 0 10-.031 0z" data-name="Stroke 3" /> | |
</g> | |
</svg> | |
), | |
}, | |
}; | |
export const WithIcon = { | |
render: Template, | |
args: { | |
...defaultProps, | |
title: "This is an alert with a custom icon", | |
icon: ( | |
<svg | |
height={24} | |
viewBox="0 0 24 24" | |
width={24} | |
role="img" | |
aria-label="User profile icon" | |
aria-hidden="false" | |
> | |
<g | |
fill="none" | |
stroke="currentColor" | |
strokeLinecap="round" | |
strokeLinejoin="round" | |
strokeMiterlimit={10} | |
strokeWidth={1.5} | |
> | |
<path | |
d="M11.845 21.662C8.153 21.662 5 21.088 5 18.787s3.133-4.425 6.845-4.425c3.692 0 6.845 2.1 6.845 4.4s-3.134 2.9-6.845 2.9z" | |
data-name="Stroke 1" | |
/> | |
<path d="M11.837 11.174a4.372 4.372 0 10-.031 0z" data-name="Stroke 3" /> | |
</g> | |
</svg> | |
), | |
}, | |
}; |
const CloseIcon = `export const CloseIcon = (props) => ( | ||
<svg | ||
aria-hidden="true" | ||
fill="none" | ||
focusable="false" | ||
height="1em" | ||
role="presentation" | ||
stroke="currentColor" | ||
strokeLinecap="round" | ||
strokeLinejoin="round" | ||
strokeWidth={2} | ||
viewBox="0 0 24 24" | ||
width="1em" | ||
{...props} | ||
> | ||
<path d="M18 6L6 18M6 6l12 12" /> | ||
</svg> | ||
);`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactor the CloseIcon
component to use JSX syntax.
Similar to the InfoCircleIcon
, the CloseIcon
component is defined as a string. Convert it to a functional component using JSX for consistency and proper React syntax.
Apply this diff to refactor the component:
-const CloseIcon = `export const CloseIcon = (props) => (
+export const CloseIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path d="M18 6L6 18M6 6l12 12" />
</svg>
-);`;
+);
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const CloseIcon = `export const CloseIcon = (props) => ( | |
<svg | |
aria-hidden="true" | |
fill="none" | |
focusable="false" | |
height="1em" | |
role="presentation" | |
stroke="currentColor" | |
strokeLinecap="round" | |
strokeLinejoin="round" | |
strokeWidth={2} | |
viewBox="0 0 24 24" | |
width="1em" | |
{...props} | |
> | |
<path d="M18 6L6 18M6 6l12 12" /> | |
</svg> | |
);`; | |
export const CloseIcon = (props) => ( | |
<svg | |
aria-hidden="true" | |
fill="none" | |
focusable="false" | |
height="1em" | |
role="presentation" | |
stroke="currentColor" | |
strokeLinecap="round" | |
strokeLinejoin="round" | |
strokeWidth={2} | |
viewBox="0 0 24 24" | |
width="1em" | |
{...props} | |
> | |
<path d="M18 6L6 18M6 6l12 12" /> | |
</svg> | |
); |
const InfoCircleIcon = `export const InfoCircleIcon = (props) => ( | ||
<svg | ||
fill="none" | ||
height="24" | ||
viewBox="0 0 24 24" | ||
width="24" | ||
xmlns="http://www.w3.org/2000/svg" | ||
{...props} | ||
> | ||
<path | ||
d="M12 22C17.51 22 22 17.51 22 12C22 6.49 17.51 2 12 2C6.49 2 2 6.49 2 12C2 17.51 6.49 22 12 22ZM12.75 16C12.75 16.41 12.41 16.75 12 16.75C11.59 16.75 11.25 16.41 11.25 16L11.25 11C11.25 10.59 11.59 10.25 12 10.25C12.41 10.25 12.75 10.59 12.75 11L12.75 16ZM11.08 7.62C11.13 7.49 11.2 7.39 11.29 7.29C11.39 7.2 11.5 7.13 11.62 7.08C11.74 7.03 11.87 7 12 7C12.13 7 12.26 7.03 12.38 7.08C12.5 7.13 12.61 7.2 12.71 7.29C12.8 7.39 12.87 7.49 12.92 7.62C12.97 7.74 13 7.87 13 8C13 8.13 12.97 8.26 12.92 8.38C12.87 8.5 12.8 8.61 12.71 8.71C12.61 8.8 12.5 8.87 12.38 8.92C12.14 9.02 11.86 9.02 11.62 8.92C11.5 8.87 11.39 8.8 11.29 8.71C11.2 8.61 11.13 8.5 11.08 8.38C11.03 8.26 11 8.13 11 8C11 7.87 11.03 7.74 11.08 7.62Z" | ||
/> | ||
</svg> | ||
);`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactor the InfoCircleIcon
component to use JSX syntax.
The InfoCircleIcon
component is defined as a string, which is not a valid React component syntax. Convert it to a functional component using JSX.
Apply this diff to refactor the component:
-const InfoCircleIcon = `export const InfoCircleIcon = (props) => (
+export const InfoCircleIcon = (props) => (
<svg
fill="none"
height="24"
viewBox="0 0 24 24"
width="24"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M12 22C17.51 22 22 17.51 22 12C22 6.49 17.51 2 12 2C6.49 2 2 6.49 2 12C2 17.51 6.49 22 12 22ZM12.75 16C12.75 16.41 12.41 16.75 12 16.75C11.59 16.75 11.25 16.41 11.25 16L11.25 11C11.25 10.59 11.59 10.25 12 10.25C12.41 10.25 12.75 10.59 12.75 11L12.75 16ZM11.08 7.62C11.13 7.49 11.2 7.39 11.29 7.29C11.39 7.2 11.5 7.13 11.62 7.08C11.74 7.03 11.87 7 12 7C12.13 7 12.26 7.03 12.38 7.08C12.5 7.13 12.61 7.2 12.71 7.29C12.8 7.39 12.87 7.49 12.92 7.62C12.97 7.74 13 7.87 13 8C13 8.13 12.97 8.26 12.92 8.38C12.87 8.5 12.8 8.61 12.71 8.71C12.61 8.8 12.5 8.87 12.38 8.92C12.14 9.02 11.86 9.02 11.62 8.92C11.5 8.87 11.39 8.8 11.29 8.71C11.2 8.61 11.13 8.5 11.08 8.38C11.03 8.26 11 8.13 11 8C11 7.87 11.03 7.74 11.08 7.62Z"
/>
</svg>
-);`;
+);
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const InfoCircleIcon = `export const InfoCircleIcon = (props) => ( | |
<svg | |
fill="none" | |
height="24" | |
viewBox="0 0 24 24" | |
width="24" | |
xmlns="http://www.w3.org/2000/svg" | |
{...props} | |
> | |
<path | |
d="M12 22C17.51 22 22 17.51 22 12C22 6.49 17.51 2 12 2C6.49 2 2 6.49 2 12C2 17.51 6.49 22 12 22ZM12.75 16C12.75 16.41 12.41 16.75 12 16.75C11.59 16.75 11.25 16.41 11.25 16L11.25 11C11.25 10.59 11.59 10.25 12 10.25C12.41 10.25 12.75 10.59 12.75 11L12.75 16ZM11.08 7.62C11.13 7.49 11.2 7.39 11.29 7.29C11.39 7.2 11.5 7.13 11.62 7.08C11.74 7.03 11.87 7 12 7C12.13 7 12.26 7.03 12.38 7.08C12.5 7.13 12.61 7.2 12.71 7.29C12.8 7.39 12.87 7.49 12.92 7.62C12.97 7.74 13 7.87 13 8C13 8.13 12.97 8.26 12.92 8.38C12.87 8.5 12.8 8.61 12.71 8.71C12.61 8.8 12.5 8.87 12.38 8.92C12.14 9.02 11.86 9.02 11.62 8.92C11.5 8.87 11.39 8.8 11.29 8.71C11.2 8.61 11.13 8.5 11.08 8.38C11.03 8.26 11 8.13 11 8C11 7.87 11.03 7.74 11.08 7.62Z" | |
/> | |
</svg> | |
);`; | |
export const InfoCircleIcon = (props) => ( | |
<svg | |
fill="none" | |
height="24" | |
viewBox="0 0 24 24" | |
width="24" | |
xmlns="http://www.w3.org/2000/svg" | |
{...props} | |
> | |
<path | |
d="M12 22C17.51 22 22 17.51 22 12C22 6.49 17.51 2 12 2C6.49 2 2 6.49 2 12C2 17.51 6.49 22 12 22ZM12.75 16C12.75 16.41 12.41 16.75 12 16.75C11.59 16.75 11.25 16.41 11.25 16L11.25 11C11.25 10.59 11.59 10.25 12 10.25C12.41 10.25 12.75 10.59 12.75 11L12.75 16ZM11.08 7.62C11.13 7.49 11.2 7.39 11.29 7.29C11.39 7.2 11.5 7.13 11.62 7.08C11.74 7.03 11.87 7 12 7C12.13 7 12.26 7.03 12.38 7.08C12.5 7.13 12.61 7.2 12.71 7.29C12.8 7.39 12.87 7.49 12.92 7.62C12.97 7.74 13 7.87 13 8C13 8.13 12.97 8.26 12.92 8.38C12.87 8.5 12.8 8.61 12.71 8.71C12.61 8.8 12.5 8.87 12.38 8.92C12.14 9.02 11.86 9.02 11.62 8.92C11.5 8.87 11.39 8.8 11.29 8.71C11.2 8.61 11.13 8.5 11.08 8.38C11.03 8.26 11 8.13 11 8C11 7.87 11.03 7.74 11.08 7.62Z" | |
/> | |
</svg> | |
); |
const App = `import React, {forwardRef, useMemo} from "react"; | ||
import {useAlert} from "@nextui-org/react"; | ||
import {InfoCircleIcon} from "./InfoCircleIcon"; | ||
import {CloseIcon} from "./CloseIcon" | ||
const styles = { | ||
base: [ | ||
"bg-slate-100", | ||
"border", | ||
"shadow", | ||
"hover:bg-slate-200", | ||
"focus-within:!bg-slate-100", | ||
"dark:bg-slate-900", | ||
"dark:hover:bg-slate-800", | ||
"dark:border-slate-800", | ||
"dark:focus-within:!bg-slate-900", | ||
"cursor-pointer" | ||
], | ||
title: [ | ||
"text-base", | ||
"text-slate-500", | ||
"font-bold" | ||
], | ||
description: [ | ||
"text-base", | ||
"text-slate-500", | ||
], | ||
} | ||
const MyAlert = forwardRef((props, ref) => { | ||
const { | ||
title, | ||
description, | ||
isClosable, | ||
domRef, | ||
handleClose, | ||
getBaseProps, | ||
getMainWrapperProps, | ||
getDescriptionProps, | ||
getTitleProps, | ||
getCloseButtonProps, | ||
color, | ||
isVisible, | ||
onClose, | ||
getCloseIconProps, | ||
getAlertIconProps, | ||
} = useAlert({ | ||
...props, | ||
ref, | ||
// this is just for the example, the props bellow should be passed by the parent component | ||
title: "Email Sent!!", | ||
description: "You will get a reply soon", | ||
// custom styles | ||
classNames: { | ||
...styles, | ||
}, | ||
}); | ||
const mainWrapper = useMemo(() => { | ||
return ( | ||
<div {...getMainWrapperProps()}> | ||
{title && <div {...getTitleProps()}>{title}</div>} | ||
<div {...getDescriptionProps()}>{description}</div> | ||
</div> | ||
); | ||
}, [title, description, getMainWrapperProps, getTitleProps, getDescriptionProps]); | ||
const baseWrapper = useMemo(() => { | ||
return isVisible ? ( | ||
<div ref={domRef} {...getBaseProps()}> | ||
<InfoCircleIcon {...getAlertIconProps()} /> | ||
{mainWrapper} | ||
{(isClosable || onClose) && ( | ||
<button onClick={handleClose} {...getCloseButtonProps()}> | ||
<CloseIcon /> | ||
</button> | ||
)} | ||
</div> | ||
) : null; | ||
}, [ | ||
mainWrapper, | ||
isClosable, | ||
getCloseButtonProps, | ||
isVisible, | ||
domRef, | ||
getBaseProps, | ||
handleClose, | ||
color, | ||
onClose, | ||
getAlertIconProps, | ||
]); | ||
return <>{baseWrapper}</>; | ||
}); | ||
MyAlert.displayName = "MyAlert"; | ||
export default MyAlert;`; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refactor the App
component to use proper JSX syntax and remove the string definition.
The App
component is defined as a string, which is not a valid React component syntax. Convert it to a functional component using JSX and remove the string definition.
Apply this diff to refactor the component:
-const App = `import React, {forwardRef, useMemo} from "react";
+import React, {forwardRef, useMemo} from "react";
import {useAlert} from "@nextui-org/react";
import {InfoCircleIcon} from "./InfoCircleIcon";
import {CloseIcon} from "./CloseIcon"
const styles = {
base: [
"bg-slate-100",
"border",
"shadow",
"hover:bg-slate-200",
"focus-within:!bg-slate-100",
"dark:bg-slate-900",
"dark:hover:bg-slate-800",
"dark:border-slate-800",
"dark:focus-within:!bg-slate-900",
"cursor-pointer"
],
title: [
"text-base",
"text-slate-500",
"font-bold"
],
description: [
"text-base",
"text-slate-500",
],
}
const MyAlert = forwardRef((props, ref) => {
const {
title,
description,
isClosable,
domRef,
handleClose,
getBaseProps,
getMainWrapperProps,
getDescriptionProps,
getTitleProps,
getCloseButtonProps,
color,
isVisible,
onClose,
getCloseIconProps,
getAlertIconProps,
} = useAlert({
...props,
ref,
// this is just for the example, the props bellow should be passed by the parent component
title: "Email Sent!!",
description: "You will get a reply soon",
// custom styles
classNames: {
...styles,
},
});
const mainWrapper = useMemo(() => {
return (
<div {...getMainWrapperProps()}>
{title && <div {...getTitleProps()}>{title}</div>}
<div {...getDescriptionProps()}>{description}</div>
</div>
);
}, [title, description, getMainWrapperProps, getTitleProps, getDescriptionProps]);
const baseWrapper = useMemo(() => {
return isVisible ? (
<div ref={domRef} {...getBaseProps()}>
<InfoCircleIcon {...getAlertIconProps()} />
{mainWrapper}
{(isClosable || onClose) && (
<button onClick={handleClose} {...getCloseButtonProps()}>
<CloseIcon />
</button>
)}
</div>
) : null;
}, [
mainWrapper,
isClosable,
getCloseButtonProps,
isVisible,
domRef,
getBaseProps,
handleClose,
color,
onClose,
getAlertIconProps,
]);
return <>{baseWrapper}</>;
});
MyAlert.displayName = "MyAlert";
export default MyAlert;`;
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const App = `import React, {forwardRef, useMemo} from "react"; | |
import {useAlert} from "@nextui-org/react"; | |
import {InfoCircleIcon} from "./InfoCircleIcon"; | |
import {CloseIcon} from "./CloseIcon" | |
const styles = { | |
base: [ | |
"bg-slate-100", | |
"border", | |
"shadow", | |
"hover:bg-slate-200", | |
"focus-within:!bg-slate-100", | |
"dark:bg-slate-900", | |
"dark:hover:bg-slate-800", | |
"dark:border-slate-800", | |
"dark:focus-within:!bg-slate-900", | |
"cursor-pointer" | |
], | |
title: [ | |
"text-base", | |
"text-slate-500", | |
"font-bold" | |
], | |
description: [ | |
"text-base", | |
"text-slate-500", | |
], | |
} | |
const MyAlert = forwardRef((props, ref) => { | |
const { | |
title, | |
description, | |
isClosable, | |
domRef, | |
handleClose, | |
getBaseProps, | |
getMainWrapperProps, | |
getDescriptionProps, | |
getTitleProps, | |
getCloseButtonProps, | |
color, | |
isVisible, | |
onClose, | |
getCloseIconProps, | |
getAlertIconProps, | |
} = useAlert({ | |
...props, | |
ref, | |
// this is just for the example, the props bellow should be passed by the parent component | |
title: "Email Sent!!", | |
description: "You will get a reply soon", | |
// custom styles | |
classNames: { | |
...styles, | |
}, | |
}); | |
const mainWrapper = useMemo(() => { | |
return ( | |
<div {...getMainWrapperProps()}> | |
{title && <div {...getTitleProps()}>{title}</div>} | |
<div {...getDescriptionProps()}>{description}</div> | |
</div> | |
); | |
}, [title, description, getMainWrapperProps, getTitleProps, getDescriptionProps]); | |
const baseWrapper = useMemo(() => { | |
return isVisible ? ( | |
<div ref={domRef} {...getBaseProps()}> | |
<InfoCircleIcon {...getAlertIconProps()} /> | |
{mainWrapper} | |
{(isClosable || onClose) && ( | |
<button onClick={handleClose} {...getCloseButtonProps()}> | |
<CloseIcon /> | |
</button> | |
)} | |
</div> | |
) : null; | |
}, [ | |
mainWrapper, | |
isClosable, | |
getCloseButtonProps, | |
isVisible, | |
domRef, | |
getBaseProps, | |
handleClose, | |
color, | |
onClose, | |
getAlertIconProps, | |
]); | |
return <>{baseWrapper}</>; | |
}); | |
MyAlert.displayName = "MyAlert"; | |
export default MyAlert;`; | |
import React, {forwardRef, useMemo} from "react"; | |
import {useAlert} from "@nextui-org/react"; | |
import {InfoCircleIcon} from "./InfoCircleIcon"; | |
import {CloseIcon} from "./CloseIcon" | |
const styles = { | |
base: [ | |
"bg-slate-100", | |
"border", | |
"shadow", | |
"hover:bg-slate-200", | |
"focus-within:!bg-slate-100", | |
"dark:bg-slate-900", | |
"dark:hover:bg-slate-800", | |
"dark:border-slate-800", | |
"dark:focus-within:!bg-slate-900", | |
"cursor-pointer" | |
], | |
title: [ | |
"text-base", | |
"text-slate-500", | |
"font-bold" | |
], | |
description: [ | |
"text-base", | |
"text-slate-500", | |
], | |
} | |
const MyAlert = forwardRef((props, ref) => { | |
const { | |
title, | |
description, | |
isClosable, | |
domRef, | |
handleClose, | |
getBaseProps, | |
getMainWrapperProps, | |
getDescriptionProps, | |
getTitleProps, | |
getCloseButtonProps, | |
color, | |
isVisible, | |
onClose, | |
getCloseIconProps, | |
getAlertIconProps, | |
} = useAlert({ | |
...props, | |
ref, | |
// this is just for the example, the props bellow should be passed by the parent component | |
title: "Email Sent!!", | |
description: "You will get a reply soon", | |
// custom styles | |
classNames: { | |
...styles, | |
}, | |
}); | |
const mainWrapper = useMemo(() => { | |
return ( | |
<div {...getMainWrapperProps()}> | |
{title && <div {...getTitleProps()}>{title}</div>} | |
<div {...getDescriptionProps()}>{description}</div> | |
</div> | |
); | |
}, [title, description, getMainWrapperProps, getTitleProps, getDescriptionProps]); | |
const baseWrapper = useMemo(() => { | |
return isVisible ? ( | |
<div ref={domRef} {...getBaseProps()}> | |
<InfoCircleIcon {...getAlertIconProps()} /> | |
{mainWrapper} | |
{(isClosable || onClose) && ( | |
<button onClick={handleClose} {...getCloseButtonProps()}> | |
<CloseIcon /> | |
</button> | |
)} | |
</div> | |
) : null; | |
}, [ | |
mainWrapper, | |
isClosable, | |
getCloseButtonProps, | |
isVisible, | |
domRef, | |
getBaseProps, | |
handleClose, | |
color, | |
onClose, | |
getAlertIconProps, | |
]); | |
return <>{baseWrapper}</>; | |
}); | |
MyAlert.displayName = "MyAlert"; | |
export default MyAlert; |
Original PR #3680
📝 Description
⛳️ Current behavior (updates)
🚀 New behavior
💣 Is this a breaking change (Yes/No):
📝 Additional Information
Summary by CodeRabbit
Release Notes
New Features
Alert
component for displaying notifications.InfoCircleIcon
,WarningIcon
,DangerIcon
, andSuccessIcon
.Documentation
Alert
component is now available, covering installation, usage, and API details.@nextui-org/alert
package has been created.Bug Fixes
Alert
component functions correctly under various conditions.