Source code for wildewidgets.widgets.headers
from __future__ import annotations
import warnings
from typing import Any
from .base import Block, TemplateWidget
from .buttons import CollapseButton, FormButton, LinkButton, ModalButton
[docs]class BasicHeader(TemplateWidget):
"""
The base header class for all header widgets in the wildewidgets library.
This class provides the core functionality for rendering HTML headers with
various styling options, including optional badges. All other header classes
inherit from this class.
Example:
.. code-block:: python
from wildewidgets import BasicHeader
header = BasicHeader(
header_text="Welcome to the Dashboard",
header_level=1,
badge_text="New",
badge_class="success"
)
Attributes:
template_name: Path to the Django template used for rendering
header_level: HTML heading level (1-6) to use
header_type: Type of header styling ("h" for standard, "display" for larger)
header_text: The text content of the header
css_class: CSS classes to apply to the header container
css_id: Optional ID attribute for the header element
badge_text: Optional text for a badge beside the header
badge_class: Bootstrap color class for the badge (e.g., "primary",
"warning")
badge_rounded_pill: Whether to style the badge as a rounded pill
Keyword Args:
header_level: the header depth, as in h1, h2, h3...
header_type: the Boostrap 5 header class, either h-*, or display-*.
header_text: the text of the header.
css_class: any css classes to apply to the header.
css_id: an ID to add to the header div.
badge_text: text to add in a badge to the right of the main header text.
badge_class: the css class to add to the badge.
"""
template_name: str = "wildewidgets/header_with_controls.html"
header_level: int = 1
header_type: str = "h"
header_text: str | None = None
css_class: str = "my-3"
css_id: str | None = None
badge_text: str | None = None
badge_class: str = "warning"
badge_rounded_pill: bool = True
def __init__(
self,
header_level: int | None = None,
header_type: str | None = None,
header_text: str | None = None,
css_class: str | None = None,
css_id: str | None = None,
badge_text: str | None = None,
badge_class: str | None = None,
badge_rounded_pill: bool | None = None,
**kwargs: Any,
):
self.header_level = header_level or self.header_level
self.header_type = header_type or self.header_type
self.header_text = header_text or self.header_text
self.css_class = css_class or self.css_class
self.css_id = css_id or self.css_id
self.badge_text = badge_text or self.badge_text
self.badge_class = badge_class or self.badge_class
self.badge_rounded_pill = (
badge_rounded_pill
if badge_rounded_pill is not None
else self.badge_rounded_pill
)
kwargs["title"] = self.header_text
super().__init__(**kwargs)
[docs] def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
"""
Prepare the context data for template rendering.
Processes header settings and adds them to the template context.
Sets the appropriate header class based on the header type and level,
and includes all other header properties.
Args:
**kwargs: Initial context dictionary
Returns:
dict: Updated context dictionary with header properties
"""
if self.header_type == "h":
kwargs["header_class"] = f"h{self.header_level}"
elif self.header_type == "display":
kwargs["header_class"] = f"display-{self.header_level}"
kwargs["header_level"] = self.header_level
kwargs["header_text"] = self.header_text
kwargs["header_type"] = self.header_type
kwargs["css_class"] = self.css_class
kwargs["css_id"] = self.css_id
kwargs["badge_text"] = self.badge_text
kwargs["badge_class"] = self.badge_class
kwargs["badge_rounded_pill"] = self.badge_rounded_pill
return kwargs
[docs]class HeaderWithLinkButton(BasicHeader):
"""
A header with an attached link button.
This combines a heading element with a button that links to a specified URL.
The button appears to the right of the header text.
Deprecated:
This class is deprecated since version 0.13.45.
Use :py:class:`HeaderWithWidget` with the :py:meth:`add_link_button`
method instead.
Example:
.. code-block:: python
from wildewidgets import HeaderWithLinkButton
header = HeaderWithLinkButton(
header_text="Users",
header_level=2,
url="/users/add/",
link_text="Add User",
button_class="success"
)
Attributes:
template_name: Path to the template for rendering this widget
url: The URL that the button links to
link_text: The text displayed on the button
button_class: Bootstrap contextual class for the button
"""
template_name = "wildewidgets/header_with_link_button.html"
url: str | None = None
link_text: str | None = None
button_class: str = "primary"
def __init__(
self,
url: str | None = None,
link_text: str | None = None,
button_class: str | None = None,
**kwargs: Any,
):
warnings.warn(
"HeaderWithLinkButton is deprecated. Use "
"wildewidgets.HeaderWithWidget instead",
DeprecationWarning,
stacklevel=2,
)
self.url = url or self.url
self.link_text = link_text or self.link_text
self.button_class = button_class or self.button_class
super().__init__(**kwargs)
[docs] def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
"""
Prepare the context data for template rendering.
Adds link button specific variables to the context dictionary.
Args:
**kwargs: Initial context dictionary from parent class
Returns:
dict: Updated context with url, link_text, and button_class
"""
kwargs = super().get_context_data(**kwargs)
kwargs["url"] = self.url
kwargs["link_text"] = self.link_text
kwargs["button_class"] = self.button_class
return kwargs
[docs]class HeaderWithFormButton(BasicHeader):
"""
A header with an attached form submission button.
This combines a heading element with a button that submits a form
when clicked. The form must be defined elsewhere in your template.
Deprecated:
This class is deprecated since version 0.13.45.
Use :py:class:`HeaderWithWidget` with the :py:meth:`add_form_button`
method instead.
Example:
.. code-block:: python
from wildewidgets import HeaderWithFormButton
header = HeaderWithFormButton(
header_text="Dangerous Action",
header_level=3,
url="/api/delete-all/",
button_text="Delete All"
)
Attributes:
template_name: Path to the template for rendering this widget
url: The URL that the form will submit to
button_text: The text displayed on the button
"""
template_name = "wildewidgets/header_with_form_button.html"
url: str | None = None
button_text: str | None = None
def __init__(
self, url: str | None = None, button_text: str | None = None, **kwargs: Any
):
warnings.warn(
"HeaderWithFormButton is deprecated. Use "
"wildewidgets.HeaderWithWidget instead",
DeprecationWarning,
stacklevel=2,
)
self.url = url or self.url
self.button_text = button_text or self.button_text
super().__init__(**kwargs)
[docs] def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
"""
Prepare the context data for template rendering.
Adds form button specific variables to the context dictionary.
Args:
**kwargs: Initial context dictionary from parent class
Returns:
dict: Updated context with url and button_text
"""
kwargs = super().get_context_data(**kwargs)
kwargs["url"] = self.url
kwargs["button_text"] = self.button_text
return kwargs
[docs]class HeaderWithCollapseButton(BasicHeader):
"""
A header with a button that toggles a Bootstrap collapsible element.
This combines a heading element with a button that expands or collapses
a target element when clicked. The collapsible element must be defined
elsewhere in your template.
Deprecated:
This class is deprecated since version 0.13.45.
Use :py:class:`HeaderWithWidget` with the :py:meth:`add_collapse_button`
method instead.
Example:
.. code-block:: python
from wildewidgets import HeaderWithCollapseButton
header = HeaderWithCollapseButton(
header_text="Advanced Options",
header_level=3,
collapse_id="advanced-options",
button_text="Toggle"
)
Attributes:
template_name: Path to the template for rendering this widget
collapse_id: ID of the collapsible element to toggle
button_text: Text displayed on the button
button_class: Bootstrap contextual class for the button
"""
template_name: str = "wildewidgets/header_with_collapse_button.html"
collapse_id: str | None = None
button_text: str | None = None
button_class: str | None = "primary"
def __init__(
self,
collapse_id: str | None = None,
button_text: str | None = None,
button_class: str | None = None,
**kwargs: Any,
):
warnings.warn(
"HeaderWithCollapseButton is deprecated. Use "
"wildewidgets.HeaderWithWidget instead",
DeprecationWarning,
stacklevel=2,
)
self.collapse_id = collapse_id or self.collapse_id
self.button_text = button_text or self.button_text
self.button_class = button_class or self.button_class
super().__init__(**kwargs)
[docs] def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
"""
Prepare the context data for template rendering.
Adds collapse button specific variables to the context dictionary.
Args:
**kwargs: Initial context dictionary from parent class
Returns:
dict: Updated context with collapse_id, button_text, and button_class
"""
kwargs = super().get_context_data(**kwargs)
kwargs["collapse_id"] = self.collapse_id
kwargs["button_text"] = self.button_text
kwargs["button_class"] = self.button_class
return kwargs
[docs]class HeaderWithModalButton(BasicHeader):
"""
A header widget with a button that triggers a Bootstrap modal.
This class combines a heading element with a button that opens a modal dialog
when clicked. The modal must be defined elsewhere in your template.
Deprecated:
This class is deprecated since version 0.13.45.
Use :py:class:`HeaderWithWidget` with the :py:meth:`add_modal_button`
Attributes:
template_name: Path to the template for rendering this widget
modal_id: ID of the modal to be triggered by the button
button_text: Text to display on the button
button_class: Bootstrap button class (e.g., "primary", "secondary")
Keyword Args:
**kwargs: Keyword arguments including modal_id, button_text, and
button_class, plus any arguments for BasicHeader
"""
template_name = "wildewidgets/header_with_modal_button.html"
modal_id: str | None = None
button_text: str | None = None
button_class: str = "primary"
def __init__(self, **kwargs: Any):
warnings.warn(
"Use wildewidgets.HeaderWithWidget instead",
DeprecationWarning,
stacklevel=2,
)
super().__init__(**kwargs)
self.modal_id = kwargs.get("modal_id", self.modal_id)
self.button_text = kwargs.get("button_text", self.button_text)
self.button_class = kwargs.get("button_class", self.button_class)
[docs] def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
"""
Prepare the context data for template rendering.
Adds modal button specific variables to the context dictionary.
Args:
**kwargs: Initial context dictionary from parent class
Returns:
dict: Updated context with modal_id, button_text, and button_class
"""
kwargs = super().get_context_data(**kwargs)
kwargs["modal_id"] = self.modal_id
kwargs["button_text"] = self.button_text
kwargs["button_class"] = self.button_class
return kwargs
[docs]class HeaderWithWidget(BasicHeader):
"""
A header widget that can contain another widget (typically a button).
This flexible header class allows adding any widget (most commonly buttons)
next to the header text. This is the recommended approach for creating headers
with interactive elements.
Example:
.. code-block:: python
from wildewidgets import HeaderWithWidget, LinkButton
# Create a header with a link button
header = HeaderWithWidget(
header_text="Products List",
header_level=2,
widget=LinkButton(text="Add Product", url="/products/add/")
)
# Or add the button after initialization
header = HeaderWithWidget(header_text="Products List")
header.add_link_button(text="Add Product", url="/products/add/")
Args:
widget: Widget to display next to the header text
Keyword Args:
header_text: Text content of the header
header_level: HTML heading level (1-6)
**kwargs: Additional arguments passed to BasicHeader
"""
template_name = "wildewidgets/header_with_widget.html"
def __init__(self, widget: Block | None = None, **kwargs: Any):
super().__init__(**kwargs)
self.widget = widget
[docs] def add_form_button(self, **kwargs: Any) -> None:
"""
Add a form submission button to the header.
This method creates a FormButton instance and adds it to the header.
The button will submit a form when clicked.
Args:
**kwargs: Arguments passed to :py:class:`wildewidgets.FormButton`
constructor.
Common arguments include:
* text: Button label text
* action: Form submission URL
* color: Bootstrap color class (default: "secondary")
* method: HTTP method (default: "post")
* confirm_text: Text for confirmation dialog (if needed)
"""
self.widget = FormButton(**kwargs)
[docs] def add_link_button(self, **kwargs: Any) -> None:
"""
Add a hyperlink button to the header.
This method creates a LinkButton instance and adds it to the header.
The button will navigate to the specified URL when clicked.
Args:
**kwargs: Arguments passed to :py:class:`wildewidgets.LinkButton`
constructor.
Common arguments include:
* text: Button label text
* url: Target URL for the link
* color: Bootstrap color class (default: "secondary")
* css_class: Additional CSS classes
"""
self.widget = LinkButton(**kwargs)
[docs] def add_modal_button(self, **kwargs: Any) -> None:
"""
Add a button that triggers a Bootstrap modal dialog.
This method creates a ModalButton instance and adds it to the header.
The button will open the specified modal when clicked.
Args:
**kwargs: Arguments passed to :py:class:`wildewidgets.ModalButton`
constructor.
Common arguments include:
* text: Button label text
* target: Modal ID to target (with # prefix)
* color: Bootstrap color class (default: "secondary")
"""
self.widget = ModalButton(**kwargs)
[docs] def add_collapse_button(self, **kwargs: Any) -> None:
"""
Add a button that toggles a Bootstrap collapsible element.
This method creates a CollapseButton instance and adds it to the header.
The button will toggle the visibility of the specified collapsible element.
Args:
**kwargs: Arguments passed to
:py:class:`wildewidgets.CollapseButton` constructor.
Common arguments include:
* text: Button label text
* target: Collapse target ID (with # prefix)
* color: Bootstrap color class (default: "secondary")
"""
self.widget = CollapseButton(**kwargs)
[docs] def set_widget(self, widget: Block) -> None:
"""
Set or replace the widget displayed next to the header.
This method allows setting any widget (not just buttons) to appear next
to the header text. This provides flexibility beyond the specialized
button methods.
Args:
widget: Any Block-derived widget to display in the header
"""
self.widget = widget
[docs] def get_context_data(self, **kwargs: Any) -> dict[str, Any]:
"""
Get the context data for rendering the template.
Adds the widget to the template context, along with other header properties.
Args:
**kwargs: Additional context variables
Returns:
dict: Updated context dictionary including the widget
"""
kwargs = super().get_context_data(**kwargs)
kwargs["widget"] = self.widget
return kwargs
[docs]class PageHeader(HeaderWithWidget):
"""
Provides a standard page header.
This is an H1 header with a widget, typically used at the top of a page
to provide a title and an action button or other interactive element.
Example:
.. code-block:: python
from wildewidgets import PageHeader, LinkButton
header = PageHeader(
header_text="Welcome to the Dashboard",
widget=LinkButton(text="Learn More", url="/about/")
)
"""
css_class: str = "my-4"
[docs]class CardHeader(HeaderWithWidget):
"""
A header specifically designed for Bootstrap card components.
This provides an H2 header with appropriate styling for use as a card header,
with the option to include an action button or other widget.
Example:
.. code-block:: python
from wildewidgets import CardHeader, LinkButton
header = CardHeader(
header_text="User Details",
widget=LinkButton(text="Edit", url="/users/123/edit/")
)
"""
css_class: str = "my-3"
header_level: int = 2
[docs]class WidgetListLayoutHeader(HeaderWithWidget):
"""
A specialized header for use with WidgetListLayout components.
This header is designed to match the styling of the WidgetListLayout
component, providing consistent margins and header size. It can include
an optional action button or other widget.
Example:
.. code-block:: python
from wildewidgets import WidgetListLayoutHeader, LinkButton
header = WidgetListLayoutHeader(
header_text="Dashboard Widgets",
widget=LinkButton(text="Add Widget", url="/widgets/add/")
)
"""
css_class: str = "mb-4"
header_level: int = 2