Skip to main content

Reusable user interaction patterns for FastHTML applications including multi-step wizards, master-detail views, modal workflows, and other stateful UI orchestration patterns.

Project description

cjm-fasthtml-interactions

Install

pip install cjm_fasthtml_interactions

Project Structure

nbs/
├── core/ (3)
│   ├── context.ipynb      # Context management for interaction patterns providing access to state, request, and custom data
│   ├── html_ids.ipynb     # Centralized HTML ID constants for interaction pattern components
│   └── state_store.ipynb  # Server-side workflow state storage implementations
└── patterns/ (7)
    ├── async_loading.ipynb           # Pattern for asynchronous content loading with skeleton loaders and loading indicators
    ├── master_detail.ipynb           # Responsive sidebar navigation pattern with master list and detail content area. On mobile devices, the sidebar is hidden in a drawer that can be toggled. On desktop (lg+ screens), the sidebar is always visible.
    ├── modal_dialog.ipynb            # Pattern for modal dialogs with customizable content, sizes, and actions
    ├── pagination.ipynb              # Pagination pattern with automatic route generation and state management
    ├── sse_connection_monitor.ipynb  # Pattern for monitoring Server-Sent Events (SSE) connections with visual status indicators and automatic reconnection
    ├── step_flow.ipynb               # Multi-step wizard pattern with state management, navigation, and route generation
    └── tabbed_interface.ipynb        # Multi-tab interface pattern with automatic routing, state management, and DaisyUI styling

Total: 10 notebooks across 2 directories

Module Dependencies

graph LR
    core_context[core.context<br/>Interaction Context]
    core_html_ids[core.html_ids<br/>HTML IDs]
    core_state_store[core.state_store<br/>Workflow State Store]
    patterns_async_loading[patterns.async_loading<br/>Async Loading Container]
    patterns_master_detail[patterns.master_detail<br/>Master-Detail]
    patterns_modal_dialog[patterns.modal_dialog<br/>Modal Dialog]
    patterns_pagination[patterns.pagination<br/>Pagination]
    patterns_sse_connection_monitor[patterns.sse_connection_monitor<br/>SSE Connection Monitor]
    patterns_step_flow[patterns.step_flow<br/>Step Flow]
    patterns_tabbed_interface[patterns.tabbed_interface<br/>Tabbed Interface]

    patterns_master_detail --> core_html_ids
    patterns_master_detail --> core_context
    patterns_modal_dialog --> core_html_ids
    patterns_modal_dialog --> patterns_async_loading
    patterns_pagination --> core_html_ids
    patterns_sse_connection_monitor --> core_html_ids
    patterns_step_flow --> core_state_store
    patterns_step_flow --> core_html_ids
    patterns_step_flow --> core_context
    patterns_tabbed_interface --> core_html_ids
    patterns_tabbed_interface --> core_context

11 cross-module dependencies detected

CLI Reference

No CLI commands found in this project.

Module Overview

Detailed documentation for each module in the project:

Async Loading Container (async_loading.ipynb)

Pattern for asynchronous content loading with skeleton loaders and loading indicators

Import

from cjm_fasthtml_interactions.patterns.async_loading import (
    LoadingType,
    AsyncLoadingContainer
)

Functions

def AsyncLoadingContainer(
    container_id: str,  # HTML ID for the container
    load_url: str,  # URL to fetch content from
    loading_type: LoadingType = LoadingType.SPINNER,  # Type of loading indicator
    loading_size: str = "lg",  # Size of loading indicator (xs, sm, md, lg)
    loading_message: Optional[str] = None,  # Optional message to display while loading
    skeleton_content: Optional[Any] = None,  # Optional skeleton/placeholder content
    trigger: str = "load",  # HTMX trigger event (default: load on page load)
    swap: str = "outerHTML",  # HTMX swap method (default: replace entire container)
    container_cls: Optional[str] = None,  # Additional CSS classes for container
    **kwargs  # Additional attributes for the container
) -> FT:  # Div element with async loading configured
    "Create a container that asynchronously loads content from a URL."

Classes

class LoadingType(Enum):
    "Types of loading indicators for async content."

Interaction Context (context.ipynb)

Context management for interaction patterns providing access to state, request, and custom data

Import

from cjm_fasthtml_interactions.core.context import (
    InteractionContext
)

Classes

