mirror of
https://github.com/django-components/django-components.git
synced 2025-10-05 03:30:19 +00:00
docs: add Form and Tabs examples (#1411)
This commit is contained in:
parent
b3ea50572d
commit
9afc89ead1
24 changed files with 1237 additions and 7 deletions
|
@ -1,3 +1,6 @@
|
|||
# `.nav.yml` is provided by https://lukasgeiter.github.io/mkdocs-awesome-nav
|
||||
nav:
|
||||
- Examples: overview.md
|
||||
- index.md
|
||||
- Components:
|
||||
- ./form.md
|
||||
- ./tabs.md
|
14
docs/examples/README.md
Normal file
14
docs/examples/README.md
Normal file
|
@ -0,0 +1,14 @@
|
|||
# Adding examples
|
||||
|
||||
Rule of thumb:
|
||||
|
||||
If the example is a 3rd party package or it lives under a different URL, only link to it in `overview.md`.
|
||||
|
||||
If the example is file(s) that we wrote:
|
||||
|
||||
1. Define the component in `sampleproject/examples/components/<component_name>/<component_name>.py`.
|
||||
2. Define a view / page component in `sampleproject/examples/pages/<component_name>/<component_name>.py`.
|
||||
3. Add a new page here in the documentation named `<component_name>.md`, similarly to [Tabs](./alpine/tabs.md).
|
||||
4. Link to that new page from `index.md`.
|
||||
5. Update `.nav.yml` if needed.
|
||||
6. Add a corresponding test file in `tests/test_example_<component_name>.py`.
|
136
docs/examples/form.md
Normal file
136
docs/examples/form.md
Normal file
|
@ -0,0 +1,136 @@
|
|||
# Form
|
||||
|
||||
A `Form` component that automatically generates labels and arranges fields in a grid. It simplifies form creation by handling the layout for you.
|
||||
|
||||

|
||||
|
||||
To get started, use the following example to create a simple form with 2 fields - `project` and `option`:
|
||||
|
||||
```django
|
||||
{% component "form" %}
|
||||
{% fill "field:project" %}
|
||||
<input name="project" required>
|
||||
{% endfill %}
|
||||
|
||||
{% fill "field:option" %}
|
||||
<select name="option" required>
|
||||
<option value="1">Option 1</option>
|
||||
<option value="2">Option 2</option>
|
||||
<option value="3">Option 3</option>
|
||||
</select>
|
||||
{% endfill %}
|
||||
{% endcomponent %}
|
||||
```
|
||||
|
||||
This will render a `<form>` where fields are defined using `field:<field_name>` slots.
|
||||
|
||||
Labels are automatically generated from the field name. If you want to define a custom label for a field,
|
||||
you can use the `label:<field_name>` slot.
|
||||
|
||||
```django
|
||||
{% component "form" %}
|
||||
{# Custom label for "description" field #}
|
||||
{% fill "label:description" %}
|
||||
{% component "form_label"
|
||||
field_name="description"
|
||||
title="Marvelous description"
|
||||
/ %}
|
||||
{% endfill %}
|
||||
|
||||
{% fill "field:description" %}
|
||||
<textarea name="description" required></textarea>
|
||||
{% endfill %}
|
||||
{% endcomponent %}
|
||||
```
|
||||
|
||||
Whether you define custom labels or not, the form will have the following structure:
|
||||
|
||||

|
||||
|
||||
## API
|
||||
|
||||
### `Form` component
|
||||
|
||||
The `Form` component is the main container for your form fields. It accepts the following arguments:
|
||||
|
||||
- **`editable`** (optional, default `True`): A boolean that determines if the form is editable.
|
||||
- **`method`** (optional, default `"post"`): The HTTP method for the form submission.
|
||||
- **`form_content_attrs`** (optional): A dictionary of HTML attributes to be added to the form's content container.
|
||||
- **`attrs`** (optional): A dictionary of HTML attributes to be added to the `<form>` element itself.
|
||||
|
||||
To define the fields, you define a slot for each field.
|
||||
|
||||
**Slots:**
|
||||
|
||||
- **`field:<field_name>`**: Use this slot to define a form field. The component will automatically generate a label for it based on `<field_name>`.
|
||||
- **`label:<field_name>`**: If you need a custom label for a field, you can define it using this slot.
|
||||
- **`prepend`**: Content in this slot will be placed at the beginning of the form, before the main fields.
|
||||
- **`append`**: Content in this slot will be placed at the end of the form, after the main fields. This is a good place for submit buttons.
|
||||
|
||||
### `FormLabel` component
|
||||
|
||||
When `Form` component automatically generates labels for fields, it uses the `FormLabel` component.
|
||||
|
||||
When you need a custom label for a field, you can use the `FormLabel` component explicitly in `label:<field_name>` slots.
|
||||
|
||||
The `FormLabel` component accepts the following arguments:
|
||||
|
||||
- **`field_name`** (required): The name of the field that this label is for. This will be used as the `for` attribute of the label.
|
||||
- **`title`** (optional): Custom text for the label. If not provided, the component will automatically generate a title from the `field_name` by replacing underscores and hyphens with spaces and applying title case.
|
||||
|
||||
**Example:**
|
||||
|
||||
```django
|
||||
{% component "form_label"
|
||||
field_name="user_name"
|
||||
title="Your Name"
|
||||
/ %}
|
||||
```
|
||||
|
||||
This will render:
|
||||
|
||||
```html
|
||||
<label for="user_name" class="font-semibold text-gray-700">
|
||||
Your Name
|
||||
</label>
|
||||
```
|
||||
|
||||
If `title` is not provided, `field_name="user_name"` would automatically generate the title "User Name",
|
||||
converting snake_case to "Title Case".
|
||||
|
||||
## Example
|
||||
|
||||
To see the component in action, you can set up a view and a URL pattern as shown below.
|
||||
|
||||
### `views.py`
|
||||
|
||||
```djc_py
|
||||
--8<-- "sampleproject/examples/pages/form.py"
|
||||
```
|
||||
|
||||
### `urls.py`
|
||||
|
||||
```python
|
||||
from django.urls import path
|
||||
|
||||
from examples.pages.form import FormPage
|
||||
|
||||
urlpatterns = [
|
||||
path("examples/form", FormPage.as_view(), name="form"),
|
||||
]
|
||||
```
|
||||
|
||||
## Definition
|
||||
|
||||
### `form.py`
|
||||
|
||||
```djc_py
|
||||
--8<-- "sampleproject/examples/components/form/form.py"
|
||||
```
|
||||
|
||||
### `form.html`
|
||||
|
||||
```django
|
||||
{% load component_tags %}
|
||||
--8<-- "sampleproject/examples/components/form/form.html"
|
||||
```
|
BIN
docs/examples/images/form.png
Normal file
BIN
docs/examples/images/form.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 56 KiB |
BIN
docs/examples/images/form_structure.png
Normal file
BIN
docs/examples/images/form_structure.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 124 KiB |
BIN
docs/examples/images/tabs.gif
Normal file
BIN
docs/examples/images/tabs.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 259 KiB |
|
@ -1,14 +1,20 @@
|
|||
# Overview
|
||||
|
||||
`django-components` makes it easy to share components between projects
|
||||
([See how to package components](../concepts/advanced/component_libraries.md)).
|
||||
|
||||
Here you will find public examples of components and component libraries.
|
||||
|
||||
If you have components that would be useful to others, open a pull request to add them to this collection.
|
||||
If you have components that would be useful to others, open a [pull request](https://github.com/django-components/django-components/pulls) to add them to this collection.
|
||||
|
||||
### Icons
|
||||
## Components
|
||||
|
||||
- [Form](./form.md) - A form component that automatically generates labels and arranges fields in a grid.
|
||||
- [Tabs](./tabs.md) - Dynamic tabs with [AlpineJS](https://alpinejs.dev/).
|
||||
|
||||
## Packages
|
||||
|
||||
Packages or projects that define components for django-components:
|
||||
|
||||
- [djc-heroicons](https://pypi.org/project/djc-heroicons/) - Icons from HeroIcons.com for django-components.
|
||||
|
||||
### HTMX
|
||||
|
||||
- [`django-htmx-components`](https://github.com/iwanalabs/django-htmx-components) - A set of components for use with [htmx](https://htmx.org/).
|
100
docs/examples/tabs.md
Normal file
100
docs/examples/tabs.md
Normal file
|
@ -0,0 +1,100 @@
|
|||
# Tabs (AlpineJS)
|
||||
|
||||
_(By [@JuroOravec](https://github.com/JuroOravec) and [@mscheper](https://github.com/mscheper))_
|
||||
|
||||
This example defines a tabs component. Tabs are dynamic - to change the currently
|
||||
opened tab, click on the tab headers.
|
||||
|
||||
To get started, use the following example to create a simple container with 2 tabs:
|
||||
|
||||
```django
|
||||
{% component "Tablist" id="my-tablist" name="My Tabs" %}
|
||||
{% component "Tab" header="Tab 1" %}
|
||||
This is the content of Tab 1
|
||||
{% endcomponent %}
|
||||
{% component "Tab" header="Tab 2" disabled=True %}
|
||||
This is the content of Tab 2
|
||||
{% endcomponent %}
|
||||
{% endcomponent %}
|
||||
```
|
||||
|
||||

|
||||
|
||||
## API
|
||||
|
||||
The tab component is composed of two parts: `Tablist` and `Tab`. Here's how you can customize them.
|
||||
|
||||
### `Tablist` component
|
||||
|
||||
The `Tablist` component is the main container for the tabs. It accepts the following arguments:
|
||||
|
||||
- **`id`** (optional): A unique ID for the tab list. If not provided, it's generated from the `name`.
|
||||
- **`name`**: The name of the tab list, used as a WAI-ARIA label for accessibility.
|
||||
- **`selected_tab`** (optional): The `id` of the tab that should be selected by default.
|
||||
- **`container_attrs`**, **`tablist_attrs`**, **`tab_attrs`**, **`tabpanel_attrs`** (optional): Dictionaries of HTML attributes to be added to the corresponding elements.
|
||||
|
||||
Inside the `Tablist`'s default slot you will define the individual tabs.
|
||||
|
||||
### `Tab` component
|
||||
|
||||
The `Tab` component defines an individual tab. It MUST be nested inside a `Tablist`. It accepts the following arguments:
|
||||
|
||||
- **`header`**: The text to be displayed in the tab's header.
|
||||
- **`disabled`** (optional): A boolean that disables the tab if `True`.
|
||||
- **`id`** (optional): A unique ID for the tab. If not provided, it's generated from the header.
|
||||
|
||||
Use the `Tab`'s default slot to define the content of the tab.
|
||||
|
||||
## Example
|
||||
|
||||
To see the component in action, you can set up a view and a URL pattern as shown below.
|
||||
|
||||
### `views.py`
|
||||
|
||||
This example shows how to render a full page with the tab component.
|
||||
|
||||
```djc_py
|
||||
--8<-- "sampleproject/examples/pages/tabs.py"
|
||||
```
|
||||
|
||||
### `urls.py`
|
||||
|
||||
```python
|
||||
from django.urls import path
|
||||
|
||||
from examples.pages.tabs import TabsPage
|
||||
|
||||
urlpatterns = [
|
||||
path("examples/tabs", TabsPage.as_view(), name="tabs"),
|
||||
]
|
||||
```
|
||||
|
||||
## How it works
|
||||
|
||||
At the start of rendering, `Tablist` defines special context that `Tab`s recognize.
|
||||
|
||||
When a `Tab` component is nested and rendered inside a `Tablist`, it registers itself with the parent `Tablist` component.
|
||||
|
||||
After the rendering of `Tablist`'s body is done, we end up with list of rendered `Tabs` that were encountered.
|
||||
|
||||
`Tablist` then uses this information to dynamically render the tab HTML.
|
||||
|
||||
## Definition
|
||||
|
||||
### `tabs.py`
|
||||
|
||||
```djc_py
|
||||
--8<-- "sampleproject/examples/components/tabs/tabs.py"
|
||||
```
|
||||
|
||||
### `tabs.html`
|
||||
|
||||
```django
|
||||
--8<-- "sampleproject/examples/components/tabs/tabs.html"
|
||||
```
|
||||
|
||||
### `tabs.css`
|
||||
|
||||
```css
|
||||
--8<-- "sampleproject/examples/components/tabs/tabs.css"
|
||||
```
|
Loading…
Add table
Add a link
Reference in a new issue