fulldev-ui 0.5.0-beta.4 → 0.5.0-beta.6

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.
Files changed (60) hide show
  1. package/CONTRIBUTING.md +10 -4
  2. package/astro.config.ts +0 -2
  3. package/package.json +4 -2
  4. package/pnpm-lock.yaml +31 -69
  5. package/src/blocks/Banner.astro +2 -1
  6. package/src/blocks/Excerpt.astro +14 -0
  7. package/src/blocks/Product.astro +51 -22
  8. package/src/components/Card.astro +1 -1
  9. package/src/components/Cart.astro +36 -0
  10. package/src/components/CartForm.astro +121 -0
  11. package/src/components/CartList.astro +134 -0
  12. package/src/components/CartSummary.astro +146 -0
  13. package/src/components/Drawer.astro +119 -52
  14. package/src/components/Footer.astro +4 -0
  15. package/src/components/Form.astro +49 -0
  16. package/src/components/Header.astro +14 -12
  17. package/src/components/Input.astro +6 -0
  18. package/src/components/Menu.astro +56 -0
  19. package/src/components/Price.astro +7 -11
  20. package/src/components/Search.astro +1 -4
  21. package/src/components/Section.astro +2 -0
  22. package/src/components/Sidebar.astro +61 -111
  23. package/src/components/ThemeSelect.astro +3 -0
  24. package/src/components/Toc.astro +36 -94
  25. package/src/components/experimental/Form.astro +29 -5
  26. package/src/components/experimental/Gallery.astro +50 -126
  27. package/src/components/experimental/Prose.astro +32 -0
  28. package/src/content/pages/base/select.mdx +0 -8
  29. package/src/content/pages/base/textarea.mdx +0 -5
  30. package/src/content/pages/blocks/_product.mdx +73 -2
  31. package/src/content/pages/index.mdx +0 -2
  32. package/src/content/pages/layouts/_layout.mdx +8 -15
  33. package/src/content/pages/layouts/docslayout.mdx +10 -1
  34. package/src/content/pages/overview/components.mdx +5 -0
  35. package/src/content/pages/overview/content-collections.mdx +139 -0
  36. package/src/content/pages/overview/installation.mdx +25 -26
  37. package/src/content/pages/overview/introduction.mdx +16 -10
  38. package/src/content/pages/overview/theming.mdx +69 -0
  39. package/src/content/pages/schemas/page.mdx +6 -0
  40. package/src/content/presets/base.yml +57 -43
  41. package/src/content/presets/blocks.yml +0 -3
  42. package/src/content/presets/docs.yml +1 -61
  43. package/src/env.d.ts +1 -1
  44. package/src/layouts/Layout.astro +28 -14
  45. package/src/layouts/PostLayout.astro +24 -0
  46. package/src/layouts/ProductLayout.astro +5 -2
  47. package/src/schemas/components/header.ts +7 -9
  48. package/src/schemas/components/menu.ts +13 -0
  49. package/src/schemas/components/sidebar.ts +15 -0
  50. package/src/schemas/components/toc.ts +3 -0
  51. package/src/schemas/pageSchema.ts +54 -30
  52. package/src/schemas/presetSchema.ts +2 -32
  53. package/src/schemas/utils/navigation.ts +3 -53
  54. package/src/stores/cart.ts +23 -0
  55. package/src/utils/cart.ts +36 -0
  56. package/tsconfig.json +1 -3
  57. package/src/components/experimental/GalleryVertical.astro +0 -161
  58. package/src/content/pages/overview/content-layer.mdx +0 -128
  59. package/src/content/pages/overview/customization.mdx +0 -83
  60. /package/src/types/{global-props.d.ts → global-props.ts} +0 -0