@dataclass
class InteractionContext:
    "Context for interaction patterns providing access to state, request, and custom data."
    
    state: Dict[str, Any] = field(...)  # Workflow state
    request: Optional[Any]  # FastHTML request object
    session: Optional[Any]  # FastHTML session object
    data: Dict[str, Any] = field(...)  # Custom data from data loaders
    metadata: Dict[str, Any] = field(...)  # Additional metadata
    
    def get(self,
                key: str,  # Key to retrieve from state
                default: Any = None  # Default value if key not found
               ) -> Any:  # Value from state or default
        "Get value from workflow state."
    
    def get_data(self,
                     key: str,  # Key to retrieve from data
                     default: Any = None  # Default value if key not found
                    ) -> Any:  # Value from data or default
        "Get value from custom data."
    
    def has(self,
                key: str  # Key to check in state
               ) -> bool:  # True if key exists in state
        "Check if key exists in workflow state."
    
    def set(self,
                key: str,  # Key to set in state
                value: Any  # Value to store
               ) -> None
        "Set value in workflow state."
    
    def get_all_state(self) -> Dict[str, Any]:  # All workflow state
            """Get all workflow state as dictionary."""
            return self.state.copy()
        
        def update_state(self, 
                         updates: Dict[str, Any]  # State updates to apply
                        ) -> None
        "Get all workflow state as dictionary."
    
    def update_state(self,
                         updates: Dict[str, Any]  # State updates to apply
                        ) -> None
        "Update multiple state values at once."

HTML IDs (html_ids.ipynb)

Centralized HTML ID constants for interaction pattern components

Import

from cjm_fasthtml_interactions.core.html_ids import (
    InteractionHtmlIds
)

Classes

class InteractionHtmlIds(AppHtmlIds):
    """
    HTML ID constants for interaction pattern components.
    
    Inherits from AppHtmlIds:
        - MAIN_CONTENT = "main-content"
        - ALERT_CONTAINER = "alert-container"
        - as_selector(id_str) - static method
    """
    
    def step_content(step_id: str  # Step identifier
                        ) -> str:  # HTML ID for step content
        "Generate HTML ID for a specific step's content."
    
    def step_indicator(step_id: str  # Step identifier
                          ) -> str:  # HTML ID for step indicator
        "Generate HTML ID for a specific step's progress indicator."
    
    def tab_radio(tab_id: str  # Tab identifier
                     ) -> str:  # HTML ID for tab radio input
        "Generate HTML ID for a specific tab's radio input."
    
    def tab_content(tab_id: str  # Tab identifier
                       ) -> str:  # HTML ID for tab content
        "Generate HTML ID for a specific tab's content."
    
    def master_item(item_id: str  # Item identifier
                       ) -> str:  # HTML ID for master list item
        "Generate HTML ID for a master list item."
    
    def master_group(group_id: str  # Group identifier
                        ) -> str:  # HTML ID for master list group
        "Generate HTML ID for master list group."
    
    def detail_content(item_id: str  # Item identifier
                          ) -> str:  # HTML ID for detail content
        "Generate HTML ID for detail content area."
    
    def modal_dialog(modal_id: str  # Modal identifier
                        ) -> str:  # HTML ID for modal dialog
        "Generate HTML ID for a modal dialog."
    
    def modal_dialog_content(modal_id: str  # Modal identifier
                               ) -> str:  # HTML ID for modal content area
        "Generate HTML ID for modal content area."
    
    def sse_status(connection_id: str  # SSE connection identifier
                      ) -> str:  # HTML ID for SSE status indicator
        "Generate HTML ID for SSE connection status indicator."
    
    def sse_element(connection_id: str  # SSE connection identifier
                       ) -> str:  # HTML ID for SSE connection element
        "Generate HTML ID for SSE connection element."
    
    def pagination_container(pagination_id: str  # Pagination identifier
                               ) -> str:  # HTML ID for pagination container
        "Generate HTML ID for pagination container (entire paginated view)."
    
    def pagination_content(pagination_id: str  # Pagination identifier
                             ) -> str:  # HTML ID for pagination content area
        "Generate HTML ID for pagination content area (items display)."
    
    def pagination_nav(pagination_id: str  # Pagination identifier
                         ) -> str:  # HTML ID for pagination navigation controls
        "Generate HTML ID for pagination navigation controls."

Master-Detail (master_detail.ipynb)

Responsive sidebar navigation pattern with master list and detail content area. On mobile devices, the sidebar is hidden in a drawer that can be toggled. On desktop (lg+ screens), the sidebar is always visible.

Import

from cjm_fasthtml_interactions.patterns.master_detail import (
    DetailItem,
    DetailItemGroup,
    MasterDetail
)

Functions

@patch
def get_item(self:MasterDetail, 
             item_id: str  # Item identifier
            ) -> Optional[DetailItem]:  # DetailItem or None
    "Get item by ID."
