@yatoday/astro-ui 0.17.32 → 0.18.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/astro.d.ts +3 -0
- package/astro.js +2 -0
- package/components/Image/Image.astro +1 -1
- package/components/WidgetNavbar/WidgetNavbar.astro +97 -5
- package/components/WidgetNavbar/types.ts +13 -0
- package/components/WidgetNavbarFlyout/WidgetNavbarFlyout.astro +576 -0
- package/package.json +1 -1
- package/styles/styles.css +96 -0
- package/svelte.d.ts +3 -0
package/astro.d.ts
CHANGED
|
@@ -48,6 +48,7 @@ import type { WidgetHero1Props as YtWidgetHero1Props } from './components/Widget
|
|
|
48
48
|
import type { WidgetHero2Props as YtWidgetHero2Props } from './components/WidgetHero2/types'
|
|
49
49
|
import type { WidgetHeroSliderProps as YtWidgetHeroSliderProps } from './components/WidgetHeroSlider/types'
|
|
50
50
|
import type { WidgetNavbarProps as YtWidgetNavbarProps } from './components/WidgetNavbar/types'
|
|
51
|
+
import type { WidgetNavbarFlyoutProps as YtWidgetNavbarFlyoutProps } from './components/WidgetNavbarFlyout/types'
|
|
51
52
|
import type { WidgetStatsProps as YtWidgetStatsProps } from './components/WidgetStats/types'
|
|
52
53
|
import type { WidgetSteps1Props as YtWidgetSteps1Props } from './components/WidgetSteps1/types'
|
|
53
54
|
import type { WidgetStepsTimelineProps as YtWidgetStepsTimelineProps } from './components/WidgetStepsTimeline/types'
|
|
@@ -107,6 +108,7 @@ declare module '@yatoday/astro-ui/astro' {
|
|
|
107
108
|
export function WidgetHero2(_props: YtWidgetHero2Props): any
|
|
108
109
|
export function WidgetHeroSlider(_props: YtWidgetHeroSliderProps): any
|
|
109
110
|
export function WidgetNavbar(_props: YtWidgetNavbarProps): any
|
|
111
|
+
export function WidgetNavbarFlyout(_props: YtWidgetNavbarFlyoutProps): any
|
|
110
112
|
export function WidgetStats(_props: YtWidgetStatsProps): any
|
|
111
113
|
export function WidgetSteps1(_props: YtWidgetSteps1Props): any
|
|
112
114
|
export function WidgetStepsTimeline(_props: YtWidgetStepsTimelineProps): any
|
|
@@ -165,6 +167,7 @@ declare module '@yatoday/astro-ui/astro' {
|
|
|
165
167
|
export type WidgetHero2Props = YtWidgetHero2Props
|
|
166
168
|
export type WidgetHeroSliderProps = YtWidgetHeroSliderProps
|
|
167
169
|
export type WidgetNavbarProps = YtWidgetNavbarProps
|
|
170
|
+
export type WidgetNavbarFlyoutProps = YtWidgetNavbarFlyoutProps
|
|
168
171
|
export type WidgetStatsProps = YtWidgetStatsProps
|
|
169
172
|
export type WidgetSteps1Props = YtWidgetSteps1Props
|
|
170
173
|
export type WidgetStepsTimelineProps = YtWidgetStepsTimelineProps
|
package/astro.js
CHANGED
|
@@ -48,6 +48,7 @@ import WidgetHero1Component from './components/WidgetHero1/WidgetHero1.astro'
|
|
|
48
48
|
import WidgetHero2Component from './components/WidgetHero2/WidgetHero2.astro'
|
|
49
49
|
import WidgetHeroSliderComponent from './components/WidgetHeroSlider/WidgetHeroSlider.astro'
|
|
50
50
|
import WidgetNavbarComponent from './components/WidgetNavbar/WidgetNavbar.astro'
|
|
51
|
+
import WidgetNavbarFlyoutComponent from './components/WidgetNavbarFlyout/WidgetNavbarFlyout.astro'
|
|
51
52
|
import WidgetStatsComponent from './components/WidgetStats/WidgetStats.astro'
|
|
52
53
|
import WidgetSteps1Component from './components/WidgetSteps1/WidgetSteps1.astro'
|
|
53
54
|
import WidgetStepsTimelineComponent from './components/WidgetStepsTimeline/WidgetStepsTimeline.astro'
|
|
@@ -106,6 +107,7 @@ export const WidgetHero1 = WidgetHero1Component
|
|
|
106
107
|
export const WidgetHero2 = WidgetHero2Component
|
|
107
108
|
export const WidgetHeroSlider = WidgetHeroSliderComponent
|
|
108
109
|
export const WidgetNavbar = WidgetNavbarComponent
|
|
110
|
+
export const WidgetNavbarFlyout = WidgetNavbarFlyoutComponent
|
|
109
111
|
export const WidgetStats = WidgetStatsComponent
|
|
110
112
|
export const WidgetSteps1 = WidgetSteps1Component
|
|
111
113
|
export const WidgetStepsTimeline = WidgetStepsTimelineComponent
|
|
@@ -30,6 +30,8 @@ const {
|
|
|
30
30
|
links: linksClass = 'hover:text-link dark:hover:text-white',
|
|
31
31
|
dropdown: dropdownClass = 'bg-background text-foreground md:shadow-lg',
|
|
32
32
|
dropdownLinks: dropdownLinksClass = 'hover:bg-black/10 hover:text-link dark:hover:text-white dark:hover:bg-white/10',
|
|
33
|
+
megaMenu: megaMenuClass = 'bg-background text-foreground md:shadow-lg',
|
|
34
|
+
megaHeading: megaHeadingClass = 'text-foreground/50',
|
|
33
35
|
darkModeIcon: darkModeIconClass = '',
|
|
34
36
|
pinned: pinnedClasses = 'bg-background md:bg-background/90 md:backdrop-blur-md',
|
|
35
37
|
unpinned: unpinnedClasses = '',
|
|
@@ -81,9 +83,82 @@ const currentPath = `/${trimSlash(new URL(Astro.url).pathname)}`;
|
|
|
81
83
|
class="flex flex-col md:flex-row md:self-center w-full md:w-auto text-xl md:text-[0.9375rem] tracking-[0.01rem] font-medium md:justify-center"
|
|
82
84
|
>
|
|
83
85
|
{
|
|
84
|
-
links.map(({ text, href, links }) => (
|
|
86
|
+
links.map(({ text, href, links, mega, icon }) => (
|
|
85
87
|
<li class={links?.length ? 'dropdown' : ''}>
|
|
86
|
-
{links?.length ? (
|
|
88
|
+
{links?.length && mega ? (
|
|
89
|
+
<>
|
|
90
|
+
<button
|
|
91
|
+
type="button"
|
|
92
|
+
class={cn('px-4 py-3 flex items-center whitespace-nowrap cursor-pointer', linksClass)}
|
|
93
|
+
>
|
|
94
|
+
{text}{' '}
|
|
95
|
+
<Icon name="tabler:chevron-down" class="w-3.5 h-3.5 ml-0.5 rtl:ml-0 rtl:mr-0.5 hidden md:inline" />
|
|
96
|
+
</button>
|
|
97
|
+
<div
|
|
98
|
+
class={cn(
|
|
99
|
+
'dropdown-menu rounded-sm md:absolute md:left-0 md:right-0 md:top-full pl-4 md:pl-0 pb-1 md:pb-0 md:hidden font-medium',
|
|
100
|
+
megaMenuClass
|
|
101
|
+
)}
|
|
102
|
+
>
|
|
103
|
+
<div class="mega-grid md:grid md:gap-x-8 md:gap-y-4 md:p-8" style={`--mega-cols: ${links.length}`}>
|
|
104
|
+
{links.map((column) => (
|
|
105
|
+
<div class="py-2 md:py-0">
|
|
106
|
+
{column.href ? (
|
|
107
|
+
<a
|
|
108
|
+
href={column.href}
|
|
109
|
+
class={cn(
|
|
110
|
+
'flex items-center gap-1.5 mb-2 text-xs font-semibold uppercase tracking-wider hover:text-link',
|
|
111
|
+
megaHeadingClass
|
|
112
|
+
)}
|
|
113
|
+
>
|
|
114
|
+
{column.icon && <Icon name={column.icon} class="w-4 h-4" />}
|
|
115
|
+
{column.text}
|
|
116
|
+
</a>
|
|
117
|
+
) : (
|
|
118
|
+
<span
|
|
119
|
+
class={cn(
|
|
120
|
+
'flex items-center gap-1.5 mb-2 text-xs font-semibold uppercase tracking-wider',
|
|
121
|
+
megaHeadingClass
|
|
122
|
+
)}
|
|
123
|
+
>
|
|
124
|
+
{column.icon && <Icon name={column.icon} class="w-4 h-4" />}
|
|
125
|
+
{column.text}
|
|
126
|
+
</span>
|
|
127
|
+
)}
|
|
128
|
+
<ul class="flex flex-col">
|
|
129
|
+
{column.links?.map(({ text: text2, href: href2, icon: icon2, description }) => (
|
|
130
|
+
<li>
|
|
131
|
+
<a
|
|
132
|
+
class={cn(
|
|
133
|
+
'group flex items-start gap-3 rounded-md py-2 px-3 -mx-3 md:px-2 md:-mx-2',
|
|
134
|
+
{ 'link-active': href2 === currentPath },
|
|
135
|
+
dropdownLinksClass
|
|
136
|
+
)}
|
|
137
|
+
href={href2}
|
|
138
|
+
>
|
|
139
|
+
{icon2 && (
|
|
140
|
+
<span class="flex-none mt-0.5 flex items-center justify-center w-8 h-8 rounded-md bg-foreground/[0.06] text-foreground/70 group-hover:bg-foreground/10">
|
|
141
|
+
<Icon name={icon2} class="w-4.5 h-4.5" />
|
|
142
|
+
</span>
|
|
143
|
+
)}
|
|
144
|
+
<span class="flex flex-col">
|
|
145
|
+
<span class="font-medium leading-tight">{text2}</span>
|
|
146
|
+
{description && (
|
|
147
|
+
<span class="mt-0.5 text-xs font-normal text-muted-foreground leading-snug normal-case">
|
|
148
|
+
{description}
|
|
149
|
+
</span>
|
|
150
|
+
)}
|
|
151
|
+
</span>
|
|
152
|
+
</a>
|
|
153
|
+
</li>
|
|
154
|
+
))}
|
|
155
|
+
</ul>
|
|
156
|
+
</div>
|
|
157
|
+
))}
|
|
158
|
+
</div>
|
|
159
|
+
</div>
|
|
160
|
+
</>
|
|
161
|
+
) : links?.length ? (
|
|
87
162
|
<>
|
|
88
163
|
<button
|
|
89
164
|
type="button"
|
|
@@ -117,12 +192,13 @@ const currentPath = `/${trimSlash(new URL(Astro.url).pathname)}`;
|
|
|
117
192
|
) : (
|
|
118
193
|
<a
|
|
119
194
|
class={cn([
|
|
120
|
-
'px-4 py-3 flex items-center whitespace-nowrap',
|
|
195
|
+
'px-4 py-3 flex items-center gap-1.5 whitespace-nowrap',
|
|
121
196
|
{ 'link-active': href === currentPath },
|
|
122
197
|
linksClass,
|
|
123
198
|
])}
|
|
124
199
|
href={href}
|
|
125
200
|
>
|
|
201
|
+
{icon && <Icon name={icon} class="w-4 h-4" />}
|
|
126
202
|
{text}
|
|
127
203
|
</a>
|
|
128
204
|
)}
|
|
@@ -140,7 +216,14 @@ const currentPath = `/${trimSlash(new URL(Astro.url).pathname)}`;
|
|
|
140
216
|
>
|
|
141
217
|
<div class="items-center flex justify-between w-full md:w-auto">
|
|
142
218
|
<div class="flex">
|
|
143
|
-
{
|
|
219
|
+
{
|
|
220
|
+
showToggleTheme && (
|
|
221
|
+
<DarkMode
|
|
222
|
+
initialMode={initialMode}
|
|
223
|
+
iconClass={cn('w-6 h-6 md:w-5 md:h-5 md:inline-block', darkModeIconClass)}
|
|
224
|
+
/>
|
|
225
|
+
)
|
|
226
|
+
}
|
|
144
227
|
</div>
|
|
145
228
|
|
|
146
229
|
<!-- Actions Buttons -->
|
|
@@ -149,7 +232,10 @@ const currentPath = `/${trimSlash(new URL(Astro.url).pathname)}`;
|
|
|
149
232
|
actions?.length ? (
|
|
150
233
|
<span class="ml-4 rtl:ml-0 rtl:mr-4">
|
|
151
234
|
{actions.map(({ class: actionClass, ...btnProps }) => (
|
|
152
|
-
<Button
|
|
235
|
+
<Button
|
|
236
|
+
{...btnProps}
|
|
237
|
+
class={cn('ml-2 py-2.5 px-5.5 md:px-6 font-semibold shadow-none text-sm w-auto', actionClass)}
|
|
238
|
+
/>
|
|
153
239
|
))}
|
|
154
240
|
</span>
|
|
155
241
|
) : (
|
|
@@ -177,6 +263,12 @@ const currentPath = `/${trimSlash(new URL(Astro.url).pathname)}`;
|
|
|
177
263
|
.dropdown:hover .dropdown-menu {
|
|
178
264
|
display: block;
|
|
179
265
|
}
|
|
266
|
+
|
|
267
|
+
@media (min-width: 768px) {
|
|
268
|
+
.mega-grid {
|
|
269
|
+
grid-template-columns: repeat(var(--mega-cols, 3), minmax(0, 1fr));
|
|
270
|
+
}
|
|
271
|
+
}
|
|
180
272
|
</style>
|
|
181
273
|
|
|
182
274
|
<script>
|
|
@@ -20,10 +20,23 @@ export interface ILink {
|
|
|
20
20
|
href?: string;
|
|
21
21
|
ariaLabel?: string;
|
|
22
22
|
icon?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Optional one-line supporting text. In a mega panel, leaf items with a
|
|
25
|
+
* `description` render Stripe-style: an icon tile, a bold title, and this
|
|
26
|
+
* muted subtitle beneath it. Ignored by regular dropdowns.
|
|
27
|
+
*/
|
|
28
|
+
description?: string;
|
|
23
29
|
}
|
|
24
30
|
|
|
25
31
|
export interface IMenuLink extends ILink {
|
|
26
32
|
links?: IMenuLink[];
|
|
33
|
+
/**
|
|
34
|
+
* When true on a top-level item, its `links` are rendered as a full-width
|
|
35
|
+
* multi-column mega panel: each child becomes a column whose `text`/`href`
|
|
36
|
+
* is the column heading and whose nested `links` are the column items.
|
|
37
|
+
* Defaults to a standard single-column dropdown.
|
|
38
|
+
*/
|
|
39
|
+
mega?: boolean;
|
|
27
40
|
}
|
|
28
41
|
|
|
29
42
|
export type SvelteWidgetNavbarProps = {
|
|
@@ -0,0 +1,576 @@
|
|
|
1
|
+
---
|
|
2
|
+
/**
|
|
3
|
+
* WidgetNavbarFlyout
|
|
4
|
+
*
|
|
5
|
+
* A navbar whose dropdowns share a single, persistent flyout panel that stays
|
|
6
|
+
* open and smoothly morphs (width / height / horizontal position) as the cursor
|
|
7
|
+
* moves between top-level items — the Stripe "one container that resizes"
|
|
8
|
+
* pattern — instead of each menu abruptly closing and the next one opening.
|
|
9
|
+
*
|
|
10
|
+
* Any top-level item with `links` becomes a flyout panel. Items flagged `mega`
|
|
11
|
+
* render multi-column Stripe-style rows (icon tile + title + description);
|
|
12
|
+
* plain items render a single-column list. Desktop interaction is JS-driven
|
|
13
|
+
* (hover with open/close delays, keyboard + Escape, outside-click). Mobile keeps
|
|
14
|
+
* an always-expanded accordion and needs no JS.
|
|
15
|
+
*
|
|
16
|
+
* Drop-in compatible with WidgetNavbar's props and slots.
|
|
17
|
+
*/
|
|
18
|
+
import type { WidgetNavbarProps as Props } from '../WidgetNavbar/types';
|
|
19
|
+
|
|
20
|
+
import { SITE } from 'vendor:config';
|
|
21
|
+
import { Icon } from 'astro-icon/components';
|
|
22
|
+
import DarkMode from '../DarkMode/DarkMode.astro';
|
|
23
|
+
import ToggleMenu from '../WidgetNavbar/ToggleMenu.astro';
|
|
24
|
+
import Button from '../Button/Button.astro';
|
|
25
|
+
import WidgetWrapper from '../WidgetWrapper/WidgetWrapper.astro';
|
|
26
|
+
import { cn, trimSlash } from '../../utils';
|
|
27
|
+
import { twMerge } from 'tailwind-merge';
|
|
28
|
+
|
|
29
|
+
const {
|
|
30
|
+
links = [],
|
|
31
|
+
actions = [],
|
|
32
|
+
isSticky = false,
|
|
33
|
+
isDark = false,
|
|
34
|
+
showToggleTheme = false,
|
|
35
|
+
initialMode = 'system',
|
|
36
|
+
position = 'center',
|
|
37
|
+
classes = {},
|
|
38
|
+
scrollOffset = 60,
|
|
39
|
+
as = 'header',
|
|
40
|
+
bg = await Astro.slots.render('bg'),
|
|
41
|
+
} = Astro.props;
|
|
42
|
+
|
|
43
|
+
const {
|
|
44
|
+
header: headerClass = '',
|
|
45
|
+
container: containerClass = 'max-w-7xl 2xl:max-w-[96rem] md:mx-auto',
|
|
46
|
+
links: linksClass = 'hover:text-link dark:hover:text-white',
|
|
47
|
+
dropdownLinks: dropdownLinksClass = 'hover:bg-black/10 hover:text-link dark:hover:text-white dark:hover:bg-white/10',
|
|
48
|
+
megaMenu: megaMenuClass = 'bg-background text-foreground md:shadow-lg',
|
|
49
|
+
megaHeading: megaHeadingClass = 'text-foreground/50',
|
|
50
|
+
darkModeIcon: darkModeIconClass = '',
|
|
51
|
+
pinned: pinnedClasses = 'bg-background md:bg-background/90 md:backdrop-blur-md',
|
|
52
|
+
unpinned: unpinnedClasses = '',
|
|
53
|
+
} = classes;
|
|
54
|
+
|
|
55
|
+
const currentPath = `/${trimSlash(new URL(Astro.url).pathname)}`;
|
|
56
|
+
|
|
57
|
+
// Top-level items that get a shared flyout panel (anything with children).
|
|
58
|
+
const panelItems = links.map((link, index) => ({ link, index })).filter(({ link }) => link.links?.length);
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
<WidgetWrapper
|
|
62
|
+
id="header"
|
|
63
|
+
isDark={isDark}
|
|
64
|
+
bg={bg}
|
|
65
|
+
as={as}
|
|
66
|
+
class={cn(
|
|
67
|
+
{ sticky: isSticky, relative: !isSticky, dark: isDark },
|
|
68
|
+
'-top-[1px] z-40 flex-none w-full transition-[opacity] ease-in-out',
|
|
69
|
+
headerClass,
|
|
70
|
+
unpinnedClasses
|
|
71
|
+
)}
|
|
72
|
+
containerClass={twMerge('py-0 md:py-0 lg:py-0', containerClass)}
|
|
73
|
+
{...isSticky ? { 'data-yt-sticky-header': true } : {}}
|
|
74
|
+
data-scroll-offset={scrollOffset}
|
|
75
|
+
data-pinned-classes={pinnedClasses}
|
|
76
|
+
data-unpinned-classes={unpinnedClasses}
|
|
77
|
+
data-yt-flyout-header
|
|
78
|
+
>
|
|
79
|
+
<div
|
|
80
|
+
class={cn(
|
|
81
|
+
'relative text-default py-3 mx-auto w-full',
|
|
82
|
+
{ 'md:flex md:justify-between': position !== 'center' },
|
|
83
|
+
{ 'md:grid md:grid-cols-3 md:items-center': position === 'center' }
|
|
84
|
+
)}
|
|
85
|
+
>
|
|
86
|
+
<div class:list={[{ 'mr-auto rtl:mr-0 rtl:ml-auto': position === 'right' }, 'flex justify-between items-center']}>
|
|
87
|
+
<!-- Logo -->
|
|
88
|
+
<slot name="logo">
|
|
89
|
+
<span>{SITE.name || 'Logo'}</span>
|
|
90
|
+
</slot>
|
|
91
|
+
<div class="flex items-center md:hidden">
|
|
92
|
+
<slot name="toggle-menu">
|
|
93
|
+
<ToggleMenu />
|
|
94
|
+
</slot>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
|
|
98
|
+
<nav
|
|
99
|
+
class="items-center w-full md:w-auto hidden md:flex md:mx-5 text-default overflow-y-auto overflow-x-hidden md:overflow-y-visible md:overflow-x-auto md:justify-self-center"
|
|
100
|
+
aria-label="Main navigation"
|
|
101
|
+
data-yt-flyout-nav
|
|
102
|
+
>
|
|
103
|
+
<ul
|
|
104
|
+
class="flex flex-col md:flex-row md:self-center w-full md:w-auto text-xl md:text-[0.9375rem] tracking-[0.01rem] font-medium md:justify-center"
|
|
105
|
+
>
|
|
106
|
+
{
|
|
107
|
+
links.map((item, index) => {
|
|
108
|
+
const hasPanel = !!item.links?.length;
|
|
109
|
+
return (
|
|
110
|
+
<li class="md:static">
|
|
111
|
+
{/* Desktop trigger / link */}
|
|
112
|
+
{hasPanel ? (
|
|
113
|
+
<button
|
|
114
|
+
type="button"
|
|
115
|
+
data-flyout-trigger
|
|
116
|
+
data-flyout-key={index}
|
|
117
|
+
aria-haspopup="true"
|
|
118
|
+
aria-expanded="false"
|
|
119
|
+
class={cn('hidden md:flex px-4 py-3 items-center whitespace-nowrap cursor-pointer', linksClass)}
|
|
120
|
+
>
|
|
121
|
+
{item.text}{' '}
|
|
122
|
+
<Icon name="tabler:chevron-down" class="w-3.5 h-3.5 ml-0.5 rtl:ml-0 rtl:mr-0.5" />
|
|
123
|
+
</button>
|
|
124
|
+
) : (
|
|
125
|
+
<a
|
|
126
|
+
href={item.href}
|
|
127
|
+
data-flyout-dismiss
|
|
128
|
+
class={cn(
|
|
129
|
+
'hidden md:flex px-4 py-3 items-center gap-1.5 whitespace-nowrap',
|
|
130
|
+
{ 'link-active': item.href === currentPath },
|
|
131
|
+
linksClass
|
|
132
|
+
)}
|
|
133
|
+
>
|
|
134
|
+
{item.icon && <Icon name={item.icon} class="w-4 h-4" />}
|
|
135
|
+
{item.text}
|
|
136
|
+
</a>
|
|
137
|
+
)}
|
|
138
|
+
|
|
139
|
+
{/* Mobile accordion (always expanded, no JS required) */}
|
|
140
|
+
<div class="md:hidden">
|
|
141
|
+
{hasPanel ? (
|
|
142
|
+
<>
|
|
143
|
+
<span class={cn('block px-4 py-3 text-base font-semibold uppercase tracking-wider', megaHeadingClass)}>
|
|
144
|
+
{item.text}
|
|
145
|
+
</span>
|
|
146
|
+
<ul class="flex flex-col pb-2">
|
|
147
|
+
{item.mega
|
|
148
|
+
? item.links?.flatMap((column) =>
|
|
149
|
+
(column.links ?? []).map((leaf) => (
|
|
150
|
+
<li>
|
|
151
|
+
<a
|
|
152
|
+
href={leaf.href}
|
|
153
|
+
class={cn(
|
|
154
|
+
'block rounded-sm py-2 px-6 text-base',
|
|
155
|
+
{ 'link-active': leaf.href === currentPath },
|
|
156
|
+
dropdownLinksClass
|
|
157
|
+
)}
|
|
158
|
+
>
|
|
159
|
+
{leaf.text}
|
|
160
|
+
</a>
|
|
161
|
+
</li>
|
|
162
|
+
))
|
|
163
|
+
)
|
|
164
|
+
: item.links?.map((leaf) => (
|
|
165
|
+
<li>
|
|
166
|
+
<a
|
|
167
|
+
href={leaf.href}
|
|
168
|
+
class={cn(
|
|
169
|
+
'block rounded-sm py-2 px-6 text-base',
|
|
170
|
+
{ 'link-active': leaf.href === currentPath },
|
|
171
|
+
dropdownLinksClass
|
|
172
|
+
)}
|
|
173
|
+
>
|
|
174
|
+
{leaf.text}
|
|
175
|
+
</a>
|
|
176
|
+
</li>
|
|
177
|
+
))}
|
|
178
|
+
</ul>
|
|
179
|
+
</>
|
|
180
|
+
) : (
|
|
181
|
+
<a
|
|
182
|
+
href={item.href}
|
|
183
|
+
class={cn('block px-4 py-3 text-xl', { 'link-active': item.href === currentPath })}
|
|
184
|
+
>
|
|
185
|
+
{item.text}
|
|
186
|
+
</a>
|
|
187
|
+
)}
|
|
188
|
+
</div>
|
|
189
|
+
</li>
|
|
190
|
+
);
|
|
191
|
+
})
|
|
192
|
+
}
|
|
193
|
+
</ul>
|
|
194
|
+
</nav>
|
|
195
|
+
|
|
196
|
+
{/* Shared morphing flyout (desktop only) */}
|
|
197
|
+
{
|
|
198
|
+
panelItems.length > 0 && (
|
|
199
|
+
<div
|
|
200
|
+
class="flyout hidden md:block absolute left-0 right-0 top-full z-40"
|
|
201
|
+
data-flyout
|
|
202
|
+
role="region"
|
|
203
|
+
aria-label="Menu details"
|
|
204
|
+
>
|
|
205
|
+
<div class={cn('flyout-bg relative overflow-hidden rounded-xl border border-border', megaMenuClass)} data-flyout-bg>
|
|
206
|
+
{panelItems.map(({ link, index }) => (
|
|
207
|
+
<div class="flyout-panel absolute top-0 left-0" data-flyout-panel data-flyout-key={index}>
|
|
208
|
+
{link.mega ? (
|
|
209
|
+
<div class="flex gap-8 p-8">
|
|
210
|
+
{link.links?.map((column) => (
|
|
211
|
+
<div class="min-w-[12rem]">
|
|
212
|
+
{column.href ? (
|
|
213
|
+
<a
|
|
214
|
+
href={column.href}
|
|
215
|
+
class={cn(
|
|
216
|
+
'flex items-center gap-1.5 mb-2 text-xs font-semibold uppercase tracking-wider hover:text-link',
|
|
217
|
+
megaHeadingClass
|
|
218
|
+
)}
|
|
219
|
+
>
|
|
220
|
+
{column.icon && <Icon name={column.icon} class="w-4 h-4" />}
|
|
221
|
+
{column.text}
|
|
222
|
+
</a>
|
|
223
|
+
) : (
|
|
224
|
+
<span
|
|
225
|
+
class={cn(
|
|
226
|
+
'flex items-center gap-1.5 mb-2 text-xs font-semibold uppercase tracking-wider',
|
|
227
|
+
megaHeadingClass
|
|
228
|
+
)}
|
|
229
|
+
>
|
|
230
|
+
{column.icon && <Icon name={column.icon} class="w-4 h-4" />}
|
|
231
|
+
{column.text}
|
|
232
|
+
</span>
|
|
233
|
+
)}
|
|
234
|
+
<ul class="flex flex-col">
|
|
235
|
+
{column.links?.map((leaf) => (
|
|
236
|
+
<li>
|
|
237
|
+
<a
|
|
238
|
+
href={leaf.href}
|
|
239
|
+
class={cn(
|
|
240
|
+
'group flex items-start gap-3 rounded-md py-2 px-2 -mx-2',
|
|
241
|
+
{ 'link-active': leaf.href === currentPath },
|
|
242
|
+
dropdownLinksClass
|
|
243
|
+
)}
|
|
244
|
+
>
|
|
245
|
+
{leaf.icon && (
|
|
246
|
+
<span class="flex-none mt-0.5 flex items-center justify-center w-8 h-8 rounded-md bg-foreground/[0.06] text-foreground/70 group-hover:bg-foreground/10">
|
|
247
|
+
<Icon name={leaf.icon} class="w-4.5 h-4.5" />
|
|
248
|
+
</span>
|
|
249
|
+
)}
|
|
250
|
+
<span class="flex flex-col">
|
|
251
|
+
<span class="font-medium leading-tight whitespace-nowrap">{leaf.text}</span>
|
|
252
|
+
{leaf.description && (
|
|
253
|
+
<span class="mt-0.5 text-xs font-normal text-muted-foreground leading-snug normal-case whitespace-nowrap">
|
|
254
|
+
{leaf.description}
|
|
255
|
+
</span>
|
|
256
|
+
)}
|
|
257
|
+
</span>
|
|
258
|
+
</a>
|
|
259
|
+
</li>
|
|
260
|
+
))}
|
|
261
|
+
</ul>
|
|
262
|
+
</div>
|
|
263
|
+
))}
|
|
264
|
+
</div>
|
|
265
|
+
) : (
|
|
266
|
+
<ul class="flex flex-col p-3 min-w-[14rem]">
|
|
267
|
+
{link.links?.map((leaf) => (
|
|
268
|
+
<li>
|
|
269
|
+
<a
|
|
270
|
+
href={leaf.href}
|
|
271
|
+
class={cn(
|
|
272
|
+
'flex items-center gap-2 rounded-md py-2 px-3 whitespace-nowrap',
|
|
273
|
+
{ 'link-active': leaf.href === currentPath },
|
|
274
|
+
dropdownLinksClass
|
|
275
|
+
)}
|
|
276
|
+
>
|
|
277
|
+
{leaf.icon && <Icon name={leaf.icon} class="w-4 h-4 opacity-70" />}
|
|
278
|
+
{leaf.text}
|
|
279
|
+
</a>
|
|
280
|
+
</li>
|
|
281
|
+
))}
|
|
282
|
+
</ul>
|
|
283
|
+
)}
|
|
284
|
+
</div>
|
|
285
|
+
))}
|
|
286
|
+
</div>
|
|
287
|
+
</div>
|
|
288
|
+
)
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
<div
|
|
292
|
+
class:list={[
|
|
293
|
+
{ 'ml-auto rtl:ml-0 rtl:mr-auto': position === 'left' },
|
|
294
|
+
'hidden md:self-center md:flex items-center md:mb-0 fixed w-full md:w-auto md:static justify-end left-0 rtl:left-auto rtl:right-0 bottom-0 p-3 md:p-0 md:justify-self-end',
|
|
295
|
+
]}
|
|
296
|
+
data-yt-actions
|
|
297
|
+
>
|
|
298
|
+
<div class="items-center flex justify-between w-full md:w-auto">
|
|
299
|
+
<div class="flex">
|
|
300
|
+
{showToggleTheme && (
|
|
301
|
+
<DarkMode initialMode={initialMode} iconClass={cn('w-6 h-6 md:w-5 md:h-5 md:inline-block', darkModeIconClass)} />
|
|
302
|
+
)}
|
|
303
|
+
</div>
|
|
304
|
+
|
|
305
|
+
<!-- Actions Buttons -->
|
|
306
|
+
<slot name="actions">
|
|
307
|
+
{
|
|
308
|
+
actions?.length ? (
|
|
309
|
+
<span class="ml-4 rtl:ml-0 rtl:mr-4">
|
|
310
|
+
{actions.map(({ class: actionClass, ...btnProps }) => (
|
|
311
|
+
<Button
|
|
312
|
+
{...btnProps}
|
|
313
|
+
class={cn('ml-2 py-2.5 px-5.5 md:px-6 font-semibold shadow-none text-sm w-auto', actionClass)}
|
|
314
|
+
/>
|
|
315
|
+
))}
|
|
316
|
+
</span>
|
|
317
|
+
) : (
|
|
318
|
+
''
|
|
319
|
+
)
|
|
320
|
+
}
|
|
321
|
+
</slot>
|
|
322
|
+
</div>
|
|
323
|
+
</div>
|
|
324
|
+
</div>
|
|
325
|
+
</WidgetWrapper>
|
|
326
|
+
|
|
327
|
+
<style>
|
|
328
|
+
#header.expanded nav {
|
|
329
|
+
position: fixed;
|
|
330
|
+
top: 100px;
|
|
331
|
+
left: 0;
|
|
332
|
+
right: 0;
|
|
333
|
+
bottom: 70px !important;
|
|
334
|
+
padding: 0 5px;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/* Flyout wrapper: fades + slides in, hidden (not just transparent) when closed
|
|
338
|
+
so it never intercepts clicks. */
|
|
339
|
+
.flyout {
|
|
340
|
+
opacity: 0;
|
|
341
|
+
visibility: hidden;
|
|
342
|
+
transform: translateY(6px);
|
|
343
|
+
transition:
|
|
344
|
+
opacity 0.18s ease,
|
|
345
|
+
transform 0.18s ease,
|
|
346
|
+
visibility 0s linear 0.18s;
|
|
347
|
+
}
|
|
348
|
+
.flyout.is-open {
|
|
349
|
+
opacity: 1;
|
|
350
|
+
visibility: visible;
|
|
351
|
+
transform: translateY(0);
|
|
352
|
+
transition:
|
|
353
|
+
opacity 0.18s ease,
|
|
354
|
+
transform 0.18s ease;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/* The visible box that morphs between panels. JS sets width/height/translateX. */
|
|
358
|
+
.flyout-bg {
|
|
359
|
+
width: 0;
|
|
360
|
+
height: 0;
|
|
361
|
+
transition:
|
|
362
|
+
width 0.28s cubic-bezier(0.4, 0, 0.2, 1),
|
|
363
|
+
height 0.28s cubic-bezier(0.4, 0, 0.2, 1),
|
|
364
|
+
transform 0.28s cubic-bezier(0.4, 0, 0.2, 1);
|
|
365
|
+
will-change: width, height, transform;
|
|
366
|
+
}
|
|
367
|
+
/* Suppress the size transition on first open so it doesn't grow from 0. */
|
|
368
|
+
.flyout.no-anim .flyout-bg {
|
|
369
|
+
transition: none;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/* Panels stack in the same spot and cross-fade. */
|
|
373
|
+
.flyout-panel {
|
|
374
|
+
opacity: 0;
|
|
375
|
+
pointer-events: none;
|
|
376
|
+
transition: opacity 0.16s ease;
|
|
377
|
+
}
|
|
378
|
+
.flyout-panel.is-active {
|
|
379
|
+
opacity: 1;
|
|
380
|
+
pointer-events: auto;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
@media (prefers-reduced-motion: reduce) {
|
|
384
|
+
.flyout,
|
|
385
|
+
.flyout-bg,
|
|
386
|
+
.flyout-panel {
|
|
387
|
+
transition-duration: 0.01ms;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
</style>
|
|
391
|
+
|
|
392
|
+
<script>
|
|
393
|
+
import { attachEvent, toggleClasses, addClasses, removeClasses } from '../../utils/DOMUtils';
|
|
394
|
+
|
|
395
|
+
// ---- Sticky header pin/unpin on scroll + mobile menu toggle (parity with WidgetNavbar) ----
|
|
396
|
+
let headerBound = false;
|
|
397
|
+
const addHeaderListeners = () => {
|
|
398
|
+
if (headerBound) return;
|
|
399
|
+
const header = document.querySelector('[data-yt-sticky-header]') as HTMLElement;
|
|
400
|
+
if (!header) return;
|
|
401
|
+
headerBound = true;
|
|
402
|
+
|
|
403
|
+
const scrollOffset = Number(header.dataset.scrollOffset) || 0;
|
|
404
|
+
const pinnedClasses = header.dataset.pinnedClasses || '';
|
|
405
|
+
const unpinnedClasses = header.dataset.unpinnedClasses || '';
|
|
406
|
+
|
|
407
|
+
let lastKnownScrollPosition = window.scrollY;
|
|
408
|
+
let ticking = true;
|
|
409
|
+
|
|
410
|
+
attachEvent('[data-yt-toggle-menu]', 'click', (_: Event, elem: HTMLElement) => {
|
|
411
|
+
requestAnimationFrame(() => {
|
|
412
|
+
toggleClasses(elem, 'expanded');
|
|
413
|
+
toggleClasses(document.body, 'overflow-hidden');
|
|
414
|
+
toggleClasses(document.getElementById('header'), 'h-screen', 'expanded');
|
|
415
|
+
toggleClasses('[data-yt-flyout-nav]', 'hidden');
|
|
416
|
+
toggleClasses('[data-yt-actions]', 'hidden');
|
|
417
|
+
});
|
|
418
|
+
});
|
|
419
|
+
|
|
420
|
+
attachEvent('[data-yt-flyout-nav]', 'click', () => hiddenNav());
|
|
421
|
+
attachEvent([window.matchMedia('(max-width: 767px)')], 'change', () => hiddenNav());
|
|
422
|
+
|
|
423
|
+
function hiddenNav() {
|
|
424
|
+
requestAnimationFrame(() => {
|
|
425
|
+
removeClasses('[data-yt-toggle-menu]', 'expanded');
|
|
426
|
+
removeClasses(document.body, 'overflow-hidden');
|
|
427
|
+
removeClasses(document.getElementById('header'), 'h-screen', 'expanded');
|
|
428
|
+
addClasses('[data-yt-flyout-nav]', 'hidden');
|
|
429
|
+
addClasses('[data-yt-actions]', 'hidden');
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
function applyHeaderStylesOnScroll() {
|
|
434
|
+
if (lastKnownScrollPosition > scrollOffset && !header.classList.contains('scroll')) {
|
|
435
|
+
addClasses(header, 'scroll', ...pinnedClasses.split(' '));
|
|
436
|
+
removeClasses(header, ...unpinnedClasses.split(' '));
|
|
437
|
+
} else if (lastKnownScrollPosition <= scrollOffset && header.classList.contains('scroll')) {
|
|
438
|
+
removeClasses(header, 'scroll', ...pinnedClasses.split(' '));
|
|
439
|
+
addClasses(header, ...unpinnedClasses.split(' '));
|
|
440
|
+
}
|
|
441
|
+
ticking = false;
|
|
442
|
+
}
|
|
443
|
+
applyHeaderStylesOnScroll();
|
|
444
|
+
|
|
445
|
+
attachEvent([document], 'scroll', function () {
|
|
446
|
+
lastKnownScrollPosition = window.scrollY;
|
|
447
|
+
if (!ticking) {
|
|
448
|
+
window.requestAnimationFrame(applyHeaderStylesOnScroll);
|
|
449
|
+
ticking = true;
|
|
450
|
+
}
|
|
451
|
+
});
|
|
452
|
+
};
|
|
453
|
+
|
|
454
|
+
// ---- Persistent morphing flyout ----
|
|
455
|
+
const initFlyout = (header: HTMLElement) => {
|
|
456
|
+
if (header.dataset.flyoutBound === 'true') return;
|
|
457
|
+
const positioner = header.querySelector('.relative') as HTMLElement | null;
|
|
458
|
+
const flyout = header.querySelector('[data-flyout]') as HTMLElement | null;
|
|
459
|
+
const bgEl = header.querySelector('[data-flyout-bg]') as HTMLElement | null;
|
|
460
|
+
if (!positioner || !flyout || !bgEl) return;
|
|
461
|
+
header.dataset.flyoutBound = 'true';
|
|
462
|
+
|
|
463
|
+
const triggers = Array.from(header.querySelectorAll<HTMLElement>('[data-flyout-trigger]'));
|
|
464
|
+
const panels = new Map<string, HTMLElement>();
|
|
465
|
+
flyout.querySelectorAll<HTMLElement>('[data-flyout-panel]').forEach((p) => {
|
|
466
|
+
panels.set(p.dataset.flyoutKey!, p);
|
|
467
|
+
});
|
|
468
|
+
|
|
469
|
+
let open = false;
|
|
470
|
+
let currentKey: string | null = null;
|
|
471
|
+
let closeTimer: number | undefined;
|
|
472
|
+
|
|
473
|
+
const triggerByKey = (key: string) => triggers.find((t) => t.dataset.flyoutKey === key) || null;
|
|
474
|
+
|
|
475
|
+
const sizeTo = (key: string) => {
|
|
476
|
+
const panel = panels.get(key);
|
|
477
|
+
const trigger = triggerByKey(key);
|
|
478
|
+
if (!panel) return;
|
|
479
|
+
const contWidth = positioner.clientWidth;
|
|
480
|
+
const w = Math.min(panel.offsetWidth, contWidth);
|
|
481
|
+
const h = panel.offsetHeight;
|
|
482
|
+
let x = 0;
|
|
483
|
+
if (trigger) {
|
|
484
|
+
const cont = positioner.getBoundingClientRect();
|
|
485
|
+
x = Math.max(0, Math.min(trigger.getBoundingClientRect().left - cont.left, contWidth - w));
|
|
486
|
+
}
|
|
487
|
+
bgEl.style.width = `${w}px`;
|
|
488
|
+
bgEl.style.height = `${h}px`;
|
|
489
|
+
bgEl.style.transform = `translateX(${x}px)`;
|
|
490
|
+
panels.forEach((p, k) => p.classList.toggle('is-active', k === key));
|
|
491
|
+
triggers.forEach((t) => t.setAttribute('aria-expanded', String(t.dataset.flyoutKey === key)));
|
|
492
|
+
currentKey = key;
|
|
493
|
+
};
|
|
494
|
+
|
|
495
|
+
const openTo = (key: string) => {
|
|
496
|
+
cancelClose();
|
|
497
|
+
if (key === currentKey && open) return;
|
|
498
|
+
if (!open) {
|
|
499
|
+
// First open: set the target size with no transition so it doesn't grow from 0.
|
|
500
|
+
flyout.classList.add('no-anim');
|
|
501
|
+
sizeTo(key);
|
|
502
|
+
void bgEl.offsetWidth; // force reflow
|
|
503
|
+
flyout.classList.remove('no-anim');
|
|
504
|
+
flyout.classList.add('is-open');
|
|
505
|
+
open = true;
|
|
506
|
+
} else {
|
|
507
|
+
sizeTo(key); // morph
|
|
508
|
+
}
|
|
509
|
+
};
|
|
510
|
+
|
|
511
|
+
const close = () => {
|
|
512
|
+
cancelClose();
|
|
513
|
+
if (!open) return;
|
|
514
|
+
flyout.classList.remove('is-open');
|
|
515
|
+
panels.forEach((p) => p.classList.remove('is-active'));
|
|
516
|
+
triggers.forEach((t) => t.setAttribute('aria-expanded', 'false'));
|
|
517
|
+
open = false;
|
|
518
|
+
currentKey = null;
|
|
519
|
+
};
|
|
520
|
+
|
|
521
|
+
const scheduleClose = () => {
|
|
522
|
+
cancelClose();
|
|
523
|
+
closeTimer = window.setTimeout(close, 140);
|
|
524
|
+
};
|
|
525
|
+
const cancelClose = () => {
|
|
526
|
+
if (closeTimer) {
|
|
527
|
+
clearTimeout(closeTimer);
|
|
528
|
+
closeTimer = undefined;
|
|
529
|
+
}
|
|
530
|
+
};
|
|
531
|
+
|
|
532
|
+
triggers.forEach((trigger) => {
|
|
533
|
+
const key = trigger.dataset.flyoutKey!;
|
|
534
|
+
trigger.addEventListener('mouseenter', () => openTo(key));
|
|
535
|
+
trigger.addEventListener('focus', () => openTo(key));
|
|
536
|
+
trigger.addEventListener('click', (e) => {
|
|
537
|
+
e.preventDefault();
|
|
538
|
+
open && key === currentKey ? close() : openTo(key);
|
|
539
|
+
});
|
|
540
|
+
});
|
|
541
|
+
|
|
542
|
+
// Hovering a plain (non-dropdown) top-level link closes the flyout.
|
|
543
|
+
header.querySelectorAll<HTMLElement>('[data-flyout-dismiss]').forEach((el) => {
|
|
544
|
+
el.addEventListener('mouseenter', scheduleClose);
|
|
545
|
+
});
|
|
546
|
+
|
|
547
|
+
// Keep open while over the panel; close shortly after leaving panel or nav.
|
|
548
|
+
flyout.addEventListener('mouseenter', cancelClose);
|
|
549
|
+
flyout.addEventListener('mouseleave', scheduleClose);
|
|
550
|
+
const nav = header.querySelector('[data-yt-flyout-nav]');
|
|
551
|
+
nav?.addEventListener('mouseleave', scheduleClose);
|
|
552
|
+
|
|
553
|
+
document.addEventListener('keydown', (e) => {
|
|
554
|
+
if (e.key === 'Escape') close();
|
|
555
|
+
});
|
|
556
|
+
document.addEventListener('click', (e) => {
|
|
557
|
+
if (open && !flyout.contains(e.target as Node) && !nav?.contains(e.target as Node)) close();
|
|
558
|
+
});
|
|
559
|
+
window.addEventListener('resize', () => {
|
|
560
|
+
if (open && currentKey) {
|
|
561
|
+
flyout.classList.add('no-anim');
|
|
562
|
+
sizeTo(currentKey);
|
|
563
|
+
void bgEl.offsetWidth;
|
|
564
|
+
flyout.classList.remove('no-anim');
|
|
565
|
+
}
|
|
566
|
+
});
|
|
567
|
+
};
|
|
568
|
+
|
|
569
|
+
const init = () => {
|
|
570
|
+
addHeaderListeners();
|
|
571
|
+
document.querySelectorAll<HTMLElement>('[data-yt-flyout-header]').forEach(initFlyout);
|
|
572
|
+
};
|
|
573
|
+
|
|
574
|
+
init();
|
|
575
|
+
document.addEventListener('astro:after-swap', init);
|
|
576
|
+
</script>
|
package/package.json
CHANGED
package/styles/styles.css
CHANGED
|
@@ -84,7 +84,10 @@
|
|
|
84
84
|
--tracking-tighter: -0.05em;
|
|
85
85
|
--tracking-tight: -0.025em;
|
|
86
86
|
--tracking-wide: 0.025em;
|
|
87
|
+
--tracking-wider: 0.05em;
|
|
87
88
|
--tracking-widest: 0.1em;
|
|
89
|
+
--leading-tight: 1.25;
|
|
90
|
+
--leading-snug: 1.375;
|
|
88
91
|
--radius-sm: 0.25rem;
|
|
89
92
|
--radius-md: 0.375rem;
|
|
90
93
|
--radius-lg: 0.5rem;
|
|
@@ -311,6 +314,9 @@
|
|
|
311
314
|
.top-2 {
|
|
312
315
|
top: calc(var(--spacing) * 2);
|
|
313
316
|
}
|
|
317
|
+
.top-full {
|
|
318
|
+
top: 100%;
|
|
319
|
+
}
|
|
314
320
|
.-right-5 {
|
|
315
321
|
right: calc(var(--spacing) * -5);
|
|
316
322
|
}
|
|
@@ -413,6 +419,12 @@
|
|
|
413
419
|
.m-auto {
|
|
414
420
|
margin: auto;
|
|
415
421
|
}
|
|
422
|
+
.-mx-2 {
|
|
423
|
+
margin-inline: calc(var(--spacing) * -2);
|
|
424
|
+
}
|
|
425
|
+
.-mx-3 {
|
|
426
|
+
margin-inline: calc(var(--spacing) * -3);
|
|
427
|
+
}
|
|
416
428
|
.mx-1 {
|
|
417
429
|
margin-inline: calc(var(--spacing) * 1);
|
|
418
430
|
}
|
|
@@ -606,6 +618,9 @@
|
|
|
606
618
|
.h-4 {
|
|
607
619
|
height: calc(var(--spacing) * 4);
|
|
608
620
|
}
|
|
621
|
+
.h-4\.5 {
|
|
622
|
+
height: calc(var(--spacing) * 4.5);
|
|
623
|
+
}
|
|
609
624
|
.h-5 {
|
|
610
625
|
height: calc(var(--spacing) * 5);
|
|
611
626
|
}
|
|
@@ -690,6 +705,9 @@
|
|
|
690
705
|
.w-4 {
|
|
691
706
|
width: calc(var(--spacing) * 4);
|
|
692
707
|
}
|
|
708
|
+
.w-4\.5 {
|
|
709
|
+
width: calc(var(--spacing) * 4.5);
|
|
710
|
+
}
|
|
693
711
|
.w-5 {
|
|
694
712
|
width: calc(var(--spacing) * 5);
|
|
695
713
|
}
|
|
@@ -777,6 +795,12 @@
|
|
|
777
795
|
.max-w-xs {
|
|
778
796
|
max-width: var(--container-xs);
|
|
779
797
|
}
|
|
798
|
+
.min-w-\[12rem\] {
|
|
799
|
+
min-width: 12rem;
|
|
800
|
+
}
|
|
801
|
+
.min-w-\[14rem\] {
|
|
802
|
+
min-width: 14rem;
|
|
803
|
+
}
|
|
780
804
|
.min-w-full {
|
|
781
805
|
min-width: 100%;
|
|
782
806
|
}
|
|
@@ -856,6 +880,9 @@
|
|
|
856
880
|
.cursor-zoom-out {
|
|
857
881
|
cursor: zoom-out;
|
|
858
882
|
}
|
|
883
|
+
.resize {
|
|
884
|
+
resize: both;
|
|
885
|
+
}
|
|
859
886
|
.list-none {
|
|
860
887
|
list-style-type: none;
|
|
861
888
|
}
|
|
@@ -1249,6 +1276,9 @@
|
|
|
1249
1276
|
.p-6 {
|
|
1250
1277
|
padding: calc(var(--spacing) * 6);
|
|
1251
1278
|
}
|
|
1279
|
+
.p-8 {
|
|
1280
|
+
padding: calc(var(--spacing) * 8);
|
|
1281
|
+
}
|
|
1252
1282
|
.\!px-0 {
|
|
1253
1283
|
padding-inline: calc(var(--spacing) * 0) !important;
|
|
1254
1284
|
}
|
|
@@ -1330,6 +1360,9 @@
|
|
|
1330
1360
|
.pb-1 {
|
|
1331
1361
|
padding-bottom: calc(var(--spacing) * 1);
|
|
1332
1362
|
}
|
|
1363
|
+
.pb-2 {
|
|
1364
|
+
padding-bottom: calc(var(--spacing) * 2);
|
|
1365
|
+
}
|
|
1333
1366
|
.pb-4 {
|
|
1334
1367
|
padding-bottom: calc(var(--spacing) * 4);
|
|
1335
1368
|
}
|
|
@@ -1448,6 +1481,14 @@
|
|
|
1448
1481
|
--tw-leading: calc(var(--spacing) * 6);
|
|
1449
1482
|
line-height: calc(var(--spacing) * 6);
|
|
1450
1483
|
}
|
|
1484
|
+
.leading-snug {
|
|
1485
|
+
--tw-leading: var(--leading-snug);
|
|
1486
|
+
line-height: var(--leading-snug);
|
|
1487
|
+
}
|
|
1488
|
+
.leading-tight {
|
|
1489
|
+
--tw-leading: var(--leading-tight);
|
|
1490
|
+
line-height: var(--leading-tight);
|
|
1491
|
+
}
|
|
1451
1492
|
.font-bold {
|
|
1452
1493
|
--tw-font-weight: var(--font-weight-bold);
|
|
1453
1494
|
font-weight: var(--font-weight-bold);
|
|
@@ -1480,6 +1521,10 @@
|
|
|
1480
1521
|
--tw-tracking: var(--tracking-wide);
|
|
1481
1522
|
letter-spacing: var(--tracking-wide);
|
|
1482
1523
|
}
|
|
1524
|
+
.tracking-wider {
|
|
1525
|
+
--tw-tracking: var(--tracking-wider);
|
|
1526
|
+
letter-spacing: var(--tracking-wider);
|
|
1527
|
+
}
|
|
1483
1528
|
.tracking-widest {
|
|
1484
1529
|
--tw-tracking: var(--tracking-widest);
|
|
1485
1530
|
letter-spacing: var(--tracking-widest);
|
|
@@ -1550,6 +1595,9 @@
|
|
|
1550
1595
|
.capitalize {
|
|
1551
1596
|
text-transform: capitalize;
|
|
1552
1597
|
}
|
|
1598
|
+
.normal-case {
|
|
1599
|
+
text-transform: none;
|
|
1600
|
+
}
|
|
1553
1601
|
.uppercase {
|
|
1554
1602
|
text-transform: uppercase;
|
|
1555
1603
|
}
|
|
@@ -1572,6 +1620,9 @@
|
|
|
1572
1620
|
.opacity-25 {
|
|
1573
1621
|
opacity: 25%;
|
|
1574
1622
|
}
|
|
1623
|
+
.opacity-70 {
|
|
1624
|
+
opacity: 70%;
|
|
1625
|
+
}
|
|
1575
1626
|
.opacity-75 {
|
|
1576
1627
|
opacity: 75%;
|
|
1577
1628
|
}
|
|
@@ -2117,6 +2168,21 @@
|
|
|
2117
2168
|
position: static;
|
|
2118
2169
|
}
|
|
2119
2170
|
}
|
|
2171
|
+
.md\:top-full {
|
|
2172
|
+
@media (width >= 48rem) {
|
|
2173
|
+
top: 100%;
|
|
2174
|
+
}
|
|
2175
|
+
}
|
|
2176
|
+
.md\:right-0 {
|
|
2177
|
+
@media (width >= 48rem) {
|
|
2178
|
+
right: calc(var(--spacing) * 0);
|
|
2179
|
+
}
|
|
2180
|
+
}
|
|
2181
|
+
.md\:left-0 {
|
|
2182
|
+
@media (width >= 48rem) {
|
|
2183
|
+
left: calc(var(--spacing) * 0);
|
|
2184
|
+
}
|
|
2185
|
+
}
|
|
2120
2186
|
.md\:order-1 {
|
|
2121
2187
|
@media (width >= 48rem) {
|
|
2122
2188
|
order: 1;
|
|
@@ -2127,6 +2193,11 @@
|
|
|
2127
2193
|
grid-column: span 3 / span 3;
|
|
2128
2194
|
}
|
|
2129
2195
|
}
|
|
2196
|
+
.md\:-mx-2 {
|
|
2197
|
+
@media (width >= 48rem) {
|
|
2198
|
+
margin-inline: calc(var(--spacing) * -2);
|
|
2199
|
+
}
|
|
2200
|
+
}
|
|
2130
2201
|
.md\:-mx-4 {
|
|
2131
2202
|
@media (width >= 48rem) {
|
|
2132
2203
|
margin-inline: calc(var(--spacing) * -4);
|
|
@@ -2308,6 +2379,16 @@
|
|
|
2308
2379
|
gap: calc(var(--spacing) * 16);
|
|
2309
2380
|
}
|
|
2310
2381
|
}
|
|
2382
|
+
.md\:gap-x-8 {
|
|
2383
|
+
@media (width >= 48rem) {
|
|
2384
|
+
column-gap: calc(var(--spacing) * 8);
|
|
2385
|
+
}
|
|
2386
|
+
}
|
|
2387
|
+
.md\:gap-y-4 {
|
|
2388
|
+
@media (width >= 48rem) {
|
|
2389
|
+
row-gap: calc(var(--spacing) * 4);
|
|
2390
|
+
}
|
|
2391
|
+
}
|
|
2311
2392
|
.md\:self-center {
|
|
2312
2393
|
@media (width >= 48rem) {
|
|
2313
2394
|
align-self: center;
|
|
@@ -2354,6 +2435,16 @@
|
|
|
2354
2435
|
padding: calc(var(--spacing) * 0);
|
|
2355
2436
|
}
|
|
2356
2437
|
}
|
|
2438
|
+
.md\:p-8 {
|
|
2439
|
+
@media (width >= 48rem) {
|
|
2440
|
+
padding: calc(var(--spacing) * 8);
|
|
2441
|
+
}
|
|
2442
|
+
}
|
|
2443
|
+
.md\:px-2 {
|
|
2444
|
+
@media (width >= 48rem) {
|
|
2445
|
+
padding-inline: calc(var(--spacing) * 2);
|
|
2446
|
+
}
|
|
2447
|
+
}
|
|
2357
2448
|
.md\:px-6 {
|
|
2358
2449
|
@media (width >= 48rem) {
|
|
2359
2450
|
padding-inline: calc(var(--spacing) * 6);
|
|
@@ -2419,6 +2510,11 @@
|
|
|
2419
2510
|
padding-top: 76px;
|
|
2420
2511
|
}
|
|
2421
2512
|
}
|
|
2513
|
+
.md\:pb-0 {
|
|
2514
|
+
@media (width >= 48rem) {
|
|
2515
|
+
padding-bottom: calc(var(--spacing) * 0);
|
|
2516
|
+
}
|
|
2517
|
+
}
|
|
2422
2518
|
.md\:pb-8 {
|
|
2423
2519
|
@media (width >= 48rem) {
|
|
2424
2520
|
padding-bottom: calc(var(--spacing) * 8);
|
package/svelte.d.ts
CHANGED
|
@@ -49,6 +49,7 @@ import type { SvelteWidgetHero1Props as YtSvelteWidgetHero1Props } from './compo
|
|
|
49
49
|
import type { SvelteWidgetHero2Props as YtSvelteWidgetHero2Props } from './components/WidgetHero2/types'
|
|
50
50
|
import type { SvelteWidgetHeroSliderProps as YtSvelteWidgetHeroSliderProps } from './components/WidgetHeroSlider/types'
|
|
51
51
|
import type { SvelteWidgetNavbarProps as YtSvelteWidgetNavbarProps } from './components/WidgetNavbar/types'
|
|
52
|
+
import type { SvelteWidgetNavbarFlyoutProps as YtSvelteWidgetNavbarFlyoutProps } from './components/WidgetNavbarFlyout/types'
|
|
52
53
|
import type { SvelteWidgetStatsProps as YtSvelteWidgetStatsProps } from './components/WidgetStats/types'
|
|
53
54
|
import type { SvelteWidgetSteps1Props as YtSvelteWidgetSteps1Props } from './components/WidgetSteps1/types'
|
|
54
55
|
import type { SvelteWidgetStepsTimelineProps as YtSvelteWidgetStepsTimelineProps } from './components/WidgetStepsTimeline/types'
|
|
@@ -108,6 +109,7 @@ declare module '@yatoday/astro-ui/svelte' {
|
|
|
108
109
|
export const WidgetHero2: Component<YtSvelteWidgetHero2Props>
|
|
109
110
|
export const WidgetHeroSlider: Component<YtSvelteWidgetHeroSliderProps>
|
|
110
111
|
export const WidgetNavbar: Component<YtSvelteWidgetNavbarProps>
|
|
112
|
+
export const WidgetNavbarFlyout: Component<YtSvelteWidgetNavbarFlyoutProps>
|
|
111
113
|
export const WidgetStats: Component<YtSvelteWidgetStatsProps>
|
|
112
114
|
export const WidgetSteps1: Component<YtSvelteWidgetSteps1Props>
|
|
113
115
|
export const WidgetStepsTimeline: Component<YtSvelteWidgetStepsTimelineProps>
|
|
@@ -166,6 +168,7 @@ declare module '@yatoday/astro-ui/svelte' {
|
|
|
166
168
|
export type WidgetHero2Props = YtSvelteWidgetHero2Props
|
|
167
169
|
export type WidgetHeroSliderProps = YtSvelteWidgetHeroSliderProps
|
|
168
170
|
export type WidgetNavbarProps = YtSvelteWidgetNavbarProps
|
|
171
|
+
export type WidgetNavbarFlyoutProps = YtSvelteWidgetNavbarFlyoutProps
|
|
169
172
|
export type WidgetStatsProps = YtSvelteWidgetStatsProps
|
|
170
173
|
export type WidgetSteps1Props = YtSvelteWidgetSteps1Props
|
|
171
174
|
export type WidgetStepsTimelineProps = YtSvelteWidgetStepsTimelineProps
|