Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Toolkit/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
- [Flowbite] Add `avatar` recipe
- [Flowbite] Add `dropdown` recipe
- [Shadcn] Add `hover-card` recipe
- [Shadcn] Add `navigation-menu` recipe
- [Shadcn] Add `resizable` recipe

## 3.0.0
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { Controller } from '@hotwired/stimulus';

export default class extends Controller {
static values = {
openDelay: { type: Number, default: 0 },
closeDelay: { type: Number, default: 0 },
};

connect() {
this.openTimeout = null;
this.closeTimeout = null;
this.element.dataset.state = 'closed';
}

disconnect() {
this.#clearTimeouts();
}

show() {
this.#clearTimeouts();
this.openTimeout = setTimeout(() => {
this.element.dataset.state = 'open';
this.openTimeout = null;
}, this.openDelayValue);
}

hide() {
this.#clearTimeouts();
this.closeTimeout = setTimeout(() => {
this.element.dataset.state = 'closed';
this.closeTimeout = null;
}, this.closeDelayValue);
}

#clearTimeouts() {
if (this.openTimeout) {
clearTimeout(this.openTimeout);
this.openTimeout = null;
}
if (this.closeTimeout) {
clearTimeout(this.closeTimeout);
this.closeTimeout = null;
}
}
}
65 changes: 65 additions & 0 deletions src/Toolkit/kits/shadcn/navigation-menu/examples/Demo.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<twig:NavigationMenu>
<twig:NavigationMenu:List>
<twig:NavigationMenu:Item>
<twig:NavigationMenu:Trigger>
<twig:Button variant="ghost" size="sm" {{ ...navigation_menu_trigger_attrs }}>
Getting started
<twig:ux:icon name="lucide:chevron-down" class="relative top-px size-3 transition-transform duration-200 in-data-[state=open]:rotate-180" aria-hidden="true" />
</twig:Button>
</twig:NavigationMenu:Trigger>
<twig:NavigationMenu:Content>
<ul class="grid gap-1 w-96">
<li>
<a class="block rounded-md p-3 hover:bg-accent" href="/docs">
<div class="text-sm font-medium leading-none">Introduction</div>
<p class="line-clamp-2 text-sm text-muted-foreground">Re-usable components built with Tailwind CSS.</p>
</a>
</li>
<li>
<a class="block rounded-md p-3 hover:bg-accent" href="/docs/installation">
<div class="text-sm font-medium leading-none">Installation</div>
<p class="line-clamp-2 text-sm text-muted-foreground">How to install dependencies and structure your app.</p>
</a>
</li>
<li>
<a class="block rounded-md p-3 hover:bg-accent" href="/docs/primitives/typography">
<div class="text-sm font-medium leading-none">Typography</div>
<p class="line-clamp-2 text-sm text-muted-foreground">Styles for headings, paragraphs, lists...etc</p>
</a>
</li>
</ul>
</twig:NavigationMenu:Content>
</twig:NavigationMenu:Item>
<twig:NavigationMenu:Item>
<twig:NavigationMenu:Trigger>
<twig:Button variant="ghost" size="sm" {{ ...navigation_menu_trigger_attrs }}>
Components
<twig:ux:icon name="lucide:chevron-down" class="relative top-px size-3 transition-transform duration-200 in-data-[state=open]:rotate-180" aria-hidden="true" />
</twig:Button>
</twig:NavigationMenu:Trigger>
<twig:NavigationMenu:Content>
<ul class="grid gap-2 w-[500px] grid-cols-2">
{% set components = [
{title: 'Alert Dialog', href: '/docs/primitives/alert-dialog', description: 'A modal dialog that interrupts the user with important content and expects a response.'},
{title: 'Hover Card', href: '/docs/primitives/hover-card', description: 'For sighted users to preview content available behind a link.'},
{title: 'Progress', href: '/docs/primitives/progress', description: 'Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.'},
{title: 'Scroll-area', href: '/docs/primitives/scroll-area', description: 'Visually or semantically separates content.'},
{title: 'Tabs', href: '/docs/primitives/tabs', description: 'A set of layered sections of content—known as tab panels—that are displayed one at a time.'},
{title: 'Tooltip', href: '/docs/primitives/tooltip', description: 'A popup that displays information related to an element when the element receives keyboard focus or the mouse hovers over it.'},
] %}
{% for c in components %}
<li>
<a class="block rounded-md p-3 hover:bg-accent" href="{{ c.href }}">
<div class="text-sm font-medium leading-none">{{ c.title }}</div>
<p class="line-clamp-2 text-sm text-muted-foreground">{{ c.description }}</p>
</a>
</li>
{% endfor %}
</ul>
</twig:NavigationMenu:Content>
</twig:NavigationMenu:Item>
<twig:NavigationMenu:Item>
<twig:NavigationMenu:Link href="/docs">Docs</twig:NavigationMenu:Link>
</twig:NavigationMenu:Item>
</twig:NavigationMenu:List>
</twig:NavigationMenu>
139 changes: 139 additions & 0 deletions src/Toolkit/kits/shadcn/navigation-menu/examples/RTL.html.twig
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
<div class="flex flex-col items-center gap-12">
{# Arabic #}
<div dir="rtl">
<twig:NavigationMenu>
<twig:NavigationMenu:List>
<twig:NavigationMenu:Item>
<twig:NavigationMenu:Trigger>
<twig:Button variant="ghost" size="sm" {{ ...navigation_menu_trigger_attrs }}>
البدء
<twig:ux:icon name="lucide:chevron-down" class="relative top-px size-3 transition-transform duration-200 in-data-[state=open]:rotate-180" aria-hidden="true" />
</twig:Button>
</twig:NavigationMenu:Trigger>
<twig:NavigationMenu:Content>
<ul class="grid gap-1 w-96">
<li>
<a class="block rounded-md p-3 hover:bg-accent" href="/docs">
<div class="text-sm font-medium leading-none">مقدمة</div>
<p class="line-clamp-2 text-sm text-muted-foreground">مكونات قابلة لإعادة الاستخدام مبنية باستخدام Tailwind CSS.</p>
</a>
</li>
<li>
<a class="block rounded-md p-3 hover:bg-accent" href="/docs/installation">
<div class="text-sm font-medium leading-none">التثبيت</div>
<p class="line-clamp-2 text-sm text-muted-foreground">كيفية تثبيت التبعيات وتنظيم تطبيقك.</p>
</a>
</li>
<li>
<a class="block rounded-md p-3 hover:bg-accent" href="/docs/primitives/typography">
<div class="text-sm font-medium leading-none">الطباعة</div>
<p class="line-clamp-2 text-sm text-muted-foreground">أنماط للعناوين والفقرات والقوائم...إلخ</p>
</a>
</li>
</ul>
</twig:NavigationMenu:Content>
</twig:NavigationMenu:Item>
<twig:NavigationMenu:Item>
<twig:NavigationMenu:Trigger>
<twig:Button variant="ghost" size="sm" {{ ...navigation_menu_trigger_attrs }}>
المكونات
<twig:ux:icon name="lucide:chevron-down" class="relative top-px size-3 transition-transform duration-200 in-data-[state=open]:rotate-180" aria-hidden="true" />
</twig:Button>
</twig:NavigationMenu:Trigger>
<twig:NavigationMenu:Content>
<ul class="grid gap-2 w-[500px] grid-cols-2">
{% set components_ar = [
{title: 'حوار التنبيه', href: '/docs/primitives/alert-dialog', description: 'حوار نافذة يقطع المستخدم بمحتوى مهم ويتوقع استجابة.'},
{title: 'بطاقة التحويم', href: '/docs/primitives/hover-card', description: 'للمستخدمين المبصرين لمعاينة المحتوى المتاح خلف الرابط.'},
{title: 'التقدم', href: '/docs/primitives/progress', description: 'يعرض مؤشرًا يوضح تقدم إتمام المهمة، عادةً يتم عرضه كشريط تقدم.'},
{title: 'منطقة التمرير', href: '/docs/primitives/scroll-area', description: 'يفصل المحتوى بصريًا أو دلاليًا.'},
{title: 'التبويبات', href: '/docs/primitives/tabs', description: 'مجموعة من أقسام المحتوى المتعددة الطبقات—المعروفة بألواح التبويب—التي يتم عرضها واحدة في كل مرة.'},
{title: 'تلميح', href: '/docs/primitives/tooltip', description: 'نافذة منبثقة تعرض معلومات متعلقة بعنصر عند تحويم الماوس فوقه.'},
] %}
{% for c in components_ar %}
<li>
<a class="block rounded-md p-3 hover:bg-accent" href="{{ c.href }}">
<div class="text-sm font-medium leading-none">{{ c.title }}</div>
<p class="line-clamp-2 text-sm text-muted-foreground">{{ c.description }}</p>
</a>
</li>
{% endfor %}
</ul>
</twig:NavigationMenu:Content>
</twig:NavigationMenu:Item>
<twig:NavigationMenu:Item>
<twig:NavigationMenu:Link href="/docs">الوثائق</twig:NavigationMenu:Link>
</twig:NavigationMenu:Item>
</twig:NavigationMenu:List>
</twig:NavigationMenu>
</div>

{# Hebrew #}
<div dir="rtl">
<twig:NavigationMenu>
<twig:NavigationMenu:List>
<twig:NavigationMenu:Item>
<twig:NavigationMenu:Trigger>
<twig:Button variant="ghost" size="sm" {{ ...navigation_menu_trigger_attrs }}>
התחלה
<twig:ux:icon name="lucide:chevron-down" class="relative top-px size-3 transition-transform duration-200 in-data-[state=open]:rotate-180" aria-hidden="true" />
</twig:Button>
</twig:NavigationMenu:Trigger>
<twig:NavigationMenu:Content>
<ul class="grid gap-1 w-96">
<li>
<a class="block rounded-md p-3 hover:bg-accent" href="/docs">
<div class="text-sm font-medium leading-none">הקדמה</div>
<p class="line-clamp-2 text-sm text-muted-foreground">רכיבים לשימוש חוזר שנבנו עם Tailwind CSS.</p>
</a>
</li>
<li>
<a class="block rounded-md p-3 hover:bg-accent" href="/docs/installation">
<div class="text-sm font-medium leading-none">התקנה</div>
<p class="line-clamp-2 text-sm text-muted-foreground">כיצד להתקין תלויות ולבנות את האפליקציה שלך.</p>
</a>
</li>
<li>
<a class="block rounded-md p-3 hover:bg-accent" href="/docs/primitives/typography">
<div class="text-sm font-medium leading-none">טיפוגרפיה</div>
<p class="line-clamp-2 text-sm text-muted-foreground">סגנונות לכותרות, פסקאות, רשימות...וכו'</p>
</a>
</li>
</ul>
</twig:NavigationMenu:Content>
</twig:NavigationMenu:Item>
<twig:NavigationMenu:Item>
<twig:NavigationMenu:Trigger>
<twig:Button variant="ghost" size="sm" {{ ...navigation_menu_trigger_attrs }}>
רכיבים
<twig:ux:icon name="lucide:chevron-down" class="relative top-px size-3 transition-transform duration-200 in-data-[state=open]:rotate-180" aria-hidden="true" />
</twig:Button>
</twig:NavigationMenu:Trigger>
<twig:NavigationMenu:Content>
<ul class="grid gap-2 w-[500px] grid-cols-2">
{% set components_he = [
{title: 'דיאלוג התראה', href: '/docs/primitives/alert-dialog', description: 'דיאלוג מודאלי שמפריע למשתמש עם תוכן חשוב ומצפה לתגובה.'},
{title: 'כרטיס ריחוף', href: '/docs/primitives/hover-card', description: 'למשתמשים רואים כדי להציג תצוגה מקדימה של תוכן זמין מאחורי קישור.'},
{title: 'התקדמות', href: '/docs/primitives/progress', description: 'מציג אינדיקטור המציג את התקדמות ההשלמה של משימה, בדרך כלל מוצג כסרגל התקדמות.'},
{title: 'אזור גלילה', href: '/docs/primitives/scroll-area', description: 'מפריד תוכן חזותית או סמנטית.'},
{title: 'כרטיסיות', href: '/docs/primitives/tabs', description: 'קבוצה של חלקי תוכן מרובדים—המכונים לוחות כרטיסיות—המוצגים אחד בכל פעם.'},
{title: 'טולטיפ', href: '/docs/primitives/tooltip', description: 'חלון קופץ המציג מידע הקשור לאלמנט כאשר העכבר מרחף מעליו.'},
] %}
{% for c in components_he %}
<li>
<a class="block rounded-md p-3 hover:bg-accent" href="{{ c.href }}">
<div class="text-sm font-medium leading-none">{{ c.title }}</div>
<p class="line-clamp-2 text-sm text-muted-foreground">{{ c.description }}</p>
</a>
</li>
{% endfor %}
</ul>
</twig:NavigationMenu:Content>
</twig:NavigationMenu:Item>
<twig:NavigationMenu:Item>
<twig:NavigationMenu:Link href="/docs">תיעוד</twig:NavigationMenu:Link>
</twig:NavigationMenu:Item>
</twig:NavigationMenu:List>
</twig:NavigationMenu>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<twig:NavigationMenu>
<twig:NavigationMenu:List>
<twig:NavigationMenu:Item>
<twig:NavigationMenu:Link href="/">Home</twig:NavigationMenu:Link>
</twig:NavigationMenu:Item>
<twig:NavigationMenu:Item>
<twig:NavigationMenu:Link href="/docs">Docs</twig:NavigationMenu:Link>
</twig:NavigationMenu:Item>
</twig:NavigationMenu:List>
</twig:NavigationMenu>
13 changes: 13 additions & 0 deletions src/Toolkit/kits/shadcn/navigation-menu/manifest.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"$schema": "../../../schema-kit-recipe-v1.json",
"type": "component",
"name": "Navigation Menu",
"description": "A collection of navigation links with optional hover-triggered submenus.",
"copy-files": {
"assets/": "assets/",
"templates/": "templates/"
},
"dependencies": {
"composer": ["tales-from-a-dev/twig-tailwind-extra:^1.0.0"]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{# @block content A `NavigationMenu:List` containing `NavigationMenu:Item` children #}
<nav
class="{{ ('relative flex max-w-max flex-1 items-center justify-center ' ~ attributes.render('class'))|tailwind_merge }}"
{{ attributes.defaults({
'data-slot': 'navigation-menu',
'aria-label': 'Main',
}) }}
>
{%- block content %}{% endblock -%}
</nav>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{# @block content The submenu revealed on hover or focus #}
<div
class="{{ ('invisible opacity-0 in-data-[state=open]:visible in-data-[state=open]:opacity-100 transition-opacity absolute start-0 top-full z-50 min-w-48 rounded-md border bg-popover p-2 text-popover-foreground shadow-md ' ~ attributes.render('class'))|tailwind_merge }}"
{{ attributes.defaults({
'data-slot': 'navigation-menu-content',
}) }}
>
{%- block content %}{% endblock -%}
</div>
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{# @prop openDelay number Delay in milliseconds before showing the submenu. Defaults to `0` #}
{# @prop closeDelay number Delay in milliseconds before hiding the submenu. Defaults to `0` #}
{# @block content The trigger and optional submenu content #}
{%- props openDelay = 0, closeDelay = 0 -%}
<li
class="{{ ('relative ' ~ attributes.render('class'))|tailwind_merge }}"
{{ attributes.defaults({
'data-slot': 'navigation-menu-item',
'data-controller': 'navigation-menu',
'data-navigation-menu-open-delay-value': openDelay,
'data-navigation-menu-close-delay-value': closeDelay,
'data-action': 'mouseenter->navigation-menu#show mouseleave->navigation-menu#hide',
}) }}
>
{%- block content %}{% endblock -%}
</li>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{# @prop href string Target URL #}
{# @block content The link label #}
{%- props href -%}
<a
href="{{ href }}"
class="{{ ('inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 ' ~ attributes.render('class'))|tailwind_merge }}"
{{ attributes.defaults({
'data-slot': 'navigation-menu-link',
}) }}
>
{%- block content %}{% endblock -%}
</a>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{# @block content The `NavigationMenu:Item` children #}
<ul
class="{{ ('group flex flex-1 list-none items-center justify-center gap-1 ' ~ attributes.render('class'))|tailwind_merge }}"
{{ attributes.defaults({
'data-slot': 'navigation-menu-list',
}) }}
>
{%- block content %}{% endblock -%}
</ul>
Loading
Loading