refactor: split dialog components into modules

This commit is contained in:
2025-12-27 22:59:13 +00:00
parent 99d4411a41
commit 5384332b01
10 changed files with 619 additions and 462 deletions

View File

@@ -1,24 +1,16 @@
// TODO: Split this file (268 LOC) into smaller organisms (<150 LOC each)
'use client'
import { forwardRef, ReactNode } from 'react'
import {
Dialog,
DialogTitle,
DialogContent,
DialogContentText,
DialogActions,
Button,
IconButton,
Typography,
} from '@mui/material'
import CloseIcon from '@mui/icons-material/Close'
import WarningAmberIcon from '@mui/icons-material/WarningAmber'
import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline'
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined'
import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline'
import { Dialog } from '@mui/material'
import {
AlertDialogContent,
AlertDialogDescription,
AlertDialogHeader,
AlertDialogTitle,
} from './alert/Content'
import { AlertDialogAction, AlertDialogCancel, AlertDialogFooter } from './alert/Actions'
// AlertDialog Root
interface AlertDialogProps {
open: boolean
onClose?: () => void
@@ -52,7 +44,6 @@ const AlertDialog = forwardRef<HTMLDivElement, AlertDialogProps>(
)
AlertDialog.displayName = 'AlertDialog'
// AlertDialogTrigger - element that opens dialog
interface AlertDialogTriggerProps {
children: ReactNode
onClick?: () => void
@@ -70,200 +61,14 @@ const AlertDialogTrigger = forwardRef<HTMLSpanElement, AlertDialogTriggerProps>(
)
AlertDialogTrigger.displayName = 'AlertDialogTrigger'
// AlertDialogContent - wrapper for dialog content
interface AlertDialogContentProps {
children: ReactNode
showCloseButton?: boolean
onClose?: () => void
className?: string
}
const AlertDialogContent = forwardRef<HTMLDivElement, AlertDialogContentProps>(
({ children, showCloseButton = false, onClose, className, ...props }, ref) => {
return (
<>
{showCloseButton && onClose && (
<IconButton
onClick={onClose}
sx={{
position: 'absolute',
right: 8,
top: 8,
color: 'text.secondary',
}}
>
<CloseIcon />
</IconButton>
)}
{children}
</>
)
}
)
AlertDialogContent.displayName = 'AlertDialogContent'
// AlertDialogHeader
interface AlertDialogHeaderProps {
children: ReactNode
icon?: 'warning' | 'error' | 'info' | 'success' | ReactNode
}
const AlertDialogHeader = forwardRef<HTMLDivElement, AlertDialogHeaderProps>(
({ children, icon, ...props }, ref) => {
const getIcon = () => {
if (!icon) return null
if (typeof icon !== 'string') return icon
const iconMap = {
warning: <WarningAmberIcon color="warning" sx={{ fontSize: 40 }} />,
error: <ErrorOutlineIcon color="error" sx={{ fontSize: 40 }} />,
info: <InfoOutlinedIcon color="info" sx={{ fontSize: 40 }} />,
success: <CheckCircleOutlineIcon color="success" sx={{ fontSize: 40 }} />,
}
return iconMap[icon]
}
const iconElement = getIcon()
return (
<DialogTitle
ref={ref}
id="alert-dialog-title"
sx={{
display: 'flex',
flexDirection: 'column',
alignItems: iconElement ? 'center' : 'flex-start',
gap: 1,
pt: 3,
pb: 0,
}}
{...props}
>
{iconElement}
{children}
</DialogTitle>
)
}
)
AlertDialogHeader.displayName = 'AlertDialogHeader'
// AlertDialogTitle
interface AlertDialogTitleProps {
children: ReactNode
className?: string
}
const AlertDialogTitle = forwardRef<HTMLHeadingElement, AlertDialogTitleProps>(
({ children, className, ...props }, ref) => {
return (
<Typography
ref={ref}
variant="h6"
component="span"
className={className}
sx={{
fontWeight: 600,
textAlign: 'inherit',
}}
{...props}
>
{children}
</Typography>
)
}
)
AlertDialogTitle.displayName = 'AlertDialogTitle'
// AlertDialogDescription
interface AlertDialogDescriptionProps {
children: ReactNode
className?: string
}
const AlertDialogDescription = forwardRef<HTMLDivElement, AlertDialogDescriptionProps>(
({ children, className, ...props }, ref) => {
return (
<DialogContent ref={ref} className={className} sx={{ pt: 2 }} {...props}>
<DialogContentText id="alert-dialog-description">
{children}
</DialogContentText>
</DialogContent>
)
}
)
AlertDialogDescription.displayName = 'AlertDialogDescription'
// AlertDialogFooter
interface AlertDialogFooterProps {
children: ReactNode
}
const AlertDialogFooter = forwardRef<HTMLDivElement, AlertDialogFooterProps>(
({ children, ...props }, ref) => {
return (
<DialogActions ref={ref} sx={{ p: 2, pt: 0 }} {...props}>
{children}
</DialogActions>
)
}
)
AlertDialogFooter.displayName = 'AlertDialogFooter'
// AlertDialogCancel
interface AlertDialogCancelProps {
children?: ReactNode
onClick?: () => void
className?: string
}
const AlertDialogCancel = forwardRef<HTMLButtonElement, AlertDialogCancelProps>(
({ children = 'Cancel', onClick, className, ...props }, ref) => {
return (
<Button ref={ref} onClick={onClick} color="inherit" className={className} {...props}>
{children}
</Button>
)
}
)
AlertDialogCancel.displayName = 'AlertDialogCancel'
// AlertDialogAction
interface AlertDialogActionProps {
children?: ReactNode
onClick?: () => void
color?: 'primary' | 'error' | 'warning' | 'success' | 'info'
variant?: 'text' | 'outlined' | 'contained'
autoFocus?: boolean
className?: string
}
const AlertDialogAction = forwardRef<HTMLButtonElement, AlertDialogActionProps>(
({ children = 'Confirm', onClick, color = 'primary', variant = 'contained', autoFocus = true, className, ...props }, ref) => {
return (
<Button
ref={ref}
onClick={onClick}
color={color}
variant={variant}
autoFocus={autoFocus}
className={className}
{...props}
>
{children}
</Button>
)
}
)
AlertDialogAction.displayName = 'AlertDialogAction'
export {
AlertDialog,
AlertDialogTrigger,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogCancel,
AlertDialogAction,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
}

View File

@@ -1,3 +1,6 @@
'use client'
export * from './command'
export * from './Command/Palette'
export * from './Command/Results'
export * from './Command/useCommandState'

View File

@@ -0,0 +1,38 @@
'use client'
import { ReactNode } from 'react'
import { CommandDialog } from '../command'
interface CommandPaletteProps {
children: ReactNode
open: boolean
onOpenChange: (open: boolean) => void
placeholder?: string
search: string
onSearchChange: (value: string) => void
}
const CommandPalette = ({
children,
open,
onOpenChange,
placeholder = 'Type a command or search...',
search,
onSearchChange,
}: CommandPaletteProps) => {
return (
<CommandDialog open={open} onClose={() => onOpenChange(false)}>
<CommandDialog.Input
value={search}
onChange={onSearchChange}
placeholder={placeholder}
autoFocus
/>
{children}
</CommandDialog>
)
}
export { CommandPalette }
export type { CommandPaletteProps }

View File

@@ -0,0 +1,56 @@
'use client'
import { ReactNode } from 'react'
import { Box, Typography } from '@mui/material'
import { CommandDialog } from '../command'
import type { CommandGroup, CommandItem } from '../command/command.types'
interface CommandResultsProps {
groups: CommandGroup[]
emptyMessage?: ReactNode
onSelect?: (item: CommandItem) => void
}
const CommandResults = ({ groups, emptyMessage = 'No results found.', onSelect }: CommandResultsProps) => {
const hasResults = groups.some((group) => group.items.length > 0)
return (
<CommandDialog.List>
{hasResults ? (
groups.map((group, index) => (
<CommandDialog.Group key={group.heading ?? index} heading={group.heading}>
{group.items.map((item) => (
<CommandDialog.Item
key={item.id}
icon={item.icon}
shortcut={item.shortcut}
disabled={item.disabled}
onSelect={() => {
item.onSelect?.()
onSelect?.(item)
}}
>
<Box sx={{ display: 'flex', flexDirection: 'column', gap: 0.5 }}>
<Typography variant="body2" component="span">
{item.label}
</Typography>
{item.description && (
<Typography variant="caption" color="text.secondary" component="span">
{item.description}
</Typography>
)}
</Box>
</CommandDialog.Item>
))}
</CommandDialog.Group>
))
) : (
<CommandDialog.Empty>{emptyMessage}</CommandDialog.Empty>
)}
</CommandDialog.List>
)
}
export { CommandResults }
export type { CommandResultsProps }

View File

@@ -0,0 +1,59 @@
'use client'
import { useMemo, useState } from 'react'
import type { CommandGroup, CommandItem } from '../command/command.types'
interface UseCommandStateOptions {
groups: CommandGroup[]
defaultOpen?: boolean
}
interface UseCommandStateResult {
filteredGroups: CommandGroup[]
open: boolean
search: string
setOpen: (open: boolean) => void
setSearch: (value: string) => void
close: () => void
}
const filterItems = (items: CommandItem[], query: string) => {
if (!query) return items
const lowered = query.toLowerCase()
return items.filter((item) => {
const labelMatch = item.label.toLowerCase().includes(lowered)
const keywordsMatch = item.keywords?.some((keyword) => keyword.toLowerCase().includes(lowered))
const descriptionMatch = item.description?.toLowerCase().includes(lowered)
return labelMatch || keywordsMatch || descriptionMatch
})
}
const useCommandState = ({ groups, defaultOpen = false }: UseCommandStateOptions): UseCommandStateResult => {
const [open, setOpen] = useState(defaultOpen)
const [search, setSearch] = useState('')
const filteredGroups = useMemo(() => {
if (!search) return groups
return groups
.map((group) => ({
...group,
items: filterItems(group.items, search),
}))
.filter((group) => group.items.length > 0)
}, [groups, search])
return {
filteredGroups,
open,
search,
setOpen,
setSearch,
close: () => setOpen(false),
}
}
export { useCommandState }
export type { UseCommandStateOptions, UseCommandStateResult }

View File

@@ -1,255 +1,4 @@
// TODO: Split this file (254 LOC) into smaller organisms (<150 LOC each)
'use client'
import { forwardRef, ReactNode } from 'react'
import {
Drawer,
DrawerProps,
Box,
IconButton,
Typography,
} from '@mui/material'
import CloseIcon from '@mui/icons-material/Close'
// Sheet (Drawer) Root Component
interface SheetProps extends Omit<DrawerProps, 'anchor'> {
children: ReactNode
side?: 'left' | 'right' | 'top' | 'bottom'
onOpenChange?: (open: boolean) => void
}
const Sheet = forwardRef<HTMLDivElement, SheetProps>(
({ children, side = 'right', open, onClose, onOpenChange, ...props }, ref) => {
const handleClose = (_event: React.SyntheticEvent | object, reason: 'backdropClick' | 'escapeKeyDown') => {
if (typeof onClose === 'function') {
onClose(_event, reason)
}
onOpenChange?.(false)
}
return (
<Drawer
ref={ref}
anchor={side}
open={open}
onClose={handleClose}
{...props}
>
{children}
</Drawer>
)
}
)
Sheet.displayName = 'Sheet'
// SheetTrigger - returns children with onClick handler
interface SheetTriggerProps {
children: ReactNode
onClick?: () => void
asChild?: boolean
}
const SheetTrigger = forwardRef<HTMLButtonElement, SheetTriggerProps>(
({ children, onClick, asChild, ...props }, ref) => {
return (
<Box
ref={ref}
component="span"
onClick={onClick}
sx={{ cursor: 'pointer' }}
{...props}
>
{children}
</Box>
)
}
)
SheetTrigger.displayName = 'SheetTrigger'
// SheetContent
interface SheetContentProps {
children: ReactNode
side?: 'left' | 'right' | 'top' | 'bottom'
onClose?: () => void
showCloseButton?: boolean
className?: string
}
const SheetContent = forwardRef<HTMLDivElement, SheetContentProps>(
({ children, side = 'right', onClose, showCloseButton = true, ...props }, ref) => {
const isHorizontal = side === 'left' || side === 'right'
return (
<Box
ref={ref}
sx={{
width: isHorizontal ? 320 : '100%',
height: isHorizontal ? '100%' : 'auto',
maxHeight: !isHorizontal ? '80vh' : undefined,
display: 'flex',
flexDirection: 'column',
p: 3,
bgcolor: 'background.paper',
}}
{...props}
>
{showCloseButton && (
<IconButton
onClick={onClose}
sx={{
position: 'absolute',
top: 8,
right: 8,
color: 'text.secondary',
}}
size="small"
>
<CloseIcon fontSize="small" />
</IconButton>
)}
{children}
</Box>
)
}
)
SheetContent.displayName = 'SheetContent'
// SheetHeader
interface SheetHeaderProps {
children: ReactNode
className?: string
}
const SheetHeader = forwardRef<HTMLDivElement, SheetHeaderProps>(
({ children, ...props }, ref) => {
return (
<Box
ref={ref}
sx={{
display: 'flex',
flexDirection: 'column',
gap: 0.5,
pb: 2,
textAlign: 'left',
}}
{...props}
>
{children}
</Box>
)
}
)
SheetHeader.displayName = 'SheetHeader'
// SheetFooter
interface SheetFooterProps {
children: ReactNode
className?: string
}
const SheetFooter = forwardRef<HTMLDivElement, SheetFooterProps>(
({ children, ...props }, ref) => {
return (
<Box
ref={ref}
sx={{
display: 'flex',
flexDirection: 'column-reverse',
gap: 1,
pt: 2,
mt: 'auto',
sm: {
flexDirection: 'row',
justifyContent: 'flex-end',
},
}}
{...props}
>
{children}
</Box>
)
}
)
SheetFooter.displayName = 'SheetFooter'
// SheetTitle
interface SheetTitleProps {
children: ReactNode
className?: string
}
const SheetTitle = forwardRef<HTMLHeadingElement, SheetTitleProps>(
({ children, ...props }, ref) => {
return (
<Typography
ref={ref}
variant="h6"
component="h2"
sx={{
fontWeight: 600,
lineHeight: 1.2,
}}
{...props}
>
{children}
</Typography>
)
}
)
SheetTitle.displayName = 'SheetTitle'
// SheetDescription
interface SheetDescriptionProps {
children: ReactNode
className?: string
}
const SheetDescription = forwardRef<HTMLParagraphElement, SheetDescriptionProps>(
({ children, ...props }, ref) => {
return (
<Typography
ref={ref}
variant="body2"
color="text.secondary"
{...props}
>
{children}
</Typography>
)
}
)
SheetDescription.displayName = 'SheetDescription'
// SheetClose - button to close sheet
interface SheetCloseProps {
children: ReactNode
onClick?: () => void
asChild?: boolean
}
const SheetClose = forwardRef<HTMLButtonElement, SheetCloseProps>(
({ children, onClick, ...props }, ref) => {
return (
<Box
ref={ref}
component="span"
onClick={onClick}
sx={{ cursor: 'pointer' }}
{...props}
>
{children}
</Box>
)
}
)
SheetClose.displayName = 'SheetClose'
export {
Sheet,
SheetTrigger,
SheetContent,
SheetHeader,
SheetFooter,
SheetTitle,
SheetDescription,
SheetClose,
}
export { Sheet, SheetClose, SheetContent, SheetTrigger } from './Sheet/Drawer'
export { SheetDescription, SheetFooter, SheetHeader, SheetTitle } from './Sheet/Header'

View File

@@ -0,0 +1,129 @@
'use client'
import { forwardRef, ReactNode, SyntheticEvent } from 'react'
import { Box, Drawer, DrawerProps, IconButton } from '@mui/material'
import CloseIcon from '@mui/icons-material/Close'
interface SheetProps extends Omit<DrawerProps, 'anchor'> {
children: ReactNode
side?: 'left' | 'right' | 'top' | 'bottom'
onOpenChange?: (open: boolean) => void
}
const Sheet = forwardRef<HTMLDivElement, SheetProps>(
({ children, side = 'right', open, onClose, onOpenChange, ...props }, ref) => {
const handleClose = (_event: SyntheticEvent | object, reason: 'backdropClick' | 'escapeKeyDown') => {
if (typeof onClose === 'function') {
onClose(_event, reason)
}
onOpenChange?.(false)
}
return (
<Drawer
ref={ref}
anchor={side}
open={open}
onClose={handleClose}
{...props}
>
{children}
</Drawer>
)
}
)
Sheet.displayName = 'Sheet'
interface SheetTriggerProps {
children: ReactNode
onClick?: () => void
asChild?: boolean
}
const SheetTrigger = forwardRef<HTMLButtonElement, SheetTriggerProps>(
({ children, onClick, asChild, ...props }, ref) => {
return (
<Box
ref={ref}
component="span"
onClick={onClick}
sx={{ cursor: 'pointer' }}
{...props}
>
{children}
</Box>
)
}
)
SheetTrigger.displayName = 'SheetTrigger'
interface SheetContentProps {
children: ReactNode
side?: 'left' | 'right' | 'top' | 'bottom'
onClose?: () => void
showCloseButton?: boolean
className?: string
}
const SheetContent = forwardRef<HTMLDivElement, SheetContentProps>(
({ children, side = 'right', onClose, showCloseButton = true, ...props }, ref) => {
const isHorizontal = side === 'left' || side === 'right'
return (
<Box
ref={ref}
sx={{
width: isHorizontal ? 320 : '100%',
height: isHorizontal ? '100%' : 'auto',
maxHeight: !isHorizontal ? '80vh' : undefined,
display: 'flex',
flexDirection: 'column',
p: 3,
bgcolor: 'background.paper',
}}
{...props}
>
{showCloseButton && (
<IconButton
onClick={onClose}
sx={{
position: 'absolute',
top: 8,
right: 8,
color: 'text.secondary',
}}
size="small"
>
<CloseIcon fontSize="small" />
</IconButton>
)}
{children}
</Box>
)
}
)
SheetContent.displayName = 'SheetContent'
interface SheetCloseProps {
children: ReactNode
onClick?: () => void
asChild?: boolean
}
const SheetClose = forwardRef<HTMLButtonElement, SheetCloseProps>(
({ children, onClick, ...props }, ref) => {
return (
<Box
ref={ref}
component="span"
onClick={onClick}
sx={{ cursor: 'pointer' }}
{...props}
>
{children}
</Box>
)
}
)
SheetClose.displayName = 'SheetClose'
export { Sheet, SheetClose, SheetContent, SheetTrigger }

View File

@@ -0,0 +1,108 @@
'use client'
import { forwardRef, ReactNode } from 'react'
import { Box, Typography } from '@mui/material'
interface SheetHeaderProps {
children: ReactNode
className?: string
}
const SheetHeader = forwardRef<HTMLDivElement, SheetHeaderProps>(
({ children, ...props }, ref) => {
return (
<Box
ref={ref}
sx={{
display: 'flex',
flexDirection: 'column',
gap: 0.5,
pb: 2,
textAlign: 'left',
}}
{...props}
>
{children}
</Box>
)
}
)
SheetHeader.displayName = 'SheetHeader'
interface SheetFooterProps {
children: ReactNode
className?: string
}
const SheetFooter = forwardRef<HTMLDivElement, SheetFooterProps>(
({ children, ...props }, ref) => {
return (
<Box
ref={ref}
sx={{
display: 'flex',
flexDirection: 'column-reverse',
gap: 1,
pt: 2,
mt: 'auto',
sm: {
flexDirection: 'row',
justifyContent: 'flex-end',
},
}}
{...props}
>
{children}
</Box>
)
}
)
SheetFooter.displayName = 'SheetFooter'
interface SheetTitleProps {
children: ReactNode
className?: string
}
const SheetTitle = forwardRef<HTMLHeadingElement, SheetTitleProps>(
({ children, ...props }, ref) => {
return (
<Typography
ref={ref}
variant="h6"
component="h2"
sx={{
fontWeight: 600,
lineHeight: 1.2,
}}
{...props}
>
{children}
</Typography>
)
}
)
SheetTitle.displayName = 'SheetTitle'
interface SheetDescriptionProps {
children: ReactNode
className?: string
}
const SheetDescription = forwardRef<HTMLParagraphElement, SheetDescriptionProps>(
({ children, ...props }, ref) => {
return (
<Typography
ref={ref}
variant="body2"
color="text.secondary"
{...props}
>
{children}
</Typography>
)
}
)
SheetDescription.displayName = 'SheetDescription'
export { SheetDescription, SheetFooter, SheetHeader, SheetTitle }

View File

@@ -0,0 +1,69 @@
'use client'
import { forwardRef, ReactNode } from 'react'
import { Button, DialogActions } from '@mui/material'
interface AlertDialogFooterProps {
children: ReactNode
}
const AlertDialogFooter = forwardRef<HTMLDivElement, AlertDialogFooterProps>(
({ children, ...props }, ref) => {
return (
<DialogActions ref={ref} sx={{ p: 2, pt: 0 }} {...props}>
{children}
</DialogActions>
)
}
)
AlertDialogFooter.displayName = 'AlertDialogFooter'
interface AlertDialogCancelProps {
children?: ReactNode
onClick?: () => void
className?: string
}
const AlertDialogCancel = forwardRef<HTMLButtonElement, AlertDialogCancelProps>(
({ children = 'Cancel', onClick, className, ...props }, ref) => {
return (
<Button ref={ref} onClick={onClick} color="inherit" className={className} {...props}>
{children}
</Button>
)
}
)
AlertDialogCancel.displayName = 'AlertDialogCancel'
interface AlertDialogActionProps {
children?: ReactNode
onClick?: () => void
color?: 'primary' | 'error' | 'warning' | 'success' | 'info'
variant?: 'text' | 'outlined' | 'contained'
autoFocus?: boolean
className?: string
}
const AlertDialogAction = forwardRef<HTMLButtonElement, AlertDialogActionProps>(
(
{ children = 'Confirm', onClick, color = 'primary', variant = 'contained', autoFocus = true, className, ...props },
ref
) => {
return (
<Button
ref={ref}
onClick={onClick}
color={color}
variant={variant}
autoFocus={autoFocus}
className={className}
{...props}
>
{children}
</Button>
)
}
)
AlertDialogAction.displayName = 'AlertDialogAction'
export { AlertDialogAction, AlertDialogCancel, AlertDialogFooter }

View File

@@ -0,0 +1,141 @@
'use client'
import { forwardRef, ReactNode } from 'react'
import {
DialogContent,
DialogContentText,
DialogTitle,
IconButton,
Typography,
} from '@mui/material'
import CheckCircleOutlineIcon from '@mui/icons-material/CheckCircleOutline'
import CloseIcon from '@mui/icons-material/Close'
import ErrorOutlineIcon from '@mui/icons-material/ErrorOutline'
import InfoOutlinedIcon from '@mui/icons-material/InfoOutlined'
import WarningAmberIcon from '@mui/icons-material/WarningAmber'
interface AlertDialogContentProps {
children: ReactNode
showCloseButton?: boolean
onClose?: () => void
className?: string
}
const AlertDialogContent = forwardRef<HTMLDivElement, AlertDialogContentProps>(
({ children, showCloseButton = false, onClose, className, ...props }, ref) => {
return (
<>
{showCloseButton && onClose && (
<IconButton
onClick={onClose}
sx={{
position: 'absolute',
right: 8,
top: 8,
color: 'text.secondary',
}}
>
<CloseIcon />
</IconButton>
)}
{children}
</>
)
}
)
AlertDialogContent.displayName = 'AlertDialogContent'
interface AlertDialogHeaderProps {
children: ReactNode
icon?: 'warning' | 'error' | 'info' | 'success' | ReactNode
}
const AlertDialogHeader = forwardRef<HTMLDivElement, AlertDialogHeaderProps>(
({ children, icon, ...props }, ref) => {
const getIcon = () => {
if (!icon) return null
if (typeof icon !== 'string') return icon
const iconMap = {
warning: <WarningAmberIcon color="warning" sx={{ fontSize: 40 }} />,
error: <ErrorOutlineIcon color="error" sx={{ fontSize: 40 }} />,
info: <InfoOutlinedIcon color="info" sx={{ fontSize: 40 }} />,
success: <CheckCircleOutlineIcon color="success" sx={{ fontSize: 40 }} />,
}
return iconMap[icon]
}
const iconElement = getIcon()
return (
<DialogTitle
ref={ref}
id="alert-dialog-title"
sx={{
display: 'flex',
flexDirection: 'column',
alignItems: iconElement ? 'center' : 'flex-start',
gap: 1,
pt: 3,
pb: 0,
}}
{...props}
>
{iconElement}
{children}
</DialogTitle>
)
}
)
AlertDialogHeader.displayName = 'AlertDialogHeader'
interface AlertDialogTitleProps {
children: ReactNode
className?: string
}
const AlertDialogTitle = forwardRef<HTMLHeadingElement, AlertDialogTitleProps>(
({ children, className, ...props }, ref) => {
return (
<Typography
ref={ref}
variant="h6"
component="span"
className={className}
sx={{
fontWeight: 600,
textAlign: 'inherit',
}}
{...props}
>
{children}
</Typography>
)
}
)
AlertDialogTitle.displayName = 'AlertDialogTitle'
interface AlertDialogDescriptionProps {
children: ReactNode
className?: string
}
const AlertDialogDescription = forwardRef<HTMLDivElement, AlertDialogDescriptionProps>(
({ children, className, ...props }, ref) => {
return (
<DialogContent ref={ref} className={className} sx={{ pt: 2 }} {...props}>
<DialogContentText id="alert-dialog-description">
{children}
</DialogContentText>
</DialogContent>
)
}
)
AlertDialogDescription.displayName = 'AlertDialogDescription'
export {
AlertDialogContent,
AlertDialogDescription,
AlertDialogHeader,
AlertDialogTitle,
}