@patch
def create_context(self:MasterDetail, 
                   request: Any,  # FastHTML request object
                   sess: Any,  # FastHTML session object
                   item: DetailItem  # Current item
                  ) -> InteractionContext:  # Interaction context for rendering
    "Create interaction context for an item."
@patch
def render_master(self:MasterDetail,
                  active_item_id: str,  # Currently active item ID
                  item_route_func: Callable[[str], str],  # Function to generate item route
                  include_wrapper: bool = True  # Whether to include outer wrapper div
                 ) -> FT:  # Master list element
    "Render master list (sidebar) with items and groups."
@patch
def _render_menu_items(self:MasterDetail,
                       active_item_id: str,  # Currently active item ID
                       item_route_func: Callable[[str], str]  # Function to generate item route
                      ) -> List[FT]:  # List of menu item elements
    "Render menu items and groups (internal helper)."
@patch
def render_master_oob(self:MasterDetail,
                      active_item_id: str,  # Currently active item ID
                      item_route_func: Callable[[str], str]  # Function to generate item route
                     ) -> FT:  # Master list with OOB swap attribute
    "Render master list with OOB swap attribute for coordinated updates."
@patch
def render_detail(self:MasterDetail,
                  item: DetailItem,  # Item to render
                  ctx: InteractionContext  # Interaction context
                 ) -> FT:  # Detail content
    "Render detail content for an item."
@patch
def render_full_interface(self:MasterDetail,
                         active_item_id: str,  # Currently active item ID
                         item_route_func: Callable[[str], str],  # Function to generate item route
                         request: Any,  # FastHTML request object
                         sess: Any  # FastHTML session object
                        ) -> FT:  # Complete master-detail interface
    "Render complete responsive master-detail interface with drawer for mobile."
@patch
def create_router(self:MasterDetail,
                  prefix: str = ""  # URL prefix for routes (e.g., "/media")
                 ) -> APIRouter:  # APIRouter with generated routes
    "Create FastHTML router with generated routes for this master-detail interface."

Classes

@dataclass
class DetailItem:
    "Definition of a single item in the master-detail pattern."
    
    id: str  # Unique identifier
    label: str  # Display text in master list
    render: Callable[[InteractionContext], Any]  # Function to render detail view
    badge_text: Optional[str]  # Optional badge text (e.g., "configured", "3 items")
    badge_color: Optional[str]  # Badge color class (e.g., badge_colors.success)
    icon: Optional[Any]  # Optional icon element
    data_loader: Optional[Callable[[Any], Dict[str, Any]]]  # Data loading function
    load_on_demand: bool = True  # Whether to load content only when item is selected
@dataclass
class DetailItemGroup:
    "Group of related detail items in a collapsible section."
    
    id: str  # Group identifier
    title: str  # Group display title
    items: List[DetailItem]  # Items in this group
    default_open: bool = True  # Whether group is expanded by default
    icon: Optional[Any]  # Optional group icon
    badge_text: Optional[str]  # Optional badge for the group
    badge_color: Optional[str]  # Badge color for the group
class MasterDetail:
    def __init__(
        self,
        interface_id: str,  # Unique identifier for this interface
        items: List[Union[DetailItem, DetailItemGroup]],  # List of items/groups
        default_item: Optional[str] = None,  # Default item ID (defaults to first item)
        container_id: str = InteractionHtmlIds.MASTER_DETAIL_CONTAINER,  # HTML ID for container
        master_id: str = InteractionHtmlIds.MASTER_DETAIL_MASTER,  # HTML ID for master list
        detail_id: str = InteractionHtmlIds.MASTER_DETAIL_DETAIL,  # HTML ID for detail area
        master_width: str = "w-64",  # Tailwind width class for master list
        master_title: Optional[str] = None,  # Optional title for master list
        show_on_htmx_only: bool = False  # Whether to show full interface for non-HTMX requests
    )
    "Manage master-detail interfaces with sidebar navigation and detail content area."
    
    def __init__(
            self,
            interface_id: str,  # Unique identifier for this interface
            items: List[Union[DetailItem, DetailItemGroup]],  # List of items/groups
            default_item: Optional[str] = None,  # Default item ID (defaults to first item)
            container_id: str = InteractionHtmlIds.MASTER_DETAIL_CONTAINER,  # HTML ID for container
            master_id: str = InteractionHtmlIds.MASTER_DETAIL_MASTER,  # HTML ID for master list
            detail_id: str = InteractionHtmlIds.MASTER_DETAIL_DETAIL,  # HTML ID for detail area
            master_width: str = "w-64",  # Tailwind width class for master list
            master_title: Optional[str] = None,  # Optional title for master list
            show_on_htmx_only: bool = False  # Whether to show full interface for non-HTMX requests
        )
        "Initialize master-detail manager."

