mirror of
https://github.com/wrabit/django-cotton.git
synced 2025-08-04 15:18:20 +00:00
merge confs
This commit is contained in:
commit
37e49caba5
46 changed files with 965 additions and 288 deletions
|
@ -9,7 +9,7 @@ COPY . .
|
|||
RUN ["npx", "tailwindcss", "-o", "./docs_project/static/app.css"]
|
||||
|
||||
# Use an official Python runtime as a base image
|
||||
FROM python:3.12-slim-bookworm as base
|
||||
FROM python:3.12-slim-bookworm AS base
|
||||
|
||||
# Setup env
|
||||
ENV PIP_DISABLE_PIP_VERSION_CHECK=on \
|
||||
|
@ -34,4 +34,7 @@ RUN poetry config virtualenvs.create false \
|
|||
|
||||
RUN SECRET_KEY=dummy STATIC_URL='/staticfiles/' python manage.py collectstatic --noinput --verbosity 2
|
||||
|
||||
# Now uninstall with poetry the container version of django-cotton, leaving the local version when we're developing
|
||||
RUN poetry remove django-cotton
|
||||
|
||||
CMD [ "python", "manage.py", "runserver", "0.0.0.0:8000" ]
|
|
@ -14,6 +14,10 @@
|
|||
|
||||
<h1 id="tabs">Re-usable tabs with alpine.js</h1>
|
||||
|
||||
<c-note>
|
||||
Be sure to checkout the notes on alpine.js support <a href="{% url 'components' %}#alpine-js-support">here</a>.
|
||||
</c-note>
|
||||
|
||||
<p>Let's tackle together a common UI requirement - tabs.</p>
|
||||
|
||||
<h3 class="mt-0 pt-2 mb-5" id="goals">We'll start by defining some goals:</h3>
|
||||
|
@ -69,7 +73,7 @@
|
|||
|
||||
<p>Now we have the design right, let's chop it up into components.</p>
|
||||
|
||||
<h4>Tabs component</h4>
|
||||
<h3>{{ '<c-tabs />'|force_escape }} component</h3>
|
||||
|
||||
<c-snippet label="cotton/tabs.html">{% cotton_verbatim %}{% verbatim %}
|
||||
<div class="bg-white rounded-lg overflow-hidden border shadow">
|
||||
|
@ -85,7 +89,7 @@
|
|||
{% endcotton_verbatim %}{% endverbatim %}
|
||||
</c-snippet>
|
||||
|
||||
<h4>Tab component</h4>
|
||||
<h3>{{ '<c-tab />'|force_escape }} component</h3>
|
||||
|
||||
<c-snippet label="cotton/tab.html">{% cotton_verbatim %}{% verbatim %}
|
||||
<div>
|
||||
|
@ -194,13 +198,13 @@
|
|||
|
||||
</c-snippet>
|
||||
|
||||
<c-navigation>
|
||||
<c-slot name="prev">
|
||||
<a href="{% url 'form-fields' %}">Form Inputs</a>
|
||||
</c-slot>
|
||||
<c-slot name="next">
|
||||
<a href="{% url 'layouts' %}">Layouts</a>
|
||||
</c-slot>
|
||||
</c-navigation>
|
||||
<c-navigation>
|
||||
<c-slot name="prev">
|
||||
<a href="{% url 'form-fields' %}">Form Inputs</a>
|
||||
</c-slot>
|
||||
<c-slot name="next">
|
||||
<a href="{% url 'layouts' %}">Layouts</a>
|
||||
</c-slot>
|
||||
</c-navigation>
|
||||
|
||||
</c-layouts.with-sidebar>
|
|
@ -11,6 +11,7 @@
|
|||
<c-index-sublink><a href="#boolean-attributes" class="no-underline">Boolean Attributes</a></c-index-sublink>
|
||||
<c-index-sublink><a href="#dynamic-components" class="no-underline">Dynamic Components</a></c-index-sublink>
|
||||
<c-index-sublink><a href="#context-isolation" class="no-underline">Context Isolation</a></c-index-sublink>
|
||||
<c-index-sublink><a href="#alpine-js-support" class="no-underline">Alpine.js Support</a></c-index-sublink>
|
||||
<c-index-sublink><a href="#summary" class="no-underline">Summary of concepts</a></c-index-sublink>
|
||||
</c-slot>
|
||||
|
||||
|
@ -19,7 +20,7 @@
|
|||
|
||||
<h2>1. The basic building block: {% verbatim %}{{ slot }}{% endverbatim %}</h2>
|
||||
|
||||
<p>The <c-highlight>{% verbatim %}{{ slot }}{% endverbatim %}</c-highlight> variable captures all content passed between a component's opening and closing tags.</p>
|
||||
<p>The <code>{% verbatim %}{{ slot }}{% endverbatim %}</code> variable captures all content passed between a component's opening and closing tags.</p>
|
||||
|
||||
<c-snippet label="cotton/box.html">{% cotton_verbatim %}{% verbatim %}
|
||||
<div class="box">
|
||||
|
@ -39,9 +40,9 @@
|
|||
</c-slot>
|
||||
</c-snippet>
|
||||
|
||||
<c-hr />
|
||||
<c-hr id="attributes" />
|
||||
|
||||
<h2 id="attributes">2. Adding Component Attributes</h2>
|
||||
<h2>2. Adding Component Attributes</h2>
|
||||
|
||||
<p>We can further customize components with attribute, which allow you to pass specific data into the component as key-value pairs.</p>
|
||||
|
||||
|
@ -58,11 +59,11 @@
|
|||
</c-slot>
|
||||
</c-snippet>
|
||||
|
||||
<c-hr />
|
||||
<c-hr id="named-slots" />
|
||||
|
||||
<h2 id="named-slots">3. Using Named Slots</h2>
|
||||
<h2>3. Using Named Slots</h2>
|
||||
|
||||
<p>If we want to pass HTML instead of just a string (or another data type) into a component, we can pass them as <c-highlight>named slots</c-highlight> with the <c-highlight>{{ '<c-slot name="...">...</c-slot>'|force_escape }}</c-highlight> syntax.</p>
|
||||
<p>If we want to pass HTML instead of just a string (or another data type) into a component, we can pass them as <c-highlight>named slots</c-highlight> with the <code>{{ '<c-slot name="...">...</c-slot>'|force_escape }}</code> syntax.</p>
|
||||
|
||||
<p>So as with normal attributes, you reference the slot content like normal variables, as in:</p>
|
||||
|
||||
|
@ -93,9 +94,13 @@
|
|||
</c-slot>
|
||||
</c-snippet>
|
||||
|
||||
<c-hr />
|
||||
<c-note>
|
||||
Component filenames should be <c-highlight>snake_cased</c-highlight> by default. To use <c-highlight>kebab-cased</c-highlight> / hyphenated filenames instead, set <code>COTTON_SNAKE_CASED_NAMES</code> to <code>False</code> in your settings.py, <a href="{% url 'configuration' %}">more</a>.
|
||||
</c-note>
|
||||
|
||||
<h2 id="dynamic-attributes">4. Dynamic Attributes with ":"</h2>
|
||||
<c-hr id="dynamic-attributes" />
|
||||
|
||||
<h2>4. Dynamic Attributes with ":"</h2>
|
||||
|
||||
<p>We saw how by default, all attributes that we pass to a component are treated as strings. If we want to pass HTML, we can use named slots. But what if we want to pass another data type like a template variable, boolean, integer, float, dictionary, list, dictionary?</p>
|
||||
|
||||
|
@ -176,9 +181,9 @@ context = { 'today': Weather.objects.get(...) }
|
|||
{% endcotton_verbatim %}{% endverbatim %}
|
||||
</c-snippet>
|
||||
|
||||
<c-hr />
|
||||
<c-hr id="attrs" />
|
||||
|
||||
<h2 id="attrs">5. Pass all attributes with {% verbatim %}{{ attrs }}{% endverbatim %}</h2>
|
||||
<h2>5. Pass all attributes with {% verbatim %}{{ attrs }}{% endverbatim %}</h2>
|
||||
|
||||
<p>Sometimes it's useful to be able to reflect all attributes provided in the parent on to an HTML element in the component. This is particularly powerful when you are building <a href="{% url 'form-fields' %}">form inputs</a>.</p>
|
||||
|
||||
|
@ -204,17 +209,17 @@ context = { 'today': Weather.objects.get(...) }
|
|||
{% endcotton_verbatim %}{% endverbatim %}
|
||||
</c-snippet>
|
||||
|
||||
<c-hr />
|
||||
<c-hr id="vars" />
|
||||
|
||||
<h2 id="vars">6. <c-highlight>{{ '<c-vars />'|force_escape }}</c-highlight>: Defining Local Variables</h2>
|
||||
<h2>6. Defining Local Variables with <code>{{ '<c-vars />'|force_escape }}</code></h2>
|
||||
|
||||
<p>{{ '<c-vars />'|force_escape }} gives components local state and default behavior, making them more self-sufficient and reducing the need for repetitive attribute declarations and maintaining UI state in the backend.</p>
|
||||
<p>The <code>{{ '<c-vars />'|force_escape }}</code> tag simplifies component design by allowing local variable definition, reducing the need for repetitive attribute declarations and maintaining backend state.</p>
|
||||
|
||||
<p>Vars are defined using a <c-highlight>{{ '<c-vars />'|force_escape }}</c-highlight> tag at the top of a component file. It can either contain key="value" pairs or just standalone keys (keep reading to understand why).</p>
|
||||
<p>Place a single <code>{{ '<c-vars />'|force_escape }}</code> at the top of a component to set key-value pairs that provide a default configuration.</p>
|
||||
|
||||
<h3 id="default-attributes">Use {{ '<c-vars />'|force_escape }} to set attribute defaults</h3>
|
||||
<h3>Example: Setting Default Attributes</h3>
|
||||
|
||||
<p>You may design a component that will often have a default behaviour and rarely needs overriding. In this case, you may opt to give a default value to your component.</p>
|
||||
<p>In components with common defaults, <code>{{ '<c-vars />'|force_escape }}</code> can pre-define attributes that rarely need overriding.</p>
|
||||
|
||||
<c-snippet label="cotton/alert.html">{% cotton_verbatim %}{% verbatim %}
|
||||
<c-vars type="success" />
|
||||
|
@ -235,9 +240,9 @@ context = { 'today': Weather.objects.get(...) }
|
|||
</c-slot>
|
||||
</c-snippet>
|
||||
|
||||
<h3 id="excluded">{{ '<c-vars />'|force_escape }} are excluded from {% verbatim %}{{ attrs }}{% endverbatim %}</h3>
|
||||
<h3>{{ '<c-vars />'|force_escape }} are excluded from {% verbatim %}{{ attrs }}{% endverbatim %}</h3>
|
||||
|
||||
<p>Keys defined in {{ '<c-vars />'|force_escape }} will not be included in {% verbatim %}{{ attrs }}{% endverbatim %}. This is useful when some of the properties you pass down to a component are for configuration purposes only and not intended as attributes.</p>
|
||||
<p>Keys in <code>{{ '<c-vars />'|force_escape }}</code> are omitted from <code>{% verbatim %}{{ attrs }}{% endverbatim %}</code>, making them ideal for configuration attributes that shouldn't appear in HTML attributes.</p>
|
||||
|
||||
<c-snippet label="cotton/input_group.html">{% cotton_verbatim %}{% verbatim %}
|
||||
<c-vars label errors />
|
||||
|
@ -271,12 +276,11 @@ context = { 'today': Weather.objects.get(...) }
|
|||
</c-slot>
|
||||
</c-snippet>
|
||||
|
||||
<c-note>Specifying an attribute as a 'var' will remove the item from {% verbatim %}{{ attrs }}{% endverbatim %}. It can also be a single key without a default value, this is when you know a particular attribute should not end up in {% verbatim %}{{ attrs }}{% endverbatim %}, whether it's defined in a parent or not.</c-note>
|
||||
<p>By specifying <code>label</code> and <code>errors</code> keys in <code>{{ '<c-vars />'|force_escape }}</code>, these attributes won’t be included in <code>{% verbatim %}{{ attrs }}{% endverbatim %}</code>, allowing you to control attributes that are designed for component configuration and those intended as attributes.</p>
|
||||
|
||||
<c-hr id="boolean-attributes" />
|
||||
|
||||
<c-hr />
|
||||
|
||||
<h2 id="boolean-attributes">7. Boolean attributes</h2>
|
||||
<h2>7. Boolean attributes</h2>
|
||||
|
||||
<p>Sometimes you just want to pass a simple boolean to a component. Cotton supports providing the attribute name without a value which will provide a boolean True to the component.</p>
|
||||
|
||||
|
@ -293,15 +297,15 @@ context = { 'today': Weather.objects.get(...) }
|
|||
<c-input name="telephone" required />
|
||||
{% endcotton_verbatim %}{% endverbatim %}
|
||||
<c-slot name="preview">
|
||||
<input type="text" autocomplete="off" class="border px-2 py-1 shadow rounded" name="telephone" placeholder="Telephone" /> <span class="text-red-500 text-3xl">*</span>
|
||||
<input type="text" autocomplete="off" class="border px-2 py-1 shadow rounded" name="telephone" placeholder="Telephone" /> <span class="text-red-500 text-2xl">*</span>
|
||||
</c-slot>
|
||||
</c-snippet>
|
||||
|
||||
<c-hr />
|
||||
<c-hr id="dynamic-components" />
|
||||
|
||||
<h2 id="dynamic-components">8. Dynamic Components</h2>
|
||||
<h2>8. Dynamic Components</h2>
|
||||
|
||||
<p>There can be times where components need to be included dynamically. For these cases we can reach for a special <c-highlight>{{ '<c-component>'|force_escape }}</c-highlight> tag with an <c-highlight>is</c-highlight> attribute:</p>
|
||||
<p>There can be times where components need to be included dynamically. For these cases we can reach for a special <code>{{ '<c-component>'|force_escape }}</code> tag with an <code>is</code> attribute:</p>
|
||||
|
||||
<c-snippet label="cotton/icon_list.html">{% cotton_verbatim %}{% verbatim %}
|
||||
{% for icon in icons %}
|
||||
|
@ -309,7 +313,7 @@ context = { 'today': Weather.objects.get(...) }
|
|||
{% endfor %}
|
||||
{% endcotton_verbatim %}{% endverbatim %}</c-snippet>
|
||||
|
||||
<p>The <c-highlight>is</c-highlight> attribute is similar to other attributes so we have a number of possibilities to define it:</p>
|
||||
<p>The <code>is</code> attribute is similar to other attributes so we have a number of possibilities to define it:</p>
|
||||
|
||||
<c-snippet label="cotton/icon_list.html">{% cotton_verbatim %}{% verbatim %}
|
||||
<!-- as variable -->
|
||||
|
@ -319,12 +323,12 @@ context = { 'today': Weather.objects.get(...) }
|
|||
<c-component is="icon_{{ icon_name }}" />
|
||||
{% endcotton_verbatim %}{% endverbatim %}</c-snippet>
|
||||
|
||||
<c-hr />
|
||||
<c-hr id="context-isolation" />
|
||||
|
||||
<h2 id="context-isolation">9. Context Isolation</h2>
|
||||
<h2>9. Context Isolation</h2>
|
||||
|
||||
<p>Cotton is inspired by patterns found in frontend frameworks like React, Vue and Svelte. When working with these
|
||||
patterns, state is not typically shared between components. This ensures data from other components do not 'leak' into
|
||||
patterns, state is not typically shared between components. This ensures data from other components does not 'leak' into
|
||||
others which can cause side effects that are difficult to trace.</p>
|
||||
|
||||
<p>Therefore, each component's context only contains, by default:</p>
|
||||
|
@ -339,22 +343,34 @@ context = { 'today': Weather.objects.get(...) }
|
|||
|
||||
<p>You can pass the <c-highlight>only</c-highlight> attribute to the component, which will prevent it from adopting any context (incl. context processors) other than it's direct attributes.</p>
|
||||
|
||||
<h3>Retain legacy behaviour</h3>
|
||||
<c-hr id="alpine-js-support" />
|
||||
|
||||
<p>Since context isolation is enabled by default since v2.0.0, there may be cases you wish to keep the legacy behaviour, for that reason, you can pass a `COTTON_CONTEXT_ISOLATION_ENABLED = False` in your settings.py. This is not recommend due to the aforementioned reason so allowing context isolation by default is encouraged.</p>
|
||||
<h2>10. Alpine.js support</h2>
|
||||
|
||||
<c-hr />
|
||||
<p>The following key features allow you to build re-usable components with alpine.js:</p>
|
||||
|
||||
<h2 id="summary">Summary of Concepts</h2>
|
||||
<c-ul>
|
||||
<li>
|
||||
<code>x-data</code> is accessible as <code>{% verbatim %}{{ x_data }}{% endverbatim %}</code> inside the component as cotton makes available snake_case versions of all kebab-cased attributes. (If you use <code>{% verbatim %}{{ attrs }}{% endverbatim %}</code> then the output will already be in the correct case).
|
||||
</li>
|
||||
<li><a href="https://alpinejs.dev/directives/bind" target="_blank">Shorthand x-bind</a> support (<code>:example</code>). Because single <code>:</code> attribute prefixing is reserved for cotton's <a href="{% url 'components' %}#dynamic-attributes">dynamic attributes</a>,
|
||||
we can escape the first colon using <code>::</code>. This will ensure the attribute maintains a single <code>:</code> inside <code>{% verbatim %}{{ attrs }}{% endverbatim %}</code>
|
||||
</li>
|
||||
</c-ul>
|
||||
|
||||
<c-hr id="summary" />
|
||||
|
||||
<h2>Summary of Concepts</h2>
|
||||
<ul>
|
||||
<li><c-highlight>{% verbatim %}{{ slot }}{% endverbatim %}</c-highlight> - Default content injection.</li>
|
||||
<li><code>{% verbatim %}{{ slot }}{% endverbatim %}</code> - Default content injection.</li>
|
||||
<li><c-highlight>Attributes</c-highlight> - Simple, straightforward customization.</li>
|
||||
<li><c-highlight>Named Slots</c-highlight> - Provide HTML or template partial as a variable in the component.</li>
|
||||
<li><c-highlight>`:` Dynamic Attributes</c-highlight> - Pass variables and other data types other than strings.</li>
|
||||
<li><c-highlight>{% verbatim %}{{ attrs }}{% endverbatim %}</c-highlight> - Prints attributes as HTML attributes.</li>
|
||||
<li><c-highlight>{{ '<c-vars />'|force_escape }}</c-highlight> - Set default values and other component state.</li>
|
||||
<li><c-highlight>Boolean attributes</c-highlight> - Attributes without values are passed down as `:bool = True`</li>
|
||||
<li><c-highlight>{{ '<c-component is=".." />'|force_escape }}</c-highlight> - Dynamically insert a component where the name is generated by a variable or template expression</li>
|
||||
<li><c-highlight><code>:</code> Dynamic Attributes</c-highlight> - Pass variables and other data types other than strings.</li>
|
||||
<li><code>{% verbatim %}{{ attrs }}{% endverbatim %}</code> - Prints attributes as HTML attributes.</li>
|
||||
<li><code>{{ '<c-vars />'|force_escape }}</code> - Set default values and other component state.</li>
|
||||
<li><c-highlight>Boolean attributes</c-highlight> - Attributes without values are passed down as <code>True</code></li>
|
||||
<li><c-highlight>Dynamic Components</c-highlight> - Insert a component where the name is generated by a variable or template expression: <code>{{ '<c-component :is="my_variable" />'|force_escape }}</code>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
|
||||
|
@ -363,7 +379,7 @@ context = { 'today': Weather.objects.get(...) }
|
|||
<a href="{% url 'quickstart' %}">Quickstart</a>
|
||||
</c-slot>
|
||||
<c-slot name="next">
|
||||
<a href="{% url 'layouts' %}">Layouts</a>
|
||||
<a href="{% url 'usage-patterns' %}">Usage Patterns</a>
|
||||
</c-slot>
|
||||
</c-navigation>
|
||||
|
||||
|
|
|
@ -3,15 +3,66 @@
|
|||
|
||||
<p>The following configuration can be provided in your `settings.py`:</p>
|
||||
|
||||
<h4>COTTON_DIR</h4>
|
||||
<p>str (default: 'cotton')</p>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<code>COTTON_DIR</code>
|
||||
<div>str (default: 'cotton')</div>
|
||||
</div>
|
||||
<div>
|
||||
Change the default path in your templates directory where cotton components can be placed, for example "components".
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<code>COTTON_ENABLE_CONTEXT_ISOLATION</code>
|
||||
<div>boolean (default: True)</div>
|
||||
</div>
|
||||
<div>
|
||||
Set to `False` to allow global context to be available through all components. (see <a href="{% url 'components' %}#context-isolation">context isolation</a> for more information.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<c-hr />
|
||||
|
||||
<h4>COTTON_CONTEXT_ISOLATION_ENABLED</h4>
|
||||
<p>str (default: 'True')</p>
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<code>COTTON_BASE_DIR</code>
|
||||
<div>str (default: None)</div>
|
||||
</div>
|
||||
<div>
|
||||
The base directory where - in addition to the app folders - cotton will search for the "templates" directory (see above).
|
||||
If not set, the `BASE_DIR` generated by `django-admin startproject` is used as a fallback, if it exists.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p>Set to `False` to allow global context to be available through all components. (see <a href="{% url 'components' %}#context-isolation">context isolation</a> for more information.</p>
|
||||
<c-hr />
|
||||
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 gap-6">
|
||||
<div>
|
||||
<code>COTTON_SNAKE_CASED_NAMES</code>
|
||||
<div>bool (default: True)</div>
|
||||
</div>
|
||||
<div>
|
||||
<div class="mb-4">By default cotton will look for snake case versions of your component names. To turn this behaviour off (useful if you want to permit hyphenated filenames) then set this key to <code>False</code>.</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<h6 class="mb-1">Example:</h6>
|
||||
<code>{{ '<c-my-button />'|force_escape }}</code>
|
||||
</div>
|
||||
|
||||
<div class="mb-4">
|
||||
<h6>As <code>True</code> (default)</h6>
|
||||
Filepath: `cotton/my_button.html`
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<h6>As <code>False</code></h6>
|
||||
Filepath: `cotton/my-button.html`
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</c-layouts.with-sidebar>
|
||||
</c-layouts.with-sidebar>
|
||||
|
|
|
@ -1 +1 @@
|
|||
<span class="font-bold dark:text-white text-[#1a384a] font-semibold border-b-2 border-teal-600 border-opacity-70">{{ slot }}</span>
|
||||
<span class="dark:text-white text-[#1a384a] font-semibold border-b-2 border-teal-600 border-opacity-70">{{ slot }}</span>
|
|
@ -1 +1 @@
|
|||
<div {{ attrs }} class="h-[2px] bg-yellow-900 bg-opacity-10 my-8 w-full dark:bg-gray-700"></div>
|
||||
<div {{ attrs }} class="h-[1px] bg-yellow-900 bg-opacity-10 mb-6 mt-12 w-full dark:bg-gray-700"></div>
|
|
@ -0,0 +1,3 @@
|
|||
<svg {{ attrs }} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="m19.5 8.25-7.5 7.5-7.5-7.5" />
|
||||
</svg>
|
After Width: | Height: | Size: 219 B |
|
@ -0,0 +1,3 @@
|
|||
<svg {{ attrs }} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="m4.5 15.75 7.5-7.5 7.5 7.5" />
|
||||
</svg>
|
After Width: | Height: | Size: 219 B |
|
@ -0,0 +1,3 @@
|
|||
<svg {{ attrs }} fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" viewBox="0 0 24 24">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M8 12a1 1 0 1 0 2 0a1 1 0 0 0 -2 0" /><path d="M14 12a1 1 0 1 0 2 0a1 1 0 0 0 -2 0" /><path d="M15.5 17c0 1 1.5 3 2 3c1.5 0 2.833 -1.667 3.5 -3c.667 -1.667 .5 -5.833 -1.5 -11.5c-1.457 -1.015 -3 -1.34 -4.5 -1.5l-.972 1.923a11.913 11.913 0 0 0 -4.053 0l-.975 -1.923c-1.5 .16 -3.043 .485 -4.5 1.5c-2 5.667 -2.167 9.833 -1.5 11.5c.667 1.333 2 3 3.5 3c.5 0 2 -2 2 -3" /><path d="M7 16.5c3.5 1 6.5 1 10 0" />
|
||||
</svg>
|
After Width: | Height: | Size: 665 B |
|
@ -1,13 +1,3 @@
|
|||
{% comment %}
|
||||
<svg {{ attrs }} xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
|
||||
stroke="currentColor">
|
||||
<path stroke-linecap="round" stroke-linejoin="round"
|
||||
d="M12 3v2.25m6.364.386-1.591 1.591M21 12h-2.25m-.386 6.364-1.591-1.591M12 18.75V21m-4.773-4.227-1.591 1.591M5.25 12H3m4.227-4.773L5.636 5.636M15.75 12a3.75 3.75 0 1 1-7.5 0 3.75 3.75 0 0 1 7.5 0Z"/>
|
||||
</svg>{% endcomment %}
|
||||
|
||||
<svg {{ attrs }} xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor"
|
||||
stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/>
|
||||
<path d="M12 12m-4 0a4 4 0 1 0 8 0a4 4 0 1 0 -8 0"/>
|
||||
<path d="M3 12h1m8 -9v1m8 8h1m-9 8v1m-6.4 -15.4l.7 .7m12.1 -.7l-.7 .7m0 11.4l.7 .7m-12.1 -.7l-.7 .7"/>
|
||||
</svg>
|
||||
<svg {{ attrs }} xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M12 12m-4 0a4 4 0 1 0 8 0a4 4 0 1 0 -8 0" /><path d="M3 12h1m8 -9v1m8 8h1m-9 8v1m-6.4 -15.4l.7 .7m12.1 -.7l-.7 .7m0 11.4l.7 .7m-12.1 -.7l-.7 .7" />
|
||||
</svg>
|
Before Width: | Height: | Size: 894 B After Width: | Height: | Size: 412 B |
|
@ -1 +1 @@
|
|||
<li class="py-0.5 pl-1 ml-5 list-disc marker:text-teal-600 text-[15px] text-[#1a384a] dark:text-gray-400">{{ slot }}</li>
|
||||
<li class="py-0.5 pl-1 ml-5 list-disc marker:text-teal-600 text-[#1a384a] dark:text-gray-400">{{ slot }}</li>
|
|
@ -11,6 +11,7 @@
|
|||
<link rel="icon" type="image/png" href="{% static 'favicon/favicon.png' %}">
|
||||
|
||||
<script src="{% static 'highlight/highlight.min.js' %}"></script>
|
||||
<script defer src="https://cdn.jsdelivr.net/npm/@alpinejs/collapse@3.x.x/dist/cdn.min.js"></script>
|
||||
<script defer src="{% static 'alpine3.min.js' %}"></script>
|
||||
<link href="{% static 'highlight/styles/atom-one-dark.min.css' %}" rel="stylesheet" />
|
||||
<script>
|
||||
|
|
|
@ -4,15 +4,76 @@
|
|||
<c-sidebar />
|
||||
</div>
|
||||
<div class="overflow-auto flex-1 pb-10">
|
||||
<div class="max-w-[760px] mx-auto px-0 pt-3 md:pt-0 md:px-5 py-0 prose !text-[16.5px] prose-a:text-teal-600 prose-h2:text-3xl prose-h3:text-2xl prose-headings:text-[#1a384a] text-[#1a384a] dark:text-white dark:text-opacity-70 prose-headings:font-semibold dark:prose-headings:text-white">
|
||||
<div class="
|
||||
max-w-[760px]
|
||||
mx-auto
|
||||
px-0
|
||||
pt-3
|
||||
md:pt-0
|
||||
md:px-5
|
||||
py-0
|
||||
!text-[16.5px]
|
||||
text-[#1a384a]
|
||||
|
||||
prose
|
||||
prose-a:text-teal-600
|
||||
prose-h1:text-3xl
|
||||
prose-h2:text-2xl
|
||||
prose-h3:text-xl
|
||||
prose-headings:text-[#1a384a]
|
||||
prose-headings:font-semibold
|
||||
prose-code:before:content-none
|
||||
prose-code:after:content-none
|
||||
prose-code:bg-yellow-900/10
|
||||
prose-code:rounded
|
||||
prose-code:px-1
|
||||
prose-code:inline-block
|
||||
prose-code:my-0
|
||||
|
||||
dark:text-white
|
||||
dark:text-opacity-70
|
||||
dark:prose-headings:text-white
|
||||
dark:prose-code:bg-gray-800
|
||||
dark:prose-code:text-gray-300/80
|
||||
dark:prose-strong:text-[#fff]
|
||||
">
|
||||
{% if page_index %}
|
||||
<div class="lg:hidden not-prose mb-6">
|
||||
|
||||
<c-ui.collapse>
|
||||
<c-slot name="trigger">
|
||||
|
||||
<c-ui.button theme="subtle" class="w-full">
|
||||
<span class="flex w-full justify-between items-center">
|
||||
<span>On this page</span>
|
||||
<template x-if="!expanded">
|
||||
<c-icons.chevron-down class="size-5" />
|
||||
</template>
|
||||
<template x-if="expanded">
|
||||
<c-icons.chevron-up class="size-5" />
|
||||
</template>
|
||||
</span>
|
||||
</c-ui.button>
|
||||
</c-slot>
|
||||
|
||||
<div class="mt-5">
|
||||
{{ page_index }}
|
||||
</div>
|
||||
|
||||
<c-hr />
|
||||
</c-ui.collapse>
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{{ slot }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="relative h-full pl-10 border-opacity-10 hidden lg:block">
|
||||
<div class="relative h-full pl-10 border-opacity-10 hidden lg:block text-[15px]">
|
||||
{% if page_index %}
|
||||
<div class="sticky top-[68px] pt-0 pb-10">
|
||||
<c-sidebar-heading>On this page</c-sidebar-heading>
|
||||
<ul class="ml-0 pl-0 mt-4">
|
||||
<ul class="ml-0 pl-0 mt-4 ">
|
||||
{{ page_index }}
|
||||
</ul>
|
||||
</div>
|
||||
|
|
|
@ -43,13 +43,13 @@
|
|||
<div class="flex items-center space-x-1">
|
||||
<c-icons.logo class="w-8 h-8 text-teal-600" />
|
||||
<span class="font-bold text-2xl ml-1.5 text-[#1a384a] dark:text-gray-100">cotton</span>
|
||||
<div class="text-gray-700 dark:text-white text-sm opacity-50 mt-0.5 px-1">for</div>
|
||||
<c-icons.django class="h-6 text-teal-600 mt-1.5" />
|
||||
<div class=" text-gray-700 dark:text-white text-sm opacity-50 mt-0.5 px-1">for</div>
|
||||
<c-icons.django class=" h-6 text-teal-600 mt-1.5" />
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="flex items-center space-x-3">
|
||||
<div class="flex items-center space-x-2">
|
||||
<a href="#" @click.prevent="toggleDark" x-data="{
|
||||
'dark': false,
|
||||
init() {
|
||||
|
@ -64,10 +64,13 @@
|
|||
localStorage.theme = this.dark ? 'dark' : 'light'
|
||||
}
|
||||
}">
|
||||
<c-icons.sun class="size-8 text-yellow-900 opacity-60 dark:text-gray-100" stroke-width="1.5" />
|
||||
<c-icons.sun class="size-7 text-yellow-900/40 dark:text-gray-100/50" />
|
||||
</a>
|
||||
<a href="https://github.com/wrabit/django-cotton" target="_blank" class="text-yellow-900 opacity-60 dark:text-gray-100 flex items-center space-x-2">
|
||||
<c-icons.github class="size-7" />
|
||||
<a href="https://github.com/wrabit/django-cotton" target="_blank" class="text-yellow-900/40 dark:text-gray-100/50 flex items-center space-x-2">
|
||||
<c-icons.github class="size-6" />
|
||||
</a>
|
||||
<a href="https://discord.gg/4x8ntQwHMe" target="_blank" class="text-yellow-900/40 dark:text-gray-100/50 flex items-center space-x-2">
|
||||
<c-icons.discord class="size-7" />
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -83,4 +86,4 @@
|
|||
@click.away="isOpen = false" class="absolute shadow-md bg-white dark:bg-gray-800 top-[67px] inset-x-0 px-5 transition transform origin-top-right md:hidden">
|
||||
<c-sidebar />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
<div class="mt-6 border border-teal-600 rounded-lg px-8 py-5 dark:border dark:bg-transparent">
|
||||
<div class="mt-6 border-2 border-teal-500 bg-teal-500/10 rounded-lg px-8 py-5">
|
||||
{{ slot }}
|
||||
</div>
|
|
@ -1,5 +1,4 @@
|
|||
<div class="sticky top-[68px] pb-6 pt-2">
|
||||
|
||||
<c-sidebar-block>
|
||||
<c-slot name="title">Getting Started</c-slot>
|
||||
<ul>
|
||||
|
@ -9,6 +8,9 @@
|
|||
<c-sidebar-link url="{% url 'components' %}">
|
||||
Components
|
||||
</c-sidebar-link>
|
||||
<c-sidebar-link url="{% url 'usage-patterns' %}">
|
||||
Usage Patterns
|
||||
</c-sidebar-link>
|
||||
</ul>
|
||||
</c-sidebar-block>
|
||||
<c-sidebar-block>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<div class="py-4 {{ class }} border-b border-yellow-900 border-opacity-15 dark:border-gray-700 dark:border-opacity-100 last:border-0 first:pt-0 leading-7">
|
||||
<div class="py-4 {{ class }} first:pt-0 leading-7">
|
||||
{% if title %}
|
||||
<c-sidebar-heading>{{ title }}</c-sidebar-heading>
|
||||
{% endif %}
|
||||
|
|
|
@ -1 +1 @@
|
|||
<div class="dark:text-white text-[#1a384a] dark:opacity-35 text-yellow-800 brightness-65 text-opacity-50 font-semibold uppercase text-[14px] mb-2 tracking-wider">{{ slot }}</div>
|
||||
<div class="dark:text-white dark:opacity-35 text-yellow-900/40 font-semibold uppercase text-[14px] mb-2 tracking-wider">{{ slot }}</div>
|
|
@ -0,0 +1,39 @@
|
|||
<c-vars
|
||||
:themes="{
|
||||
'primary': 'bg-sky-500',
|
||||
'subtle': 'bg-neutral-50 text-gray-800 dark:bg-gray-300/10 dark:text-neutral-300',
|
||||
'danger': 'bg-red-500',
|
||||
'warning': 'bg-yellow-500',
|
||||
'info': 'bg-blue-500',
|
||||
}"
|
||||
theme="primary"
|
||||
:outlined-themes="{
|
||||
'primary': 'border border-sky-500 text-sky-500',
|
||||
'subtle': 'border border-neutral-50 text-gray-800',
|
||||
'danger': 'border border-red-500 text-red-500',
|
||||
'warning': 'border border-yellow-500 text-yellow-500',
|
||||
'info': 'border border-blue-500 text-blue-500',
|
||||
}"
|
||||
:outlined="False"
|
||||
class
|
||||
/>
|
||||
|
||||
<button {{ attrs }} type="button" class="
|
||||
{% if outlined %}
|
||||
{{ outlined_themes|get_item:theme }}
|
||||
{% else %}
|
||||
{{ themes|get_item:theme }}
|
||||
{% endif %}
|
||||
cursor-pointer whitespace-nowrap rounded-md
|
||||
px-4 py-2 text-sm font-medium tracking-wide transition hover:opacity-75 text-center
|
||||
focus-visible:outline
|
||||
focus-visible:outline-2
|
||||
focus-visible:outline-offset-2
|
||||
focus-visible:outline-sky-500
|
||||
active:opacity-100
|
||||
active:outline-offset-0
|
||||
disabled:opacity-75
|
||||
disabled:cursor-not-allowed
|
||||
{{ class }}">
|
||||
{{ slot }}
|
||||
</button>
|
|
@ -0,0 +1,13 @@
|
|||
<c-vars trigger_text trigger />
|
||||
|
||||
<div x-data="{ expanded: false }">
|
||||
{% if trigger %}
|
||||
<span @click="expanded = ! expanded" class="cursor-pointer">{{ trigger }}</span>
|
||||
{% else %}
|
||||
<button @click="expanded = ! expanded">{% firstof trigger_text "Toggle" %}</button>
|
||||
{% endif %}
|
||||
|
||||
<div x-show="expanded" x-collapse x-cloak>
|
||||
{{ slot }}
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,41 @@
|
|||
<c-vars trigger_text />
|
||||
|
||||
<div x-data="{ isOpen: false, openedWithKeyboard: false }" class="relative" @keydown.esc.window="isOpen = false, openedWithKeyboard = false">
|
||||
<!-- Toggle Button -->
|
||||
<button
|
||||
type="button"
|
||||
@click="isOpen = ! isOpen"
|
||||
class="inline-flex cursor-pointer items-center gap-2 whitespace-nowrap rounded-md border border-neutral-300 bg-neutral-50 px-4 py-2 text-sm font-medium tracking-wide transition
|
||||
hover:opacity-75
|
||||
focus-visible:outline
|
||||
focus-visible:outline-2
|
||||
focus-visible:outline-offset-2
|
||||
focus-visible:outline-neutral-800
|
||||
dark:border-neutral-700
|
||||
dark:bg-gray-800
|
||||
dark:focus-visible:outline-neutral-300"
|
||||
aria-haspopup="true"
|
||||
@keydown.space.prevent="openedWithKeyboard = true"
|
||||
@keydown.enter.prevent="openedWithKeyboard = true"
|
||||
@keydown.down.prevent="openedWithKeyboard = true"
|
||||
:class="isOpen || openedWithKeyboard ? 'text-neutral-900 dark:text-white' : 'text-neutral-600 dark:text-neutral-300'"
|
||||
aria-expanded="isOpen || openedWithKeyboard">
|
||||
{% firstof trigger_text "Select" %}
|
||||
<svg aria-hidden="true" fill="none" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="size-4 totate-0">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" d="M19.5 8.25l-7.5 7.5-7.5-7.5"/>
|
||||
</svg>
|
||||
</button>
|
||||
<!-- Dropdown Menu -->
|
||||
<div x-cloak x-show="isOpen || openedWithKeyboard"
|
||||
x-transition
|
||||
x-trap="openedWithKeyboard"
|
||||
@click.outside="isOpen = false, openedWithKeyboard = false"
|
||||
@keydown.down.prevent="$focus.wrap().next()"
|
||||
@keydown.up.prevent="$focus.wrap().previous()"
|
||||
class="absolute top-11 left-0 flex w-full min-w-[12rem] flex-col overflow-hidden rounded-md border border-neutral-300 bg-neutral-50 py-1.5
|
||||
dark:border-neutral-700
|
||||
dark:bg-gray-800"
|
||||
role="menu">
|
||||
{{ slot }}
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,8 @@
|
|||
<a href="#" class="bg-neutral-50 px-4 py-2 text-sm text-neutral-600
|
||||
hover:bg-neutral-900/5
|
||||
hover:text-neutral-900 focus-visible:bg-neutral-900/10 focus-visible:text-neutral-900 focus-visible:outline-none
|
||||
dark:bg-black/10
|
||||
dark:text-neutral-300
|
||||
dark:hover:bg-neutral-50/5 dark:hover:text-white
|
||||
dark:focus-visible:bg-neutral-50/10
|
||||
dark:focus-visible:text-white" role="menuitem">{{ slot }}</a>
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
<h2 id="type">Change the input type</h2>
|
||||
|
||||
<p>You will probably need more than just a text input in your project. So let's declare an attribute `text` in <c-highlight>{{ '<c-vars />'|force_escape }}</c-highlight>. Adding it as a var will allow us to set "text" as the default. Additionally, it will be excluded from <c-highlight>{% verbatim %}{{ attrs }}{% endverbatim %}</c-highlight>:</p>
|
||||
<p>You will probably need more than just a text input in your project. So let's declare an attribute `text` in <code>{{ '<c-vars />'|force_escape }}</code>. Adding it as a var will allow us to set "text" as the default. Additionally, it will be excluded from <code>{% verbatim %}{{ attrs }}{% endverbatim %}</code>:</p>
|
||||
|
||||
<c-snippet label="cotton/input.html">{% cotton_verbatim %}{% verbatim %}
|
||||
<c-vars type="text" />
|
||||
|
@ -140,7 +140,7 @@
|
|||
|
||||
<c-navigation>
|
||||
<c-slot name="prev">
|
||||
<a href="{% url 'components' %}">Components</a>
|
||||
<a href="{% url 'usage-patterns' %}">Usage Patterns</a>
|
||||
</c-slot>
|
||||
<c-slot name="next">
|
||||
<a href="{% url 'alpine-js' %}">Tabs with Alpine.js</a>
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
<div class="w-full shrink-0"></div>
|
||||
<span class="pt-0 md:pt-5 clear-both flex-wrap inline-flex justify-center items-center space-x-2">
|
||||
<span class="">Hello</span>
|
||||
<span class="shrink-0 px-3 py-1 bg-teal-600 font-mono text-xl sm:text-2xl md:text-4xl rounded-lg text-white inline-block font-normal leading-normal">{{ '<c-component />' }}</span>
|
||||
<span class="shrink-0 px-3 py-1 bg-teal-500/10 border-[3px] border-teal-600 font-mono text-xl sm:text-2xl md:text-4xl rounded-3xl text-teal-600 dark:text-white inline-block font-normal leading-normal">{{ '<c-comp />'|force_escape }}</span>
|
||||
</span>
|
||||
</h1>
|
||||
|
||||
|
@ -32,7 +32,7 @@
|
|||
|
||||
<div class="grid md:grid-cols-2 gap-4">
|
||||
<div class="col-span-1 flex flex-col overflow-x-auto">
|
||||
<h2 class="!font-normal !text-xl mb-3 mt-0 text-center"><span class="font-semibold">Before:</span> Strongly Coupled, Verbose</h2>
|
||||
<h2 class="!font-normal !text-lg mb-3 mt-0 text-center"><span class="font-semibold">Before:</span> Strongly Coupled, Verbose</h2>
|
||||
<div class="flex h-full rounded-xl overflow-hidden">
|
||||
<c-demo.snippet-tabs labels="view.html|product_layout.html" tabs_id="compare">
|
||||
<div class="flex flex-col h-full" x-show="active === 0">
|
||||
|
@ -44,7 +44,7 @@
|
|||
icon.png
|
||||
{% endblock %}
|
||||
|
||||
{% block header %}
|
||||
{% block title %}
|
||||
Item Title
|
||||
{% endblock %}
|
||||
|
||||
|
@ -88,7 +88,7 @@ Item Title
|
|||
</div>
|
||||
</div>
|
||||
<div class="col-span-1 rounded-lg overflow-hidden flex flex-col">
|
||||
<h2 class="!font-normal !text-xl mb-3 mt-0 text-center"><span class="font-semibold">After:</span> Decoupled, Clean & Re-usable</h2>
|
||||
<h2 class="!font-normal !text-lg mb-3 mt-0 text-center"><span class="font-semibold">After:</span> Decoupled, Clean & Re-usable</h2>
|
||||
<div class="flex h-full rounded-xl overflow-hidden">
|
||||
<c-demo.snippet-tabs labels="view.html|product.html" tabs_id="compare">
|
||||
<div class="flex flex-col h-full" x-show="active === 0">
|
||||
|
@ -179,4 +179,4 @@ Item Title
|
|||
|
||||
</div>
|
||||
|
||||
</c-layouts.with-sidebar>
|
||||
</c-layouts.with-sidebar>
|
||||
|
|
|
@ -2,23 +2,19 @@
|
|||
<c-slot name="page_index">
|
||||
<c-index-link><a href="#install" class="no-underline">Install Cotton</a></c-index-link>
|
||||
<c-index-link><a href="#create-a-component" class="no-underline">Create a component</a></c-index-link>
|
||||
<c-index-link><a href="#templates-location" class="no-underline">Templates location</a></c-index-link>
|
||||
<c-index-link><a href="#include-a-component" class="no-underline">Include a component</a></c-index-link>
|
||||
<c-index-link><a href="#usage" class="no-underline">Usage</a></c-index-link>
|
||||
<c-index-sublink><a href="#basics" class="no-underline text-opacity-70">Basics</a></c-index-sublink>
|
||||
<c-index-sublink><a href="#naming" class="no-underline">Naming</a></c-index-sublink>
|
||||
<c-index-sublink><a href="#subfolders" class="no-underline">Subfolders</a></c-index-sublink>
|
||||
<c-index-sublink><a href="#tag-style" class="no-underline">Tag Style</a></c-index-sublink>
|
||||
</c-slot>
|
||||
|
||||
<h1 id="install">Quickstart</h1>
|
||||
|
||||
<h2>Install cotton</h2>
|
||||
<h2 class="mt-0">Install cotton</h2>
|
||||
<p>Run the following command:</p>
|
||||
<c-snippet language="python">pip install django-cotton</c-snippet>
|
||||
|
||||
<p>Then update your settings.py:</p>
|
||||
|
||||
<h3>Automatic configuration:</h3>
|
||||
<h3>For automatic configuration:</h3>
|
||||
|
||||
<c-snippet language="python" label="settings.py">{% cotton_verbatim %}{% verbatim %}
|
||||
INSTALLED_APPS = [
|
||||
|
@ -26,9 +22,9 @@ INSTALLED_APPS = [
|
|||
]
|
||||
{% endverbatim %}{% endcotton_verbatim %}</c-snippet>
|
||||
|
||||
<p>This will automatically handle the settings.py adding the required loader and templatetags.</p>
|
||||
<p>This will attempt to automatically handle the settings.py by adding the required loader and templatetags.</p>
|
||||
|
||||
<h3>Customised configuration</h3>
|
||||
<h3>For custom configuration</h3>
|
||||
|
||||
<p>If your project requires any non-default loaders or you do not wish Cotton to manage your settings, you should instead provide `django_cotton.apps.SimpleAppConfig` in your INSTALLED_APPS:</p>
|
||||
|
||||
|
@ -72,6 +68,21 @@ TEMPLATES = [
|
|||
</div>
|
||||
{% endverbatim %}{% endcotton_verbatim %}</c-snippet>
|
||||
|
||||
<c-hr id="templates-location" />
|
||||
|
||||
<h2>Templates location</h2>
|
||||
|
||||
<p>Cotton supports 2 common approaches regarding the location of the <code>templates</code> directory:</p>
|
||||
|
||||
<c-ul>
|
||||
<li><strong>App level</strong> - You can place your cotton folder in any of your installed app folders, like: <div><code>[project]/[app]/templates/cotton/row.html</code></div></li>
|
||||
<li>
|
||||
<strong>Project root</strong> - You can place your cotton folder in a project level templates directory, like: <div><code>[project]/templates/cotton/row.html</code></div>
|
||||
(<code>[project]</code> location is provided by `BASE_DIR` if present or you may set it with `COTTON_BASE_DIR`)
|
||||
</li>
|
||||
</c-ul>
|
||||
|
||||
<p>Any style will allow you to include your component the same way: <code>{{ '<c-row />'|force_escape }}</code></p>
|
||||
|
||||
<c-hr id="include-a-component" />
|
||||
|
||||
|
@ -105,34 +116,6 @@ def dashboard_view(request):
|
|||
</c-slot>
|
||||
</c-snippet>
|
||||
|
||||
<c-hr />
|
||||
|
||||
<h2 id="usage">Usage</h2>
|
||||
|
||||
<h3 id="basics">Basics</h3>
|
||||
<c-ul>
|
||||
<li>Cotton components should be placed in the <c-highlight>templates/cotton</c-highlight> folder (unless you have set COTTON_DIR).</li>
|
||||
</c-ul>
|
||||
|
||||
<h3 id="naming">Naming</h3>
|
||||
<p>Cotton uses the following naming conventions:</p>
|
||||
<c-ul>
|
||||
<li>Component file names are in snake_case: <c-highlight>my_component.html</c-highlight></li>
|
||||
<li>but are called using kebab-case: <c-highlight>{{ "<c-my-component />"|force_escape }}</c-highlight></li>
|
||||
</c-ul>
|
||||
|
||||
<h3 id="subfolders">Subfolders</h3>
|
||||
|
||||
<c-ul>
|
||||
<li>Components in subfolders can be defined using dot notation</li>
|
||||
<li>A component in <c-highlight>sidebar/menu/link.html</c-highlight> would be included as <c-highlight>{{ "<c-sidebar.menu.link />"|force_escape }}</c-highlight></li>
|
||||
</c-ul>
|
||||
|
||||
<h3 id="tag-style">Tag Style</h3>
|
||||
<c-ul>
|
||||
<li>Components can either be self-closing <c-highlight>{{ "<c-my-component />"|force_escape }}</c-highlight> or have a closing tag <c-highlight>{{ "<c-my-component></c-my-component>"|force_escape }}</c-highlight></li>
|
||||
</c-ul>
|
||||
|
||||
<c-navigation>
|
||||
<c-slot name="prev">
|
||||
<a href="{% url 'home' %}">Home</a>
|
||||
|
|
79
docs/docs_project/docs_project/templates/usage_patterns.html
Normal file
79
docs/docs_project/docs_project/templates/usage_patterns.html
Normal file
|
@ -0,0 +1,79 @@
|
|||
<c-layouts.with-sidebar>
|
||||
<h1 id="components">Usage Patterns</h1>
|
||||
|
||||
<c-slot name="page_index">
|
||||
<c-index-link><a href="#components" class="no-underline">Components</a></c-index-link>
|
||||
<c-index-sublink><a href="#basics" class="no-underline text-opacity-70">Basics</a></c-index-sublink>
|
||||
<c-index-sublink><a href="#naming" class="no-underline">Naming</a></c-index-sublink>
|
||||
<c-index-sublink><a href="#subfolders" class="no-underline">Subfolders</a></c-index-sublink>
|
||||
<c-index-sublink><a href="#index" class="no-underline">index.html</a></c-index-sublink>
|
||||
<c-index-sublink><a href="#tag-style" class="no-underline">Tag Style</a></c-index-sublink>
|
||||
</c-slot>
|
||||
|
||||
<h3 id="basics">Basics</h3>
|
||||
<c-ul>
|
||||
<li>Cotton components should be placed in the <c-highlight>templates/cotton</c-highlight> folder ('cotton' path is <a href="{% url 'configuration' %}">configurable</a> using <code>COTTON_DIR</code>).</li>
|
||||
<li>The <code>templates</code> folder can be located in either an app-level or top-level project root folder.</li>
|
||||
</c-ul>
|
||||
|
||||
<c-hr />
|
||||
|
||||
<h3 id="naming">Naming</h3>
|
||||
<p>Cotton uses the following naming conventions:</p>
|
||||
<c-ul>
|
||||
<li>By default, component file names are in snake_case (<c-highlight>my_component.html</c-highlight>).
|
||||
<li>kebab-case filenames (<c-highlight>my-component.html</c-highlight>) can be enabled with <code>COTTON_SNAKE_CASED_NAMES = False</code> see <a href="{% url 'configuration' %}">configuration</a>.</li>
|
||||
<li>Components are included in templates using kebab-case name of the component: <code>{{ "<c-my-component />"|force_escape }}</code></li>
|
||||
</c-ul>
|
||||
|
||||
<c-hr />
|
||||
|
||||
<h3 id="subfolders">Subfolders</h3>
|
||||
|
||||
<c-ul>
|
||||
<li>Components in subfolders can be called using dot notation to represent folder levels.</li>
|
||||
<li>A component in <c-highlight>sidebar/menu/link.html</c-highlight> would be included with <code>{{ "<c-sidebar.menu.link />"|force_escape }}</code></li>
|
||||
</c-ul>
|
||||
|
||||
<c-hr />
|
||||
|
||||
<h3 id="index">The index.html component</h3>
|
||||
|
||||
<p>When your component has sub-components, you can define the default component of a folder by adding an <code>index.html</code>. This helps to keep your project structure tidy and reduce additional code in the template.</p>
|
||||
|
||||
<c-snippet label="Project structure">
|
||||
{% cotton_verbatim %}{% verbatim %}
|
||||
templates/
|
||||
├── cotton/
|
||||
│ ├── card/
|
||||
│ │ ├── index.html
|
||||
│ │ ├── header.html
|
||||
{% endverbatim %}{% endcotton_verbatim %}
|
||||
</c-snippet>
|
||||
|
||||
<c-snippet label="Usage">
|
||||
{% cotton_verbatim %}{% verbatim %}
|
||||
<c-card>
|
||||
<c-card.header>...</c-card.header>
|
||||
</c-card>
|
||||
{% endverbatim %}{% endcotton_verbatim %}
|
||||
</c-snippet>
|
||||
|
||||
<c-hr />
|
||||
|
||||
<h3 id="tag-style">Tag Style</h3>
|
||||
<c-ul>
|
||||
<li>Components can either be self-closing <code>{{ "<c-my-component />"|force_escape }}</code> or have a closing tag <code>{{ "<c-my-component></c-my-component>"|force_escape }}</code></li>
|
||||
</c-ul>
|
||||
|
||||
|
||||
<c-navigation>
|
||||
<c-slot name="prev">
|
||||
<a href="{% url 'components' %}">Components</a>
|
||||
</c-slot>
|
||||
<c-slot name="next">
|
||||
<a href="{% url 'form-fields' %}">Form Inputs</a>
|
||||
</c-slot>
|
||||
</c-navigation>
|
||||
|
||||
</c-layouts.with-sidebar>
|
|
@ -10,8 +10,9 @@ urlpatterns = [
|
|||
name="home",
|
||||
),
|
||||
path("docs/quickstart", views.build_view("quickstart"), name="quickstart"),
|
||||
path("docs/installation", views.build_view("installation"), name="installation"),
|
||||
path("docs/usage", views.build_view("usage"), name="usage"),
|
||||
path(
|
||||
"docs/usage-patterns", views.build_view("usage_patterns"), name="usage-patterns"
|
||||
),
|
||||
# Features
|
||||
path("docs/components", views.build_view("components"), name="components"),
|
||||
path("docs/slots", views.build_view("slots"), name="slots"),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue