Page Footer
Use the page footer when forms need to be saved, or inside a wizard. It’s a mandatory component inside the wizard template, which allows the user to perform the primary and secondary action of the wizard flow.
Example
function MyPageFooter() { const actions = { primaryAction: { onClick: () => console.log('primaryAction clicked'), label: 'Save', isLoading: true, disabled: true, tooltip: { content: 'Saving please wait...' }, dataTestId: 'primary-btn' }, secondaryAction: { onClick: () => console.log('secondaryAction clicked'), label: 'Reset', dataTestId: 'secondary-btn' }, destructiveAction: { onClick: () => console.log('destructiveAction clicked'), label: 'Delete', dataTestId: 'destructive-btn', disabled: true, tooltip: { content: 'Delete action is disabled' } } }; return ( <PageFooter primaryAction={actions.primaryAction} secondaryAction={actions.secondaryAction} destructiveAction={actions.destructiveAction} contextMessage="This is a contextual message." isFluidWidth css={{ position: 'relative' }} // to fit with Preview Container. /> ); }
Variants
Action with Icons
Primary action and destructive action can add an icon with iconName
and iconAlignment
.
function MyPageFooter() { const actions = { primaryAction: { label: 'Next', dataTestId: 'primary-btn', iconName: 'ChevronRight', iconAlignment: 'right' }, secondaryAction: { label: 'Secondary', dataTestId: 'secondary-btn' }, destructiveAction: { label: 'Delete', dataTestId: 'destructive-btn', iconName: 'Trash', iconAlignment: 'left' } }; return ( <> <PageFooter primaryAction={actions.primaryAction} secondaryAction={actions.secondaryAction} destructiveAction={actions.destructiveAction} isFluidWidth css={{ position: 'relative' }} // to fit with Preview Container. /> </> ); }
Actions with Type Property
Primary Action also can specify the type
as button
, submit
, or reset
.
function MyPageFooter() { const actions = { primaryAction: { label: 'Next', dataTestId: 'primary-btn', type: 'submit' }, secondaryAction: { label: 'Secondary', dataTestId: 'secondary-btn' }, destructiveAction: { label: 'Delete', dataTestId: 'destructive-btn', } }; return ( <> <PageFooter primaryAction={actions.primaryAction} secondaryAction={actions.secondaryAction} destructiveAction={actions.destructiveAction} isFluidWidth css={{ position: 'relative' }} // to fit with Preview Container. /> </> ); }
Checkbox
When the checkbox is used destructiveAction
and contextMessage
will be ignored and not displayed.
A checkbox can be added with same props as in Checkbox using prop checkboxProps
;
function MyPageFooter() { const actions = { primaryAction: { label: 'Next', dataTestId: 'primary-btn' }, secondaryAction: { label: 'Back', dataTestId: 'secondary-btn' } }; const [termsCheck, setTermsCheck] = useState(false); const handleCheck = (e) => { setTermsCheck(e.target.checked); }; const checkboxProps = { label: 'I’ve read and accept the Terms of Use for the Twitter Ad Network', helperText: 'It is required to agree to the terms before enabling this feature.', checked: termsCheck, onChange: (e) => handleCheck(e), required: true }; return ( <PageFooter primaryAction={actions.primaryAction} secondaryAction={actions.secondaryAction} checkboxProps={checkboxProps} isFluidWidth css={{ position: 'relative' }} // to fit with Preview Container. /> ); }
Context Message
A short message contextMessage
can be displayed in the footer for additional information on the status (eg. a feedback label if data has been saved), or to provide helpful information about the current, or upcoming step. If there is a destructive button inside the footer, as well as a context message, the messages moves to the right.
If the message is too long, it will be truncated. Using showTooltip
to see the full measgage.
function MyPageFooter() { const actions = { primaryAction: { label: 'Next', dataTestId: 'primary-btn' }, secondaryAction: { label: 'Back', dataTestId: 'secondary-btn' }, destructiveAction: { label: 'Delete', dataTestId: 'destructive-btn' } }; return ( <> <PageFooter primaryAction={actions.primaryAction} contextMessage="This is a contextual message." isFluidWidth css={{ position: 'relative' }} // to fit with Preview Container. /> <br /> <PageFooter destructiveAction={actions.destructiveAction} primaryAction={actions.primaryAction} contextMessage="This is a contextual message." isFluidWidth css={{ position: 'relative' }} // to fit with Preview Container. /> <br /> <PageFooter primaryAction={actions.primaryAction} secondaryAction={actions.secondaryAction} contextMessage="This is a contextual message. This is a contextual message. This is a contextual message. This is a contextual message." isFluidWidth showTooltip css={{ position: 'relative' }} // to fit with Preview Container. /> </> ); }
Custom Footer Actions
You can use the following props if you need to manage your action buttons with custom components.
customActionsLeft
:
This prop allows you to provide a custom component for the left-footer action area.
customActionsRight
:
This prop allows you to provide a custom component for the right-footer action area.
When considering the integration of custom slots within the PageFooter component, we encourage developers to adhere to the following guidelines:
- Responsiveness is Key: Ensure that all custom content inserted into the PageFooter component remains fully responsive across various screen sizes and resolutions. This ensures a consistent user experience and maintains the integrity of your application's design.
- Stay True to Atlas Design Guidelines: The PageFooter component is an essential part of the Atlas design system. Custom content should seamlessly blend with Atlas design principles to maintain visual harmony and a cohesive user interface.
- Prefer Atlas Components: Whenever possible, we recommend using Atlas components as custom content within the PageFooter. This ensures compatibility, consistency, and adherence to the Atlas design language.
By following these guidelines, you can effectively leverage custom slots in the PageFooter component while maintaining the quality, responsiveness, and visual coherence of your application.
function MyPageFooter() { const [termsChecked, setTermsChecked] = useState(false); const handleChange = (e) => { setTermsChecked(e.target.checked); }; const CustomActionsLeft = () => { return <Button label="Delete" kind="negative" />; }; const CustomActionsLeftWithCheckbox = () => { return ( <Checkbox label="I agree to the Terms and Conditions" helperText="It’s required to agree to the terms before enabling this feature." checked={termsChecked} onChange={(e) => handleChange(e)} required /> ); }; const CustomActionsRight = () => { return ( <> <Button label="Save" kind="primary" /> </> ); }; return ( <> <PageFooter contextMessage="This is a contextual message." customActionsLeft={<CustomActionsLeft />} customActionsRight={<CustomActionsRight />} isFluidWidth css={{ position: 'relative' }} // to fit with Preview Container. /> <PageFooter customActionsLeft={<CustomActionsLeftWithCheckbox />} customActionsRight={<CustomActionsRight />} isFluidWidth css={{ position: 'relative' }} // to fit with Preview Container. /> </> ); }
Disabled Actions
Actions can be disabled under certain conditions with disabled
.
function MyPageFooter() { const actions = { primaryAction: { label: 'Primary', dataTestId: 'primary-btn', disabled: true }, secondaryAction: { label: 'Secondary', dataTestId: 'secondary-btn', disabled: true }, destructiveAction: { label: 'Destructive', dataTestId: 'destructive-btn', disabled: true } }; return ( <> <PageFooter primaryAction={actions.primaryAction} secondaryAction={actions.secondaryAction} destructiveAction={actions.destructiveAction} isFluidWidth css={{ position: 'relative' }} // to fit with Preview Container. /> </> ); }
Layouts
The wizard footer is available as a fixed content width version (default), you can manage fixed width using layout
prop, as well as a fluid version with isFluidWidth
.
function MyPageFooter() { const [show, setShow] = useState(false); const [showXL, setShowXL] = useState(false); const [showFluid, setShowFluid] = useState(false); const actions = { primaryAction: { label: 'Primary', dataTestId: 'primary-btn' }, secondaryAction: { label: 'Secondary', dataTestId: 'secondary-btn', disabled: true }, destructiveAction: { label: 'Destructive', dataTestId: 'destructive-btn' } }; return ( <> <Button label="Default layout!" onClick={() => { setShow(!show); setShowFluid(false); setShowXL(false); }} /> {show && ( <PageFooter primaryAction={actions.primaryAction} secondaryAction={actions.secondaryAction} destructiveAction={actions.destructiveAction} contextMessage="This is a contextual message." css={{ margin: 0 }} // due to margin of Preview /> )} <Button label="XLlayout!" onClick={() => { setShowXL(!showXL); setShowFluid(false); setShow(false); }} /> {showXL && ( <PageFooter primaryAction={actions.primaryAction} secondaryAction={actions.secondaryAction} destructiveAction={actions.destructiveAction} contextMessage="This is a contextual message." css={{ margin: 0 }} // due to margin of Preview layout="x-large" /> )} <Button label="Fluid layout!" onClick={() => { setShowFluid(!showFluid); setShow(false); setShowXL(false); }} /> {showFluid && ( <PageFooter primaryAction={actions.primaryAction} secondaryAction={actions.secondaryAction} destructiveAction={actions.destructiveAction} contextMessage="This is a contextual message." isFluidWidth css={{ margin: 0 }} // due to margin of Preview /> )} </> ); }
Props
Name | Type | Default |
---|---|---|
secondaryAction Secondary action |
| — |
destructiveAction Destructive action |
| — |
contextMessage Context Message |
| — |
showTooltip Show the Tooltip for Context Message |
| false |
isFluidWidth Fluid Layout |
| false |
checkboxProps Checkbox properties |
| — |
dataTestId Context Message |
| "page-footer" |
layout Layout to set Max-width |
| "large" |
customActionsLeft Custom Action for the left side of the footer |
| — |
css Add custom styles to this component. Use with caution. Learn more here: Link |
| — |
inputFieldCss |
| — |
primaryAction Primary action and it's mandatory |
| — |
customActionsRight Custom Action for the right side of the footer |
| — |
data-{foo} Data attributes can be used by testing libraries to retrieve components or assert their existence |
| — |
* - the prop is required. |