diff --git a/components/fakemui/email/atoms/MarkAsReadCheckbox.tsx b/components/fakemui/email/atoms/MarkAsReadCheckbox.tsx index 719037e4e..af78901fb 100644 --- a/components/fakemui/email/atoms/MarkAsReadCheckbox.tsx +++ b/components/fakemui/email/atoms/MarkAsReadCheckbox.tsx @@ -1,42 +1,49 @@ +// fakemui/email/atoms/MarkAsReadCheckbox.tsx import React, { forwardRef, useState } from 'react' import { useAccessible } from '../../../../hooks/useAccessible' -export interface MarkAsReadCheckboxProps extends React.InputHTMLAttributes { +export interface MarkAsReadCheckboxProps + extends React.InputHTMLAttributes { isRead?: boolean onToggleRead?: (read: boolean) => void testId?: string } -export const MarkAsReadCheckbox = forwardRef( - ({ isRead = false, onToggleRead, testId: customTestId, ...props }, ref) => { - const [read, setRead] = useState(isRead) +export const MarkAsReadCheckbox = forwardRef< + HTMLInputElement, + MarkAsReadCheckboxProps +>(({ isRead = false, onToggleRead, testId, ...props }, ref) => { + const [read, setRead] = useState(isRead) - const accessible = useAccessible({ - feature: 'email', - component: 'read-checkbox', - identifier: customTestId || 'read-status' - }) + const accessible = useAccessible({ + feature: 'email', + component: 'read-checkbox', + identifier: testId || 'read-status' + }) - const handleChange = (e: React.ChangeEvent) => { - const newState = e.target.checked - setRead(newState) - onToggleRead?.(newState) - props.onChange?.(e) - } - - return ( - - ) + const handleChange = ( + e: React.ChangeEvent + ) => { + const next = e.target.checked + setRead(next) + onToggleRead?.(next) + props.onChange?.(e) } -) + + const label = read ? 'Mark as unread' : 'Mark as read' + + return ( + + ) +}) MarkAsReadCheckbox.displayName = 'MarkAsReadCheckbox' diff --git a/components/fakemui/email/atoms/StarButton.tsx b/components/fakemui/email/atoms/StarButton.tsx index 2f50c6c29..ac8bc5b93 100644 --- a/components/fakemui/email/atoms/StarButton.tsx +++ b/components/fakemui/email/atoms/StarButton.tsx @@ -1,43 +1,54 @@ +// fakemui/email/atoms/StarButton.tsx import React, { forwardRef, useState } from 'react' +import { MaterialIcon } from '../../../../icons/react/fakemui' import { useAccessible } from '../../../../hooks/useAccessible' -export interface StarButtonProps extends React.ButtonHTMLAttributes { +export interface StarButtonProps + extends React.ButtonHTMLAttributes { isStarred?: boolean onToggleStar?: (starred: boolean) => void testId?: string } -export const StarButton = forwardRef( - ({ isStarred = false, onToggleStar, testId: customTestId, ...props }, ref) => { - const [starred, setStarred] = useState(isStarred) +export const StarButton = forwardRef< + HTMLButtonElement, + StarButtonProps +>(({ isStarred = false, onToggleStar, testId, ...props }, ref) => { + const [starred, setStarred] = useState(isStarred) - const accessible = useAccessible({ - feature: 'email', - component: 'star-button', - identifier: customTestId || 'star' - }) + const accessible = useAccessible({ + feature: 'email', + component: 'star-button', + identifier: testId || 'star' + }) - const handleClick = (e: React.MouseEvent) => { - const newState = !starred - setStarred(newState) - onToggleStar?.(newState) - props.onClick?.(e) - } - - return ( - - ) + const handleClick = ( + e: React.MouseEvent + ) => { + const next = !starred + setStarred(next) + onToggleStar?.(next) + props.onClick?.(e) } -) + + const label = starred ? 'Remove star' : 'Add star' + const icon = starred ? 'star' : 'star_border' + + return ( + + ) +}) StarButton.displayName = 'StarButton' diff --git a/components/fakemui/email/data-display/EmailHeader.tsx b/components/fakemui/email/data-display/EmailHeader.tsx index 58a5f98ba..7915b124e 100644 --- a/components/fakemui/email/data-display/EmailHeader.tsx +++ b/components/fakemui/email/data-display/EmailHeader.tsx @@ -31,15 +31,23 @@ export const EmailHeader = ({ component: 'email-header', identifier: customTestId || subject }) + const iso = new Date(receivedAt).toISOString() + const display = new Date(receivedAt).toLocaleString() return (
- + {subject}
- + From: {from} - + To: {to.join(', ')} {cc && cc.length > 0 && ( - + Cc: {cc.join(', ')} )} - - {new Date(receivedAt).toLocaleString()} + +
diff --git a/components/fakemui/email/data-display/ThreadList.tsx b/components/fakemui/email/data-display/ThreadList.tsx index 41a53f165..ff5b30450 100644 --- a/components/fakemui/email/data-display/ThreadList.tsx +++ b/components/fakemui/email/data-display/ThreadList.tsx @@ -5,11 +5,14 @@ import { useAccessible } from '../../../../hooks/useAccessible' import { EmailCard, type EmailCardProps } from '../surfaces' export interface ThreadListProps extends BoxProps { - emails: Array> + emails: Array> selectedEmailId?: string onSelectEmail?: (emailId: string) => void - onToggleRead?: (emailId: string, read: boolean) => void - onToggleStar?: (emailId: string, starred: boolean) => void + onToggleRead?: (id: string, read: boolean) => void + onToggleStar?: (id: string, star: boolean) => void testId?: string } @@ -28,23 +31,44 @@ export const ThreadList = ({ identifier: customTestId || 'threads' }) + const emailId = (e: typeof emails[0], i: number) => + e.testId || `email-${i}` + return ( {emails.length === 0 ? ( -
No emails
+
+ No emails +
) : ( emails.map((email, idx) => ( - onSelectEmail?.(email.testId || `email-${idx}`)} - onToggleRead={(read) => onToggleRead?.(email.testId || `email-${idx}`, read)} - onToggleStar={(starred) => onToggleStar?.(email.testId || `email-${idx}`, starred)} - /> +
+ + onSelectEmail?.(emailId(email, idx)) + } + onToggleRead={(read) => + onToggleRead?.( + emailId(email, idx), read + ) + } + onToggleStar={(starred) => + onToggleStar?.( + emailId(email, idx), starred + ) + } + /> +
)) )}
diff --git a/components/fakemui/email/inputs/BodyEditor.tsx b/components/fakemui/email/inputs/BodyEditor.tsx index e5c2ee238..d94c1dff1 100644 --- a/components/fakemui/email/inputs/BodyEditor.tsx +++ b/components/fakemui/email/inputs/BodyEditor.tsx @@ -3,48 +3,62 @@ import React, { forwardRef } from 'react' import { Box } from '../../layout/Box' import { useAccessible } from '../../../../hooks/useAccessible' -export interface BodyEditorProps extends React.TextareaHTMLAttributes { +export interface BodyEditorProps + extends React.TextareaHTMLAttributes< + HTMLTextAreaElement + > { mode?: 'plain' | 'html' onModeChange?: (mode: 'plain' | 'html') => void testId?: string } -export const BodyEditor = forwardRef( - ({ mode = 'plain', onModeChange, testId: customTestId, ...props }, ref) => { - const accessible = useAccessible({ - feature: 'email', - component: 'body-editor', - identifier: customTestId || 'body' - }) +export const BodyEditor = forwardRef< + HTMLTextAreaElement, + BodyEditorProps +>(({ + mode = 'plain', + onModeChange, + testId: customTestId, + ...props +}, ref) => { + const accessible = useAccessible({ + feature: 'email', + component: 'body-editor', + identifier: customTestId || 'body', + ariaLabel: 'Email body' + }) - return ( - -
- - -
-