mirror of
https://github.com/hunvreus/basecoat.git
synced 2026-11-11 04:38:18 +00:00
Most docs are complete
This commit is contained in:
Vendored
+24
-81
@@ -69,8 +69,6 @@
|
||||
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
|
||||
--shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
|
||||
--shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25);
|
||||
--ease-in: cubic-bezier(0.4, 0, 1, 1);
|
||||
--ease-out: cubic-bezier(0, 0, 0.2, 1);
|
||||
--ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
|
||||
--animate-spin: spin 1s linear infinite;
|
||||
--animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
|
||||
@@ -255,6 +253,9 @@
|
||||
.pointer-events-none {
|
||||
pointer-events: none;
|
||||
}
|
||||
.invisible {
|
||||
visibility: hidden;
|
||||
}
|
||||
.sr-only {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
@@ -383,6 +384,10 @@
|
||||
.aspect-video {
|
||||
aspect-ratio: var(--aspect-video);
|
||||
}
|
||||
.size-2 {
|
||||
width: calc(var(--spacing) * 2);
|
||||
height: calc(var(--spacing) * 2);
|
||||
}
|
||||
.size-3\.5 {
|
||||
width: calc(var(--spacing) * 3.5);
|
||||
height: calc(var(--spacing) * 3.5);
|
||||
@@ -533,21 +538,10 @@
|
||||
--tw-translate-y: calc(calc(1/2 * 100%) * -1);
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
.translate-y-0 {
|
||||
--tw-translate-y: calc(var(--spacing) * 0);
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
.translate-y-0\.5 {
|
||||
--tw-translate-y: calc(var(--spacing) * 0.5);
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
.translate-y-2 {
|
||||
--tw-translate-y: calc(var(--spacing) * 2);
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
.transform {
|
||||
transform: var(--tw-rotate-x) var(--tw-rotate-y) var(--tw-rotate-z) var(--tw-skew-x) var(--tw-skew-y);
|
||||
}
|
||||
.animate-pulse {
|
||||
animation: var(--animate-pulse);
|
||||
}
|
||||
@@ -720,6 +714,9 @@
|
||||
.bg-background {
|
||||
background-color: var(--color-background);
|
||||
}
|
||||
.bg-foreground {
|
||||
background-color: var(--color-foreground);
|
||||
}
|
||||
.bg-muted {
|
||||
background-color: var(--color-muted);
|
||||
}
|
||||
@@ -890,9 +887,6 @@
|
||||
.text-sidebar-primary-foreground {
|
||||
color: var(--color-sidebar-primary-foreground);
|
||||
}
|
||||
.text-transparent {
|
||||
color: transparent;
|
||||
}
|
||||
.text-zinc-50 {
|
||||
color: var(--color-zinc-50);
|
||||
}
|
||||
@@ -906,18 +900,12 @@
|
||||
.underline-offset-4 {
|
||||
text-underline-offset: 4px;
|
||||
}
|
||||
.opacity-0 {
|
||||
opacity: 0%;
|
||||
}
|
||||
.opacity-50 {
|
||||
opacity: 50%;
|
||||
}
|
||||
.opacity-60 {
|
||||
opacity: 60%;
|
||||
}
|
||||
.opacity-100 {
|
||||
opacity: 100%;
|
||||
}
|
||||
.shadow-none {
|
||||
--tw-shadow: 0 0 #0000;
|
||||
box-shadow: var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow);
|
||||
@@ -947,11 +935,6 @@
|
||||
.filter {
|
||||
filter: var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,);
|
||||
}
|
||||
.transition {
|
||||
transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to, opacity, box-shadow, transform, translate, scale, rotate, filter, -webkit-backdrop-filter, backdrop-filter;
|
||||
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
||||
transition-duration: var(--tw-duration, var(--default-transition-duration));
|
||||
}
|
||||
.transition-\[margin-left\] {
|
||||
transition-property: margin-left;
|
||||
transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
|
||||
@@ -981,22 +964,10 @@
|
||||
--tw-duration: 200ms;
|
||||
transition-duration: 200ms;
|
||||
}
|
||||
.duration-300 {
|
||||
--tw-duration: 300ms;
|
||||
transition-duration: 300ms;
|
||||
}
|
||||
.ease-in {
|
||||
--tw-ease: var(--ease-in);
|
||||
transition-timing-function: var(--ease-in);
|
||||
}
|
||||
.ease-in-out {
|
||||
--tw-ease: var(--ease-in-out);
|
||||
transition-timing-function: var(--ease-in-out);
|
||||
}
|
||||
.ease-out {
|
||||
--tw-ease: var(--ease-out);
|
||||
transition-timing-function: var(--ease-out);
|
||||
}
|
||||
.outline-none {
|
||||
--tw-outline-style: none;
|
||||
outline-style: none;
|
||||
@@ -1010,6 +981,11 @@
|
||||
rotate: 180deg;
|
||||
}
|
||||
}
|
||||
.group-aria-checked\:visible {
|
||||
&:is(:where(.group)[aria-checked="true"] *) {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
.peer-aria-hidden\:ml-0 {
|
||||
&:is(:where(.peer)[aria-hidden="true"] ~ *) {
|
||||
margin-left: calc(var(--spacing) * 0);
|
||||
@@ -1564,16 +1540,6 @@
|
||||
height: calc(var(--spacing) * 4);
|
||||
}
|
||||
}
|
||||
.\[\&\>\[role\=img\]\>svg\]\:w-full {
|
||||
&>[role=img]>svg {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.\[\&\>\[role\=img\]\>svg\]\:shrink-0 {
|
||||
&>[role=img]>svg {
|
||||
flex-shrink: 0;
|
||||
}
|
||||
}
|
||||
.\[\&\>h2\]\:mt-16 {
|
||||
&>h2 {
|
||||
margin-top: calc(var(--spacing) * 16);
|
||||
@@ -2780,7 +2746,7 @@
|
||||
translate: var(--tw-translate-x) var(--tw-translate-y);
|
||||
}
|
||||
}
|
||||
[role='menuitem'], [role='option'] {
|
||||
[role='menuitem'], [role='menuitemcheckbox'], [role='menuitemradio'], [role='option'] {
|
||||
position: relative;
|
||||
display: flex;
|
||||
width: 100%;
|
||||
@@ -2829,7 +2795,7 @@
|
||||
color: var(--color-muted-foreground);
|
||||
}
|
||||
}
|
||||
[role='menuitem'] {
|
||||
[role='menuitem'], [role='menuitemcheckbox'], [role='menuitemradio'] {
|
||||
&:hover {
|
||||
@media (hover: hover) {
|
||||
background-color: var(--color-accent);
|
||||
@@ -3676,6 +3642,7 @@
|
||||
[data-tooltip] {
|
||||
position: relative;
|
||||
&:before {
|
||||
pointer-events: none;
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
z-index: 50;
|
||||
@@ -3710,6 +3677,9 @@
|
||||
scale: var(--tw-scale-x) var(--tw-scale-y);
|
||||
opacity: 100%;
|
||||
}
|
||||
&:focus-visible:not(:hover):before {
|
||||
display: none;
|
||||
}
|
||||
&:not([data-side]), &[data-side='top'] {
|
||||
&::before {
|
||||
content: var(--tw-content);
|
||||
@@ -3930,6 +3900,9 @@
|
||||
li {
|
||||
margin-bottom: calc(var(--spacing) * 2);
|
||||
}
|
||||
ul, ol {
|
||||
margin-block: calc(var(--spacing) * 2);
|
||||
}
|
||||
}
|
||||
.prose > *:first-child {
|
||||
margin-top: calc(var(--spacing) * 0) !important;
|
||||
@@ -3983,31 +3956,6 @@
|
||||
inherits: false;
|
||||
initial-value: 0;
|
||||
}
|
||||
@property --tw-rotate-x {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
initial-value: rotateX(0);
|
||||
}
|
||||
@property --tw-rotate-y {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
initial-value: rotateY(0);
|
||||
}
|
||||
@property --tw-rotate-z {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
initial-value: rotateZ(0);
|
||||
}
|
||||
@property --tw-skew-x {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
initial-value: skewX(0);
|
||||
}
|
||||
@property --tw-skew-y {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
initial-value: skewY(0);
|
||||
}
|
||||
@property --tw-space-y-reverse {
|
||||
syntax: "*";
|
||||
inherits: false;
|
||||
@@ -4222,11 +4170,6 @@
|
||||
--tw-translate-x: 0;
|
||||
--tw-translate-y: 0;
|
||||
--tw-translate-z: 0;
|
||||
--tw-rotate-x: rotateX(0);
|
||||
--tw-rotate-y: rotateY(0);
|
||||
--tw-rotate-z: rotateZ(0);
|
||||
--tw-skew-x: skewX(0);
|
||||
--tw-skew-y: skewY(0);
|
||||
--tw-space-y-reverse: 0;
|
||||
--tw-space-x-reverse: 0;
|
||||
--tw-border-style: solid;
|
||||
|
||||
Vendored
+13
-2
@@ -627,10 +627,14 @@
|
||||
}
|
||||
}
|
||||
[role='menuitem'],
|
||||
[role='menuitemcheckbox'],
|
||||
[role='menuitemradio'],
|
||||
[role='option'] {
|
||||
@apply aria-hidden:hidden [&_svg]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none [&_svg]:shrink-0 [&_svg]:size-4 aria-disabled:opacity-50 aria-disabled:pointer-events-none disabled:opacity-50 disabled:pointer-events-none w-full truncate;
|
||||
}
|
||||
[role='menuitem'] {
|
||||
[role='menuitem'],
|
||||
[role='menuitemcheckbox'],
|
||||
[role='menuitemradio'] {
|
||||
@apply focus-visible:bg-accent focus-visible:text-accent-foreground hover:bg-accent hover:text-accent-foreground;
|
||||
}
|
||||
[role='option'] {
|
||||
@@ -860,11 +864,14 @@
|
||||
@apply relative;
|
||||
|
||||
&:before {
|
||||
@apply absolute content-[attr(data-tooltip)] bg-primary text-primary-foreground z-50 truncate max-w-xs w-fit rounded-md px-3 py-1.5 text-xs invisible opacity-0 scale-95 transition-all;
|
||||
@apply absolute content-[attr(data-tooltip)] bg-primary text-primary-foreground z-50 truncate max-w-xs w-fit rounded-md px-3 py-1.5 text-xs invisible opacity-0 scale-95 transition-all pointer-events-none;
|
||||
}
|
||||
&:hover:before {
|
||||
@apply visible opacity-100 scale-100;
|
||||
}
|
||||
&:focus-visible:not(:hover):before {
|
||||
@apply hidden;
|
||||
}
|
||||
&:not([data-side]),
|
||||
&[data-side='top'] {
|
||||
@apply before:bottom-full before:mb-1.5 before:translate-y-2 hover:before:translate-y-0 ;
|
||||
@@ -979,6 +986,10 @@
|
||||
li {
|
||||
@apply mb-2;
|
||||
}
|
||||
ul,
|
||||
ol {
|
||||
@apply my-2;
|
||||
}
|
||||
}
|
||||
.prose > *:first-child {
|
||||
@apply !mt-0;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
init() {
|
||||
this.$nextTick(() => {
|
||||
this.menuItems = Array.from(this.$el.querySelectorAll('[role=menuitem]:not([disabled])'));
|
||||
this.menuItems = Array.from(this.$el.querySelectorAll('[role=menuitem]:not([disabled]),[role=menuitemcheckbox]:not([disabled]),[role=menuitemradio]:not([disabled])'));
|
||||
});
|
||||
},
|
||||
focusMenuitem() {
|
||||
@@ -44,7 +44,7 @@
|
||||
}
|
||||
},
|
||||
handleMenuitemClick(event) {
|
||||
const menuitem = event.target.closest('[role=menuitem]');
|
||||
const menuitem = event.target.closest('[role=menuitem],[role=menuitemcheckbox],[role=menuitemradio]');
|
||||
if (menuitem && menuitem.getAttribute('aria-disabled') !== 'true' && !menuitem.disabled) {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.trigger.focus();
|
||||
@@ -53,7 +53,7 @@
|
||||
}
|
||||
},
|
||||
handleMenuitemMousemove(event) {
|
||||
const menuitem = event.target.closest('[role=menuitem]');
|
||||
const menuitem = event.target.closest('[role=menuitem],[role=menuitemcheckbox],[role=menuitemradio]');
|
||||
if (menuitem && menuitem.getAttribute('aria-disabled') !== 'true' && !menuitem.disabled) {
|
||||
this.focusedIndex = this.menuItems.indexOf(menuitem);
|
||||
this.focusMenuitem();
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
{% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
|
||||
{% endfor %}
|
||||
>
|
||||
<div
|
||||
<nav
|
||||
role="tablist"
|
||||
aria-orientation="horizontal"
|
||||
x-bind="$tablist"
|
||||
@@ -43,7 +43,7 @@
|
||||
{{ tabset.tab | safe }}
|
||||
</button>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
{% for tabset in tabsets %}
|
||||
{% if tabset.panel %}
|
||||
|
||||
@@ -66,7 +66,7 @@
|
||||
type="button"
|
||||
class="btn-outline"
|
||||
>
|
||||
Trigger dialog:control
|
||||
Trigger dialog:open
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -8,12 +8,12 @@
|
||||
<div class="flex flex-wrap items-start gap-4">
|
||||
{% call dropdown_menu(
|
||||
id="dropdown-menu",
|
||||
trigger="Open Menu",
|
||||
trigger="Open",
|
||||
trigger_attrs={"class": "btn-outline"},
|
||||
content_attrs={"class": "min-w-56"}
|
||||
) %}
|
||||
<div role="group" aria-labelledby="account-options">
|
||||
<span id="account-options" role="heading">Account Options</span>
|
||||
<span id="account-options" role="heading">My Account</span>
|
||||
<button type="button" role="menuitem">
|
||||
Profile
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⇧⌘P</span>
|
||||
@@ -42,6 +42,97 @@
|
||||
</button>
|
||||
{% endcall %}
|
||||
|
||||
{% call dropdown_menu(
|
||||
id="dropdown-menu-checkboxes",
|
||||
trigger="Checkboxes",
|
||||
trigger_attrs={"class": "btn-outline"},
|
||||
content_attrs={"class": "min-w-56"},
|
||||
register_on=["alpine:init", "htmx:afterSwap"]
|
||||
) %}
|
||||
<div role="group" aria-labelledby="account-options">
|
||||
<span id="account-options" role="heading">Account Options</span>
|
||||
<button type="button" role="menuitem">
|
||||
{% lucide "user" %}
|
||||
Profile
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⇧⌘P</span>
|
||||
</button>
|
||||
<button type="button" role="menuitem">
|
||||
{% lucide "credit-card" %}
|
||||
Billing
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⌘B</span>
|
||||
</button>
|
||||
<button type="button" role="menuitem">
|
||||
{% lucide "settings" %}
|
||||
Settings
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⌘S</span>
|
||||
</button>
|
||||
</div>
|
||||
<hr role="separator">
|
||||
<div role="group" aria-labelledby="appearance-options">
|
||||
<span id="appearance-options" role="heading">Appearance</span>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitemcheckbox"
|
||||
aria-checked="true"
|
||||
class="group"
|
||||
x-data="{ checked: true }"
|
||||
@click="checked = !checked"
|
||||
:aria-checked="checked"
|
||||
>
|
||||
{% lucide "check", {
|
||||
"class": "invisible group-aria-checked:visible",
|
||||
"aria-hidden": "true",
|
||||
"focusable": "false"
|
||||
} %}
|
||||
Status Bar
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⇧⌘P</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitemcheckbox"
|
||||
aria-checked="false"
|
||||
class="group"
|
||||
disabled
|
||||
x-data="{ checked: false }"
|
||||
@click="checked = !checked"
|
||||
:aria-checked="checked"
|
||||
>
|
||||
{% lucide "check", {
|
||||
"class": "invisible group-aria-checked:visible",
|
||||
"aria-hidden": "true",
|
||||
"focusable": "false"
|
||||
} %}
|
||||
Activity Bar
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⌘B</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitemcheckbox"
|
||||
aria-checked="false"
|
||||
class="group"
|
||||
x-data="{ checked: false }"
|
||||
@click="checked = !checked"
|
||||
:aria-checked="checked"
|
||||
>
|
||||
{% lucide "check", {
|
||||
"class": "invisible group-aria-checked:visible",
|
||||
"aria-hidden": "true",
|
||||
"focusable": "false"
|
||||
} %}
|
||||
Panel
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⌘S</span>
|
||||
</button>
|
||||
</div>
|
||||
<hr role="separator">
|
||||
<button type="button" role="menuitem">
|
||||
{% lucide "log-out" %}
|
||||
Logout
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⇧⌘P</span>
|
||||
</button>
|
||||
{% endcall %}
|
||||
|
||||
|
||||
|
||||
{% set profile_menu %}
|
||||
<div class="flex items-center gap-2 px-1 py-1.5 text-left text-sm">
|
||||
<img alt="@hunvreus" src="https://github.com/hunvreus.png" class="size-8 shrink-0 rounded-full" alt="Ronan Berder"/>
|
||||
@@ -69,28 +160,79 @@
|
||||
Notifications
|
||||
</button>
|
||||
<hr role="separator">
|
||||
<div role="group" aria-labelledby="theme-options">
|
||||
<span id="theme-options" role="heading">Theme</span>
|
||||
<button type="button" role="menuitem">
|
||||
{% lucide "check", { "class": "text-foreground" } %}
|
||||
Light
|
||||
</button>
|
||||
<button type="button" role="menuitem" >
|
||||
{% lucide "check", { "class": "text-transparent" } %}
|
||||
Dark
|
||||
</button>
|
||||
<button type="button" role="menuitem">
|
||||
{% lucide "check", { "class": "text-transparent" } %}
|
||||
System
|
||||
</button>
|
||||
</div>
|
||||
<hr role="separator">
|
||||
<button type="button" role="menuitem">
|
||||
{% lucide "log-out" %}
|
||||
Signout
|
||||
</button>
|
||||
{% endset %}
|
||||
|
||||
{% call dropdown_menu(
|
||||
id="dropdown-menu-radio-group",
|
||||
trigger="Radio Group",
|
||||
trigger_attrs={"class": "btn-outline"},
|
||||
content_attrs={"class": "min-w-56"},
|
||||
register_on=["alpine:init", "htmx:afterSwap"]
|
||||
) %}
|
||||
<div role="group" aria-labelledby="position-options" x-data="{ checked: 'bottom' }">
|
||||
<span id="position-options" role="heading">Panel Position</span>
|
||||
<hr role="separator">
|
||||
<button
|
||||
type="button"
|
||||
role="menuitemradio"
|
||||
aria-checked="false"
|
||||
class="group"
|
||||
@click="checked = 'top'"
|
||||
:aria-checked="checked == 'top'"
|
||||
>
|
||||
<div class="size-4 flex items-center justify-center">
|
||||
<div
|
||||
class="size-2 rounded-full bg-foreground invisible group-aria-checked:visible"
|
||||
aria-hidden="true",
|
||||
focusable="false"
|
||||
></div>
|
||||
</div>
|
||||
Status Bar
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⇧⌘P</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitemradio"
|
||||
aria-checked="false"
|
||||
class="group"
|
||||
@click="checked = 'bottom'"
|
||||
:aria-checked="checked == 'bottom'"
|
||||
>
|
||||
<div class="size-4 flex items-center justify-center">
|
||||
<div
|
||||
class="size-2 rounded-full bg-foreground invisible group-aria-checked:visible"
|
||||
aria-hidden="true",
|
||||
focusable="false"
|
||||
></div>
|
||||
</div>
|
||||
Activity Bar
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⌘B</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitemradio"
|
||||
aria-checked="false"
|
||||
class="group"
|
||||
@click="checked = 'right'"
|
||||
:aria-checked="checked == 'right'"
|
||||
>
|
||||
<div class="size-4 flex items-center justify-center">
|
||||
<div
|
||||
class="size-2 rounded-full bg-foreground invisible group-aria-checked:visible"
|
||||
aria-hidden="true",
|
||||
focusable="false"
|
||||
></div>
|
||||
</div>
|
||||
Panel
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⌘S</span>
|
||||
</button>
|
||||
</div>
|
||||
{% endcall %}
|
||||
|
||||
{% set trigger %}
|
||||
<img alt="@hunvreus" src="https://github.com/hunvreus.png" class="size-8 shrink-0 rounded-full" alt="Ronan Berder"/>
|
||||
<div class="grid flex-1 text-left text-sm leading-tight">
|
||||
|
||||
@@ -6,6 +6,8 @@ toc:
|
||||
- label: Usage
|
||||
id: usage
|
||||
children:
|
||||
- label: HTML + Javascript
|
||||
id: usage-default
|
||||
- label: Jinja or Nunjucks
|
||||
id: usage-jinja
|
||||
---
|
||||
@@ -14,7 +16,8 @@ toc:
|
||||
{% from "macros/code_block.njk" import code_block %}
|
||||
{% from "components/dialog.njk" import dialog %}
|
||||
|
||||
{% set code %}{% set footer %}
|
||||
{% set code_html %}
|
||||
{% set footer %}
|
||||
<button class="btn-outline" @click="open = false">Cancel</button>
|
||||
<button class="btn-primary" @click="open = false">Continue</button>
|
||||
{% endset %}
|
||||
@@ -28,39 +31,35 @@ toc:
|
||||
close_button=false,
|
||||
close_on_overlay_click=false,
|
||||
register_on=["alpine:init", "htmx:afterSwap"]
|
||||
) }}{% endset %}
|
||||
{{ code_preview("alert-dialog", code | prettyHtml) }}
|
||||
) }}
|
||||
{% endset %}
|
||||
|
||||
{% set code_script %}
|
||||
{% include "components/dialog-script.njk" %}
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("alert-dialog", code_script | prettyHtml ~ code_html | prettyHtml) }}
|
||||
|
||||
<h2 id="usage"><a href="#usage">Usage</a></h2>
|
||||
|
||||
<h3 id="usage-default"><a href="#usage-default">HTML + Javascript</a></h3>
|
||||
|
||||
<div class="alert my-6">
|
||||
{% lucide "circle-alert" %}
|
||||
<h2>This component requires Javascript.</h2>
|
||||
<section>
|
||||
<p>You will need to include the Javascript (Alpine.js) code provided below before the HTML code for this component. As with all interactive components, you will need to add some Alpine.js properties to certain elements (e.g. <code class="text-xs">x-bind</code>, <code class="text-xs">x-data</code>, <code class="text-xs">@click</code>).</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<p class="prose my-6">The Alert Dialog component uses the same Alpine.js code as the <a href="/components/dialog" class="font-medium underline underline-offset-4">Dialog</a> component with one small difference: we set <code>initialCloseOnOverlayClick</code> to <code>false</code> to prevent the dialog from closing when the overlay is clicked.</p>
|
||||
|
||||
<h4 class="badge-secondary">HTML</h4>
|
||||
|
||||
<section class="my-6">
|
||||
{% set code_html %}{% set footer %}
|
||||
<button class="btn-outline" @click="open = false">Cancel</button>
|
||||
<button class="btn-primary" @click="open = false">Continue</button>
|
||||
{% endset %}
|
||||
{{ dialog(
|
||||
id="alert-dialog",
|
||||
title="Are you absolutely sure?",
|
||||
description="This action cannot be undone. This will permanently delete your account and remove your data from our servers.",
|
||||
trigger="Open alert dialog",
|
||||
trigger_attrs={"class": "btn-outline"},
|
||||
footer=footer,
|
||||
close_button=false,
|
||||
close_on_overlay_click=false
|
||||
) }}{% endset %}
|
||||
{{ code_block(code_html | prettyHtml) }}
|
||||
</section>
|
||||
|
||||
<h4 class="badge-secondary">Javascript (Alpine.js)</h4>
|
||||
|
||||
<section class="my-6">
|
||||
{% set code_script %}{% include "components/dialog-script.njk" %}{% endset %}
|
||||
{{ code_block(code_script | prettyHtml) }}
|
||||
</section>
|
||||
{% from "components/tabs.njk" import tabs %}
|
||||
{% set tabsets = [
|
||||
{ tab: "HTML", panel: code_block(code_html | prettyHtml) },
|
||||
{ tab: "Javascipt (Alpine.js)", panel: code_block(code_script | prettyHtml) }
|
||||
] %}
|
||||
{{ tabs(id="alert-dialog", tabsets=tabsets) }}
|
||||
|
||||
<h3 id="usage-jinja"><a href="#usage-jinja">Jinja or Nunjucks</a></h3>
|
||||
|
||||
|
||||
@@ -16,8 +16,12 @@ toc:
|
||||
<h2>There is no dedicated breadcrumb component in Basecoat.</h2>
|
||||
</div>
|
||||
|
||||
{% set code_script %}{% include "components/dropdown-menu-script.njk" %}{% endset %}
|
||||
{% set code_html %}<ol class="text-muted-foreground flex flex-wrap items-center gap-1.5 text-sm break-words sm:gap-2.5">
|
||||
{% set code_script %}
|
||||
{% include "components/dropdown-menu-script.njk" %}
|
||||
{% endset %}
|
||||
|
||||
{% set code_html %}
|
||||
<ol class="text-muted-foreground flex flex-wrap items-center gap-1.5 text-sm break-words sm:gap-2.5">
|
||||
<li class="inline-flex items-center gap-1.5">
|
||||
<a href="#" class="hover:text-foreground transition-colors">Home</a>
|
||||
</li>
|
||||
@@ -47,8 +51,10 @@ toc:
|
||||
<li class="inline-flex items-center gap-1.5">
|
||||
<span class="text-foreground font-normal">Breadcrumb</span>
|
||||
</li>
|
||||
</ol>{% endset %}
|
||||
{{ code_preview("dropdown-menu", code_script ~ code_html | prettyHtml) }}
|
||||
</ol>
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("dropdown-menu", code_script | prettyHtml ~ code_html | prettyHtml) }}
|
||||
|
||||
<h2 id="usage"><a href="#usage">Usage</a></h2>
|
||||
|
||||
@@ -56,14 +62,9 @@ toc:
|
||||
<p>The example above uses some simple Tailwind CSS along with the <a href="/components/dropdown-menu">Dropdown Menu</a>.</p>
|
||||
</section>
|
||||
|
||||
<h4 class="badge-secondary">HTML</h3>
|
||||
|
||||
<section class="my-6">
|
||||
{{ code_block(code_html | prettyHtml) }}
|
||||
</section>
|
||||
|
||||
<h4 class="badge-secondary">Javascript (Alpine.js) for the Dropdown Menu</h3>
|
||||
|
||||
<section class="my-6">
|
||||
{{ code_block(code_script | prettyHtml) }}
|
||||
</section>
|
||||
{% from "components/tabs.njk" import tabs %}
|
||||
{% set tabsets = [
|
||||
{ tab: "HTML", panel: code_block(code_html | prettyHtml) },
|
||||
{ tab: "Javascipt (Alpine.js)", panel: code_block(code_script | prettyHtml) }
|
||||
] %}
|
||||
{{ tabs(id="alert-dialog", tabsets=tabsets) }}
|
||||
@@ -6,6 +6,8 @@ toc:
|
||||
- label: Usage
|
||||
id: usage
|
||||
children:
|
||||
- label: HTML + Javascript
|
||||
id: usage-default
|
||||
- label: Jinja or Nunjucks
|
||||
id: usage-jinja
|
||||
- label: Examples
|
||||
@@ -22,7 +24,7 @@ toc:
|
||||
{% from "components/select.njk" import select %}
|
||||
|
||||
{% set options_frameworks = ["Next.js", "SvelteKit", "Nuxt.js", "Remix", "Astro"] %}
|
||||
{% set code %}
|
||||
{% set code_html %}
|
||||
{% call select(
|
||||
trigger_attrs={"class": "w-[200px]"},
|
||||
listbox_attrs={"data-empty": "No framework found."},
|
||||
@@ -33,11 +35,27 @@ toc:
|
||||
{% for framework in options_frameworks %}
|
||||
<div role="option" data-value="{{ framework }}">{{ framework }}</div>
|
||||
{% endfor %}
|
||||
{% endcall %}{% endset %}
|
||||
{{ code_preview("combobox", code | prettyHtml) }}
|
||||
{% endcall %}
|
||||
{% endset %}
|
||||
|
||||
{% set code_script %}
|
||||
{% include "components/select-script.njk" %}
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("combobox", code_script | prettyHtml ~ code_html | prettyHtml) }}
|
||||
|
||||
<h2 id="usage"><a href="#usage">Usage</a></h2>
|
||||
|
||||
<h3 id="usage-default"><a href="#usage-default">HTML + Javascript</a></h3>
|
||||
|
||||
<div class="alert my-6">
|
||||
{% lucide "circle-alert" %}
|
||||
<h2>This component requires Javascript.</h2>
|
||||
<section>
|
||||
<p>You will need to include the Javascript (Alpine.js) code provided below before the HTML code for this component. As with all interactive components, you will need to add some Alpine.js properties to certain elements (e.g. <code class="text-xs">x-bind</code>, <code class="text-xs">x-data</code>, <code class="text-xs">@click</code>).</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section class="prose my-6">
|
||||
<p>Combobox uses the same Alpine.js code and markup as the <a href="/components/select">Select</a> component, the only difference being the search box at the top of the listbox.</p>
|
||||
<p>You can set up a few additional options on the <code><div data-popover></code> element:</p>
|
||||
@@ -48,30 +66,12 @@ toc:
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<h4 class="badge-secondary">HTML</h4>
|
||||
|
||||
<section class="my-6">
|
||||
{% set code_html %}
|
||||
{% call select(
|
||||
trigger_attrs={"class": "w-[200px]"},
|
||||
listbox_attrs={"data-empty": "No framework found."},
|
||||
is_combobox=true,
|
||||
search_placeholder="Search framework...",
|
||||
register_on=["alpine:init", "htmx:afterSwap"]
|
||||
) %}
|
||||
{% for framework in options_frameworks %}
|
||||
<div role="option" data-value="{{ framework }}">{{ framework }}</div>
|
||||
{% endfor %}
|
||||
{% endcall %}{% endset %}
|
||||
{{ code_block(code_html | prettyHtml) }}
|
||||
</section>
|
||||
|
||||
<h4 class="badge-secondary">Javascript (Alpine.js)</h4>
|
||||
|
||||
<section class="my-6">
|
||||
{% set code_script %}{% include "components/select-script.njk" %}{% endset %}
|
||||
{{ code_block(code_script | prettyHtml) }}
|
||||
</section>
|
||||
{% from "components/tabs.njk" import tabs %}
|
||||
{% set tabsets = [
|
||||
{ tab: "HTML", panel: code_block(code_html | prettyHtml) },
|
||||
{ tab: "Javascipt (Alpine.js)", panel: code_block(code_script | prettyHtml) }
|
||||
] %}
|
||||
{{ tabs(id="combobox", tabsets=tabsets) }}
|
||||
|
||||
<h3 id="usage-jinja"><a href="#usage-jinja">Jinja or Nunjucks</a></h3>
|
||||
|
||||
|
||||
+60
-28
@@ -6,7 +6,7 @@ toc:
|
||||
- label: Usage
|
||||
id: usage
|
||||
children:
|
||||
- label: Default
|
||||
- label: HTML + Javascript
|
||||
id: usage-default
|
||||
- label: Jinja or Nunjucks
|
||||
id: usage-jinja
|
||||
@@ -21,7 +21,7 @@ toc:
|
||||
{% from "macros/code_preview.njk" import code_preview %}
|
||||
{% from "components/dialog.njk" import dialog %}
|
||||
|
||||
{% set code %}
|
||||
{% set code_html %}
|
||||
{% set footer %}
|
||||
<button class="btn-outline" @click="open = false">Cancel</button>
|
||||
<button class="btn" @click="open = false">Save changes</button>
|
||||
@@ -49,47 +49,79 @@ toc:
|
||||
</form>
|
||||
{% endcall %}
|
||||
{% endset %}
|
||||
{{ code_preview("dialog", code | prettyHtml) }}
|
||||
|
||||
{% set code_script %}
|
||||
{% include "components/dialog-script.njk" %}
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("dialog", code_script | prettyHtml ~ code_html | prettyHtml) }}
|
||||
|
||||
<h2 id="usage"><a href="#usage">Usage</a></h2>
|
||||
|
||||
<h3 id="usage-default"><a href="#usage-default">Default</a></h3>
|
||||
<h3 id="usage-default"><a href="#usage-default">HTML + Javascript</a></h3>
|
||||
|
||||
<div class="alert my-6">
|
||||
{% lucide "circle-alert" %}
|
||||
<h2>This component requires Javascript.</h2>
|
||||
<section>
|
||||
<p>You will need to include the Javascript (Alpine.js) code provided below before the HTML code for this component. As with all interactive components, you will need to add some Alpine.js properties to certain elements (e.g. <code class="text-xs">x-bind</code>, <code class="text-xs">x-data</code>, <code class="text-xs">@click</code>).</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section class="prose my-6">
|
||||
<p></p>
|
||||
</section>
|
||||
|
||||
{{ code_block(code | prettyHtml) }}
|
||||
|
||||
<h3 id="usage-jinja"><a href="#usage-jinja">Jinja or Nunjucks</a></h3>
|
||||
|
||||
<section class="prose my-6">
|
||||
<p>If you use Jinja (or Nunjucks), you can use the <code>dialog()</code> macro directly, making sure to set <code>close_on_overlay_click</code> to <code>False</code> (or <code>false</code> for Nunjucks).</p>
|
||||
<p>The component is structured as such:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/jinja-and-nunjucks">Read more about using Basecoat with Jinja or Nunjucks</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/components/dialog">Read more about the Dialog component</a>
|
||||
<li>A <code><div class="dialog"></code> which wraps around the entire component and holds it state (e.g. open/close).</li>
|
||||
<li>A <code><button></code> that acts as the trigger to open or close the popover.</li>
|
||||
<li>A <code><div role="dialog"></code> that holds the dialog itself. It also acts as the backdrop for the dialog.</li>
|
||||
<li>Inside of it, we have:
|
||||
<ul>
|
||||
<li>A <code><header></code> that contains the title (<code><h2></code>) and description (<code><p></code>) of the dialog.</li>
|
||||
<li>A <code><section></code> for the content.</li>
|
||||
<li>A <code><footer></code> that usually contains actions.</li>
|
||||
<li>A close <code><button></code>.</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
{% from "components/tabs.njk" import tabs %}
|
||||
{% set tabsets = [
|
||||
{ tab: "HTML", panel: code_block(code_html | prettyHtml) },
|
||||
{ tab: "Javascipt (Alpine.js)", panel: code_block(code_script | prettyHtml) }
|
||||
] %}
|
||||
{{ tabs(id="combobox", tabsets=tabsets) }}
|
||||
|
||||
<h3 id="usage-jinja"><a href="#usage-jinja">Jinja or Nunjucks</a></h3>
|
||||
|
||||
<p class="my-6 prose">If you use Jinja (or Nunjucks), you can use the <code>dialog()</code> macro directly. <a href="/installation#jinja-and-nunjucks">Read more about using Basecoat with Jinja and Nunjucks</a>.</p>
|
||||
|
||||
{% set raw_code %}{% raw %}{% set footer %}
|
||||
<button class="btn-outline" @click="open = false">Cancel</button>
|
||||
<button class="btn-primary" @click="open = false">Continue</button>
|
||||
<button class="btn" @click="open = false">Save changes</button>
|
||||
{% endset %}
|
||||
{{ dialog(
|
||||
id="demo-alert-dialog",
|
||||
title="Are you absolutely sure?",
|
||||
description="This action cannot be undone. This will permanently delete your account and remove your data from our servers.",
|
||||
trigger="Open Alert Dialog",
|
||||
{% call dialog(
|
||||
id="demo-dialog-edit-profile",
|
||||
title="Edit profile",
|
||||
description="Make changes to your profile here. Click save when you're done.",
|
||||
main_attrs={"x-ref": "myDialog"},
|
||||
trigger="Edit Profile",
|
||||
trigger_attrs={"class": "btn-outline"},
|
||||
content_attrs={"class": "w-full sm:max-w-[425px] max-h-[612px]"},
|
||||
footer=footer,
|
||||
close_button=False,
|
||||
close_on_overlay_click=False
|
||||
) }}{% endraw %}
|
||||
{% endset%}
|
||||
register_on=["alpine:init", "htmx:afterSwap"]
|
||||
) %}
|
||||
<form class="form grid gap-4">
|
||||
<div class="grid gap-3">
|
||||
<label for="demo-dialog-edit-profile-name">Name</label>
|
||||
<input type="text" value="Pedro Duarte" id="demo-dialog-edit-profile-name" />
|
||||
</div>
|
||||
<div class="grid gap-3">
|
||||
<label for="demo-dialog-edit-profile-username">Username</label>
|
||||
<input type="text" value="@peduarte" id="demo-dialog-edit-profile-username" />
|
||||
</div>
|
||||
</form>
|
||||
{% endcall %}{% endraw %}{% endset%}
|
||||
{{ code_block(raw_code, "jinja") }}
|
||||
|
||||
<h2 id="examples"><a href="#examples">Examples</a></h2>
|
||||
|
||||
@@ -2,19 +2,179 @@
|
||||
layout: layouts/component.njk
|
||||
title: Dropdown Menu
|
||||
description: Displays a menu to the user — such as a set of actions or functions — triggered by a button.
|
||||
toc:
|
||||
- label: Usage
|
||||
id: usage
|
||||
children:
|
||||
- label: HTML + Javascript
|
||||
id: usage-default
|
||||
- label: Jinja or Nunjucks
|
||||
id: usage-jinja
|
||||
- label: Examples
|
||||
id: examples
|
||||
children:
|
||||
- label: Checkboxes
|
||||
id: example-checkboxes
|
||||
- label: Radio Group
|
||||
id: example-radio-group
|
||||
---
|
||||
|
||||
{% from "macros/code_block.njk" import code_block %}
|
||||
{% from "macros/code_preview.njk" import code_preview %}
|
||||
{% from "components/dropdown-menu.njk" import dropdown_menu %}
|
||||
|
||||
{% set code %}{% call dropdown_menu(
|
||||
{% set code_html %}
|
||||
{% call dropdown_menu(
|
||||
id="dropdown-menu",
|
||||
trigger="Open",
|
||||
trigger_attrs={"class": "btn-outline"},
|
||||
content_attrs={"class": "min-w-56"},
|
||||
register_on=["alpine:init", "htmx:afterSwap"]
|
||||
) %}
|
||||
<div role="group" aria-labelledby="account-options">
|
||||
<span id="account-options" role="heading">My Account</span>
|
||||
<button type="button" role="menuitem">
|
||||
Profile
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⇧⌘P</span>
|
||||
</button>
|
||||
<button type="button" role="menuitem">
|
||||
Billing
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⌘B</span>
|
||||
</button>
|
||||
<button type="button" role="menuitem">
|
||||
Settings
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⌘S</span>
|
||||
</button>
|
||||
<button type="button" role="menuitem">
|
||||
Keyboard shortcuts
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⌘K</span>
|
||||
</button>
|
||||
</div>
|
||||
<hr role="separator">
|
||||
<button type="button" role="menuitem">
|
||||
GitHub
|
||||
</button>
|
||||
<button type="button" role="menuitem">
|
||||
Support
|
||||
</button>
|
||||
<button type="button" role="menuitem" disabled>
|
||||
API
|
||||
</button>
|
||||
<hr role="separator">
|
||||
<button type="button" role="menuitem">
|
||||
Logout
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⇧⌘P</span>
|
||||
</button>
|
||||
{% endcall %}
|
||||
{% endset %}
|
||||
|
||||
{% set code_script %}
|
||||
{% include "components/dropdown-menu-script.njk" %}
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("dropdown-menu", code_script | prettyHtml ~ code_html | prettyHtml) }}
|
||||
|
||||
<h2 id="usage">Usage</h2>
|
||||
|
||||
<h3 id="usage-default"><a href="#usage-default">HTML + Javascript</a></h3>
|
||||
|
||||
<div class="alert my-6">
|
||||
{% lucide "circle-alert" %}
|
||||
<h2>This component requires Javascript.</h2>
|
||||
<section>
|
||||
<p>You will need to include the Javascript (Alpine.js) code provided below before the HTML code for this component. As with all interactive components, you will need to add some Alpine.js properties to certain elements (e.g. <code class="text-xs">x-bind</code>, <code class="text-xs">x-data</code>, <code class="text-xs">@click</code>).</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section class="prose my-6">
|
||||
<p>The component is structured as such:</p>
|
||||
<ul>
|
||||
<li>A <code><div class="popover"></code> which wraps around the entire component and holds it state (e.g. open/close).</li>
|
||||
<li>A <code><button></code> that acts as the trigger to open or close the popover.</li>
|
||||
<li>A <code><div data-popover></code> that holds the content of the popover.</li>
|
||||
<li>Inside of the <code><div data-popover></code> is a <code><nav role="menu"></code> that contains a combination of:
|
||||
<ul>
|
||||
<li><code><button role="menuitem"></code> for menu items.</li>
|
||||
<li><code><button role="menuitemcheckbox"></code> for menu items with checkboxes.</li>
|
||||
<li><code><button role="menuitemradio"></code> for menu items with radio buttons.</li>
|
||||
<li><code><hr role="separator"></code> to display a horizontal separator.</li>
|
||||
<li><code><div role="group"></code> to group options.</li>
|
||||
<li><code><span role="heading"></code> for group headings.</li>
|
||||
</ul>
|
||||
</ul>
|
||||
<p>As with the <a href="/components/popover">Popover</a> component, you can set up a few additional options on the <code><div data-popover></code> element:</p>
|
||||
<ul>
|
||||
<li><code>data-side</code> can be set to <code>top</code>, <code>bottom</code>, <code>left</code>, or <code>right</code> to change the side of the popover.</li>
|
||||
<li><code>data-align</code> can be set to <code>start</code>, <code>center</code>, or <code>end</code> to change the alignment of the popover.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
{% from "components/tabs.njk" import tabs %}
|
||||
{% set tabsets = [
|
||||
{ tab: "HTML", panel: code_block(code_html | prettyHtml) },
|
||||
{ tab: "Javascipt (Alpine.js)", panel: code_block(code_script | prettyHtml) }
|
||||
] %}
|
||||
{{ tabs(id="dropdown-menu", tabsets=tabsets) }}
|
||||
|
||||
<h3 id="usage-jinja"><a href="#usage-jinja">Jinja or Nunjucks</a></h3>
|
||||
|
||||
<p class="my-6 prose">If you use Jinja (or Nunjucks), you can use the <code>dropdown_menu()</code> macro directly. <a href="/installation#jinja-and-nunjucks">Read more about using Basecoat with Jinja and Nunjucks</a>.</p>
|
||||
|
||||
{% set raw_code %}{% raw %}{% call dropdown_menu(
|
||||
id="dropdown-menu",
|
||||
trigger="Open",
|
||||
trigger_attrs={"class": "btn-outline"},
|
||||
content_attrs={"class": "min-w-56"},
|
||||
register_on=["alpine:init", "htmx:afterSwap"]
|
||||
) %}
|
||||
<div role="group" aria-labelledby="account-options">
|
||||
<span id="account-options" role="heading">My Account</span>
|
||||
<button type="button" role="menuitem">
|
||||
Profile
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⇧⌘P</span>
|
||||
</button>
|
||||
<button type="button" role="menuitem">
|
||||
Billing
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⌘B</span>
|
||||
</button>
|
||||
<button type="button" role="menuitem">
|
||||
Settings
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⌘S</span>
|
||||
</button>
|
||||
<button type="button" role="menuitem">
|
||||
Keyboard shortcuts
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⌘K</span>
|
||||
</button>
|
||||
</div>
|
||||
<hr role="separator">
|
||||
<button type="button" role="menuitem">
|
||||
GitHub
|
||||
</button>
|
||||
<button type="button" role="menuitem">
|
||||
Support
|
||||
</button>
|
||||
<button type="button" role="menuitem" disabled>
|
||||
API
|
||||
</button>
|
||||
<hr role="separator">
|
||||
<button type="button" role="menuitem">
|
||||
Logout
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⇧⌘P</span>
|
||||
</button>
|
||||
{% endcall %}{% endraw %}{% endset%}
|
||||
{{ code_block(raw_code, "jinja") }}
|
||||
|
||||
<h2 id="examples"><a href="#examples">Examples</a></h2>
|
||||
|
||||
<h3 id="example-checkboxes"><a href="#example-checkboxes">Checkboxes</a></h3>
|
||||
|
||||
{% set code %}{% call dropdown_menu(
|
||||
id="dropdown-menu-checkboxes",
|
||||
trigger="Open",
|
||||
trigger_attrs={"class": "btn-outline"},
|
||||
content_attrs={"class": "min-w-56"},
|
||||
register_on=["alpine:init", "htmx:afterSwap"]
|
||||
) %}
|
||||
<div role="group" aria-labelledby="account-options">
|
||||
<span id="account-options" role="heading">Account Options</span>
|
||||
<button type="button" role="menuitem">
|
||||
@@ -32,49 +192,138 @@ description: Displays a menu to the user — such as a set of actions or functio
|
||||
Settings
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⌘S</span>
|
||||
</button>
|
||||
<button type="button" role="menuitem">
|
||||
{% lucide "keyboard" %}
|
||||
Keyboard shortcuts
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⌘K</span>
|
||||
</button>
|
||||
</div>
|
||||
<hr role="separator">
|
||||
<button type="button" role="menuitem">
|
||||
{% lucide "github" %}
|
||||
GitHub
|
||||
</button>
|
||||
<button type="button" role="menuitem">
|
||||
{% lucide "life-buoy" %}
|
||||
Support
|
||||
</button>
|
||||
<button type="button" role="menuitem" disabled>
|
||||
{% lucide "cloud" %}
|
||||
API
|
||||
</button>
|
||||
<div role="group" aria-labelledby="appearance-options">
|
||||
<span id="appearance-options" role="heading">Appearance</span>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitemcheckbox"
|
||||
aria-checked="true"
|
||||
class="group"
|
||||
x-data="{ checked: true }"
|
||||
@click="checked = !checked"
|
||||
:aria-checked="checked"
|
||||
>
|
||||
{% lucide "check", {
|
||||
"class": "invisible group-aria-checked:visible",
|
||||
"aria-hidden": "true",
|
||||
"focusable": "false"
|
||||
} %}
|
||||
Status Bar
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⇧⌘P</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitemcheckbox"
|
||||
aria-checked="false"
|
||||
class="group"
|
||||
disabled
|
||||
x-data="{ checked: false }"
|
||||
@click="checked = !checked"
|
||||
:aria-checked="checked"
|
||||
>
|
||||
{% lucide "check", {
|
||||
"class": "invisible group-aria-checked:visible",
|
||||
"aria-hidden": "true",
|
||||
"focusable": "false"
|
||||
} %}
|
||||
Activity Bar
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⌘B</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitemcheckbox"
|
||||
aria-checked="false"
|
||||
class="group"
|
||||
x-data="{ checked: false }"
|
||||
@click="checked = !checked"
|
||||
:aria-checked="checked"
|
||||
>
|
||||
{% lucide "check", {
|
||||
"class": "invisible group-aria-checked:visible",
|
||||
"aria-hidden": "true",
|
||||
"focusable": "false"
|
||||
} %}
|
||||
Panel
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⌘S</span>
|
||||
</button>
|
||||
</div>
|
||||
<hr role="separator">
|
||||
<button type="button" role="menuitem">
|
||||
{% lucide "log-out" %}
|
||||
Logout
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⇧⌘P</span>
|
||||
</button>{% endcall %}{% endset %}
|
||||
{{ code_preview("dropdown-menu", code | prettyHtml) }}
|
||||
</button>
|
||||
{% endcall %}{% endset %}
|
||||
{{ code_preview("dropdown-menu-checkboxes", code | prettyHtml) }}
|
||||
|
||||
<h2 id="usage">Usage</h2>
|
||||
<h3 id="example-radio-group"><a href="#example-radio-group">Radio Group</a></h3>
|
||||
|
||||
<section class="prose my-6">
|
||||
<p>You can use one of the <code class="">btn</code> classes to style any element as a button:</p>
|
||||
|
||||
<ul>
|
||||
<li>
|
||||
<b>Variants</b>: <code>btn</code> or <code>btn-primary</code> for primary
|
||||
buttons, then <code>btn-secondary</code>, <code>btn-destructive</code>, <code>btn-outline</code>,
|
||||
<code>btn-ghost</code>, <code>btn-link</code>. You can also use <code>btn-icon</code> to
|
||||
style an icon as a button, along with all of its variants (e.g. <code>btn-icon-destructive</code>).
|
||||
</li>
|
||||
<li>
|
||||
<b>Sizes</b>: <code>btn-sm</code> for small and <code>btn-lg</code> for large.
|
||||
You can combine this with other attributes, for example <code>btn-lg-destructive</code>
|
||||
or <code>btn-icon-sm-secondary</code>.
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
{% set code %}{% call dropdown_menu(
|
||||
id="dropdown-menu-radio-group",
|
||||
trigger="Open",
|
||||
trigger_attrs={"class": "btn-outline"},
|
||||
content_attrs={"class": "min-w-56"},
|
||||
register_on=["alpine:init", "htmx:afterSwap"]
|
||||
) %}
|
||||
<div role="group" aria-labelledby="position-options" x-data="{ checked: 'bottom' }">
|
||||
<span id="position-options" role="heading">Panel Position</span>
|
||||
<hr role="separator">
|
||||
<button
|
||||
type="button"
|
||||
role="menuitemradio"
|
||||
aria-checked="false"
|
||||
class="group"
|
||||
@click="checked = 'top'"
|
||||
:aria-checked="checked == 'top'"
|
||||
>
|
||||
<div class="size-4 flex items-center justify-center">
|
||||
<div
|
||||
class="size-2 rounded-full bg-foreground invisible group-aria-checked:visible"
|
||||
aria-hidden="true",
|
||||
focusable="false"
|
||||
></div>
|
||||
</div>
|
||||
Status Bar
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⇧⌘P</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitemradio"
|
||||
aria-checked="false"
|
||||
class="group"
|
||||
@click="checked = 'bottom'"
|
||||
:aria-checked="checked == 'bottom'"
|
||||
>
|
||||
<div class="size-4 flex items-center justify-center">
|
||||
<div
|
||||
class="size-2 rounded-full bg-foreground invisible group-aria-checked:visible"
|
||||
aria-hidden="true",
|
||||
focusable="false"
|
||||
></div>
|
||||
</div>
|
||||
Activity Bar
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⌘B</span>
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
role="menuitemradio"
|
||||
aria-checked="false"
|
||||
class="group"
|
||||
@click="checked = 'right'"
|
||||
:aria-checked="checked == 'right'"
|
||||
>
|
||||
<div class="size-4 flex items-center justify-center">
|
||||
<div
|
||||
class="size-2 rounded-full bg-foreground invisible group-aria-checked:visible"
|
||||
aria-hidden="true",
|
||||
focusable="false"
|
||||
></div>
|
||||
</div>
|
||||
Panel
|
||||
<span class="text-muted-foreground ml-auto text-xs tracking-widest">⌘S</span>
|
||||
</button>
|
||||
</div>
|
||||
{% endcall %}{% endset %}
|
||||
{{ code_preview("dropdown-menu", code | prettyHtml) }}
|
||||
@@ -0,0 +1,79 @@
|
||||
---
|
||||
layout: layouts/component.njk
|
||||
title: Input
|
||||
description: Displays a form input field or a component that looks like an input field.
|
||||
toc:
|
||||
- label: Usage
|
||||
id: usage
|
||||
---
|
||||
|
||||
{% from "macros/code_preview.njk" import code_preview %}
|
||||
{% from "macros/code_block.njk" import code_block %}
|
||||
|
||||
{% set code %}<form class="form grid gap-6">
|
||||
<div class="grid gap-2">
|
||||
<label for="demo-form-text">Username</label>
|
||||
<input type="text" id="demo-form-text" placeholder="hunvreus">
|
||||
<p class="text-muted-foreground text-sm">This is your public display name.</p>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-2">
|
||||
<label for="demo-form-select">Email</label>
|
||||
<select id="demo-form-select">
|
||||
<option value="bob@example.com">m@example.com</option>
|
||||
<option value="alice@example.com">m@google.com</option>
|
||||
<option value="john@example.com">m@support.com</option>
|
||||
</select>
|
||||
<p class="text-muted-foreground text-sm">You can manage email addresses in your email settings.</p>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-2">
|
||||
<label for="demo-form-text">Bio</label>
|
||||
<textarea id="demo-form-textarea" placeholder="I like to..." rows="3"></textarea>
|
||||
<p class="text-muted-foreground text-sm">You can @mention other users and organizations.</p>
|
||||
</div>
|
||||
|
||||
<div class="grid gap-2">
|
||||
<label for="demo-form-date">Date of birth</label>
|
||||
<input type="date" id="demo-form-date">
|
||||
<p class="text-muted-foreground text-sm">Your date of birth is used to calculate your age.</p>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col gap-3">
|
||||
<label for="demo-form-radio">Notify me about...</label>
|
||||
<fieldset id="demo-form-radio" class="grid gap-3">
|
||||
<label class="font-normal"><input type="radio" name="demo-form-radio" value="1" checked>All new messages</label>
|
||||
<label class="font-normal"><input type="radio" name="demo-form-radio" value="2">Direct messages and mentions</label>
|
||||
<label class="font-normal"><input type="radio" name="demo-form-radio" value="3" >Nothing</label>
|
||||
</fieldset>
|
||||
</div>
|
||||
|
||||
<section class="grid gap-4">
|
||||
<h3 class="text-lg font-medium">Email Notifications</h3>
|
||||
<div class="gap-2 flex flex-row items-start justify-between rounded-lg border p-4 shadow-xs">
|
||||
<div class="flex flex-col gap-0.5">
|
||||
<label for="demo-form-switch" class="leading-normal">Marketing emails</label>
|
||||
<p class="text-muted-foreground text-sm">Receive emails about new products, features, and more.</p>
|
||||
</div>
|
||||
<input type="checkbox" id="demo-form-switch" role="switch">
|
||||
</div>
|
||||
<div class="gap-2 flex flex-row items-start justify-between rounded-lg border p-4 shadow-xs">
|
||||
<div class="flex flex-col gap-0.5 opacity-60">
|
||||
<label for="demo-form-switch-disabled" class="leading-normal">Security emails</label>
|
||||
<p class="text-muted-foreground text-sm">Receive emails about your account security.</p>
|
||||
</div>
|
||||
<input type="checkbox" id="demo-form-switch-disabled" role="switch" disabled>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<button type="submit" class="btn">Submit</button>
|
||||
</form>{% endset %}
|
||||
{{ code_preview("input", code, "w-full max-w-sm") }}
|
||||
|
||||
<h2 id="usage">Usage</h2>
|
||||
|
||||
<section class="prose my-6">
|
||||
<p>Adding the <code>form</code> class to the parent of any form element (<code><label></code>, <code><input></code>, <code><textarea></code>, <code><select></code>) will automatically apply the style you would get from adding <code>label</code>, <code>input</code>, <code>textarea</code>, or <code>select</code> classes. Read more about <a href="/components/label">Label</a>, <a href="/components/input">Input</a>, <a href="/components/textarea">Textarea</a>, and <a href="/components/select">Select</a>.</p>
|
||||
</section>
|
||||
|
||||
{{ code_block(code) }}
|
||||
@@ -40,8 +40,6 @@ toc:
|
||||
|
||||
<h2 id="examples"><a href="#examples">Examples</a></h2>
|
||||
|
||||
<h3 id="example-default"><a href="#example-default">Default</a></h3>
|
||||
|
||||
{{ code_preview("input-default", code) }}
|
||||
|
||||
<h3 id="example-invalid"><a href="#example-invalid">Invalid</a></h3>
|
||||
|
||||
@@ -5,6 +5,11 @@ description: Renders an accessible label associated with controls.
|
||||
toc:
|
||||
- label: Usage
|
||||
id: usage
|
||||
- label: Examples
|
||||
id: examples
|
||||
children:
|
||||
- label: Disabled
|
||||
id: example-disabled
|
||||
---
|
||||
|
||||
{% from "macros/code_preview.njk" import code_preview %}
|
||||
@@ -19,8 +24,18 @@ toc:
|
||||
<h2 id="usage">Usage</h2>
|
||||
|
||||
<section class="prose my-6">
|
||||
<p>Simply add the <code>label</code> class to your <code><label></code> element or have a parent with the <code>form</code> class (<a href="/components/form">read more about form</a>). Labels will be styled accordingly if a peer or child element is disabled.</p>
|
||||
<p>Simply add the <code>label</code> class to your <code><label></code> element or have a parent with the <code>form</code> class (<a href="/components/form">read more about form</a>). Labels' style may be affected by the presence of a disabled peer or child element.</p>
|
||||
</section>
|
||||
|
||||
{% set code %}<label class="label" for="email">Your email address</label>{% endset %}
|
||||
{{ code_block(code) }}
|
||||
{{ code_block(code) }}
|
||||
|
||||
<h2 id="examples"><a href="#examples">Examples</a></h2>
|
||||
|
||||
<h3 id="example-disabled"><a href="#example-disabled">Disabled</a></h3>
|
||||
|
||||
{% set code %}<div class="grid gap-3">
|
||||
<label class="label" for="email">Email</label>
|
||||
<input class="input" id="email" type="email" placeholder="Email" disabled>
|
||||
</div>{% endset %}
|
||||
{{ code_preview("label-disabled", code) }}
|
||||
+62
-47
@@ -6,7 +6,7 @@ toc:
|
||||
- label: Usage
|
||||
id: usage
|
||||
children:
|
||||
- label: Default
|
||||
- label: HTML + Javascript
|
||||
id: usage-default
|
||||
- label: Jinja or Nunjucks
|
||||
id: usage-jinja
|
||||
@@ -16,7 +16,7 @@ toc:
|
||||
{% from "macros/code_block.njk" import code_block %}
|
||||
{% from "components/popover.njk" import popover %}
|
||||
|
||||
{% set code %}
|
||||
{% set code_html %}
|
||||
{% call popover(
|
||||
id="demo-popover",
|
||||
trigger="Open popover",
|
||||
@@ -32,13 +32,7 @@ toc:
|
||||
<form class="form grid gap-2">
|
||||
<div class="grid grid-cols-3 items-center gap-4">
|
||||
<label for="demo-popover-width">Width</label>
|
||||
<input type="text" id="demo-popover-width" value="100%" class="col-span-2 h-8" x-init="$watch('open', (value) => {
|
||||
if (value) {
|
||||
setTimeout(() => $el.focus(), 50)
|
||||
} else {
|
||||
$el.blur()
|
||||
}
|
||||
})"/>
|
||||
<input type="text" id="demo-popover-width" value="100%" class="col-span-2 h-8"/>
|
||||
</div>
|
||||
<div class="grid grid-cols-3 items-center gap-4">
|
||||
<label for="demo-popover-max-width">Max. width</label>
|
||||
@@ -56,61 +50,82 @@ toc:
|
||||
</div>
|
||||
{% endcall %}
|
||||
{% endset %}
|
||||
{{ code_preview("popover", code | prettyHtml ) }}
|
||||
|
||||
{% set code_script %}
|
||||
{% include "components/popover-script.njk" %}
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("combobox", code_script | prettyHtml ~ code_html | prettyHtml) }}
|
||||
|
||||
<h2 id="usage"><a href="#usage">Usage</a></h2>
|
||||
|
||||
<h3 id="usage-html"><a href="#usage-html">Default</a></h3>
|
||||
<h3 id="usage-default"><a href="#usage-default">HTML + Javascript</a></h3>
|
||||
|
||||
<div class="alert my-6">
|
||||
{% lucide "circle-alert" %}
|
||||
<h2>This component requires Javascript.</h2>
|
||||
<section>
|
||||
<p>You will need to include the Javascript (Alpine.js) code provided below before the HTML code for this component. As with all interactive components, you will need to add some Alpine.js properties to certain elements (e.g. <code class="text-xs">x-bind</code>, <code class="text-xs">x-data</code>, <code class="text-xs">@click</code>).</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section class="prose my-6">
|
||||
<p>If you need to do more than what <code><select></code> allows (e.g. HTML options), you can use the code below which uses the <a href="/components/combobox">Popover</a> component. Make sure to include the hidden input with the name you want to use for that field.</p>
|
||||
<p>The component is structured as such:</p>
|
||||
<ul>
|
||||
<li>A <code><div class="popover"></code> which wraps around the entire component and holds it state (e.g. open/close).</li>
|
||||
<li>A <code><button></code> that acts as the trigger to open or close the popover.</li>
|
||||
<li>A <code><div data-popover></code> that holds the content of the popover.</li>
|
||||
</ul>
|
||||
<p>You can set up a few additional options on the <code><div data-popover></code> element:</p>
|
||||
<ul>
|
||||
<li><code>data-side</code> can be set to <code>top</code>, <code>bottom</code>, <code>left</code>, or <code>right</code> to change the side of the popover.</li>
|
||||
<li><code>data-align</code> can be set to <code>start</code>, <code>center</code>, or <code>end</code> to change the alignment of the popover.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
{{ code_block(code | prettyHtml) }}
|
||||
{% from "components/tabs.njk" import tabs %}
|
||||
{% set tabsets = [
|
||||
{ tab: "HTML", panel: code_block(code_html | prettyHtml) },
|
||||
{ tab: "Javascipt (Alpine.js)", panel: code_block(code_script | prettyHtml) }
|
||||
] %}
|
||||
{{ tabs(id="popover", tabsets=tabsets) }}
|
||||
|
||||
<h3 id="usage-jinja"><a href="#usage-jinja">Jinja or Nunjucks</a></h3>
|
||||
|
||||
<section class="prose my-6">
|
||||
<p>If you use Jinja (or Nunjucks), you can use the <code>popover()</code> macro directly.</p>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/jinja-and-nunjucks">Read more about using Basecoat with Jinja or Nunjucks</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/components/popover">Read more about the Popover component</a>
|
||||
</li>
|
||||
</ul>
|
||||
<p class="my-6 prose">If you use Jinja (or Nunjucks), you can use the <code>popover()</code> macro directly. <a href="/installation#jinja-and-nunjucks">Read more about using Basecoat with Jinja and Nunjucks</a>.</p>
|
||||
</section>
|
||||
|
||||
{% set raw_code %}{% raw %}{% call popover(
|
||||
id="demo-popover",
|
||||
trigger="Open popover",
|
||||
trigger_attrs={"class": "btn-outline"},
|
||||
content_attrs={"class": "w-80 p-4"}
|
||||
content_attrs={"class": "w-80 p-4"},
|
||||
register_on=["alpine:init", "htmx:afterSwap"]
|
||||
) %}
|
||||
<div class="grid gap-4">
|
||||
<header class="grid gap-1.5">
|
||||
<h4 class="leading-none font-medium">Dimensions</h4>
|
||||
<p class="text-muted-foreground text-sm">Set the dimensions for the layer.</p>
|
||||
</header>
|
||||
<form class="form grid gap-2">
|
||||
<div class="grid grid-cols-3 items-center gap-4">
|
||||
<label for="demo-popover-width">Width</label>
|
||||
<input type="text" id="demo-popover-width" value="100%" class="col-span-2 h-8"/>
|
||||
</div>
|
||||
<div class="grid grid-cols-3 items-center gap-4">
|
||||
<label for="demo-popover-max-width">Max. width</label>
|
||||
<input type="text" id="demo-popover-max-width" value="300px" class="col-span-2 h-8"/>
|
||||
</div>
|
||||
<div class="grid grid-cols-3 items-center gap-4">
|
||||
<label for="demo-popover-height">Height</label>
|
||||
<input type="text" id="demo-popover-height" value="25px" class="col-span-2 h-8"/>
|
||||
</div>
|
||||
<div class="grid grid-cols-3 items-center gap-4">
|
||||
<label for="demo-popover-max-height">Max. height</label>
|
||||
<input type="text" id="demo-popover-max-height" value="none" class="col-span-2 h-8"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<div class="grid gap-4">
|
||||
<header class="grid gap-1.5">
|
||||
<h4 class="leading-none font-medium">Dimensions</h4>
|
||||
<p class="text-muted-foreground text-sm">Set the dimensions for the layer.</p>
|
||||
</header>
|
||||
<form class="form grid gap-2">
|
||||
<div class="grid grid-cols-3 items-center gap-4">
|
||||
<label for="demo-popover-width">Width</label>
|
||||
<input type="text" id="demo-popover-width" value="100%" class="col-span-2 h-8"/>
|
||||
</div>
|
||||
<div class="grid grid-cols-3 items-center gap-4">
|
||||
<label for="demo-popover-max-width">Max. width</label>
|
||||
<input type="text" id="demo-popover-max-width" value="300px" class="col-span-2 h-8"/>
|
||||
</div>
|
||||
<div class="grid grid-cols-3 items-center gap-4">
|
||||
<label for="demo-popover-height">Height</label>
|
||||
<input type="text" id="demo-popover-height" value="25px" class="col-span-2 h-8"/>
|
||||
</div>
|
||||
<div class="grid grid-cols-3 items-center gap-4">
|
||||
<label for="demo-popover-max-height">Max. height</label>
|
||||
<input type="text" id="demo-popover-max-height" value="none" class="col-span-2 h-8"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
{% endcall %}{% endraw %}{% endset %}
|
||||
{{ code_block(raw_code, "jinja") }}
|
||||
+48
-47
@@ -6,8 +6,10 @@ toc:
|
||||
- label: Usage
|
||||
id: usage
|
||||
children:
|
||||
- label: Default
|
||||
id: usage-default
|
||||
- label: HTML
|
||||
id: usage-html
|
||||
- label: HTML + Javascript
|
||||
id: usage-js
|
||||
- label: Jinja or Nunjucks
|
||||
id: usage-jinja
|
||||
- label: Examples
|
||||
@@ -35,7 +37,7 @@ toc:
|
||||
</select>{% endset %}
|
||||
{{ code_preview("select-native", code_native) }}
|
||||
|
||||
{% set code_alpine %}
|
||||
{% set code_html %}
|
||||
{% call select(
|
||||
name="select-js",
|
||||
trigger_attrs={"class": "w-[180px]"},
|
||||
@@ -51,11 +53,16 @@ toc:
|
||||
</div>
|
||||
{% endcall %}
|
||||
{% endset %}
|
||||
{{ code_preview("select", code_alpine | prettyHtml) }}
|
||||
|
||||
{% set code_script %}
|
||||
{% include "components/select-script.njk" %}
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("combobox", code_script | prettyHtml ~ code_html | prettyHtml) }}
|
||||
|
||||
<h2 id="usage"><a href="#usage">Usage</a></h2>
|
||||
|
||||
<h3 id="usage-html"><a href="#usage-html">Pure HTML</a></h3>
|
||||
<h3 id="usage-html"><a href="#usage-html">HTML</a></h3>
|
||||
|
||||
<section class="prose my-6">
|
||||
<p>If you use a <code><select></code> element, just add the <code>select</code> class to it or have a parent with the <code>form</code> class (<a href="/components/form">read more about form</a>).</p>
|
||||
@@ -63,55 +70,49 @@ toc:
|
||||
|
||||
{{ code_block(code_native) }}
|
||||
|
||||
<h3 id="usage-js"><a href="#usage-js">With Javascript</a></h3>
|
||||
<h3 id="usage-js"><a href="#usage-js">HTML + Javascript</a></h3>
|
||||
|
||||
<div class="alert my-6">
|
||||
{% lucide "circle-alert" %}
|
||||
<h2>This component requires Javascript.</h2>
|
||||
<section>
|
||||
<p>You will need to include the Javascript (Alpine.js) code provided below before the HTML code for this component. As with all interactive components, you will need to add some Alpine.js properties to certain elements (e.g. <code class="text-xs">x-bind</code>, <code class="text-xs">x-data</code>, <code class="text-xs">@click</code>).</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section class="prose my-6">
|
||||
<p>If you need to do more than what <code><select></code> allows (e.g. HTML options), you can use the code below which uses the <a href="/components/combobox">Popover</a> component. Make sure to include the hidden input with the name you want to use for that field.</p>
|
||||
<p>If you need to do more than what <code><select></code> allows (e.g. HTML options), you can use this component. It is structured as such:</p>
|
||||
<ul>
|
||||
<li>A <code><div class="popover"></code> which wraps around the entire component and holds it state (e.g. open/close).</li>
|
||||
<li>A <code><button></code> that acts as the trigger to open or close the popover.</li>
|
||||
<li>A <code><div data-popover></code> that holds the content of the popover.</li>
|
||||
<li>Inside of the <code><div data-popover></code> is a <code><nav role="listbox"></code> that contains a combination of:
|
||||
<ul>
|
||||
<li><code><div role="option"></code> for the options with a <code>data-value</code> attribute.</li>
|
||||
<li><code><hr role="separator"></code> to display a horizontal separator.</li>
|
||||
<li><code><div role="group"></code> to group options.</li>
|
||||
<li><code><span role="heading"></code> for group headings.</li>
|
||||
</ul>
|
||||
</li>
|
||||
<li>An <code><input type="hidden"></code> to hold the value of the field (if needed).</li>
|
||||
</ul>
|
||||
<p>As with the <a href="/components/popover">Popover</a> component, you can set up a few additional options on the <code><div data-popover></code> element:</p>
|
||||
<ul>
|
||||
<li><code>data-side</code> can be set to <code>top</code>, <code>bottom</code>, <code>left</code>, or <code>right</code> to change the side of the popover.</li>
|
||||
<li><code>data-align</code> can be set to <code>start</code>, <code>center</code>, or <code>end</code> to change the alignment of the popover.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
<h4 class="badge-secondary">HTML</h4>
|
||||
|
||||
<section class="prose my-6">
|
||||
{% set code_html %}
|
||||
{% call select(
|
||||
name="select-js",
|
||||
trigger_attrs={"class": "w-[180px]"},
|
||||
register_on=["alpine:init", "htmx:afterSwap"],
|
||||
include_script=false
|
||||
) %}
|
||||
<div role="group" aria-labelledby="fruit-options-label">
|
||||
<span id="fruit-options-label" role="heading">Fruits</span>
|
||||
<div role="option" data-value="apple">Apple</div>
|
||||
<div role="option" data-value="banana">Banana</div>
|
||||
<div role="option" data-value="blueberry">Blueberry</div>
|
||||
<div role="option" data-value="pineapple">Grapes</div>
|
||||
<div role="option" data-value="pineapple">Pineapple</div>
|
||||
</div>
|
||||
{% endcall %}
|
||||
{% endset %}
|
||||
{{ code_block(code_html | prettyHtml) }}
|
||||
</section>
|
||||
|
||||
<h4 class="badge-secondary">Javascript</h4>
|
||||
|
||||
<section class="prose my-6">
|
||||
{% set code_script %}{% include "components/select-script.njk" %}{% endset %}
|
||||
{{ code_block(code_script | prettyHtml, "html") }}
|
||||
</section>
|
||||
{% from "components/tabs.njk" import tabs %}
|
||||
{% set tabsets = [
|
||||
{ tab: "HTML", panel: code_block(code_html | prettyHtml) },
|
||||
{ tab: "Javascipt (Alpine.js)", panel: code_block(code_script | prettyHtml) }
|
||||
] %}
|
||||
{{ tabs(id="select", tabsets=tabsets) }}
|
||||
|
||||
<h3 id="usage-jinja"><a href="#usage-jinja">Jinja or Nunjucks</a></h3>
|
||||
|
||||
<section class="prose my-6">
|
||||
<p>If you use Jinja (or Nunjucks), you can use the <code>select()</code> macro directly.</p>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/jinja-and-nunjucks">Read more about using Basecoat with Jinja or Nunjucks</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/components/popover">Read more about the Popover component</a>
|
||||
</li>
|
||||
</ul>
|
||||
</section>
|
||||
<p class="my-6 prose">If you use Jinja (or Nunjucks), you can use the <code>dropdown_menu()</code> macro directly. <a href="/installation#jinja-and-nunjucks">Read more about using Basecoat with Jinja and Nunjucks</a>.</p>
|
||||
|
||||
{% set raw_code %}{% raw %}{% call select(name="select-js") %}
|
||||
<div role="group" aria-labelledby="fruit-options-label">
|
||||
|
||||
+106
-9
@@ -5,12 +5,18 @@ description: A set of layered sections of content—known as tab panels—that a
|
||||
toc:
|
||||
- label: Usage
|
||||
id: usage
|
||||
children:
|
||||
- label: HTML + Javascript
|
||||
id: usage-default
|
||||
- label: Jinja or Nunjucks
|
||||
id: usage-jinja
|
||||
---
|
||||
|
||||
{% from "macros/code_preview.njk" import code_preview %}
|
||||
{% from "macros/code_block.njk" import code_block %}
|
||||
{% from "components/tabs.njk" import tabs %}
|
||||
{% set code %}
|
||||
|
||||
{% set code_html %}
|
||||
{% set account_panel %}
|
||||
<div class="card">
|
||||
<header>
|
||||
@@ -62,19 +68,110 @@ toc:
|
||||
{ tab: "Password", panel: password_panel }
|
||||
] %}
|
||||
{{ tabs(
|
||||
id='demo-tabs-with-panels',
|
||||
tabsets=tabsets_demo,
|
||||
main_attrs={ "class": "w-full" },
|
||||
tablist_attrs={ "class": "w-full" },
|
||||
register_on=["alpine:init", "htmx:afterSwap"]
|
||||
id='demo-tabs-with-panels',
|
||||
tabsets=tabsets_demo,
|
||||
main_attrs={ "class": "w-full" },
|
||||
tablist_attrs={ "class": "w-full" },
|
||||
register_on=["alpine:init", "htmx:afterSwap"]
|
||||
) }}
|
||||
{% endset %}
|
||||
{{ code_preview("tabs", code | prettyHtml, "max-w-[300px] w-full") }}
|
||||
|
||||
{% set code_script %}
|
||||
{% include "components/tabs-script.njk" %}
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("tabs", code_script | prettyHtml ~ code_html | prettyHtml, "max-w-[300px] w-full") }}
|
||||
|
||||
<h2 id="usage"><a href="#usage">Usage</a></h2>
|
||||
|
||||
<h3 id="usage-default"><a href="#usage-default">HTML + Javascript</a></h3>
|
||||
|
||||
<div class="alert my-6">
|
||||
{% lucide "circle-alert" %}
|
||||
<h2>This component requires Javascript.</h2>
|
||||
<section>
|
||||
<p>You will need to include the Javascript (Alpine.js) code provided below before the HTML code for this component. As with all interactive components, you will need to add some Alpine.js properties to certain elements (e.g. <code class="text-xs">x-bind</code>, <code class="text-xs">x-data</code>, <code class="text-xs">@click</code>).</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<section class="prose my-6">
|
||||
<p>You can style an <code><input type="range"></code> element by either adding the <code>input</code> class or having a parent with the <code>form</code> class (<a href="/components/form">read more about form</a>). However, the range input also requries some Javacript code to be able to paint the left side of the slider.</p>
|
||||
<p>The component is structured as such:</p>
|
||||
<ul>
|
||||
<li>A <code><div class="tabs"></code> which wraps around the entire component and holds it state (e.g. open/close).</li>
|
||||
<li>A <code><nav role="tablist"></code> that holds the tab buttons (<code><button role="tab"></code>).</li>
|
||||
<li>A series of <code><div role="tabpanel"></code> that holds the tab panels corresponding to each tab button.</li>
|
||||
</ul>
|
||||
</section>
|
||||
|
||||
{{ code_block(code) }}
|
||||
{% from "components/tabs.njk" import tabs %}
|
||||
{% set tabsets = [
|
||||
{ tab: "HTML", panel: code_block(code_html | prettyHtml) },
|
||||
{ tab: "Javascipt (Alpine.js)", panel: code_block(code_script | prettyHtml) }
|
||||
] %}
|
||||
{{ tabs(id="combobox", tabsets=tabsets) }}
|
||||
|
||||
<h3 id="usage-jinja"><a href="#usage-jinja">Jinja or Nunjucks</a></h3>
|
||||
|
||||
<p class="my-6 prose">If you use Jinja (or Nunjucks), you can use the <code>tabs()</code> macro directly. <a href="/installation#jinja-and-nunjucks">Read more about using Basecoat with Jinja and Nunjucks</a>.</p>
|
||||
|
||||
{% set raw_code %}{% raw %}{% set account_panel %}
|
||||
<div class="card">
|
||||
<header>
|
||||
<h2>Account</h2>
|
||||
<p>Make changes to your account here. Click save when you're done.</p>
|
||||
</header>
|
||||
<section>
|
||||
<form class="form grid gap-6">
|
||||
<div class="grid gap-3">
|
||||
<label for="demo-tabs-account-name">Name</label>
|
||||
<input type="text" id="demo-tabs-account-name" value="Pedro Duarte" />
|
||||
</div>
|
||||
<div class="grid gap-3">
|
||||
<label for="demo-tabs-account-username">Username</label>
|
||||
<input type="text" id="demo-tabs-account-username" value="@peduarte" />
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
<footer>
|
||||
<button type="button" class="btn">Save changes</button>
|
||||
</footer>
|
||||
</div>
|
||||
{% endset %}
|
||||
|
||||
{% set password_panel %}
|
||||
<div class="card">
|
||||
<header>
|
||||
<h2>Password</h2>
|
||||
<p>Change your password here. After saving, you'll be logged out.</p>
|
||||
</header>
|
||||
<section>
|
||||
<form class="form grid gap-6">
|
||||
<div class="grid gap-3">
|
||||
<label for="demo-tabs-password-current">Current password</label>
|
||||
<input type="password" id="demo-tabs-password-current" />
|
||||
</div>
|
||||
<div class="grid gap-3">
|
||||
<label for="demo-tabs-password-new">New password</label>
|
||||
<input type="password" id="demo-tabs-password-new"/>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
<footer>
|
||||
<button type="button" class="btn">Save Password</button>
|
||||
</footer>
|
||||
</div>
|
||||
{% endset %}
|
||||
|
||||
{% set tabsets_demo = [
|
||||
{ tab: "Account", panel: account_panel },
|
||||
{ tab: "Password", panel: password_panel }
|
||||
] %}
|
||||
|
||||
{{ tabs(
|
||||
id='demo-tabs-with-panels',
|
||||
tabsets=tabsets_demo,
|
||||
main_attrs={ "class": "w-full" },
|
||||
tablist_attrs={ "class": "w-full" },
|
||||
register_on=["alpine:init", "htmx:afterSwap"]
|
||||
) }}{% endraw %}{% endset%}
|
||||
{{ code_block(raw_code, "jinja") }}
|
||||
@@ -40,8 +40,6 @@ toc:
|
||||
|
||||
<h2 id="examples"><a href="#examples">Examples</a></h2>
|
||||
|
||||
<h3 id="example-default"><a href="#example-default">Default</a></h3>
|
||||
|
||||
{{ code_preview("textarea-default", code, "w-full") }}
|
||||
|
||||
<h3 id="example-invalid"><a href="#example-invalid">Invalid</a></h3>
|
||||
|
||||
Reference in New Issue
Block a user