Modal Dialog (modal_dialog.ipynb)

Pattern for modal dialogs with customizable content, sizes, and actions

Import

from cjm_fasthtml_interactions.patterns.modal_dialog import (
    ModalSize,
    ModalDialog,
    ModalTriggerButton
)

Functions

def ModalDialog(
    modal_id: str,  # Unique identifier for the modal
    content: Any,  # Content to display in the modal
    size: Union[ModalSize, str] = ModalSize.MEDIUM,  # Size preset or custom size
    show_close_button: bool = True,  # Whether to show X close button in top-right
    close_on_backdrop: bool = True,  # Whether clicking backdrop closes modal
    auto_show: bool = False,  # Whether to show modal immediately on render
    content_id: Optional[str] = None,  # Optional ID for content area (for HTMX targeting)
    custom_width: Optional[str] = None,  # Custom width class (e.g., "w-96")
    custom_height: Optional[str] = None,  # Custom height class (e.g., "h-screen")
    box_cls: Optional[str] = None,  # Additional classes for modal box
    **kwargs  # Additional attributes for the dialog element
) -> FT:  # Dialog element with modal dialog configured
    "Create a modal dialog using native HTML dialog element with DaisyUI styling."
def ModalTriggerButton(
    modal_id: str,  # ID of the modal to trigger
    label: str,  # Button label text
    button_cls: Optional[str] = None,  # Additional button classes
    **kwargs  # Additional button attributes
) -> FT:  # Button element that triggers modal
    "Create a button that opens a modal dialog."

Classes

class ModalSize(Enum):
    "Predefined size options for modal dialogs."

Pagination (pagination.ipynb)

Pagination pattern with automatic route generation and state management

Import

from cjm_fasthtml_interactions.patterns.pagination import (
    PaginationStyle,
    Pagination
)

Functions

@patch
def get_total_pages(self:Pagination, 
                    total_items: int  # Total number of items
                   ) -> int:  # Total number of pages
    "Calculate total number of pages."
@patch
def get_page_items(self:Pagination,
                   all_items: List[Any],  # All items
                   page: int  # Current page number (1-indexed)
                  ) -> tuple:  # (page_items, start_idx, end_idx)
    "Get items for the current page."
@patch
def build_route(self:Pagination,
                page: int,  # Page number
                request: Any,  # FastHTML request object
                page_route_func: Callable  # Route function from create_router
               ) -> str:  # Complete route with preserved params
    "Build route URL with preserved query parameters."
@patch
def render_navigation_controls(self:Pagination,
                               current_page: int,  # Current page number
                               total_pages: int,  # Total number of pages
                               route_func: Callable[[int], str]  # Function to generate route for page
                              ) -> FT:  # Navigation controls element
    "Render pagination navigation controls."
@patch
def render_page_content(self:Pagination,
                       page_items: List[Any],  # Items for current page
                       current_page: int,  # Current page number
                       total_pages: int,  # Total number of pages
                       request: Any,  # FastHTML request object
                       route_func: Callable[[int], str]  # Function to generate route for page
                      ) -> FT:  # Complete page content with items and navigation
    "Render complete page content with items and pagination controls."
@patch
def create_router(self:Pagination,
                  prefix: str = ""  # URL prefix for routes (e.g., "/library")
                 ) -> APIRouter:  # APIRouter with generated routes
    "Create FastHTML router with generated routes for pagination."

Classes

class PaginationStyle(Enum):
    "Display styles for pagination controls."
