Skip to main content

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

PropTypeRequiredDefaultDescription
showbooleanYes--Whether the popover is visible
positionobjectYes--Positioning with top, left, and showAbove fields
popoverRefrefYes--Ref for the popover container element
shelvesarrayYes--Array of shelf objects with id, name, is_default
selectedShelfIdstringYes--Currently selected shelf ID
noteTextstringYes--Current note text value
noteExpandedbooleanYes--Whether the note input is expanded
showShelfDropdownbooleanYes--Whether the shelf selection dropdown is open
creatingInlinebooleanYes--Whether the inline shelf creation input is shown
newShelfNamestringYes--Name for a new shelf being created inline
creatingShelfbooleanYes--Whether shelf creation is in progress
savingbooleanYes--Whether the save operation is in progress
shelfDropdownRefrefYes--Ref for the shelf dropdown container
newShelfInputRefrefYes--Ref for the new shelf name input
onShelfSelectfunctionYes--Callback when a shelf is selected
onToggleShelfDropdownfunctionYes--Callback to toggle the shelf dropdown
onNoteChangefunctionYes--Callback when note text changes
onToggleNoteExpandedfunctionYes--Callback to toggle note input expansion
onStartCreateShelffunctionYes--Callback to show inline shelf creation
onCreateShelffunctionYes--Callback to create a new shelf
onNewShelfNameChangefunctionYes--Callback when new shelf name changes
onCancelInlineCreatefunctionYes--Callback to cancel inline shelf creation
onConfirmSavefunctionYes--Callback to confirm and execute the save
onCancelSavefunctionYes--Callback to cancel the save operation

Key Behaviors

  • Portal Rendering: Uses createPortal to render on document.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)}
/>
  • 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