mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-23 16:31:08 -05:00
Add standardized HTMX conventions, interaction patterns, and migration guide for ThrillWiki UX
This commit is contained in:
133
backend/templates/components/navigation/README.md
Normal file
133
backend/templates/components/navigation/README.md
Normal file
@@ -0,0 +1,133 @@
|
||||
# Navigation Components
|
||||
|
||||
This directory contains navigation-related template components.
|
||||
|
||||
## Components
|
||||
|
||||
### breadcrumbs.html
|
||||
|
||||
Semantic breadcrumb navigation with Schema.org structured data support.
|
||||
|
||||
#### Features
|
||||
|
||||
- Accessible navigation with proper ARIA attributes
|
||||
- Schema.org BreadcrumbList JSON-LD for SEO
|
||||
- Responsive design with mobile-friendly collapse
|
||||
- Customizable separators and icons
|
||||
- Truncation for long labels
|
||||
|
||||
#### Basic Usage
|
||||
|
||||
```django
|
||||
{# Breadcrumbs are automatically included from context processor #}
|
||||
{% include 'components/navigation/breadcrumbs.html' %}
|
||||
```
|
||||
|
||||
#### Setting Breadcrumbs in Views
|
||||
|
||||
```python
|
||||
from apps.core.utils.breadcrumbs import build_breadcrumb, BreadcrumbBuilder
|
||||
from django.urls import reverse
|
||||
|
||||
def park_detail(request, slug):
|
||||
park = get_object_or_404(Park, slug=slug)
|
||||
|
||||
# Option 1: Build breadcrumbs manually
|
||||
request.breadcrumbs = [
|
||||
build_breadcrumb('Home', '/', icon='fas fa-home'),
|
||||
build_breadcrumb('Parks', reverse('parks:list')),
|
||||
build_breadcrumb(park.name, is_current=True),
|
||||
]
|
||||
|
||||
# Option 2: Use the builder pattern
|
||||
request.breadcrumbs = (
|
||||
BreadcrumbBuilder()
|
||||
.add_home()
|
||||
.add('Parks', reverse('parks:list'))
|
||||
.add_current(park.name)
|
||||
.build()
|
||||
)
|
||||
|
||||
return render(request, 'parks/detail.html', {'park': park})
|
||||
```
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Parameter | Type | Default | Description |
|
||||
|-----------|------|---------|-------------|
|
||||
| `items` | list | `breadcrumbs` | List of Breadcrumb objects |
|
||||
| `show_schema` | bool | `True` | Include Schema.org JSON-LD |
|
||||
| `show_home_icon` | bool | `True` | Show icon on home breadcrumb |
|
||||
| `separator` | str | chevron | Custom separator character |
|
||||
| `max_visible` | int | `3` | Max items before mobile collapse |
|
||||
| `container_class` | str | `""` | Additional CSS classes |
|
||||
|
||||
#### Accessibility
|
||||
|
||||
- Uses `<nav>` element with `aria-label="Breadcrumb"`
|
||||
- Ordered list (`<ol>`) for semantic structure
|
||||
- `aria-current="page"` on current page item
|
||||
- Hidden separators for screen readers
|
||||
|
||||
#### Examples
|
||||
|
||||
**Custom separator:**
|
||||
```django
|
||||
{% include 'components/navigation/breadcrumbs.html' with separator='/' %}
|
||||
```
|
||||
|
||||
**Without Schema.org:**
|
||||
```django
|
||||
{% include 'components/navigation/breadcrumbs.html' with show_schema=False %}
|
||||
```
|
||||
|
||||
**Custom breadcrumbs:**
|
||||
```django
|
||||
{% include 'components/navigation/breadcrumbs.html' with items=custom_crumbs %}
|
||||
```
|
||||
|
||||
## Breadcrumb Utilities
|
||||
|
||||
### BreadcrumbBuilder
|
||||
|
||||
Fluent builder for constructing breadcrumbs:
|
||||
|
||||
```python
|
||||
from apps.core.utils.breadcrumbs import BreadcrumbBuilder
|
||||
|
||||
breadcrumbs = (
|
||||
BreadcrumbBuilder()
|
||||
.add_home()
|
||||
.add_from_url('parks:list', 'Parks')
|
||||
.add_model(park)
|
||||
.add_from_url('rides:list', 'Rides', {'park_slug': park.slug})
|
||||
.add_model_current(ride)
|
||||
.build()
|
||||
)
|
||||
```
|
||||
|
||||
### get_model_breadcrumb
|
||||
|
||||
Generate breadcrumbs for model instances with parent relationships:
|
||||
|
||||
```python
|
||||
from apps.core.utils.breadcrumbs import get_model_breadcrumb
|
||||
|
||||
# For a Ride that belongs to a Park
|
||||
breadcrumbs = get_model_breadcrumb(
|
||||
ride,
|
||||
parent_attr='park',
|
||||
list_url_name='rides:list',
|
||||
list_label='Rides',
|
||||
)
|
||||
# Returns: [Home, Parks, Cedar Point, Rides, Millennium Force]
|
||||
```
|
||||
|
||||
## Context Processor
|
||||
|
||||
The `breadcrumbs` context processor (`apps.core.context_processors.breadcrumbs`) provides:
|
||||
|
||||
- `breadcrumbs`: List of Breadcrumb objects from view
|
||||
- `breadcrumbs_json`: Schema.org JSON-LD string
|
||||
- `BreadcrumbBuilder`: Builder class for templates
|
||||
- `build_breadcrumb`: Helper function for creating items
|
||||
120
backend/templates/components/navigation/breadcrumbs.html
Normal file
120
backend/templates/components/navigation/breadcrumbs.html
Normal file
@@ -0,0 +1,120 @@
|
||||
{% comment %}
|
||||
Breadcrumb Navigation Component
|
||||
===============================
|
||||
|
||||
Semantic breadcrumb navigation with Schema.org structured data support.
|
||||
|
||||
Purpose:
|
||||
Renders accessible breadcrumb navigation with proper ARIA attributes,
|
||||
Schema.org BreadcrumbList markup, and responsive design.
|
||||
|
||||
Usage Examples:
|
||||
Basic usage (breadcrumbs from context processor):
|
||||
{% include 'components/navigation/breadcrumbs.html' %}
|
||||
|
||||
Custom breadcrumbs:
|
||||
{% include 'components/navigation/breadcrumbs.html' with items=custom_breadcrumbs %}
|
||||
|
||||
Without Schema.org markup:
|
||||
{% include 'components/navigation/breadcrumbs.html' with show_schema=False %}
|
||||
|
||||
Custom separator:
|
||||
{% include 'components/navigation/breadcrumbs.html' with separator='>' %}
|
||||
|
||||
Without home icon:
|
||||
{% include 'components/navigation/breadcrumbs.html' with show_home_icon=False %}
|
||||
|
||||
Parameters:
|
||||
Optional:
|
||||
- items: List of Breadcrumb objects (default: breadcrumbs from context)
|
||||
- show_schema: Include Schema.org JSON-LD (default: True)
|
||||
- show_home_icon: Show icon on home breadcrumb (default: True)
|
||||
- separator: Separator character/icon (default: chevron icon)
|
||||
- max_visible: Maximum items to show on mobile before collapsing (default: 3)
|
||||
- container_class: Additional CSS classes for container
|
||||
|
||||
Dependencies:
|
||||
- Tailwind CSS for styling
|
||||
- Font Awesome icons (for home icon and separator)
|
||||
- breadcrumbs context processor for default breadcrumbs
|
||||
|
||||
Accessibility:
|
||||
- Uses <nav> element with aria-label="Breadcrumb"
|
||||
- Ordered list for semantic structure
|
||||
- aria-current="page" on current page item
|
||||
- Hidden separators (aria-hidden) for screen readers
|
||||
{% endcomment %}
|
||||
|
||||
{% with items=items|default:breadcrumbs show_schema=show_schema|default:True show_home_icon=show_home_icon|default:True max_visible=max_visible|default:3 %}
|
||||
|
||||
{% if items %}
|
||||
{# Main Navigation #}
|
||||
<nav aria-label="Breadcrumb"
|
||||
class="breadcrumb-nav py-3 {{ container_class }}"
|
||||
data-breadcrumb>
|
||||
|
||||
<ol class="flex flex-wrap items-center gap-1 text-sm" role="list">
|
||||
{% for crumb in items %}
|
||||
<li class="flex items-center {% if not forloop.last %}{% if forloop.counter > 1 and forloop.counter < items|length|add:'-1' %}hidden sm:flex{% endif %}{% endif %}">
|
||||
{# Separator (except for first item) #}
|
||||
{% if not forloop.first %}
|
||||
<span class="mx-2 text-muted-foreground/50" aria-hidden="true">
|
||||
{% if separator %}
|
||||
{{ separator }}
|
||||
{% else %}
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
|
||||
</svg>
|
||||
{% endif %}
|
||||
</span>
|
||||
{% endif %}
|
||||
|
||||
{# Breadcrumb Item #}
|
||||
{% if crumb.is_current %}
|
||||
{# Current page (not a link) #}
|
||||
<span class="font-medium text-foreground truncate max-w-[200px] sm:max-w-[300px]"
|
||||
aria-current="page"
|
||||
title="{{ crumb.label }}">
|
||||
{% if crumb.icon %}
|
||||
<i class="{{ crumb.icon }} mr-1.5" aria-hidden="true"></i>
|
||||
{% endif %}
|
||||
{{ crumb.label }}
|
||||
</span>
|
||||
{% else %}
|
||||
{# Clickable breadcrumb #}
|
||||
<a href="{{ crumb.url }}"
|
||||
class="text-muted-foreground hover:text-foreground transition-colors truncate max-w-[150px] sm:max-w-[200px] inline-flex items-center"
|
||||
title="{{ crumb.label }}">
|
||||
{% if crumb.icon and show_home_icon %}
|
||||
<i class="{{ crumb.icon }} mr-1.5" aria-hidden="true"></i>
|
||||
<span class="sr-only sm:not-sr-only">{{ crumb.label }}</span>
|
||||
{% else %}
|
||||
{{ crumb.label }}
|
||||
{% endif %}
|
||||
</a>
|
||||
{% endif %}
|
||||
</li>
|
||||
|
||||
{# Mobile ellipsis for long breadcrumb trails #}
|
||||
{% if forloop.counter == 1 and items|length > max_visible %}
|
||||
<li class="flex items-center sm:hidden" aria-hidden="true">
|
||||
<span class="mx-2 text-muted-foreground/50">
|
||||
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
|
||||
</svg>
|
||||
</span>
|
||||
<span class="text-muted-foreground">...</span>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ol>
|
||||
</nav>
|
||||
|
||||
{# Schema.org Structured Data #}
|
||||
{% if show_schema and breadcrumbs_json %}
|
||||
<script type="application/ld+json">{{ breadcrumbs_json|safe }}</script>
|
||||
{% endif %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% endwith %}
|
||||
Reference in New Issue
Block a user