class Pagination:
    def __init__(
        self,
        pagination_id: str,  # Unique identifier for this pagination instance
        data_loader: Callable[[Any], List[Any]],  # Function that returns all items
        render_items: Callable[[List[Any], int, Any], Any],  # Function to render items for a page
        items_per_page: int = 20,  # Number of items per page
        container_id: str = None,  # HTML ID for container (auto-generated if None)
        content_id: str = None,  # HTML ID for content area (auto-generated if None)
        preserve_params: List[str] = None,  # Query parameters to preserve
        style: PaginationStyle = PaginationStyle.SIMPLE,  # Pagination display style
        prev_text: str = "« Previous",  # Text for previous button
        next_text: str = "Next »",  # Text for next button
        page_info_format: str = "Page {current} of {total}",  # Format for page info
        button_size: str = None,  # Button size class
        push_url: bool = True,  # Whether to update URL with hx-push-url
        show_endpoints: bool = False,  # Whether to show First/Last buttons
        first_text: str = "«« First",  # Text for first page button
        last_text: str = "Last »»",  # Text for last page button
        redirect_route: Optional[Callable[[int, Dict[str, Any]], str]] = None,  # Route to redirect non-HTMX requests
    )
    "Manage paginated views with automatic route generation and state management."
    
    def __init__(
            self,
            pagination_id: str,  # Unique identifier for this pagination instance
            data_loader: Callable[[Any], List[Any]],  # Function that returns all items
            render_items: Callable[[List[Any], int, Any], Any],  # Function to render items for a page
            items_per_page: int = 20,  # Number of items per page
            container_id: str = None,  # HTML ID for container (auto-generated if None)
            content_id: str = None,  # HTML ID for content area (auto-generated if None)
            preserve_params: List[str] = None,  # Query parameters to preserve
            style: PaginationStyle = PaginationStyle.SIMPLE,  # Pagination display style
            prev_text: str = "« Previous",  # Text for previous button
            next_text: str = "Next »",  # Text for next button
            page_info_format: str = "Page {current} of {total}",  # Format for page info
            button_size: str = None,  # Button size class
            push_url: bool = True,  # Whether to update URL with hx-push-url
            show_endpoints: bool = False,  # Whether to show First/Last buttons
            first_text: str = "«« First",  # Text for first page button
            last_text: str = "Last »»",  # Text for last page button
            redirect_route: Optional[Callable[[int, Dict[str, Any]], str]] = None,  # Route to redirect non-HTMX requests
        )
        "Initialize pagination manager."

SSE Connection Monitor (sse_connection_monitor.ipynb)

Pattern for monitoring Server-Sent Events (SSE) connections with visual status indicators and automatic reconnection

Import

from cjm_fasthtml_interactions.patterns.sse_connection_monitor import (
    SSEConnectionConfig,
    create_connection_status_indicators,
    SSEConnectionMonitorScript,
    SSEConnectionMonitor
)

Functions

def create_connection_status_indicators(
    status_size: str = "sm",  # Size of status indicator dot (xs, sm, md, lg)
    show_text: bool = True,  # Whether to show status text
    text_size: str = "text-sm",  # Text size class
    hide_text_on_mobile: bool = True  # Hide text on small screens
) -> Dict[str, FT]:  # Dictionary of status state to indicator element
    "Create status indicator elements for different connection states."
def SSEConnectionMonitorScript(
    connection_id: str,  # Unique identifier for this SSE connection
    status_indicators: Dict[str, FT],  # Status indicator elements for each state
    config: Optional[SSEConnectionConfig] = None  # Configuration options
) -> FT:  # Script element with monitoring code
    "Create a script that monitors SSE connection status and manages reconnection."
def SSEConnectionMonitor(
    connection_id: str,  # Unique identifier for this SSE connection
    status_size: str = "sm",  # Size of status indicator
    show_text: bool = True,  # Whether to show status text
    hide_text_on_mobile: bool = True,  # Hide text on small screens
    config: Optional[SSEConnectionConfig] = None,  # Configuration options
    container_cls: Optional[str] = None  # Additional CSS classes for status container
) -> tuple[FT, FT]:  # Tuple of (status_container, monitor_script)
    "Create a complete SSE connection monitoring system."

Classes

@dataclass
class SSEConnectionConfig:
    "Configuration for SSE connection monitoring."
    
    max_reconnect_attempts: int = 10  # Maximum number of reconnection attempts
    reconnect_delay: int = 1000  # Initial reconnect delay in milliseconds
    max_backoff_multiplier: int = 5  # Maximum backoff multiplier for reconnect delay
    monitor_visibility: bool = True  # Monitor tab visibility and reconnect when visible
    log_to_console: bool = True  # Enable console logging for debugging

Workflow State Store (state_store.ipynb)

Server-side workflow state storage implementations

Import

from cjm_fasthtml_interactions.core.state_store import (
    WorkflowStateStore,
    get_session_id,
    InMemoryWorkflowStateStore
)

Functions

def get_session_id(
    sess: Any,  # FastHTML session object
    key: str = "_workflow_session_id"  # Session key for storing the ID
) -> str:  # Stable session identifier
    "Get or create a stable session identifier."

Classes

