diff --git a/src/app/features/room/PollCreator.tsx b/src/app/features/room/PollCreator.tsx index b80e38bc8..8b7f018a6 100644 --- a/src/app/features/room/PollCreator.tsx +++ b/src/app/features/room/PollCreator.tsx @@ -1,7 +1,24 @@ -import React, { useState } from 'react'; +import React, { FormEventHandler, useState } from 'react'; +import FocusTrap from 'focus-trap-react'; +import { + Box, + Button, + Header, + Icon, + IconButton, + Icons, + Input, + Overlay, + OverlayBackdrop, + OverlayCenter, + Spinner, + Text, + color, + config, +} from 'folds'; import { Room } from 'matrix-js-sdk'; -import { Box, Button, Icon, IconButton, Icons, Text, config } from 'folds'; import { useMatrixClient } from '../../hooks/useMatrixClient'; +import { stopPropagation } from '../../utils/keyboard'; interface PollCreatorProps { roomId: string; @@ -35,7 +52,10 @@ export function PollCreator({ roomId, onClose }: PollCreatorProps) { setOptions((prev) => prev.filter((_, i) => i !== index)); }; - const handleSubmit = async () => { + const handleSubmit: FormEventHandler = async (e) => { + e.preventDefault(); + if (submitting) return; + const trimmedQuestion = question.trim(); if (!trimmedQuestion) { setError('Please enter a question.'); @@ -68,182 +88,177 @@ export function PollCreator({ roomId, onClose }: PollCreatorProps) { }; return ( -
{ - if (e.target === e.currentTarget) onClose(); - }} - > -
- - Create Poll - - - - - -
- Question - }> + + + setQuestion(e.target.value)} - autoFocus - /> -
- -
- Options - {options.map((opt, index) => ( -
+ {/* Header */} +
- handleOptionChange(index, e.target.value)} - /> - handleRemoveOption(index)} - disabled={options.length <= 2} - aria-label={`Remove option ${index + 1}`} - > - + + + Create Poll + + + + -
- ))} - {options.length < 10 && ( - - )} -
+ - - Selection Type - - {(['single', 'multiple'] as const).map((type) => { - const active = type === 'multiple' ? isMultiple : !isMultiple; - return ( + {/* Body */} + + {/* Question */} + + + Question + + ) => setQuestion(e.target.value)} + // eslint-disable-next-line jsx-a11y/no-autofocus + autoFocus + /> + + + {/* Options */} + + Options + {options.map((opt, index) => ( + // eslint-disable-next-line react/no-array-index-key + + ) => + handleOptionChange(index, e.target.value) + } + aria-label={`Option ${index + 1}`} + /> + handleRemoveOption(index)} + disabled={options.length <= 2} + aria-label={`Remove option ${index + 1}`} + > + + + + ))} + {options.length < 10 && ( + + + + )} + + + {/* Selection type */} + + Selection Type + + {(['single', 'multiple'] as const).map((type) => { + const active = type === 'multiple' ? isMultiple : !isMultiple; + return ( + + ); + })} + + + + {/* Error */} + {error && ( + + {error} + + )} + + {/* Footer actions */} + - ); - })} + + + - - - {error && ( - - {error} - - )} - - - - - -
-
+ + + ); }