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/ (2)
│   ├── 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
└── patterns/ (2)
    ├── 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: 4 notebooks across 2 directories

Module Dependencies

graph LR
    core_context[core.context<br/>Interaction Context]
    core_html_ids[core.html_ids<br/>HTML IDs]
    patterns_step_flow[patterns.step_flow<br/>Step Flow]
    patterns_tabbed_interface[patterns.tabbed_interface<br/>Tabbed Interface]

    patterns_step_flow --> core_context
    patterns_step_flow --> core_html_ids
    patterns_tabbed_interface --> core_context
    patterns_tabbed_interface --> core_html_ids

4 cross-module dependencies detected

CLI Reference

No CLI commands found in this project.

Module Overview

Detailed documentation for each module in the project:

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."

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 session."
@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 session."
@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 session."
@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 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
        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
    )
    "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
            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
        )
        "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.9.tar.gz (22.0 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.9-py3-none-any.whl (20.9 kB view details)

Uploaded Python 3

File details

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

File metadata

File hashes

Hashes for cjm_fasthtml_interactions-0.0.9.tar.gz
Algorithm Hash digest
SHA256 84b45064911492547794c68e71839ce3559af058a8554ab0218412c29a04cc1d
MD5 a6e5e9949f6537ac56a864a1fc0987cd
BLAKE2b-256 eb25a19fff1eda0f1a1422e599d3c14a52572f1736fa87d260c17dfc41728b0a

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for cjm_fasthtml_interactions-0.0.9-py3-none-any.whl
Algorithm Hash digest
SHA256 446ec9eefd85c872391bd75eea9c6d827c2b9270aea0e4f5f058821d71763f9f
MD5 3ed449d5007db5fdf1b6f8c7259f4a4e
BLAKE2b-256 89692944a6fb670fd29971821e8425129beb13e71f12aa7b6a88323b7c8163b1

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