@runtime_checkable
class WorkflowStateStore(Protocol):
    "Protocol for workflow state storage backends."
    
    def get_current_step(self,
                             flow_id: str,  # Workflow identifier
                             sess: Any  # FastHTML session object
                            ) -> Optional[str]:  # Current step ID or None
        "Get current step ID for a workflow."
    
    def set_current_step(self,
                             flow_id: str,  # Workflow identifier
                             sess: Any,  # FastHTML session object
                             step_id: str  # Step ID to set as current
                            ) -> None
        "Set current step ID for a workflow."
    
    def get_state(self,
                      flow_id: str,  # Workflow identifier
                      sess: Any  # FastHTML session object
                     ) -> Dict[str, Any]:  # Workflow state dictionary
        "Get all workflow state."
    
    def update_state(self,
                         flow_id: str,  # Workflow identifier
                         sess: Any,  # FastHTML session object
                         updates: Dict[str, Any]  # State updates to apply
                        ) -> None
        "Update workflow state with new values."
    
    def clear_state(self,
                        flow_id: str,  # Workflow identifier
                        sess: Any  # FastHTML session object
                       ) -> None
        "Clear all workflow state."
class InMemoryWorkflowStateStore:
    def __init__(self):
        """Initialize empty state storage."""
        self._current_steps: Dict[str, str] = {}  # {flow_id:session_id -> step_id}
    "In-memory workflow state storage for development and testing."
    
    def __init__(self):
            """Initialize empty state storage."""
            self._current_steps: Dict[str, str] = {}  # {flow_id:session_id -> step_id}
        "Initialize empty state storage."
    
    def get_current_step(self,
                             flow_id: str,  # Workflow identifier
                             sess: Any  # FastHTML session object
                            ) -> Optional[str]:  # Current step ID or None
        "Get current step ID for a workflow."
    
    def set_current_step(self,
                             flow_id: str,  # Workflow identifier
                             sess: Any,  # FastHTML session object
                             step_id: str  # Step ID to set as current
                            ) -> None
        "Set current step ID for a workflow."
    
    def get_state(self,
                      flow_id: str,  # Workflow identifier
                      sess: Any  # FastHTML session object
                     ) -> Dict[str, Any]:  # Workflow state dictionary
        "Get all workflow state."
    
    def update_state(self,
                         flow_id: str,  # Workflow identifier
                         sess: Any,  # FastHTML session object
                         updates: Dict[str, Any]  # State updates to apply
                        ) -> None
        "Update workflow state with new values."
    
    def clear_state(self,
                        flow_id: str,  # Workflow identifier
                        sess: Any  # FastHTML session object
                       ) -> None
        "Clear all workflow state."

Step Flow (step_flow.ipynb)

Multi-step wizard pattern with state management, navigation, and route generation

Import

from cjm_fasthtml_interactions.patterns.step_flow import (
    Step,
    StepFlow
)

Functions

@patch
def get_step(self:StepFlow, 
             step_id: str  # Step identifier
            ) -> Optional[Step]:  # Step object or None
    "Get step by ID."
@patch
def get_step_index(self:StepFlow, 
                   step_id: str  # Step identifier
                  ) -> Optional[int]:  # Step index or None
    "Get step index by ID."
@patch
def get_current_step_id(self:StepFlow, 
                        sess: Any  # FastHTML session object
                       ) -> str:  # Current step ID
    "Get current step ID from state store."
@patch
def set_current_step(self:StepFlow, 
                     sess: Any,  # FastHTML session object
                     step_id: str  # Step ID to set as current
                    ) -> None
    "Set current step in state store."
@patch
def get_next_step_id(self:StepFlow, 
                     current_step_id: str  # Current step ID
                    ) -> Optional[str]:  # Next step ID or None if last step
    "Get the ID of the next step."
@patch
def get_previous_step_id(self:StepFlow, 
                         current_step_id: str  # Current step ID
                        ) -> Optional[str]:  # Previous step ID or None if first step
    "Get the ID of the previous step."
@patch
def is_last_step(self:StepFlow, 
                 step_id: str  # Step ID to check
                ) -> bool:  # True if this is the last step
    "Check if step is the last step."
@patch
def is_first_step(self:StepFlow, 
                  step_id: str  # Step ID to check
                 ) -> bool:  # True if this is the first step
    "Check if step is the first step."
@patch
def get_workflow_state(self:StepFlow, 
                       sess: Any  # FastHTML session object
                      ) -> Dict[str, Any]:  # All workflow state
    "Get all workflow state from state store."
@patch
def update_workflow_state(self:StepFlow, 
                          sess: Any,  # FastHTML session object
                          updates: Dict[str, Any]  # State updates
                         ) -> None
    "Update workflow state with new values."
@patch
def clear_workflow(self:StepFlow, 
                   sess: Any  # FastHTML session object
                  ) -> None
    "Clear all workflow state."
@patch
def _summarize_state(self:StepFlow, 
                     state: Dict[str, Any]  # State dictionary to summarize
                    ) -> str:  # Human-readable summary string
    "Create a concise summary of state for debug output."
