SavePopover
Location: src/components/post-parts/SavePopover.jsx
Overview
SavePopover is a portal-rendered popover that appears when a user wants to save a post with specific options (shelf selection and optional note). It renders via createPortal to document.body to avoid clipping by parent overflow styles.
The popover includes a shelf dropdown (with inline shelf creation), an expandable note input, and save/cancel action buttons. Position is calculated dynamically to appear above or below the save button.
Props
| Prop | Type | Required | Default | Description |
|---|---|---|---|---|
show | boolean | Yes | -- | Whether the popover is visible |
position | object | Yes | -- | Positioning with top, left, and showAbove fields |
popoverRef | ref | Yes | -- | Ref for the popover container element |
shelves | array | Yes | -- | Array of shelf objects with id, name, is_default |
selectedShelfId | string | Yes | -- | Currently selected shelf ID |
noteText | string | Yes | -- | Current note text value |
noteExpanded | boolean | Yes | -- | Whether the note input is expanded |
showShelfDropdown | boolean | Yes | -- | Whether the shelf selection dropdown is open |
creatingInline | boolean | Yes | -- | Whether the inline shelf creation input is shown |
newShelfName | string | Yes | -- | Name for a new shelf being created inline |
creatingShelf | boolean | Yes | -- | Whether shelf creation is in progress |
saving | boolean | Yes | -- | Whether the save operation is in progress |
shelfDropdownRef | ref | Yes | -- | Ref for the shelf dropdown container |
newShelfInputRef | ref | Yes | -- | Ref for the new shelf name input |
onShelfSelect | function | Yes | -- | Callback when a shelf is selected |
onToggleShelfDropdown | function | Yes | -- | Callback to toggle the shelf dropdown |
onNoteChange | function | Yes | -- | Callback when note text changes |
onToggleNoteExpanded | function | Yes | -- | Callback to toggle note input expansion |
onStartCreateShelf | function | Yes | -- | Callback to show inline shelf creation |
onCreateShelf | function | Yes | -- | Callback to create a new shelf |
onNewShelfNameChange | function | Yes | -- | Callback when new shelf name changes |
onCancelInlineCreate | function | Yes | -- | Callback to cancel inline shelf creation |
onConfirmSave | function | Yes | -- | Callback to confirm and execute the save |
onCancelSave | function | Yes | -- | Callback to cancel the save operation |
Key Behaviors
- Portal Rendering: Uses
createPortalto render ondocument.body, avoiding overflow clipping from post cards. - Dynamic Positioning: Supports rendering above or below the trigger element based on
position.showAbove. - Shelf Dropdown: Shows all available shelves with a checkmark on the selected one. Default shelves are marked with an asterisk.
- Inline Shelf Creation: Users can create a new shelf directly within the dropdown without leaving the save flow.
- Expandable Note: The note field starts collapsed as a "+ Add note" button, expanding to an input on click. Supports Enter to save and Escape to collapse.
- Overlay Dismiss: Clicking the overlay background cancels the save operation.
- Shelf Name Limit: New shelf names are capped at 30 characters.
Usage
import SavePopover from '@/components/post-parts/SavePopover';
<SavePopover
show={showSaveOptions}
position={popoverPosition}
popoverRef={popoverRef}
shelves={userShelves}
selectedShelfId={selectedShelf}
noteText={note}
noteExpanded={noteOpen}
showShelfDropdown={shelfOpen}
creatingInline={creatingShelf}
newShelfName={shelfName}
creatingShelf={creatingShelfLoading}
saving={saving}
shelfDropdownRef={shelfRef}
newShelfInputRef={shelfInputRef}
onShelfSelect={handleShelfSelect}
onToggleShelfDropdown={() => setShelfOpen(!shelfOpen)}
onNoteChange={setNote}
onToggleNoteExpanded={setNoteOpen}
onStartCreateShelf={() => setCreatingShelf(true)}
onCreateShelf={handleCreateShelf}
onNewShelfNameChange={setShelfName}
onCancelInlineCreate={() => setCreatingShelf(false)}
onConfirmSave={handleSave}
onCancelSave={() => setShowSaveOptions(false)}
/>
Related
- Post -- Parent component that manages save popover state
- PostActions -- Contains the save button that triggers this popover
- SavedPage -- Displays posts saved via this popover
Last updated: 2026-02-07