@@ -0,0 +1,134 @@
1
+ ---
2
+ import Element from 'fulldev-ui/components/Element.astro'
3
+ import Button from './Button.astro'
4
+ import Card from './Card.astro'
5
+ import Heading from './Heading.astro'
6
+ import Text from './Text.astro'
7
+
8
+ const { ...rest } = Astro.props
9
+ ---
10
+
11
+ <Element
12
+ if
13
+ class:list="cart-list"
14
+ {...rest}
15
+ />
16
+
17
+ <template>
18
+ <Card class="cart-list-card">
19
+ <img class="cart-list-image image" />
20
+ <Element class="column">
21
+ <Heading
22
+ if
23
+ level={4}
24
+ class="heading"
25
+ />
26
+ <Element class="row">
27
+ <Text
28
+ if
29
+ class="cart-list-price"
30
+ />
31
+ <Button
32
+ class:list="cart-list-remove"
33
+ variant="tertiary"
34
+ icon="trash"
35
+ type="button"
36
+ />
37
+ </Element>
38
+ </Element>
39
+ </Card>
40
+ </template>
41
+
42
+ <script>
43
+ import { $cart } from 'fulldev-ui/stores/cart.ts'
44
+ import { formatPrice } from 'fulldev-ui/utils/cart'
45
+
46
+ function setCards(items: any) {
47
+ const template = document.querySelector('template')
48
+ const container = document.querySelector('.cart-list')
49
+
50
+ if (!container || !template) return
51
+
52
+ container.innerHTML = ''
53
+
54
+ items.forEach((item: any, index: number) => {
55
+ const clone = template?.content.cloneNode(true)
56
+ if (!(clone instanceof DocumentFragment)) return
57
+ const card = clone.querySelector('.cart-list-card')
58
+ if (!card) return
59
+
60
+ const img = card.querySelector('img')
61
+ if (img) img.src = item.image
62
+
63
+ const h4 = card.querySelector('h4')
64
+ if (h4) h4.textContent = item.name
65
+
66
+ const p = card.querySelector('p')
67
+ if (p) p.textContent = formatPrice(item.price)
68
+
69
+ const button = card.querySelector('button')
70
+ if (button) {
71
+ button.addEventListener('click', () => {
72
+ const currentCart = $cart.get()
73
+ const newCart = [...currentCart]
74
+ newCart.splice(index, 1)
75
+ $cart.set(newCart)
76
+ })
77
+ }
78
+
79
+ container.appendChild(clone)
80
+ })
81
+ }
82
+
83
+ document.addEventListener('astro:page-load', () => {
84
+ setCards($cart.get())
85
+
86
+ $cart.subscribe((items: any) => {
87
+ setCards(items)
88
+ })
89
+ })
90
+ </script>
91
+
92
+ <style lang="scss" is:global>
93
+ @layer fulldev {
94
+ .cart-list {
95
+ display: flex;
96
+ flex-direction: column;
97
+
98
+ .card {
99
+ display: flex;
100
+ flex-direction: row;
101
+ gap: var(--space-5);
102
+ width: 100%;
103
+
104
+ &:not(:first-child) {
105
+ margin-top: var(--space-5);
106
+ border-top: 1px solid var(--color-a6);
107
+ padding-top: var(--space-5);
108
+ }
109
+
110
+ .image {
111
+ display: block;
112
+ width: 100px;
113
+ height: auto;
114
+ }
115
+
116
+ .column {
117
+ display: flex;
118
+ flex-direction: column;
119
+ justify-content: space-between;
120
+ gap: var(--space-3);
121
+ width: 100%;
122
+ height: 100%;
123
+ }
124
+
125
+ .row {
126
+ display: flex;
127
+ flex-direction: row;
128
+ justify-content: space-between;
129
+ align-items: center;
130
+ }
131
+ }
132
+ }
133
+ }
134
+ </style>
@@ -0,0 +1,146 @@
1
+ ---
2
+ import Button from './Button.astro'
3
+ import Element from './Element.astro'
4
+ import Price from './Price.astro'
5
+ import Text from './Text.astro'
6
+
7
+ interface Props {}
8
+
9
+ const { ...rest } = Astro.props
10
+ ---
11
+
12
+ <Element
13
+ size="md"
14
+ class="cart-summary"
15
+ >
16
+ <div
17
+ class="row"
18
+ {...rest}
19
+ >
20
+ <Text
21
+ class:list="total"
22
+ text="Totaal"
23
+ contrast
24
+ />
25
+ <Price value={10} />
26
+ </div>
27
+ <Text
28
+ class:list="shipping"
29
+ text="Verzendkosten worden berekend bij het afrekenen."
30
+ />
31
+ <Button
32
+ class:list="checkout-button"
33
+ variant="primary"
34
+ color="brand"
35
+ text="Afrekenen"
36
+ />
37
+ </Element>
38
+
39
+ <style is:global lang="scss">
40
+ @layer fulldev {
41
+ .cart-summary {
42
+ display: flex;
43
+ flex-direction: column;
44
+ gap: var(--space-3);
45
+
46
+ .price,
47
+ .total {
48
+ font-size: var(--text-4);
49
+ }
50
+
51
+ .row {
52
+ display: flex;
53
+ justify-content: space-between;
54
+ align-items: center;
55
+ }
56
+
57
+ .shipping {
58
+ font-size: var(--text-1);
59
+ }
60
+ }
61
+ }
62
+ </style>
63
+
64
+ <script>
65
+ import { $cart } from 'fulldev-ui/stores/cart.ts'
66
+ import { formatPrice } from 'fulldev-ui/utils/cart'
67
+ import Stripe from 'stripe'
68
+
69
+ const stripe = new Stripe(import.meta.env.PUBLIC_STRIPE_CHECKOUT_KEY)
70
+
71
+ function setPrice(items: any) {
72
+ const price = document.querySelector('.cart-summary .price')
73
+ if (price)
74
+ price.textContent = formatPrice(
75
+ items.reduce(
76
+ (acc: number, item: { price: number }) => acc + item.price,
77
+ 0
78
+ )
79
+ )
80
+ }
81
+
82
+ document.addEventListener('astro:page-load', () => {
83
+ setPrice($cart.get())
84
+
85
+ $cart.subscribe((items: any) => {
86
+ setPrice(items)
87
+ })
88
+
89
+ const button = document.querySelector('.cart-summary .checkout-button')
90
+
91
+ button?.addEventListener('click', async () => {
92
+ const items = $cart.get()
93
+
94
+ const checkoutConfig = {
95
+ success_url: `${import.meta.env.PUBLIC_SITE_URL}/checkout`,
96
+ mode: 'payment',
97
+ customer_creation: 'always',
98
+ shipping_address_collection: {
99
+ allowed_countries: ['NL'],
100
+ },
101
+ phone_number_collection: {
102
+ enabled: true,
103
+ },
104
+ }
105
+
106
+ try {
107
+ const lineItems = items.map((item: any) => ({
108
+ price_data: {
109
+ currency: 'eur',
110
+ product: item.id,
111
+ },
112
+ quantity: 1,
113
+ }))
114
+
115
+ // @ts-ignore
116
+ const checkoutSession = await stripe.checkout.sessions.create({
117
+ line_items: lineItems,
118
+ ...checkoutConfig,
119
+ })
120
+
121
+ checkoutSession.url && window.location.replace(checkoutSession.url)
122
+ } catch (error) {
123
+ console.error(error)
124
+
125
+ const lineItems = items.map((item: any) => ({
126
+ quantity: 1,
127
+ price_data: {
128
+ currency: 'eur',
129
+ product_data: {
130
+ name: item.name,
131
+ },
132
+ unit_amount: Math.round(item.price * 100),
133
+ },
134
+ }))
135
+
136
+ // @ts-ignore
137
+ const checkoutSession = await stripe.checkout.sessions.create({
138
+ line_items: lineItems,
139
+ ...checkoutConfig,
140
+ })
141
+
142
+ checkoutSession.url && window.location.replace(checkoutSession.url)
143
+ }
144
+ })
145
+ })
146
+ </script>
@@ -1,95 +1,162 @@
1
1
  ---