@patch
def create_context(self:StepFlow, 
                   request: Any,  # FastHTML request object
                   sess: Any,  # FastHTML session object
                   step: Step  # Current step
                  ) -> InteractionContext:  # Interaction context for rendering
    "Create interaction context for a step."
@patch
def render_progress(self:StepFlow, 
                    sess: Any  # FastHTML session object
                   ) -> FT:  # Progress indicator or empty Div
    "Render progress indicator showing all steps."
@patch
def render_step_content(self:StepFlow,
                        step_obj: Step,  # Step to render
                        ctx: InteractionContext,  # Interaction context
                        next_route: str,  # Route for next/submit
                        back_route: Optional[str] = None,  # Route for back
                        cancel_route: Optional[str] = None  # Route for cancel
                       ) -> FT:  # Complete step content with optional progress and navigation
    "Render step content with optional progress indicator and navigation."
@patch
def render_navigation(self:StepFlow,
                      step_id: str,  # Current step ID
                      next_route: str,  # Route for next/submit action
                      back_route: Optional[str] = None,  # Route for back action
                      cancel_route: Optional[str] = None,  # Route for cancel action
                     ) -> FT:  # Navigation button container
    "Render navigation buttons for a step."
@patch
def create_router(self:StepFlow,
                  prefix: str = ""  # URL prefix for routes (e.g., "/transcription")
                 ) -> APIRouter:  # APIRouter with generated routes
    "Create FastHTML router with generated routes for this flow."

Classes

@dataclass
class Step:
    "Definition of a single step in a multi-step workflow."
    
    id: str  # Unique step identifier (used in URLs)
    title: str  # Display title for the step
    render: Callable[[InteractionContext], Any]  # Function to render step UI
    validate: Optional[Callable[[Dict[str, Any]], bool]]  # Validation function
    data_loader: Optional[Callable[[Any], Dict[str, Any]]]  # Data loading function
    data_keys: List[str] = field(...)  # State keys managed by this step
    can_skip: bool = False  # Whether this step can be skipped
    show_back: bool = True  # Whether to show back button
    show_cancel: bool = True  # Whether to show cancel button
    next_button_text: str = 'Continue'  # Text for next/submit button
    
    def is_valid(self, state: Dict[str, Any]  # Current workflow state
                    ) -> bool:  # True if step is complete and valid
        "Check if step has valid data in state."
class StepFlow:
    def __init__(
        self,
        flow_id: str,  # Unique identifier for this workflow
        steps: List[Step],  # List of step definitions
        state_store: Optional[WorkflowStateStore] = None,  # Storage backend (defaults to InMemoryWorkflowStateStore)
        container_id: str = InteractionHtmlIds.STEP_FLOW_CONTAINER,  # HTML ID for content container
        on_complete: Optional[Callable[[Dict[str, Any], Any], Any]] = None,  # Completion handler
        show_progress: bool = False,  # Whether to show progress indicator
        wrap_in_form: bool = True,  # Whether to wrap content + navigation in a form
        debug: bool = False  # Whether to print debug information
    )
    "Manage multi-step workflows with automatic route generation and state management."
    
    def __init__(
            self,
            flow_id: str,  # Unique identifier for this workflow
            steps: List[Step],  # List of step definitions
            state_store: Optional[WorkflowStateStore] = None,  # Storage backend (defaults to InMemoryWorkflowStateStore)
            container_id: str = InteractionHtmlIds.STEP_FLOW_CONTAINER,  # HTML ID for content container
            on_complete: Optional[Callable[[Dict[str, Any], Any], Any]] = None,  # Completion handler
            show_progress: bool = False,  # Whether to show progress indicator
            wrap_in_form: bool = True,  # Whether to wrap content + navigation in a form
            debug: bool = False  # Whether to print debug information
        )
        "Initialize step flow manager."

Tabbed Interface (tabbed_interface.ipynb)

Multi-tab interface pattern with automatic routing, state management, and DaisyUI styling

Import

from cjm_fasthtml_interactions.patterns.tabbed_interface import (
    Tab,
    TabbedInterface
)

Functions

@patch
def get_tab(self:TabbedInterface, 
            tab_id: str  # Tab identifier
           ) -> Optional[Tab]:  # Tab object or None
    "Get tab by ID."
@patch
def get_tab_index(self:TabbedInterface, 
                  tab_id: str  # Tab identifier
                 ) -> Optional[int]:  # Tab index or None
    "Get tab index by ID."
@patch
def create_context(self:TabbedInterface, 
                   request: Any,  # FastHTML request object
                   sess: Any,  # FastHTML session object
                   tab: Tab  # Current tab
                  ) -> InteractionContext:  # Interaction context for rendering
    "Create interaction context for a tab."
