I have a form component that uses Fluent UI v9 for styling. For some reason my form inputs (located in the drawer body) overlap the footer border (located in the drawer footer) when scrolling but I am not sure why. I also observed the switch control components do not have this effect on the footer border.
Form body Fluent ui Input controls overlapping form footer border Form body Fluent ui Switch controls do not overlap form footer border
//FORM BODY
const useStyles = makeStyles({
root: {
display: 'flex',
flexDirection: 'column',
alignItems: 'flex-start',
...shorthands.gap('12px'),
marginTop: '20px',
marginBottom: '40px',
paddingBottom: '24px',
paddingLeft: '20px',
...shorthands.overflow('auto'),
borderLeftWidth: '1.5px',
borderLeftStyle: 'solid',
borderLeftColor: '#954ac7',
borderBottomStyle: 'none',
borderBottomWidth: 'none',
borderBottomColor: 'none',
},
filterContainer: {
...commonStyles.filterContainer,
width: '500px',
},
label: commonStyles.label,
});
type Props = {
formMode: FormMode;
};
function NewEventForm({ formMode }: Props) {
const [selectedEvent] = useAtom(selectedEventAtom);
console.log(selectedEvent);
const classNames = useStyles();
const [isExternal, setIsExternal] = useState(false);
const [isAllDay, setIsAllDay] = useState(false);
const [isRecurring, setIsRecurring] = useState(false);
const [isCle, setIsCle] = useState(false);
const eventStartTime = selectedEvent?.start ? new Date(selectedEvent.start) : undefined;
const formattedTime = eventStartTime ? eventStartTime.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit', hour12: true }) : undefined;
return (
<DrawerBody>
<div className={classNames.root}>
<div className={classNames.filterContainer}>
<Label className={classNames.label}>Event name</Label>
<Input
placeholder='Event Name'
value={selectedEvent?.title || ''}
{...(formMode === 'preview' ? {
disabled: true,
defaultValue: selectedEvent?.title
} : formMode === 'edit' ? {defaultValue: selectedEvent?.title} : '')}
/>
</div>
<div className={classNames.filterContainer}>
<Label className={classNames.label}>Internal/External</Label>
<Switch
label={isExternal ? 'External' : 'Internal'}
onChange={() => setIsExternal(!isExternal)}
value={selectedEvent?.externalOrInternal || ''}
{...(formMode === 'preview' && { disabled: true, defaultValue: selectedEvent?.externalOrInternal })}
/>
</div>
{isExternal ? (
<div className={classNames.filterContainer}>
<Label className={classNames.label}>Location (External)</Label>
<Input
required placeholder="Enter location"
value={selectedEvent?.location || ''}
{...(formMode === 'preview' && { disabled: true, defaultValue: selectedEvent?.location })}
/>
</div>
) : (
<div className={classNames.filterContainer}>
<Label className={classNames.label}>Location (Internal)</Label>
<Dropdown
placeholder="Select location"
value={selectedEvent?.location || ''}
{...(formMode === 'preview' && { disabled: true, defaultValue: selectedEvent?.location })}
>
{INTERNAL_LOCATIONS.map((location) => (
<Option key={location} value={location}>
{location}
</Option>
))}
</Dropdown>
</div>
)}
<div className={classNames.filterContainer}>
<Label className={classNames.label}>Event date</Label>
<DatePicker
placeholder="Select date" required
value={selectedEvent?.start || null}
{...(formMode === 'preview' && {
disabled: true,
defaultValue: selectedEvent?.start
})}
/>
</div>
<div className={classNames.filterContainer}>
<Label className={classNames.label}>Event time</Label>
<TimePicker
placeholder="Select time" required hourCycle="h12"
value={formattedTime || ''}
{...(formMode === 'preview' && {
disabled: true,
defaultValue: formattedTime
})}
/>
</div>
<div className={classNames.filterContainer}>
<Label className={classNames.label}>Time Zone</Label>
<Dropdown
placeholder="Select time zone"
value={selectedEvent?.eventTimeZone || ''}
{...(formMode === 'preview' && { disabled: true, defaultValue: selectedEvent?.eventTimeZone })}
>
{TIME_ZONES.map((tz) => (
<Option key={tz} value={tz}>
{tz}
</Option>
))}
</Dropdown>
</div>
<div className={classNames.filterContainer}>
<Label className={classNames.label}>Description</Label>
<Textarea
placeholder="Edit description"
value={selectedEvent?.description || ''}
{...(formMode === 'preview' && { disabled: true, defaultValue: selectedEvent?.description })}
/>
</div>
<div className={classNames.filterContainer}>
<Label className={classNames.label}>CLE</Label>
<Switch
label={isCle ? 'Yes' : 'No'}
onChange={() => setIsCle(!isCle)}
{...(formMode === 'preview' && {
disabled: true,
label: selectedEvent?.cle ? 'Yes' : 'No',
defaultChecked: selectedEvent?.cle
})}
/>
</div>
<div className={classNames.filterContainer}>
<Label className={classNames.label}>All day</Label>
<Switch
label={isAllDay ? 'Yes' : 'No'}
onChange={() => setIsAllDay(!isAllDay)}
{...(formMode === 'preview' && {
disabled: true,
label: selectedEvent?.allDay ? 'Yes' : 'No',
defaultChecked: selectedEvent?.allDay
})}
/>
</div>
<div className={classNames.filterContainer}>
<Label className={classNames.label}>Recurring</Label>
<Switch
label={isRecurring ? 'Yes' : 'No'}
onChange={() => setIsRecurring(!isRecurring)}
/>
</div>
<div className={classNames.filterContainer}>
<Label className={classNames.label}>Category</Label>
<Combobox
placeholder="Choose category"
required
freeform
value={selectedEvent?.category || ''}
{...(formMode === 'preview' && { disabled: true, defaultValue: selectedEvent?.category })}
>
{CATEGORIES.map((category) => (
<Option key={category} value={category}>
{category}
</Option>
))}
</Combobox>
</div>
<div className={classNames.filterContainer}>
<Label className={classNames.label}>Event Type</Label>
<Combobox
placeholder="Choose event type"
required
freeform
value={selectedEvent?.eventType || ''}
{...(formMode === 'preview' && { disabled: true, defaultValue: selectedEvent?.eventType })}
>
{EVENT_TYPES.map((eventType) => (
<Option key={eventType} value={eventType}>
{eventType}
</Option>
))}
</Combobox>
</div>
</div>
</DrawerBody>
);
}
// FORM FOOTER
const useStyles = makeStyles({
button: {
marginTop: '24px',
backgroundColor: '#5c3380',
...shorthands.border('2px', 'solid', '#5c3380'),
":hover": {
backgroundColor: '#954ac7',
...shorthands.border('2px', 'solid', '#954ac7'),
}
},
buttonSecondary: {
marginTop: '24px',
backgroundColor: '#ffffff',
color: '#000000',
fontWeight: 'bold',
...shorthands.border('2px', 'solid', '#000000'),
":hover": { color: '#7b7b7e' },
},
footer:{
borderTopWidth: '1px',
borderTopStyle: 'solid',
borderTopColor: '#000000',
marginTop: '20px',
}
});
function Footer({ handleClose }: Props) {
const classNames = useStyles();
const [formMode, setFormMode] = useAtom(formModeAtom);
const [, setSelectedEvent] = useAtom(selectedEventAtom);
return (
<DrawerFooter className={classNames.footer}>
<Button
className={classNames.button}
appearance="primary"
onClick={() => {
const newFormMode = formMode === 'preview' ? 'edit' : 'new';
newFormMode === 'edit' && console.log('Edit') || newFormMode === 'new' && console.log('Submit');
formMode === 'edit' && setSelectedEvent(null);
setFormMode(newFormMode);
newFormMode === 'new' && handleClose();
}}
>
{formMode === 'preview' ? 'Edit' : 'Submit'}
</Button>
<Button
className={classNames.buttonSecondary}
appearance="secondary"
onClick={() => { handleClose() }}
>
Cancel
</Button>
</DrawerFooter>
);
}
export default Footer;