mirror of
https://github.com/hunvreus/basecoat.git
synced 2026-11-13 13:48:28 +00:00
Working on charts and sidebar
This commit is contained in:
@@ -744,6 +744,9 @@
|
||||
|
||||
/* Sidebar */
|
||||
.sidebar {
|
||||
&[data-uninitialized] {
|
||||
@apply max-md:hidden;
|
||||
}
|
||||
&:not([aria-hidden]),
|
||||
&[aria-hidden=false] {
|
||||
@apply max-md:bg-black/50 max-md:fixed max-md:inset-0 max-md:z-40;
|
||||
@@ -809,7 +812,7 @@
|
||||
|
||||
> a,
|
||||
> details > summary {
|
||||
@apply flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-data-[sidebar=menu-action]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:size-8! group-data-[collapsible=icon]:p-2! [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0;
|
||||
@apply flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-hidden ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 aria-disabled:pointer-events-none aria-disabled:opacity-50 [&[aria-current=page]]:bg-sidebar-accent [&[aria-current=page]]:font-medium [&[aria-current=page]]:text-sidebar-accent-foreground [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0;
|
||||
|
||||
&:not([data-variant]),
|
||||
&[data-variant=default] {
|
||||
|
||||
+11
-9
@@ -2,22 +2,24 @@ window.basecoat = window.basecoat || {};
|
||||
window.basecoat.registerSidebar= function(Alpine) {
|
||||
if (Alpine.components && Alpine.components.sidebar) return;
|
||||
|
||||
Alpine.data('sidebar', (initialOpen = true) => ({
|
||||
id: null,
|
||||
open: true,
|
||||
Alpine.data('sidebar', (initialOpen = true, initialMobileOpen = false) => ({
|
||||
open: window.innerWidth >= 768
|
||||
? initialOpen
|
||||
: initialMobileOpen,
|
||||
|
||||
init() {
|
||||
this.id = this.$el.id;
|
||||
this.open = initialOpen;
|
||||
this.$nextTick(() => {
|
||||
this.$el.removeAttribute('data-uninitialized');
|
||||
});
|
||||
},
|
||||
|
||||
$main: {
|
||||
'@sidebar:open.window'(e) { if (!this.id || (e.detail && e.detail.id === this.id)) this.open = true },
|
||||
'@sidebar:close.window'(e) { if (!this.id || (e.detail && e.detail.id === this.id)) this.open = false },
|
||||
'@sidebar:toggle.window'(e) { if (!this.id || (e.detail && e.detail.id === this.id)) this.open = !this.open },
|
||||
'@sidebar:open.window'(e) { this.open = true },
|
||||
'@sidebar:close.window'(e) { this.open = false },
|
||||
'@sidebar:toggle.window'(e) { this.open = !this.open },
|
||||
'@click'(e) { if (e.target === this.$el) this.open = false },
|
||||
':aria-hidden'() { return !this.open },
|
||||
':inert'() { return !this.open },
|
||||
':inert'() { return !this.open }
|
||||
},
|
||||
}));
|
||||
};
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
@param id {string} [optional] - Unique identifier for the dropdown component.
|
||||
@param trigger {string} [optional] - HTML content for the button that triggers the dropdown.
|
||||
@param menu {array} [optional] - Array of menu items for the dropdown.
|
||||
@param main_attrs {object} [optional] - Additional HTML attributes for the main container div.
|
||||
@param trigger_attrs {object} [optional] - Additional HTML attributes for the trigger button.
|
||||
@param content_attrs {object} [optional] - Additional HTML attributes for the dropdown content div.
|
||||
@@ -10,6 +11,7 @@
|
||||
{% macro dropdown_menu(
|
||||
id=None,
|
||||
trigger=None,
|
||||
menu=None,
|
||||
main_attrs={},
|
||||
trigger_attrs={},
|
||||
content_attrs={}
|
||||
@@ -20,7 +22,7 @@
|
||||
@click.away="open = false"
|
||||
{% if id %}id="{{ id }}"{% endif %}
|
||||
{% for key, value in main_attrs %}
|
||||
{% if key != 'class' %}{{ key }}="{{ value }}"{% endif %}
|
||||
{% if key != "class" %}{{ key }}="{{ value }}"{% endif %}
|
||||
{% endfor %}
|
||||
>
|
||||
{% if trigger %}
|
||||
@@ -50,8 +52,62 @@
|
||||
{% endfor %}
|
||||
>
|
||||
<nav role="menu">
|
||||
{{ caller() if caller }}
|
||||
{% if menu %}
|
||||
{{ render_dropdown_items(menu, id ~ "-items" if id else "items") }}
|
||||
{% else %}
|
||||
{{ caller() if caller }}
|
||||
{% endif %}
|
||||
</nav>
|
||||
</div>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{#
|
||||
Renders dropdown menu items recursively.
|
||||
|
||||
@param items {array} - The array of items to render.
|
||||
@param parent_id_prefix {string} [optional] - Prefix for generating element IDs.
|
||||
#}
|
||||
{% macro render_dropdown_items(items, parent_id_prefix="items") %}
|
||||
{% for item in items %}
|
||||
{% set item_id = parent_id_prefix ~ "-" ~ loop.index %}
|
||||
|
||||
{% if item.type == "group" %}
|
||||
{% set group_label_id = item.id if item.id else "group-label-" + item_id %}
|
||||
<div
|
||||
role="group"
|
||||
aria-labelledby="{{ group_label_id }}"
|
||||
{% for key, value in item.attrs %}
|
||||
{{ key }}="{{ value }}"
|
||||
{% endfor %}
|
||||
>
|
||||
<div role="heading" id="{{ group_label_id }}">{{ item.label }}</div>
|
||||
{{ render_dropdown_items(item.items, item_id) if item.items }}
|
||||
</div>
|
||||
{% elif item.type == "separator" %}
|
||||
<hr role="separator" />
|
||||
{% elif item.type == "item" or not item.type %}
|
||||
{% if item.url %}
|
||||
<a
|
||||
role="menuitem"
|
||||
href="{{ item.url }}"
|
||||
{% for key, value in item.attrs %}
|
||||
{% if key != "url" %} {{ key }}="{{ value }}" {% endif %}
|
||||
{% endfor %}
|
||||
>
|
||||
{{ item.label | safe }}
|
||||
</a>
|
||||
{% else %}
|
||||
<button
|
||||
role="menuitem"
|
||||
type="button"
|
||||
{% for key, value in item.attrs %}
|
||||
{{ key }}="{{ value }}"
|
||||
{% endfor %}
|
||||
>
|
||||
{{ item.label | safe }}
|
||||
</button>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endmacro %}
|
||||
+44
-1
@@ -16,6 +16,7 @@
|
||||
id=None,
|
||||
selected=None,
|
||||
name=None,
|
||||
items=None,
|
||||
main_attrs={},
|
||||
trigger_attrs={},
|
||||
content_attrs={},
|
||||
@@ -91,7 +92,11 @@
|
||||
{{ key }}="{{ value }}"
|
||||
{% endfor %}
|
||||
>
|
||||
{{ caller() if caller }}
|
||||
{% if items %}
|
||||
{{ render_select_items(items, id ~ "-items" if id else "items") }}
|
||||
{% else %}
|
||||
{{ caller() if caller }}
|
||||
{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% if name is defined %}
|
||||
@@ -105,4 +110,42 @@
|
||||
>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{#
|
||||
Renders a list of items for the select component.
|
||||
|
||||
@param items {array} - The array of items to render.
|
||||
@param parent_id_prefix {string} [optional] - The prefix for the item id.
|
||||
#}
|
||||
{% macro render_select_items(items, parent_id_prefix="items") %}
|
||||
{% for item in items %}
|
||||
{% set item_id = parent_id_prefix ~ "-" ~ loop.index %}
|
||||
|
||||
{% if item.type == "group" %}
|
||||
{% set group_label_id = item.id if item.id else "group-label-" + item_id %}
|
||||
<div
|
||||
role="group"
|
||||
aria-labelledby="{{ group_label_id }}"
|
||||
{% for key, value in item.attrs %}
|
||||
{{ key }}="{{ value }}"
|
||||
{% endfor %}
|
||||
>
|
||||
<div role="heading" id="{{ group_label_id }}">{{ item.label }}</div>
|
||||
{{ render_select_items(item.items, item_id) if item.items }}
|
||||
</div>
|
||||
{% elif item.type == "separator" %}
|
||||
<hr role="separator" />
|
||||
{% elif item.type == "item" or not item.type %}
|
||||
<div
|
||||
role="option"
|
||||
data-value="{{ item.value }}"
|
||||
{% for key, value in item.attrs %}
|
||||
{{ key }}="{{ value }}"
|
||||
{% endfor %}
|
||||
>
|
||||
{{ item.label | safe }}
|
||||
</div>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endmacro %}
|
||||
+79
-55
@@ -1,42 +1,14 @@
|
||||
{% macro render_menu_items(items, level=0, parent_id="") %}
|
||||
<ul>
|
||||
{% for item in items %}
|
||||
{% set item_id = parent_id ~ loop.index %}
|
||||
{% if item.type == 'item' %}
|
||||
<li>
|
||||
<a
|
||||
href="{{ item.url }}"
|
||||
{{ 'aria-current="page"' if item.current }}
|
||||
{% for key, value in item.attrs %}
|
||||
{% if key != 'href' and key != 'aria-current' %}{{ key }}="{{ value }}"{% endif %}
|
||||
{% endfor %}
|
||||
>
|
||||
{% if item.icon %}{{ item.icon | safe }}{% endif %}
|
||||
<span>{{ item.label }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{% elif item.type == 'submenu' %}
|
||||
<li>
|
||||
<details {{ 'open' if item.open }} id="submenu-{{ item_id }}">
|
||||
<summary
|
||||
aria-controls="submenu-{{ item_id }}-content"
|
||||
{% for key, value in item.attrs %}
|
||||
{% if key != 'aria-controls' %}{{ key }}="{{ value }}"{% endif %}
|
||||
{% endfor %}
|
||||
>
|
||||
{% if item.icon %}{{ item.icon | safe }}{% endif %}
|
||||
{{ item.label }}
|
||||
</summary>
|
||||
<div id="submenu-{{ item_id }}-content">
|
||||
{{ render_menu_items(item.items, level + 1, item_id + '-') }}
|
||||
</div>
|
||||
</details>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% endmacro %}
|
||||
{#
|
||||
Renders a sidebar component.
|
||||
|
||||
@param id {string} [optional] - Unique identifier for the sidebar component.
|
||||
@param label {string} [optional] - Label for the sidebar navigation.
|
||||
@param open {boolean} [optional] - Whether the sidebar is open.
|
||||
@param side {string} [optional] - Side of the sidebar to display.
|
||||
@param header {string} [optional] - Header content for the sidebar.
|
||||
@param footer {string} [optional] - Footer content for the sidebar.
|
||||
@param menu {array} [optional] - Array of menu items for the sidebar.
|
||||
#}
|
||||
{% macro sidebar(
|
||||
id=None,
|
||||
label="Sidebar navigation",
|
||||
@@ -54,13 +26,14 @@
|
||||
<div
|
||||
{% if id %}id="{{ id }}"{% endif %}
|
||||
class="sidebar {{ main_attrs.class }}"
|
||||
aria-hidden="{{ 'false' if open else 'true' }}"
|
||||
data-side="{{ side if side else 'left' }}"
|
||||
{{ 'inert' if not open }}
|
||||
data-uninitialized
|
||||
data-side="{{ side if side else "left" }}"
|
||||
aria-hidden="{{ "true" if not open else "false" }}"
|
||||
{{ "inert" if not open }}
|
||||
{% for key, value in main_attrs %}
|
||||
{% if key != "class" %}{{ key }}="{{ value }}"{% endif %}
|
||||
{% endfor %}
|
||||
x-data="sidebar({{ 'true' if open else 'false' }})"
|
||||
x-data="sidebar({{ "true" if open else "false" }})"
|
||||
x-bind="$main"
|
||||
>
|
||||
<nav
|
||||
@@ -82,19 +55,7 @@
|
||||
{% endfor %}
|
||||
>
|
||||
{% if menu %}
|
||||
{% for group_or_item in menu %}
|
||||
{% set group_id = loop.index %}
|
||||
{% if group_or_item.type == 'group' %}
|
||||
<div role="group" aria-labelledby="nav-group-{{ group_id }}">
|
||||
<h3 id="nav-group-{{ group_id }}">{{ group_or_item.label }}</h3>
|
||||
{{ render_menu_items(group_or_item.items, 0, group_id + '-') }}
|
||||
</div>
|
||||
{% elif group_or_item.type == 'separator' %}
|
||||
<hr role="separator"/>
|
||||
{% elif group_or_item.type == 'item' or group_or_item.type == 'submenu' %}
|
||||
{{ render_menu_items([group_or_item], 0, 'top-' + group_id + '-') }}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{{ render_sidebar_content(menu, id ~ "-content" if id else "content") }}
|
||||
{% else %}
|
||||
{{ caller() if caller }}
|
||||
{% endif %}
|
||||
@@ -111,4 +72,67 @@
|
||||
{% endif %}
|
||||
</nav>
|
||||
</div>
|
||||
{% endmacro %}
|
||||
|
||||
{#
|
||||
Renders sidebar content recursively (groups, items, submenus, separators).
|
||||
|
||||
@param items {array} - The array of items to render.
|
||||
@param parent_id_prefix {string} [optional] - Prefix for generating element IDs.
|
||||
#}
|
||||
{% macro render_sidebar_content(items, parent_id_prefix="content") %}
|
||||
{% for item in items %}
|
||||
{% set item_id = parent_id_prefix ~ "-" ~ loop.index %}
|
||||
|
||||
{% if item.type == "group" %}
|
||||
{% set group_label_id = item.id if item.id else "group-label-" + item_id %}
|
||||
<div
|
||||
role="group"
|
||||
{% if item.label %}aria-labelledby="{{ group_label_id }}"{% endif %}
|
||||
{% for key, value in item.attrs %}
|
||||
{{ key }}="{{ value }}"
|
||||
{% endfor %}
|
||||
>
|
||||
{% if item.label %}
|
||||
<h3 id="{{ group_label_id }}">{{ item.label }}</h3>
|
||||
{% endif %}
|
||||
<ul>
|
||||
{{ render_sidebar_content(item.items, item_id) if item.items }}
|
||||
</ul>
|
||||
</div>
|
||||
{% elif item.type == "separator" %}
|
||||
<hr role="separator"/>
|
||||
{% elif item.type == "submenu" %}
|
||||
<li>
|
||||
<details
|
||||
id="submenu-{{ item_id }}"
|
||||
{{ "open" if item.open }}
|
||||
{% for key, value in item.attrs %}
|
||||
{% if key != "open" %}{{ key }}="{{ value }}"{% endif %}
|
||||
{% endfor %}
|
||||
>
|
||||
<summary aria-controls="submenu-{{ item_id }}-content">
|
||||
{% if item.icon %}{{ item.icon | safe }}{% endif %}
|
||||
{{ item.label }}
|
||||
</summary>
|
||||
<ul id="submenu-{{ item_id }}-content">
|
||||
{{ render_sidebar_content(item.items, item_id) if item.items }}
|
||||
</ul>
|
||||
</details>
|
||||
</li>
|
||||
{% elif item.type == "item" or not item.type %}
|
||||
<li>
|
||||
<a
|
||||
href="{{ item.url }}"
|
||||
{{ 'aria-current="page"' if item.current }}
|
||||
{% for key, value in item.attrs %}
|
||||
{% if key != "href" and key != "aria-current" %}{{ key }}="{{ value }}"{% endif %}
|
||||
{% endfor %}
|
||||
>
|
||||
{% if item.icon %}{{ item.icon | safe }}{% endif %}
|
||||
<span>{{ item.label }}</span>
|
||||
</a>
|
||||
</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endmacro %}
|
||||
Reference in New Issue
Block a user