mirror of
https://github.com/hunvreus/basecoat.git
synced 2026-11-13 13:48:28 +00:00
PoC for new components, including select
This commit is contained in:
@@ -78,24 +78,12 @@
|
||||
<link rel="stylesheet" href="/assets/styles.css">
|
||||
|
||||
<!-- JS -->
|
||||
<script src="/assets/js/dialog.js" defer></script>
|
||||
<script src="/assets/js/dropdown-menu.js" defer></script>
|
||||
<script src="/assets/js/popover.js" defer></script>
|
||||
<script src="/assets/js/toast.js" defer></script>
|
||||
|
||||
<script src="/assets/js/select.js" defer></script>
|
||||
<script src="/assets/js/sidebar.js" defer></script>
|
||||
<script src="/assets/js/tabs.js" defer></script>
|
||||
<script src="/assets/js/toast.js" defer></script>
|
||||
<script>
|
||||
document.addEventListener('alpine:init', () => {
|
||||
window.basecoat.registerDialog(Alpine);
|
||||
window.basecoat.registerDropdownMenu(Alpine);
|
||||
window.basecoat.registerPopover(Alpine);
|
||||
window.basecoat.registerSelect(Alpine);
|
||||
window.basecoat.registerSidebar(Alpine);
|
||||
window.basecoat.registerTabs(Alpine);
|
||||
window.basecoat.registerToast(Alpine);
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/alpinejs@3.x.x/dist/cdn.min.js" defer></script>
|
||||
<script src="https://unpkg.com/htmx.org@2.0.4"></script>
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github-dark.min.css">
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
] %}
|
||||
|
||||
{{ tabs(
|
||||
id="code-block-{{ id }}",
|
||||
tabsets=tabsets,
|
||||
default_tab_index=(2 if default_code else 1),
|
||||
register_on=["alpine:init", "htmx:afterSwap"]
|
||||
|
||||
@@ -1,18 +1,12 @@
|
||||
<div class="flex h-14 w-full items-center gap-2 px-4">
|
||||
<button
|
||||
type="button"
|
||||
aria-label="Hide sidebar"
|
||||
data-tooltip="Hide sidebar"
|
||||
:data-tooltip="sidebarOpen ? 'Hide sidebar' : 'Show sidebar'"
|
||||
onclick="window.dispatchEvent(new CustomEvent('sidebar:toggle'))"
|
||||
aria-label="Toggle sidebar"
|
||||
data-tooltip="Toggle sidebar"
|
||||
data-side="bottom"
|
||||
data-align="start"
|
||||
class="btn-sm-icon-ghost mr-auto size-7 -ml-1.5"
|
||||
x-init
|
||||
x-data="{ sidebarOpen: true }"
|
||||
@click="
|
||||
sidebarOpen = !sidebarOpen;
|
||||
$dispatch('sidebar:toggle');
|
||||
"
|
||||
>
|
||||
{% lucide "panel-left" %}
|
||||
</button>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{% from "popover.njk" import popover %}
|
||||
{% from "dropdown-menu.njk" import dropdown_menu %}
|
||||
|
||||
<section id="breadcrumb" class="w-full rounded-lg border scroll-mt-14">
|
||||
<header class="border-b px-4 py-3 flex items-center justify-between">
|
||||
@@ -17,17 +17,17 @@
|
||||
{% set trigger %}
|
||||
{% lucide "ellipsis" %}
|
||||
{% endset %}
|
||||
{% call popover(
|
||||
{{ dropdown_menu(
|
||||
id="demo-breadcrumb-menu",
|
||||
trigger=trigger,
|
||||
trigger_attrs={"class": "flex size-9 items-center justify-center h-4 w-4 hover:text-foreground cursor-pointer"}
|
||||
) %}
|
||||
<nav role="menu">
|
||||
<button type="button" role="menuitem">Documentation</button>
|
||||
<button type="button" role="menuitem">Themes</button>
|
||||
<button type="button" role="menuitem">GitHub</button>
|
||||
</nav>
|
||||
{% endcall %}
|
||||
trigger_attrs={"class": "flex size-9 items-center justify-center h-4 w-4 hover:text-foreground cursor-pointer"},
|
||||
popover_attrs={"class": "p-1"},
|
||||
items=[
|
||||
{ label: "Documentation" },
|
||||
{ label: "Themes" },
|
||||
{ label: "GitHub" }
|
||||
]
|
||||
) }}
|
||||
</li>
|
||||
<li>{% lucide "chevron-right", { "class": "size-3.5" } %}</li>
|
||||
<li class="inline-flex items-center gap-1.5">
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<div class="p-4">
|
||||
<div class="flex flex-wrap items-start gap-4">
|
||||
{% call dropdown_menu(
|
||||
id="dropdown-menu",
|
||||
id="dropdown-menu-default",
|
||||
trigger="Open",
|
||||
trigger_attrs={"class": "btn-outline"},
|
||||
content_attrs={"class": "min-w-56"}
|
||||
@@ -134,8 +134,6 @@
|
||||
</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"/>
|
||||
@@ -170,7 +168,6 @@
|
||||
{% endset %}
|
||||
|
||||
{% call dropdown_menu(
|
||||
id="dropdown-menu-radio-group",
|
||||
trigger="Radio Group",
|
||||
trigger_attrs={"class": "btn-outline"},
|
||||
content_attrs={"class": "min-w-56"},
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
id="demo-popover",
|
||||
trigger="Open popover",
|
||||
trigger_attrs={"class": "btn-outline"},
|
||||
content_attrs={"class": "w-80 p-4"}
|
||||
popover_attrs={"class": "w-80"}
|
||||
) %}
|
||||
<div class="grid gap-4">
|
||||
<header class="grid gap-1.5">
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
</a>
|
||||
</header>
|
||||
<div class="p-4 gap">
|
||||
|
||||
<div class="flex flex-col gap-4">
|
||||
<div class="flex flex-wrap items-center gap-2 md:flex-row">
|
||||
<select class="select w-[180px]">
|
||||
@@ -28,46 +27,70 @@
|
||||
|
||||
<div class="flex flex-wrap items-center gap-4">
|
||||
<div class="flex flex-wrap items-center gap-2 md:flex-row">
|
||||
{% call select(trigger_attrs={"class": "w-[180px]"}) %}
|
||||
<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>
|
||||
<div role="group" aria-labelledby="vegetable-options-label">
|
||||
<span id="vegetable-options-label" role="heading">Grapes</span>
|
||||
<div role="option" data-value="pineapple">Pineapple</div>
|
||||
</div>
|
||||
{% endcall %}
|
||||
|
||||
{{ select(
|
||||
id="select-default",
|
||||
trigger_attrs={"class": "w-[180px]"},
|
||||
selected="blueberry",
|
||||
items=[
|
||||
{
|
||||
type: "group",
|
||||
label: "Fruits",
|
||||
items: [
|
||||
{ type: "item", label: "Apple", value: "apple" },
|
||||
{ type: "item", label: "Banana", value: "banana" },
|
||||
{ type: "item", label: "Blueberry Blueberry Blueberry Blueberry Blueberry", value: "blueberry" }
|
||||
]
|
||||
},
|
||||
{
|
||||
type: "group",
|
||||
label: "Grapes",
|
||||
items: [
|
||||
{ type: "item", label: "Pineapple", value: "pineapple" }
|
||||
]
|
||||
}
|
||||
]
|
||||
) }}
|
||||
{% call select(
|
||||
id="select-scrollbar",
|
||||
trigger_attrs={"class": "w-[180px]"},
|
||||
listbox_attrs={"class": "scrollbar overflow-y-auto max-h-64"}
|
||||
) %}
|
||||
{% for i in range(0, 99) %}
|
||||
<div role="option" data-value="item-{{ i }}">Item {{ i }}</div>
|
||||
{% endfor %}
|
||||
{% for i in range(0, 99) %}
|
||||
<div role="option" data-value="item-{{ i }}">Item {{ i }}</div>
|
||||
{% endfor %}
|
||||
{% endcall %}
|
||||
|
||||
{% call select(trigger_attrs={"disabled": "disabled", "class": "w-[180px]"}) %}
|
||||
{% call select(
|
||||
id="select-disabled",
|
||||
trigger_attrs={"disabled": "disabled", "class": "w-[180px]"}
|
||||
) %}
|
||||
<div role="option" data-value="disabled">Disabled</div>
|
||||
{% endcall %}
|
||||
|
||||
|
||||
{% call select(name="just-testing", trigger_attrs={'class': 'w-[180px]'}) %}
|
||||
<div type="button" role="option" data-value="bar">
|
||||
{% lucide "chart-bar", {"class": "text-muted-foreground"} %}
|
||||
Bar
|
||||
</div>
|
||||
<div type="button" role="option" data-value="line">
|
||||
{% lucide "chart-line", {"class": "text-muted-foreground"} %}
|
||||
Line
|
||||
</div>
|
||||
<div type="button" role="option" data-value="pie">
|
||||
{% lucide "chart-pie", {"class": "text-muted-foreground"} %}
|
||||
Pie
|
||||
</div>
|
||||
{% call select(
|
||||
id="select-with-icon",
|
||||
name="chart-type",
|
||||
trigger_attrs={'class': 'w-[180px]'}
|
||||
) %}
|
||||
<div type="button" role="option" data-value="bar">
|
||||
<span class="flex items-center gap-2">
|
||||
{% lucide "chart-bar", {"class": "text-muted-foreground"} %}
|
||||
Bar
|
||||
</span>
|
||||
</div>
|
||||
<div type="button" role="option" data-value="line">
|
||||
<span class="flex items-center gap-2">
|
||||
{% lucide "chart-line", {"class": "text-muted-foreground"} %}
|
||||
Line
|
||||
</span>
|
||||
</div>
|
||||
<div type="button" role="option" data-value="pie">
|
||||
<span class="flex items-center gap-2">
|
||||
{% lucide "chart-pie", {"class": "text-muted-foreground"} %}
|
||||
Pie
|
||||
</span>
|
||||
</div>
|
||||
{% endcall %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -13,18 +13,24 @@
|
||||
min="0"
|
||||
max="27"
|
||||
value="12"
|
||||
x-data="{
|
||||
updatePercent(el) {
|
||||
const min = parseFloat(el.min || 0);
|
||||
const max = parseFloat(el.max || 100);
|
||||
const value = parseFloat(el.value);
|
||||
const percent = (max === min) ? 0 : ((value - min) / (max - min)) * 100;
|
||||
el.style.setProperty('--slider-value', `${percent}%`);
|
||||
}
|
||||
}"
|
||||
x-init="updatePercent($el)"
|
||||
@input="updatePercent($el)"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
<script>
|
||||
(() => {
|
||||
const sliderEl = document.querySelector('input[type="range"].input');
|
||||
if (!sliderEl) return;
|
||||
|
||||
const updateSlider = (el) => {
|
||||
const min = parseFloat(el.min || 0);
|
||||
const max = parseFloat(el.max || 100);
|
||||
const value = parseFloat(el.value);
|
||||
const percent = (max === min) ? 0 : ((value - min) / (max - min)) * 100;
|
||||
el.style.setProperty('--slider-value', `${percent}%`);
|
||||
};
|
||||
|
||||
updateSlider(sliderEl);
|
||||
sliderEl.addEventListener('input', (e) => updateSlider(e.target));
|
||||
})();
|
||||
</script>
|
||||
@@ -63,7 +63,7 @@
|
||||
"hx-select": "#content",
|
||||
"hx-target": "#content",
|
||||
"hx-swap": "outerHTML",
|
||||
"@click": "if (window.innerWidth < 768) { open = false }"
|
||||
"data-sidebar-close-on-mobile": ""
|
||||
} %}
|
||||
|
||||
{% set icon_home %}{% lucide "house" %}{% endset %}
|
||||
@@ -79,7 +79,7 @@
|
||||
{ label: "Kitchen sink", url: "/kitchen-sink", icon: icon_layout_dashboard, attrs: link_attrs },
|
||||
{ label: "GitHub", url: "https://github.com/hunvreus/basecoat", icon: icon_github, attrs: {
|
||||
"target": "_blank",
|
||||
"@click": "if (window.innerWidth < 768) { open = false }"
|
||||
"data-sidebar-close-on-mobile": ""
|
||||
}
|
||||
}
|
||||
]},
|
||||
@@ -117,6 +117,7 @@
|
||||
|
||||
|
||||
{{ sidebar(
|
||||
id="sidebar",
|
||||
label="Sidebar navigation",
|
||||
header=header,
|
||||
footer=footer,
|
||||
|
||||
+341
-448
File diff suppressed because it is too large
Load Diff
@@ -18,8 +18,8 @@ toc:
|
||||
|
||||
{% set code_html %}
|
||||
{% set footer %}
|
||||
<button class="btn-outline" @click="open = false">Cancel</button>
|
||||
<button class="btn-primary" @click="open = false">Continue</button>
|
||||
<button class="btn-outline" onClick="document.getElementById('alert-dialog').close()">Cancel</button>
|
||||
<button class="btn-primary" onClick="document.getElementById('alert-dialog').close()">Continue</button>
|
||||
{% endset %}
|
||||
{{ dialog(
|
||||
id="alert-dialog",
|
||||
@@ -105,8 +105,8 @@ document.addEventListener('alpine:init', () => {
|
||||
</div>
|
||||
|
||||
{% 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-outline" onClick="document.getElementById('demo-alert-dialog').close()">Cancel</button>
|
||||
<button class="btn-primary" onClick="document.getElementById('demo-alert-dialog').close()">Continue</button>
|
||||
{% endset %}
|
||||
{{ dialog(
|
||||
id="demo-alert-dialog",
|
||||
|
||||
@@ -23,8 +23,8 @@ toc:
|
||||
|
||||
{% set code_html %}
|
||||
{% set footer %}
|
||||
<button class="btn-outline" @click="open = false">Cancel</button>
|
||||
<button class="btn" @click="open = false">Save changes</button>
|
||||
<button class="btn-outline" onClick="this.closest('dialog').close()">Cancel</button>
|
||||
<button class="btn" onClick="this.closest('dialog').close()">Save changes</button>
|
||||
{% endset %}
|
||||
{% call dialog(
|
||||
id="demo-dialog-edit-profile",
|
||||
@@ -175,7 +175,7 @@ document.addEventListener('alpine:init', () => {
|
||||
|
||||
{% set code %}
|
||||
{% set footer %}
|
||||
<button class="btn-outline" @click="open = false">Close</button>
|
||||
<button class="btn-outline" onClick="this.closest('dialog').close()">Close</button>
|
||||
{% endset %}
|
||||
{% call dialog(
|
||||
id="dialog-example",
|
||||
|
||||
@@ -21,8 +21,7 @@ toc:
|
||||
id="demo-popover",
|
||||
trigger="Open popover",
|
||||
trigger_attrs={"class": "btn-outline"},
|
||||
content_attrs={"class": "w-80 p-4"},
|
||||
register_on=["alpine:init", "htmx:afterSwap"]
|
||||
popover_attrs={"class": "w-80"}
|
||||
) %}
|
||||
<div class="grid gap-4">
|
||||
<header class="grid gap-1.5">
|
||||
@@ -52,13 +51,13 @@ toc:
|
||||
{% endset %}
|
||||
|
||||
{% set code_script %}
|
||||
<script>
|
||||
{# <script>
|
||||
{% fetchCode "src/js/popover.js" %}
|
||||
|
||||
document.addEventListener('alpine:init', () => {
|
||||
window.basecoat.registerPopover(Alpine);
|
||||
});
|
||||
</script>
|
||||
</script> #}
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("popover", code_script | prettyHtml ~ code_html | prettyHtml) }}
|
||||
|
||||
@@ -34,34 +34,30 @@ toc:
|
||||
<option>Blueberry</option>
|
||||
<option>Grapes</option>
|
||||
<option>Pineapple</option>
|
||||
</optgroup>
|
||||
</select>{% endset %}
|
||||
{{ code_preview("select-native", code_native) }}
|
||||
|
||||
{% set code_html %}
|
||||
{% call select(
|
||||
name="select-js",
|
||||
{{ select(
|
||||
trigger_attrs={"class": "w-[180px]"},
|
||||
register_on=["alpine:init", "htmx:afterSwap"]
|
||||
) %}
|
||||
<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 %}
|
||||
items=[
|
||||
{
|
||||
type: "group",
|
||||
label: "Fruits",
|
||||
items: [
|
||||
{ type: "item", value: "apple", label: "Apple" },
|
||||
{ type: "item", value: "banana", label: "Banana" },
|
||||
{ type: "item", value: "blueberry", label: "Blueberry" },
|
||||
{ type: "item", value: "pineapple", label: "Grapes" },
|
||||
{ type: "item", value: "pineapple", label: "Pineapple" }
|
||||
]
|
||||
}
|
||||
]
|
||||
) }}
|
||||
{% endset %}
|
||||
|
||||
{% set code_script %}
|
||||
<script>
|
||||
{% fetchCode "src/js/select.js" %}
|
||||
|
||||
document.addEventListener('alpine:init', () => {
|
||||
window.basecoat.registerSelect(Alpine);
|
||||
});
|
||||
</script>
|
||||
{% endset %}
|
||||
|
||||
{{ code_preview("select", code_script | prettyHtml ~ code_html | prettyHtml) }}
|
||||
@@ -153,16 +149,21 @@ document.addEventListener('alpine:init', () => {
|
||||
</a>
|
||||
</div>
|
||||
|
||||
{% set raw_code %}{% raw %}{% call select(name="select-js") %}
|
||||
<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 %}{% endraw %}{% endset %}
|
||||
{% set raw_code %}{% raw %}{{ select(
|
||||
items=[
|
||||
{
|
||||
type: "group",
|
||||
label: "Fruits",
|
||||
items: [
|
||||
{ type: "item", value: "apple", label: "Apple" },
|
||||
{ type: "item", value: "banana", label: "Banana" },
|
||||
{ type: "item", value: "blueberry", label: "Blueberry" },
|
||||
{ type: "item", value: "pineapple", label: "Grapes" },
|
||||
{ type: "item", value: "pineapple", label: "Pineapple" }
|
||||
]
|
||||
}
|
||||
]
|
||||
) }}{% endraw %}{% endset %}
|
||||
{{ code_block(raw_code, "jinja") }}
|
||||
|
||||
<h2 id="examples"><a href="#examples">Examples</a></h2>
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
layout: layouts/base.njk
|
||||
---
|
||||
|
||||
|
||||
|
||||
<div id="my-popover" open popover="manual">
|
||||
SOMETHING
|
||||
SOMETHING
|
||||
SOMETHING
|
||||
SOMETHING
|
||||
SOMETHING
|
||||
</div>
|
||||
|
||||
<button popovertarget="my-popover">
|
||||
TOGGLE SIDEBAR
|
||||
</button>
|
||||
@@ -84,13 +84,13 @@ toc:
|
||||
|
||||
|
||||
{% set code_script %}
|
||||
<script>
|
||||
{# <script>
|
||||
{% fetchCode "src/js/popover.js" %}
|
||||
|
||||
document.addEventListener('alpine:init', () => {
|
||||
window.basecoat.registerPopover(Alpine);
|
||||
});
|
||||
</script>
|
||||
</script> #}
|
||||
{% endset %}
|
||||
|
||||
{% set code_html_toaster %}{{ toaster() }}{% endset %}
|
||||
|
||||
+9
-8
@@ -32,16 +32,17 @@ layout: layouts/layout.njk
|
||||
<p class="text-sm text-muted-foreground">m@example.com</p>
|
||||
</div>
|
||||
|
||||
{% call select(
|
||||
{{ select(
|
||||
is_combobox=true,
|
||||
selected="owner",
|
||||
content_attrs={"data-align": "end"}
|
||||
) %}
|
||||
<div role="option" data-value="viewer">Viewer</div>
|
||||
<div role="option" data-value="developer">Developer</div>
|
||||
<div role="option" data-value="billing">Billing</div>
|
||||
<div role="option" data-value="owner">Owner</div>
|
||||
{% endcall %}
|
||||
popover_attrs={"data-align": "end"},
|
||||
items=[
|
||||
{ type: "item", value: "viewer", label: "Viewer" },
|
||||
{ type: "item", value: "developer", label: "Developer" },
|
||||
{ type: "item", value: "billing", label: "Billing" },
|
||||
{ type: "item", value: "owner", label: "Owner" }
|
||||
]
|
||||
) }}
|
||||
</li>
|
||||
<li class="flex items-center gap-4">
|
||||
<img src="/assets/images/avatar-2.png" alt="Jackson Lee" class="w-10 h-10 rounded-full" />
|
||||
|
||||
Reference in New Issue
Block a user