TaskPanel
The TaskPanel component is used to group related actions or a single task together in a right drawer. Its internal content is defined by the children of the component.
Component
Storybook
Storybook - Task Panel DocumentationFigma Demo
Guidelines
Variations
The Task Panel offers two variants:
- Default: For most use cases with a footer and CTAS.
- Minimal: For use cases where the Task Panel is only used for messaging.
The Task Panel is offered in a single layout:
- Fixed Width: For larger screens (700px or above).
- Full Takeover: For smaller screens (699px & below).
The Task Panel must include:
- Title & Close Control: In the header area.
- One or Two CTAs: In the footer area, unless using the ‘minimal’ variant.
- Additional content will scroll in the main content area of the Task Panel.
Usage
The Task Panel should be used to surface tasks without leaving the current page, such as adding a distributor account number from the cart.
Using the Task Panel in Figma
Button Layout:
- By default, a pair of CTAs in the Task Panel footer will sit side-by-side with the primary button to the right. However, due to the fixed width of the panel on most screen sizes, this button layout may not allow for the full character count (~20 characters) intended for our buttons.
- A Figma variant of the panel is provided to switch between this default side-by-side layout and a stacked layout. If your button content is within the character count but too long for the default button layout, you may switch to the stacked layout for all breakpoints.
Task Panel Content:
- To allow for multiple use cases of the Task Panel, the main content area of the Figma component has a slot that is intended to be replaced with specific content.
- Create your arrangement of content that will go inside the Task Panel as a separate element.
- Consider space between elements in your layout, but the padding around your content will come from the panel itself.
- Set up your content to fill its parent container.
- Component-ize it.
- Give your component a unique name following the convention
TaskPanelContent_UniqueName
. - Place an instance of your component on the TaskPanel Content artboard in the Craft file (this helps us keep an eye on how Task Panel is getting used).
- Swap the placeholder component with your new component.
This process allows us to re-use the Task Panel without needing to detach instances to add content to the panel. Over time, we will have an assortment of distinct Task Panel content instances which will provide a high-level view of how the component is getting used.
Best Practices
- Use the Task Panel for tasks, not communication. For simple messaging purposes, consider an Alert or a Dialog.
Accessibility
Follow the intended purpose of the Task Panel by using content that helps users get things done. If there are no actionable items in the main content area for your use case — such as inputs or other choices to be made — another component might be better suited for your needs.
Component Specs
API
clickOutsideCallback:
() => void
Callback function when clicking outside the Task Panel.closeBtnClick:
() => void
Callback function when clicking the close button.id:
string
| Default:'task-panel'
Id for the Task Panel.hidden:
boolean
| Default:true
Boolean to show or hide the Task Panel.noPadding:
boolean
| Default:false
Boolean to remove padding from the main area of the Task Panel.open:
boolean
Boolean to open or close the Task Panel.primaryBtnProps:
HTMLButtonAttributes
Props for the primary button.primaryClick:
() => void
Callback function when clicking the primary button.primaryLabel:
string
| Default:'Save'
Label for the primary button.primaryType:
HTMLButtonAttributes['type']
| Default:'button'
Type for the primary button.secondaryBtnProps:
HTMLButtonAttributes
Props for the secondary button.secondaryClick:
() => void
Callback function when clicking the secondary button.secondaryLabel:
string | null
| Default:'Cancel'
Label for the secondary button. Set to null to hide the secondary button.secondaryType:
HTMLButtonAttributes['type']
| Default:'button'
Type for the secondary button.sortStack:
boolean
| Default:false
Boolean to change the order of the primary and secondary buttons when there is long copy.title:
string
Title for the Task Panel.testId:
string
| Default:'test-task-panel'
Id for the test.variant:
string
| Default:'default'
Variant for the Task Panel.@slot default: Slot for the content of the Task Panel.
@slot footer: Slot for the footer of the Task Panel.
Example
<script>
import { TaskPanel, DrawerTrigger } from '@getprovi/craft-svelte';
</script>
<!-- TaskPanel needs a DrawerTrigger right or a button with the same id -->
<DrawerTrigger
variant="right"
id="task-panel"
label="Open Drawer"
triggerClick={() => (open = !open)}
testId="test-drawer-trigger"
/>
<TaskPanel
title="Task Panel"
id="task-panel"
testId="test-task-panel"
clickOutsideCallback={() => 'Task Panel Closed'}
closeBtnClick={() => 'Close Button Clicked'}
primaryClick={() => 'Primary Button Clicked'}
primaryLabel="Save"
secondaryClick={() => 'Secondary Button Clicked'}
secondaryLabel="Cancel"
>
<div>Task Panel Content</div>
</TaskPanel>
<TaskPanel
title="Only Primary CTA"
id="primary-cta"
primaryLabel="Only Primary"
secondaryLabel={null}
>
<div>Task Panel Content</div>
</TaskPanel>
<!-- sortStack prop is used to change the order of the primary and secondary buttons when there is long copy -->
<TaskPanel
title="Task Panel"
id="sort-stack"
primaryLabel="A long label for the primary button"
secondaryLabel="A long label for the secondary button"
sortStack
>
<div>Task Panel Content</div>
</TaskPanel>
Types
interface Props {
clickOutsideCallback?: () => void;
closeBtnClick?: () => void;
hidden?: boolean;
id?: string;
noPadding?: boolean;
open?: boolean;
primaryBtnProps?: HTMLButtonAttributes;
primaryClick?: () => void;
primaryLabel?: string;
primaryType?: HTMLButtonAttributes['type'];
secondaryBtnProps?: HTMLButtonAttributes;
secondaryClick?: () => void;
secondaryLabel?: string | null;
secondaryType?: HTMLButtonAttributes['type'];
sortStack?: boolean;
title: string;
testId?: string;
variant?: 'default' | 'minimal';
}