2
- import type { ComponentProps } from 'astro/types'
2
+ import type { ComponentProps, HTMLAttributes } from 'astro/types'
3
3
  import Button from 'fulldev-ui/components/Button.astro'
4
- import Card from 'fulldev-ui/components/Card.astro'
5
4
  import Element from 'fulldev-ui/components/Element.astro'
5
+ import Logo from 'fulldev-ui/components/experimental/Logo.astro'
6
+ import Menu from 'fulldev-ui/components/Menu.astro'
7
+ import type { GlobalProps } from 'fulldev-ui/types/global-props'
8
+ import Heading from './Heading.astro'
6
9
 
7
- interface Props extends Omit<ComponentProps<typeof Card>, 'position'> {
8
- label?: string | undefined
9
- icon?: string | undefined
10
- position?: 'left' | 'right' | undefined
11
- panel?: boolean | undefined
10
+ interface Props extends GlobalProps, HTMLAttributes<'aside'> {
11
+ variant?: ComponentProps<typeof Button>['variant']
12
+ text?: ComponentProps<typeof Button>['text']
13
+ icon?: ComponentProps<typeof Button>['icon']
14
+ heading?: ComponentProps<typeof Heading>['text']
15
+ logo?: ComponentProps<typeof Logo> | undefined
16
+ company?: ComponentProps<typeof Logo>['company']
17
+ menu?: ComponentProps<typeof Menu>['groups']
12
18
  }
13
19
 
14
20
  const {
15
21
  id = 'drawer',
16
- position = 'left',
17
- panel,
18
- label,
19
- icon,
22
+ size = 'sm',
23
+ icon = 'menu-2',
24
+ color,
25
+ variant,
26
+ text,
27
+ heading,
28
+ logo,
29
+ company,
30
+ menu,
20
31
  ...rest
21
32
  } = Astro.props
22
33
  ---
23
34
 
24
35
  <Button
25
- class:list="drawer-button"
26
36
  variant="secondary"
27
- id={`${id}-button`}
28
- text={label}
29
- icon={icon}
37
+ class:list={['drawer-button', `${id}-button`]}
30
38
  onclick={`document.getElementById('${id}').showModal()`}
39
+ {variant}
40
+ {text}
41
+ {icon}
42
+ {color}
31
43
  />
32
44
 
33
45
  <Element
46
+ onclick={`event.target === this && this.close()`}
47
+ class:list="drawer"
34
48
  as="dialog"
35
- class="drawer"
36
49
  {id}
37
- {position}
38
- onclick={`event.target === this && this.close()`}
50
+ {text}
51
+ {icon}
52
+ {...rest}
39
53
  >
40
- <Element
41
- class:list={[panel, `position-${position}`]}
42
- {...rest}
43
- >
44
- <slot />
54
+ <Element class:list="drawer-body">
55
+ <Element
56
+ class:list="drawer-header"
57
+ as="header"
58
+ >
59
+ <Logo
60
+ {company}
61
+ {...logo}
62
+ />
63
+ <Heading
64
+ level={4}
65
+ text={heading}
66
+ />
67
+ <Button
68
+ variant="secondary"
69
+ icon="x"
70
+ onclick={`document.getElementById('${id}').close()`}
71
+ />
72
+ <slot name="header" />
73
+ </Element>
74
+ <Element class:list="drawer-content">
75
+ <Menu groups={menu} />
76
+ <slot />
77
+ </Element>
78
+ <Element
79
+ class:list="drawer-footer"
80
+ as="footer"
81
+ >
82
+ <slot name="footer" />
83
+ </Element>
45
84
  </Element>
46
85
  </Element>
47
86
 
48
87
  <style lang="scss" is:global>
49
88
  @layer fulldev {
89
+ body:has(dialog[open]) {
90
+ overflow: hidden;
91
+
92
+ @media (min-width: 768px) {
93
+ overflow: auto;
94
+ }
95
+ }
96
+
50
97
  .drawer {
51
- flex-shrink: 0;
52
- align-items: stretch;
53
- box-sizing: border-box;
54
- margin: 0 !important;
55
- outline: 0;
56
- border: 0;
57
- background: var(--color-2);
98
+ top: 0;
99
+ bottom: 0;
100
+ margin: 0;
58
101
  padding: 0;
59
- padding: var(--space-7) var(--space-7) var(--space-7) var(--gutter);
60
- min-width: 260px;
61
- max-width: 360px;
62
- height: 100vh;
63
- max-height: 100vh;
102
+ width: 100%;
103
+ max-width: 100%;
104
+ height: 100%;
105
+ max-height: 100%;
106
+
107
+ @media (min-width: 768px) {
108
+ width: 440px;
109
+ }
64
110
 
65
111
  &::backdrop {
112
+ cursor: pointer;
66
113
  background: rgba(0, 0, 0, 0.5);
67
114
  }
68
115
 
69
- &.position-left {
70
- margin-right: 0;
116
+ .drawer-body {
117
+ display: flex;
118
+ flex-shrink: 1;
119
+ flex-direction: column;
120
+ border-right: 1px solid var(--color-a6);
121
+ height: 100%;
122
+ overflow: auto;
123
+ }
124
+
125
+ .drawer-content {
126
+ display: flex;
127
+ flex-direction: column;
128
+ padding: var(--space-6) var(--gutter);
71
129
  }
72
130
 
73
- &.position-right {
74
- right: 0;
131
+ .drawer-header,
132
+ .drawer-footer {
133
+ display: flex;
134
+ position: sticky;
135
+ flex-shrink: 0;
136
+ z-index: 1;
137
+ border-style: solid;
138
+ border-color: var(--color-a6);
139
+ background-color: var(--base-background);
75
140
  }
76
141
 
77
- .box {
78
- padding: calc(var(--space-5) * 2) calc(var(--space-7) * 3);
79
- min-width: calc(var(--space-7) * 14);
80
- height: 100vh;
81
- overflow-x: hidden;
82
- overflow-y: auto;
142
+ .drawer-header {
143
+ top: 0;
144
+ align-items: center;
145
+ border-bottom-width: 1px;
146
+ padding: 0 var(--gutter);
147
+ height: 56px;
83
148
 
84
- &.position-left {
85
- border-right: 1px solid var(--color-a6);
86
- padding-left: var(--gutter);
149
+ .button {
150
+ margin-left: auto;
87
151
  }
152
+ }
88
153
 
89
- &.position-right {
90
- border-left: 1px solid var(--color-a6);
91
- padding-right: var(--gutter);
92
- }
154
+ .drawer-footer {
155
+ bottom: 0;
156
+ flex-direction: column;
157
+ margin-top: auto;
158
+ border-top-width: 1px;
159
+ padding: var(--space-5) var(--gutter);
93
160
  }
94
161
  }
95
162
  }
@@ -132,6 +132,10 @@ const {
132
132
  flex-direction: column;
133
133
  }
134
134
 
135
+ > .column {
136
+ gap: var(--space-4);
137
+ }
138
+
135
139
  .socials {
136
140
  display: flex;
137
141
  }
@@ -0,0 +1,49 @@
1
+ ---
2
+ import type { ComponentProps, HTMLAttributes } from 'astro/types'
3
+ import Button from 'fulldev-ui/components/Button.astro'
4
+ import Element from 'fulldev-ui/components/Element.astro'
5
+ import Input from 'fulldev-ui/components/Input.astro'
6
+ import Select from 'fulldev-ui/components/Select.astro'
7
+ import Textarea from 'fulldev-ui/components/Textarea.astro'
8
+ import type { GlobalProps } from 'fulldev-ui/types/global-props'
9
+
10
+ interface Props extends GlobalProps, HTMLAttributes<'form'> {
11
+ fields: (
12
+ | ComponentProps<typeof Input>
13
+ | ComponentProps<typeof Select>
14
+ | (ComponentProps<typeof Textarea> & { type?: 'textarea' | undefined })
15
+ )[]
16
+ submit?: ComponentProps<typeof Button>['text']
17
+ }
18
+
19
+ const { fields, submit, ...rest } = Astro.props
20
+ ---
21
+
22
+ <Element
23
+ class:list="form"
24
+ as="form"
25
+ {...rest}
26
+ >
27
+ {
28
+ fields.map((field) => {
29
+ if ('options' in field) return <Select {...field} />
30
+ if ('type' in field && field.type === 'textarea')
31
+ return <Textarea {...field} />
32
+ return <Input {...(field as any)} />
33
+ })
34
+ }
35
+ <Button
36
+ type="submit"
37
+ text={submit}
38
+ />
39
+ </Element>
40
+
41
+ <style is:global lang="scss">
42
+ .form {
43
+ display: flex;
44
+ flex-direction: column;
45
+ gap: var(--space-4);
46
+ width: 100%;
47
+ max-width: calc(var(--space-4) * 44);
48
+ }
49
+ </style>
@@ -1,21 +1,24 @@
1
1
  ---
2
2
  import type { ComponentProps, HTMLAttributes } from 'astro/types'
3
- import Button from 'fulldev-ui/components/Button.astro'
4
3
  import Buttons from 'fulldev-ui/components/Buttons.astro'
5
4
  import Element from 'fulldev-ui/components/Element.astro'
6
5
  import Logo from 'fulldev-ui/components/experimental/Logo.astro'
7
- import Search from 'fulldev-ui/components/Search.astro'
8
6
  import ThemeSelect from 'fulldev-ui/components/ThemeSelect.astro'
9
7
  import type { GlobalProps } from 'fulldev-ui/types/global-props'
8
+ import Cart from './Cart.astro'
9
+ import Drawer from './Drawer.astro'
10
+ import type Menu from './Menu.astro'
10
11
 
11
12
  interface Props extends GlobalProps, HTMLAttributes<'header'> {
12
- logo?: ComponentProps<typeof Logo>['src']
13
+ logo?: ComponentProps<typeof Logo>
13
14
  company?: ComponentProps<typeof Logo>['company']
14
15
  buttons?: ComponentProps<typeof Buttons>['buttons']
16
+ menu?: ComponentProps<typeof Menu>['groups']
15
17
  panel?: boolean | undefined
16
18
  search?: boolean | undefined
17
19
  open?: boolean | undefined
18
20
  themeselect?: boolean | undefined
21
+ cart?: string | undefined
19
22
  }
20
23
 
21
24
  const {
@@ -26,7 +29,9 @@ const {
26
29
  buttons,
27
30
  search,
28
31
  panel,
32
+ menu,
29
33
  themeselect,
34
+ cart,
30
35
  ...rest
31
36
  } = Astro.props
32
37
  ---
@@ -47,14 +52,15 @@ const {
47
52
  {buttons}
48
53
  variant="link"
49
54
  />
50
- {search && <Search />}
51
55
  {themeselect && <ThemeSelect />}
52
- <Button
53
- class="menu-button"
54
- variant="tertiary"
56
+ <Drawer
55
57
  icon="menu-2"
56
- for="sidebar"
58
+ id="menu"
59
+ {menu}
60
+ {logo}
61
+ {company}
57
62
  />
63
+ <Cart heading={cart} />
58
64
  </Element>
59
65
 
60
66
  <style lang="scss" is:global>
@@ -118,10 +124,6 @@ const {
118
124
  }
119
125
 
120
126
  .menu-button {
121
- .icon {
122
- transform: scale(1.56);
123
- }
124
-
125
127
  @media (min-width: 1024px) {
126
128
  display: none;
127
129
  }
@@ -17,6 +17,7 @@ const {
17
17
  disabled,
18
18
  required,
19
19
  placeholder,
20
+ readonly,
20
21
  name = placeholder,
21
22
  type = 'text',
22
23
  ...rest
@@ -41,6 +42,7 @@ const {
41
42
  {value}
42
43
  {disabled}
43
44
  {required}
45
+ {readonly}
44
46
  />
45
47
  <Icon name={icon} />
46
48
  </Element>
@@ -97,6 +99,10 @@ const {
97
99
  cursor: not-allowed;
98
100
  pointer-events: none;
99
101
  }
102
+
103
+ &[readonly] {
104
+ pointer-events: none;
105
+ }
100
106
  }
101
107
  }
102
108
  }
@@ -0,0 +1,56 @@
1
+ ---
2
+ import type { ComponentProps, HTMLAttributes } from 'astro/types'
3
+ import Button from 'fulldev-ui/components/Button.astro'
4
+ import Element from 'fulldev-ui/components/Element.astro'
5
+ import Heading from 'fulldev-ui/components/Heading.astro'
6
+ import type { GlobalProps } from 'fulldev-ui/types/global-props'
7
+
8
+ interface Props extends GlobalProps, HTMLAttributes<'div'> {
9
+ groups?:
10
+ | {
11
+ heading?: ComponentProps<typeof Heading>['text']
12
+ buttons?: ComponentProps<typeof Button>[]
13
+ }[]
14
+ | undefined
15
+ }
16
+
17
+ const { groups, ...rest } = Astro.props
18
+ ---
19
+
20
+ <Element
21
+ class:list="menu"
22
+ {...rest}
23
+ >
24
+ {
25
+ groups?.map(({ heading, buttons }) => (
26
+ <Element class:list="menu-group">
27
+ <Heading
28
+ level={6}
29
+ text={heading}
30
+ />
31
+ {buttons?.map((button) => (
32
+ <Button
33
+ variant="link"
34
+ {...button}
35
+ />
36
+ ))}
37
+ </Element>
38
+ ))
39
+ }
40
+ </Element>
41
+
42
+ <style lang="scss" is:global>
43
+ @layer fulldev {
44
+ .menu {
45
+ display: flex;
46
+ flex-direction: column;
47
+ gap: var(--space-5);
48
+
49
+ .menu-group {
50
+ display: flex;
51
+ flex-direction: column;
52
+ gap: var(--space-4);
53
+ }
54
+ }
55
+ }
56
+ </style>