@patch
def render_tabs(self:TabbedInterface,
                current_tab_id: str,  # Currently active tab ID
                tab_route_func: Callable[[str], str]  # Function to generate tab route
               ) -> FT:  # Tab navigation element
    "Render tab navigation using DaisyUI radio-based tabs."
@patch
def render_tab_content(self:TabbedInterface,
                       tab_obj: Tab,  # Tab to render
                       ctx: InteractionContext  # Interaction context
                      ) -> FT:  # Tab content
    "Render tab content."
@patch
def render_full_interface(self:TabbedInterface,
                         current_tab_id: str,  # Currently active tab ID
                         tab_route_func: Callable[[str], str],  # Function to generate tab route
                         request: Any,  # FastHTML request object
                         sess: Any  # FastHTML session object
                        ) -> FT:  # Complete tabbed interface
    "Render complete tabbed interface with tabs and content area."
@patch
def create_router(self:TabbedInterface,
                  prefix: str = ""  # URL prefix for routes (e.g., "/dashboard")
                 ) -> APIRouter:  # APIRouter with generated routes
    "Create FastHTML router with generated routes for this tabbed interface."

Classes

@dataclass
class Tab:
    "Definition of a single tab in a tabbed interface."
    
    id: str  # Unique tab identifier (used in URLs)
    label: str  # Display label for the tab
    render: Callable[[InteractionContext], Any]  # Function to render tab content
    title: Optional[str]  # Optional title/tooltip for the tab
    data_loader: Optional[Callable[[Any], Dict[str, Any]]]  # Data loading function
    load_on_demand: bool = True  # Whether to load content only when tab is selected
class TabbedInterface:
    def __init__(
        self,
        interface_id: str,  # Unique identifier for this interface
        tabs_list: List[Tab],  # List of tab definitions
        default_tab: Optional[str] = None,  # Default tab ID (defaults to first tab)
        container_id: str = InteractionHtmlIds.TABBED_INTERFACE_CONTAINER,  # HTML ID for container
        tabs_id: str = InteractionHtmlIds.TABBED_INTERFACE_TABS,  # HTML ID for tabs element
        content_id: str = InteractionHtmlIds.TABBED_INTERFACE_CONTENT,  # HTML ID for content area
        tab_style: Optional[str] = None,  # DaisyUI tab style (lift, bordered, boxed)
        show_on_htmx_only: bool = False  # Whether to show full page layout for non-HTMX requests
    )
    "Manage multi-tab interfaces with automatic route generation and HTMX content loading."
    
    def __init__(
            self,
            interface_id: str,  # Unique identifier for this interface
            tabs_list: List[Tab],  # List of tab definitions
            default_tab: Optional[str] = None,  # Default tab ID (defaults to first tab)
            container_id: str = InteractionHtmlIds.TABBED_INTERFACE_CONTAINER,  # HTML ID for container
            tabs_id: str = InteractionHtmlIds.TABBED_INTERFACE_TABS,  # HTML ID for tabs element
            content_id: str = InteractionHtmlIds.TABBED_INTERFACE_CONTENT,  # HTML ID for content area
            tab_style: Optional[str] = None,  # DaisyUI tab style (lift, bordered, boxed)
            show_on_htmx_only: bool = False  # Whether to show full page layout for non-HTMX requests
        )
        "Initialize tabbed interface manager."

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

cjm_fasthtml_interactions-0.0.26.tar.gz (64.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

cjm_fasthtml_interactions-0.0.26-py3-none-any.whl (61.4 kB view details)

Uploaded Python 3

File details

Details for the file cjm_fasthtml_interactions-0.0.26.tar.gz.

File metadata

File hashes

Hashes for cjm_fasthtml_interactions-0.0.26.tar.gz
Algorithm Hash digest
SHA256 d8b87c90eddc39a2423d768b5ea621b350097e30b39538bb4cdfee939e1d4355
MD5 db7c84c6f098f77ad2e17bdec58430b0
BLAKE2b-256 b954f3ab362a0968a597826ef581e858894986cac38d518a638293e927c8f70f

See more details on using hashes here.

File details

Details for the file cjm_fasthtml_interactions-0.0.26-py3-none-any.whl.

File metadata

File hashes

Hashes for cjm_fasthtml_interactions-0.0.26-py3-none-any.whl
Algorithm Hash digest
SHA256 f43b57eaf5d03cb3d3748b1e9a809c35db42a63ee9deeef1fd352636ef531566
MD5 1aa75799d9fd06caf049acc851f842a7
BLAKE2b-256 ae86a58c6d3e849e419057482b8f75f41a72c656c0b91df9f41a87d1c2daa5be

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page