mirror of
https://github.com/wrabit/django-cotton.git
synced 2025-08-04 15:18:20 +00:00
on this page collapsible
This commit is contained in:
parent
f41d300874
commit
12833f753c
13 changed files with 169 additions and 32 deletions
|
@ -40,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>
|
||||
|
||||
|
@ -59,9 +59,9 @@
|
|||
</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 <code>{{ '<c-slot name="...">...</c-slot>'|force_escape }}</code> syntax.</p>
|
||||
|
||||
|
@ -98,9 +98,9 @@
|
|||
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>
|
||||
|
||||
<c-hr />
|
||||
<c-hr id="dynamic-attributes" />
|
||||
|
||||
<h2 id="dynamic-attributes">4. Dynamic Attributes with ":"</h2>
|
||||
<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>
|
||||
|
||||
|
@ -181,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>
|
||||
|
||||
|
@ -209,15 +209,15 @@ context = { 'today': Weather.objects.get(...) }
|
|||
{% endcotton_verbatim %}{% endverbatim %}
|
||||
</c-snippet>
|
||||
|
||||
<c-hr />
|
||||
<c-hr id="vars" />
|
||||
|
||||
<h2 id="vars">6. Defining Local Variables with <code>{{ '<c-vars />'|force_escape }}</code></h2>
|
||||
<h2>6. Defining Local Variables with <code>{{ '<c-vars />'|force_escape }}</code></h2>
|
||||
|
||||
<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>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">Example: Setting Default Attributes</h3>
|
||||
<h3>Example: Setting Default Attributes</h3>
|
||||
|
||||
<p>In components with common defaults, <code>{{ '<c-vars />'|force_escape }}</code> can pre-define attributes that rarely need overriding.</p>
|
||||
|
||||
|
@ -240,7 +240,7 @@ 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 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>
|
||||
|
||||
|
@ -278,9 +278,9 @@ context = { 'today': Weather.objects.get(...) }
|
|||
|
||||
<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 />
|
||||
<c-hr id="boolean-attributes" />
|
||||
|
||||
<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>
|
||||
|
||||
|
@ -301,9 +301,9 @@ context = { 'today': Weather.objects.get(...) }
|
|||
</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 <code>{{ '<c-component>'|force_escape }}</code> tag with an <code>is</code> attribute:</p>
|
||||
|
||||
|
@ -323,15 +323,15 @@ 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 with `only`</h2>
|
||||
<h2>9. Context Isolation with `only`</h2>
|
||||
|
||||
<p>Similar to Django's <code>{% verbatim %}{% include %}{% endverbatim %}</code> tag you can add an "<code>only</code>" attribute which will prevent the component from inheriting the parent's context.</p>
|
||||
|
||||
<c-hr />
|
||||
<c-hr id="alpine-js-support" />
|
||||
|
||||
<h2 id="alpine-js-support">10. Alpine.js support</h2>
|
||||
<h2>10. Alpine.js support</h2>
|
||||
|
||||
<p>The following key features allow you to build re-usable components with alpine.js:</p>
|
||||
|
||||
|
@ -344,9 +344,9 @@ context = { 'today': Weather.objects.get(...) }
|
|||
</li>
|
||||
</c-ul>
|
||||
|
||||
<c-hr />
|
||||
<c-hr id="summary" />
|
||||
|
||||
<h2 id="summary">Summary of Concepts</h2>
|
||||
<h2>Summary of Concepts</h2>
|
||||
<ul>
|
||||
<li><code>{% verbatim %}{{ slot }}{% endverbatim %}</code> - Default content injection.</li>
|
||||
<li><c-highlight>Attributes</c-highlight> - Simple, straightforward customization.</li>
|
||||
|
|
|
@ -1 +1 @@
|
|||
<div {{ attrs }} class="h-[1px] 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 |
|
@ -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>
|
||||
|
|
|
@ -17,8 +17,9 @@
|
|||
|
||||
prose
|
||||
prose-a:text-teal-600
|
||||
prose-h2:text-3xl
|
||||
prose-h3:text-2xl
|
||||
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
|
||||
|
@ -36,6 +37,35 @@
|
|||
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>
|
||||
|
|
|
@ -64,9 +64,9 @@
|
|||
localStorage.theme = this.dark ? 'dark' : 'light'
|
||||
}
|
||||
}">
|
||||
<c-icons.sun class="size-8 text-yellow-900/40 dark:text-gray-100" stroke-width="1.5" />
|
||||
<c-icons.sun class="size-8 text-yellow-900/40 dark:text-gray-100/50" stroke-width="1.5" />
|
||||
</a>
|
||||
<a href="https://github.com/wrabit/django-cotton" target="_blank" class="text-yellow-900/40 dark:text-gray-100 flex items-center space-x-2">
|
||||
<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-7" />
|
||||
</a>
|
||||
</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>
|
||||
|
|
|
@ -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 text-white 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>
|
||||
{{ 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>
|
|
@ -13,7 +13,7 @@
|
|||
|
||||
<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>
|
||||
|
||||
|
@ -124,15 +124,15 @@ def dashboard_view(request):
|
|||
|
||||
<h3 id="basics">Basics</h3>
|
||||
<c-ul>
|
||||
<li>Cotton components should be placed in the <c-highlight>templates/cotton</c-highlight> folder ('cotton' directory is <a href="{% url 'configuration' %}">configurable</a> using COTTON_DIR).</li>
|
||||
<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>
|
||||
|
||||
<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: <code>{{ "<c-my-component />"|force_escape }}</code></li>
|
||||
<li>Component file names by default are in snake_case: <c-highlight>my_component.html</c-highlight> (kebab-case filenames can be enabled, see <a href="{% url 'configuration' %}">configuration</a>)</li>
|
||||
<li>and are included using kebab-case: <code>{{ "<c-my-component />"|force_escape }}</code></li>
|
||||
</c-ul>
|
||||
|
||||
<h3 id="subfolders">Subfolders</h3>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue