fulldev-ui 0.10.1 → 0.11.0

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 (248) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/README.md +7 -1
  3. package/package.json +6 -4
  4. package/public/r/accordion.json +7 -1
  5. package/public/r/alert-dialog.json +7 -1
  6. package/public/r/alert.json +6 -0
  7. package/public/r/article-1.json +7 -1
  8. package/public/r/article-2.json +7 -1
  9. package/public/r/articles-1.json +7 -1
  10. package/public/r/articles-2.json +7 -1
  11. package/public/r/articles-3.json +7 -1
  12. package/public/r/articles-4.json +7 -1
  13. package/public/r/avatar.json +6 -0
  14. package/public/r/badge.json +6 -0
  15. package/public/r/banner-1.json +7 -1
  16. package/public/r/banner-2.json +7 -1
  17. package/public/r/banner.json +6 -0
  18. package/public/r/blocks-1.json +6 -1
  19. package/public/r/blocks.json +92 -0
  20. package/public/r/breadcrumb.json +6 -0
  21. package/public/r/button.json +6 -0
  22. package/public/r/card.json +6 -0
  23. package/public/r/carousel.json +6 -0
  24. package/public/r/checkbox.json +6 -0
  25. package/public/r/collapsible.json +7 -1
  26. package/public/r/combobox.json +6 -0
  27. package/public/r/command.json +6 -0
  28. package/public/r/components.json +14 -3
  29. package/public/r/contact-1.json +10 -2
  30. package/public/r/contact-2.json +10 -2
  31. package/public/r/contact-3.json +10 -2
  32. package/public/r/content-1.json +7 -1
  33. package/public/r/content-2.json +7 -1
  34. package/public/r/content-3.json +7 -1
  35. package/public/r/content-4.json +7 -1
  36. package/public/r/cta-1.json +7 -1
  37. package/public/r/cta-2.json +7 -1
  38. package/public/r/cta-3.json +7 -1
  39. package/public/r/cta-4.json +7 -1
  40. package/public/r/cta-5.json +7 -1
  41. package/public/r/cta-6.json +7 -1
  42. package/public/r/cta-7.json +7 -1
  43. package/public/r/cta-8.json +7 -1
  44. package/public/r/dialog.json +7 -1
  45. package/public/r/doc-1.json +7 -1
  46. package/public/r/dropdown-menu.json +7 -1
  47. package/public/r/empty.json +6 -0
  48. package/public/r/faqs-1.json +7 -1
  49. package/public/r/faqs-2.json +7 -1
  50. package/public/r/faqs-3.json +7 -1
  51. package/public/r/faqs-4.json +7 -1
  52. package/public/r/features-1.json +7 -1
  53. package/public/r/features-2.json +7 -1
  54. package/public/r/features-3.json +7 -1
  55. package/public/r/features-4.json +7 -1
  56. package/public/r/features-5.json +7 -1
  57. package/public/r/features-6.json +7 -1
  58. package/public/r/field.json +6 -0
  59. package/public/r/footer-1.json +7 -1
  60. package/public/r/footer-2.json +7 -1
  61. package/public/r/footer-3.json +7 -1
  62. package/public/r/form.json +6 -0
  63. package/public/r/header-1.json +7 -1
  64. package/public/r/header-2.json +7 -1
  65. package/public/r/header-3.json +7 -1
  66. package/public/r/header-4.json +7 -1
  67. package/public/r/header-5.json +7 -1
  68. package/public/r/header.json +6 -0
  69. package/public/r/hero-1.json +7 -1
  70. package/public/r/hero-10.json +7 -1
  71. package/public/r/hero-11.json +7 -1
  72. package/public/r/hero-12.json +7 -1
  73. package/public/r/hero-13.json +7 -1
  74. package/public/r/hero-2.json +7 -1
  75. package/public/r/hero-3.json +7 -1
  76. package/public/r/hero-4.json +7 -1
  77. package/public/r/hero-5.json +7 -1
  78. package/public/r/hero-6.json +7 -1
  79. package/public/r/hero-7.json +7 -1
  80. package/public/r/hero-8.json +7 -1
  81. package/public/r/hero-9.json +7 -1
  82. package/public/r/hover-card.json +7 -1
  83. package/public/r/icon.json +7 -1
  84. package/public/r/init.json +28 -0
  85. package/public/r/input-group.json +6 -0
  86. package/public/r/input.json +6 -0
  87. package/public/r/item.json +6 -0
  88. package/public/r/kbd.json +6 -0
  89. package/public/r/label.json +6 -0
  90. package/public/r/layout.json +6 -0
  91. package/public/r/links-2.json +7 -1
  92. package/public/r/logo.json +6 -0
  93. package/public/r/logos-1.json +7 -1
  94. package/public/r/logos-2.json +7 -1
  95. package/public/r/logos-3.json +7 -1
  96. package/public/r/marquee.json +6 -0
  97. package/public/r/native-select.json +6 -0
  98. package/public/r/navigation-menu.json +7 -1
  99. package/public/r/popover.json +7 -1
  100. package/public/r/price.json +6 -0
  101. package/public/r/pricing-1.json +7 -1
  102. package/public/r/pricing-2.json +7 -1
  103. package/public/r/pricing-3.json +7 -1
  104. package/public/r/product-1.json +7 -1
  105. package/public/r/products-1.json +7 -1
  106. package/public/r/products-2.json +7 -1
  107. package/public/r/products-3.json +7 -1
  108. package/public/r/products-4.json +7 -1
  109. package/public/r/products-5.json +7 -1
  110. package/public/r/radio-group.json +7 -1
  111. package/public/r/rating.json +6 -0
  112. package/public/r/registry.json +1645 -457
  113. package/public/r/reviews-1.json +7 -1
  114. package/public/r/reviews-2.json +7 -1
  115. package/public/r/reviews-3.json +7 -1
  116. package/public/r/reviews-4.json +7 -1
  117. package/public/r/reviews-5.json +7 -1
  118. package/public/r/section.json +18 -2
  119. package/public/r/select.json +6 -0
  120. package/public/r/separator.json +6 -0
  121. package/public/r/services-1.json +7 -1
  122. package/public/r/services-2.json +7 -1
  123. package/public/r/services-3.json +7 -1
  124. package/public/r/services-4.json +7 -1
  125. package/public/r/services-5.json +7 -1
  126. package/public/r/services-6.json +7 -1
  127. package/public/r/services-7.json +7 -1
  128. package/public/r/sheet.json +8 -2
  129. package/public/r/sidebar-1.json +5 -0
  130. package/public/r/sidebar.json +6 -0
  131. package/public/r/skeleton.json +6 -0
  132. package/public/r/slider.json +7 -1
  133. package/public/r/spinner.json +6 -0
  134. package/public/r/switch.json +7 -1
  135. package/public/r/table.json +6 -0
  136. package/public/r/tabs.json +7 -1
  137. package/public/r/textarea.json +6 -0
  138. package/public/r/theme-toggle.json +6 -0
  139. package/public/r/toc.json +6 -0
  140. package/public/r/toggle.json +7 -1
  141. package/public/r/tooltip.json +7 -1
  142. package/public/r/typography.json +6 -0
  143. package/public/r/video.json +6 -0
  144. package/registry/init/global.css +187 -0
  145. package/registry.json +1137 -454
  146. package/src/components/blocks/article-1.astro +4 -3
  147. package/src/components/blocks/article-2.astro +4 -3
  148. package/src/components/blocks/articles-1.astro +18 -9
  149. package/src/components/blocks/articles-2.astro +4 -3
  150. package/src/components/blocks/articles-3.astro +11 -9
  151. package/src/components/blocks/articles-4.astro +11 -4
  152. package/src/components/blocks/banner-1.astro +4 -3
  153. package/src/components/blocks/banner-2.astro +10 -4
  154. package/src/components/blocks/blocks-1.astro +1 -1
  155. package/src/components/blocks/contact-1.astro +72 -39
  156. package/src/components/blocks/contact-2.astro +69 -35
  157. package/src/components/blocks/contact-3.astro +61 -34
  158. package/src/components/blocks/content-1.astro +15 -10
  159. package/src/components/blocks/content-2.astro +15 -10
  160. package/src/components/blocks/content-3.astro +14 -12
  161. package/src/components/blocks/content-4.astro +15 -10
  162. package/src/components/blocks/cta-1.astro +14 -10
  163. package/src/components/blocks/cta-2.astro +11 -8
  164. package/src/components/blocks/cta-3.astro +15 -8
  165. package/src/components/blocks/cta-4.astro +14 -9
  166. package/src/components/blocks/cta-5.astro +12 -8
  167. package/src/components/blocks/cta-6.astro +11 -8
  168. package/src/components/blocks/cta-7.astro +17 -10
  169. package/src/components/blocks/cta-8.astro +15 -10
  170. package/src/components/blocks/doc-1.astro +1 -1
  171. package/src/components/blocks/faqs-1.astro +22 -11
  172. package/src/components/blocks/faqs-2.astro +19 -9
  173. package/src/components/blocks/faqs-3.astro +19 -9
  174. package/src/components/blocks/faqs-4.astro +12 -9
  175. package/src/components/blocks/features-1.astro +21 -13
  176. package/src/components/blocks/features-2.astro +22 -13
  177. package/src/components/blocks/features-3.astro +14 -13
  178. package/src/components/blocks/features-4.astro +18 -9
  179. package/src/components/blocks/features-5.astro +22 -13
  180. package/src/components/blocks/features-6.astro +19 -9
  181. package/src/components/blocks/footer-1.astro +4 -3
  182. package/src/components/blocks/footer-2.astro +4 -3
  183. package/src/components/blocks/footer-3.astro +4 -3
  184. package/src/components/blocks/header-1.astro +13 -7
  185. package/src/components/blocks/header-2.astro +12 -6
  186. package/src/components/blocks/header-3.astro +12 -6
  187. package/src/components/blocks/header-4.astro +13 -6
  188. package/src/components/blocks/header-5.astro +16 -6
  189. package/src/components/blocks/hero-1.astro +11 -8
  190. package/src/components/blocks/hero-10.astro +7 -3
  191. package/src/components/blocks/hero-11.astro +4 -2
  192. package/src/components/blocks/hero-12.astro +11 -4
  193. package/src/components/blocks/hero-13.astro +11 -4
  194. package/src/components/blocks/hero-2.astro +11 -8
  195. package/src/components/blocks/hero-3.astro +11 -3
  196. package/src/components/blocks/hero-4.astro +4 -2
  197. package/src/components/blocks/hero-5.astro +4 -3
  198. package/src/components/blocks/hero-6.astro +4 -3
  199. package/src/components/blocks/hero-7.astro +4 -3
  200. package/src/components/blocks/hero-8.astro +11 -4
  201. package/src/components/blocks/hero-9.astro +4 -3
  202. package/src/components/blocks/links-2.astro +4 -4
  203. package/src/components/blocks/logos-1.astro +14 -16
  204. package/src/components/blocks/logos-2.astro +14 -12
  205. package/src/components/blocks/logos-3.astro +5 -4
  206. package/src/components/blocks/pricing-1.astro +13 -16
  207. package/src/components/blocks/pricing-2.astro +14 -13
  208. package/src/components/blocks/pricing-3.astro +20 -16
  209. package/src/components/blocks/product-1.astro +4 -3
  210. package/src/components/blocks/products-1.astro +11 -9
  211. package/src/components/blocks/products-2.astro +12 -9
  212. package/src/components/blocks/products-3.astro +12 -9
  213. package/src/components/blocks/products-4.astro +18 -9
  214. package/src/components/blocks/products-5.astro +18 -9
  215. package/src/components/blocks/reviews-1.astro +13 -12
  216. package/src/components/blocks/reviews-2.astro +4 -4
  217. package/src/components/blocks/reviews-3.astro +13 -12
  218. package/src/components/blocks/reviews-4.astro +13 -12
  219. package/src/components/blocks/reviews-5.astro +13 -12
  220. package/src/components/blocks/services-1.astro +19 -9
  221. package/src/components/blocks/services-2.astro +11 -8
  222. package/src/components/blocks/services-3.astro +11 -8
  223. package/src/components/blocks/services-4.astro +19 -9
  224. package/src/components/blocks/services-5.astro +11 -8
  225. package/src/components/blocks/services-6.astro +4 -3
  226. package/src/components/blocks/services-7.astro +12 -8
  227. package/src/components/ui/accordion/accordion.astro +1 -0
  228. package/src/components/ui/alert-dialog/alert-dialog.astro +1 -0
  229. package/src/components/ui/collapsible/collapsible.astro +1 -0
  230. package/src/components/ui/dialog/dialog.astro +1 -0
  231. package/src/components/ui/dropdown-menu/dropdown-menu.astro +1 -0
  232. package/src/components/ui/hover-card/hover-card.astro +7 -3
  233. package/src/components/ui/icon/icon.astro +46 -29
  234. package/src/components/ui/navigation-menu/navigation-menu.astro +1 -0
  235. package/src/components/ui/popover/popover.astro +1 -0
  236. package/src/components/ui/radio-group/radio-group.astro +1 -0
  237. package/src/components/ui/section/index.ts +2 -0
  238. package/src/components/ui/section/section-container.astro +1 -0
  239. package/src/components/ui/section/section-description.astro +20 -0
  240. package/src/components/ui/section/section-title.astro +20 -0
  241. package/src/components/ui/sheet/sheet-close.astro +4 -2
  242. package/src/components/ui/sheet/sheet.astro +1 -0
  243. package/src/components/ui/slider/slider.astro +1 -0
  244. package/src/components/ui/switch/switch.astro +1 -0
  245. package/src/components/ui/tabs/tabs.astro +1 -0
  246. package/src/components/ui/toggle/toggle.astro +1 -0
  247. package/src/components/ui/tooltip/tooltip.astro +1 -0
  248. package/src/lib/pages.ts +12 -0
@@ -1,14 +1,14 @@
1
1
  ---
2
2
  import type { ImageMetadata } from "astro"
3
3
  import { Image } from "astro:assets"
4
+ import type { HTMLAttributes } from "astro/types"
4
5
 
5
6
  import { cn } from "@/lib/utils"
6
7
  import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
7
8
  import { Badge } from "@/components/ui/badge"
8
9
  import { Section, SectionContainer } from "@/components/ui/section"
9
10
 
10
- type Props = {
11
- class?: string
11
+ type Props = HTMLAttributes<"section"> & {
12
12
  badge?: string
13
13
  title: string
14
14
  description: string
@@ -31,10 +31,11 @@ const {
31
31
  description,
32
32
  author,
33
33
  image,
34
+ ...props
34
35
  } = Astro.props
35
36
  ---
36
37
 
37
- <Section class={cn("", className)}>
38
+ <Section class={cn("", className)} {...props}>
38
39
  <SectionContainer class="mx-auto max-w-2xl gap-8">
39
40
  <div class="mx-auto flex w-full max-w-2xl flex-col gap-6">
40
41
  {
@@ -1,14 +1,14 @@
1
1
  ---
2
2
  import type { ImageMetadata } from "astro"
3
3
  import { Image } from "astro:assets"
4
+ import type { HTMLAttributes } from "astro/types"
4
5
 
5
6
  import { cn } from "@/lib/utils"
6
7
  import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
7
8
  import { Badge } from "@/components/ui/badge"
8
9
  import { Section, SectionContainer } from "@/components/ui/section"
9
10
 
10
- type Props = {
11
- class?: string
11
+ type Props = HTMLAttributes<"section"> & {
12
12
  badge?: string
13
13
  title: string
14
14
  description: string
@@ -32,10 +32,11 @@ const {
32
32
  description,
33
33
  author,
34
34
  image,
35
+ ...props
35
36
  } = Astro.props
36
37
  ---
37
38
 
38
- <Section class={cn("", className)}>
39
+ <Section class={cn("", className)} {...props}>
39
40
  <SectionContainer class="mx-auto max-w-2xl items-center gap-8 text-center">
40
41
  <div class="mx-auto flex w-full max-w-2xl flex-col items-center gap-6">
41
42
  {badge && <Badge variant="secondary">{badge}</Badge>}
@@ -1,14 +1,18 @@
1
1
  ---
2
2
  import type { ImageMetadata } from "astro"
3
3
  import { Image } from "astro:assets"
4
+ import type { HTMLAttributes } from "astro/types"
4
5
 
5
6
  import { cn } from "@/lib/utils"
6
7
  import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
7
8
  import { Badge } from "@/components/ui/badge"
8
- import { Section, SectionContainer } from "@/components/ui/section"
9
+ import {
10
+ Section,
11
+ SectionContainer,
12
+ SectionTitle,
13
+ } from "@/components/ui/section"
9
14
 
10
- type Props = {
11
- class?: string
15
+ type Props = HTMLAttributes<"section"> & {
12
16
  badge?: string
13
17
  title: string
14
18
  description: string
@@ -30,10 +34,17 @@ type Props = {
30
34
  }[]
31
35
  }
32
36
 
33
- const { class: className, badge, title, description, articles } = Astro.props
37
+ const {
38
+ class: className,
39
+ badge,
40
+ title,
41
+ description,
42
+ articles,
43
+ ...props
44
+ } = Astro.props
34
45
  ---
35
46
 
36
- <Section class={cn("", className)}>
47
+ <Section class={cn("", className)} {...props}>
37
48
  <SectionContainer class="gap-8">
38
49
  <div class="flex max-w-2xl flex-col gap-4">
39
50
  {
@@ -43,11 +54,9 @@ const { class: className, badge, title, description, articles } = Astro.props
43
54
  </Badge>
44
55
  )
45
56
  }
46
- <h2
47
- class="text-3xl font-semibold tracking-tight text-balance sm:text-4xl"
48
- >
57
+ <SectionTitle>
49
58
  {title}
50
- </h2>
59
+ </SectionTitle>
51
60
  <p class="text-muted-foreground text-base leading-7">
52
61
  {description}
53
62
  </p>
@@ -1,14 +1,14 @@
1
1
  ---
2
2
  import type { ImageMetadata } from "astro"
3
3
  import { Image } from "astro:assets"
4
+ import type { HTMLAttributes } from "astro/types"
4
5
 
5
6
  import { cn } from "@/lib/utils"
6
7
  import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
7
8
  import { Badge } from "@/components/ui/badge"
8
9
  import { Section, SectionContainer } from "@/components/ui/section"
9
10
 
10
- type Props = {
11
- class?: string
11
+ type Props = HTMLAttributes<"section"> & {
12
12
  badge?: string
13
13
  title: string
14
14
  description: string
@@ -53,10 +53,11 @@ const {
53
53
  description,
54
54
  featured,
55
55
  articles,
56
+ ...props
56
57
  } = Astro.props
57
58
  ---
58
59
 
59
- <Section class={cn("", className)}>
60
+ <Section class={cn("", className)} {...props}>
60
61
  <SectionContainer class="gap-8">
61
62
  <div class="mx-auto max-w-2xl text-center">
62
63
  {badge && <Badge variant="secondary">{badge}</Badge>}
@@ -1,14 +1,18 @@
1
1
  ---
2
2
  import type { ImageMetadata } from "astro"
3
3
  import { Image } from "astro:assets"
4
+ import type { HTMLAttributes } from "astro/types"
4
5
 
5
6
  import { cn } from "@/lib/utils"
6
7
  import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
7
8
  import { Badge } from "@/components/ui/badge"
8
- import { Section, SectionContainer } from "@/components/ui/section"
9
+ import {
10
+ Section,
11
+ SectionContainer,
12
+ SectionTitle,
13
+ } from "@/components/ui/section"
9
14
 
10
- type Props = {
11
- class?: string
15
+ type Props = HTMLAttributes<"section"> & {
12
16
  badge?: string
13
17
  title: string
14
18
  articles: {
@@ -29,10 +33,10 @@ type Props = {
29
33
  }[]
30
34
  }
31
35
 
32
- const { class: className, badge, title, articles } = Astro.props
36
+ const { class: className, badge, title, articles, ...props } = Astro.props
33
37
  ---
34
38
 
35
- <Section class={cn("", className)}>
39
+ <Section class={cn("", className)} {...props}>
36
40
  <SectionContainer class="gap-8">
37
41
  <div class="flex flex-wrap items-end justify-between gap-4">
38
42
  <div class="flex flex-col gap-4">
@@ -43,11 +47,9 @@ const { class: className, badge, title, articles } = Astro.props
43
47
  </Badge>
44
48
  )
45
49
  }
46
- <h2
47
- class="text-3xl font-semibold tracking-tight text-balance sm:text-4xl"
48
- >
50
+ <SectionTitle>
49
51
  {title}
50
- </h2>
52
+ </SectionTitle>
51
53
  </div>
52
54
  </div>
53
55
 
@@ -1,13 +1,13 @@
1
1
  ---
2
2
  import type { ImageMetadata } from "astro"
3
+ import type { HTMLAttributes } from "astro/types"
3
4
 
4
5
  import { cn } from "@/lib/utils"
5
6
  import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
6
7
  import { Badge } from "@/components/ui/badge"
7
8
  import { Section, SectionContainer } from "@/components/ui/section"
8
9
 
9
- type Props = {
10
- class?: string
10
+ type Props = HTMLAttributes<"section"> & {
11
11
  badge?: string
12
12
  title: string
13
13
  description: string
@@ -25,10 +25,17 @@ type Props = {
25
25
  }[]
26
26
  }
27
27
 
28
- const { class: className, badge, title, description, articles } = Astro.props
28
+ const {
29
+ class: className,
30
+ badge,
31
+ title,
32
+ description,
33
+ articles,
34
+ ...props
35
+ } = Astro.props
29
36
  ---
30
37
 
31
- <Section class={cn("", className)}>
38
+ <Section class={cn("", className)} {...props}>
32
39
  <SectionContainer class="gap-8">
33
40
  <div class="mx-auto max-w-2xl text-center">
34
41
  {badge && <Badge variant="secondary">{badge}</Badge>}
@@ -1,11 +1,11 @@
1
1
  ---
2
+ import type { HTMLAttributes } from "astro/types"
2
3
  import ArrowRightIcon from "@lucide/astro/icons/arrow-right"
3
4
 
4
5
  import { cn } from "@/lib/utils"
5
6
  import { Banner, BannerContainer } from "@/components/ui/banner"
6
7
 
7
- type Props = {
8
- class?: string
8
+ type Props = HTMLAttributes<"aside"> & {
9
9
  title: string
10
10
  description: string
11
11
  link?: {
@@ -14,12 +14,13 @@ type Props = {
14
14
  }
15
15
  }
16
16
 
17
- const { class: className, title, description, link } = Astro.props
17
+ const { class: className, title, description, link, ...props } = Astro.props
18
18
  ---
19
19
 
20
20
  <Banner
21
21
  storageKey="banner-1"
22
22
  class={cn("dark bg-background text-foreground", className)}
23
+ {...props}
23
24
  >
24
25
  <BannerContainer class="flex-row items-center gap-x-4 gap-y-1">
25
26
  <p class="text-sm leading-relaxed">
@@ -1,10 +1,11 @@
1
1
  ---
2
+ import type { HTMLAttributes } from "astro/types"
3
+
2
4
  import { cn } from "@/lib/utils"
3
5
  import { Banner, BannerContainer } from "@/components/ui/banner"
4
6
  import { Button } from "@/components/ui/button"
5
7
 
6
- type Props = {
7
- class?: string
8
+ type Props = HTMLAttributes<"aside"> & {
8
9
  title: string
9
10
  description: string
10
11
  buttons?: {
@@ -14,10 +15,15 @@ type Props = {
14
15
  }[]
15
16
  }
16
17
 
17
- const { class: className, title, description, buttons } = Astro.props
18
+ const { class: className, title, description, buttons, ...props } = Astro.props
18
19
  ---
19
20
 
20
- <Banner variant="floating" storageKey="banner-2" class={cn("", className)}>
21
+ <Banner
22
+ variant="floating"
23
+ storageKey="banner-2"
24
+ class={cn("", className)}
25
+ {...props}
26
+ >
21
27
  <BannerContainer class="gap-4 py-1" showClose={false}>
22
28
  <div
23
29
  class="flex flex-1 flex-col gap-0.5 @5xl:flex-row @5xl:items-center @5xl:gap-x-4"
@@ -70,7 +70,7 @@ const showCopyButton = Boolean(copyButton)
70
70
  const showOpenButton = Boolean(markdownUrl)
71
71
  const showPagination = Boolean(previousPage || nextPage)
72
72
  const assistantPrompt = markdownUrl
73
- ? `Read ${markdownUrl}, I want to ask questions about it.`
73
+ ? `Read ${new URL(markdownUrl, Astro.site ?? Astro.url.origin).href}, I want to ask questions about it.`
74
74
  : ""
75
75
  const openLinks = markdownUrl
76
76
  ? [
@@ -1,4 +1,6 @@
1
1
  ---
2
+ import type { HTMLAttributes } from "astro/types"
3
+
2
4
  import { cn } from "@/lib/utils"
3
5
  import { Button } from "@/components/ui/button"
4
6
  import {
@@ -9,13 +11,18 @@ import {
9
11
  FieldLegend,
10
12
  FieldSet,
11
13
  } from "@/components/ui/field"
14
+ import { Form } from "@/components/ui/form"
12
15
  import { Icon } from "@/components/ui/icon"
13
16
  import { Input } from "@/components/ui/input"
14
- import { Section, SectionContainer } from "@/components/ui/section"
17
+ import {
18
+ Section,
19
+ SectionContainer,
20
+ SectionDescription,
21
+ SectionTitle,
22
+ } from "@/components/ui/section"
15
23
  import { Textarea } from "@/components/ui/textarea"
16
24
 
17
- type Props = {
18
- class?: string
25
+ type Props = HTMLAttributes<"section"> & {
19
26
  title: string
20
27
  description: string
21
28
  contactItems: {
@@ -25,6 +32,9 @@ type Props = {
25
32
  href?: string
26
33
  }[]
27
34
  form: {
35
+ id?: string
36
+ action?: string
37
+ method?: "get" | "post"
28
38
  legend: string
29
39
  nameLabel: string
30
40
  namePlaceholder: string
@@ -37,22 +47,26 @@ type Props = {
37
47
  }
38
48
  }
39
49
 
40
- const { class: className, title, description, contactItems, form } = Astro.props
50
+ const {
51
+ class: className,
52
+ title,
53
+ description,
54
+ contactItems,
55
+ form,
56
+ ...props
57
+ } = Astro.props
58
+ const formId = form.id ?? `contact-${crypto.randomUUID()}`
41
59
  ---
42
60
 
43
- <Section class={cn("", className)}>
61
+ <Section class={cn("", className)} {...props}>
44
62
  <SectionContainer class="items-center gap-6 text-center">
45
63
  <div class="flex max-w-2xl flex-col items-center gap-4">
46
- <h2
47
- class="text-foreground text-3xl font-semibold tracking-tight text-balance sm:text-4xl"
48
- >
64
+ <SectionTitle>
49
65
  {title}
50
- </h2>
51
- <p
52
- class="text-muted-foreground max-w-2xl text-lg leading-relaxed text-balance"
53
- >
66
+ </SectionTitle>
67
+ <SectionDescription class="max-w-2xl">
54
68
  {description}
55
- </p>
69
+ </SectionDescription>
56
70
  </div>
57
71
  </SectionContainer>
58
72
  <SectionContainer>
@@ -92,35 +106,54 @@ const { class: className, title, description, contactItems, form } = Astro.props
92
106
  </SectionContainer>
93
107
  <SectionContainer>
94
108
  <div class="mx-auto w-full max-w-2xl rounded-xl border p-6 sm:p-8">
95
- <FieldSet>
96
- <FieldLegend class="sr-only">{form.legend}</FieldLegend>
97
- <FieldGroup>
98
- <div class="grid gap-4 md:grid-cols-2">
99
- <Field>
100
- <FieldLabel for="contact-name-1">{form.nameLabel}</FieldLabel>
101
- <Input id="contact-name-1" placeholder={form.namePlaceholder} />
102
- </Field>
109
+ <Form id={formId} action={form.action} method={form.method ?? "post"}>
110
+ <FieldSet>
111
+ <FieldLegend class="sr-only">{form.legend}</FieldLegend>
112
+ <FieldGroup>
113
+ <div class="grid gap-4 md:grid-cols-2">
114
+ <Field>
115
+ <FieldLabel for={`${formId}-name`}>{form.nameLabel}</FieldLabel>
116
+ <Input
117
+ id={`${formId}-name`}
118
+ name="name"
119
+ autocomplete="name"
120
+ required
121
+ placeholder={form.namePlaceholder}
122
+ />
123
+ </Field>
124
+ <Field>
125
+ <FieldLabel for={`${formId}-email`}
126
+ >{form.emailLabel}</FieldLabel
127
+ >
128
+ <Input
129
+ id={`${formId}-email`}
130
+ name="email"
131
+ autocomplete="email"
132
+ required
133
+ type="email"
134
+ placeholder={form.emailPlaceholder}
135
+ />
136
+ </Field>
137
+ </div>
103
138
  <Field>
104
- <FieldLabel for="contact-email-1">{form.emailLabel}</FieldLabel>
105
- <Input
106
- id="contact-email-1"
107
- type="email"
108
- placeholder={form.emailPlaceholder}
139
+ <FieldLabel for={`${formId}-message`}
140
+ >{form.messageLabel}</FieldLabel
141
+ >
142
+ <Textarea
143
+ id={`${formId}-message`}
144
+ name="message"
145
+ required
146
+ rows={5}
147
+ placeholder={form.messagePlaceholder}
109
148
  />
149
+ <FieldDescription>{form.messageDescription}</FieldDescription>
110
150
  </Field>
111
- </div>
112
- <Field>
113
- <FieldLabel for="contact-message-1">{form.messageLabel}</FieldLabel>
114
- <Textarea
115
- id="contact-message-1"
116
- rows={5}
117
- placeholder={form.messagePlaceholder}
118
- />
119
- <FieldDescription>{form.messageDescription}</FieldDescription>
120
- </Field>
121
- <Button size="lg" class="w-full">{form.actionLabel}</Button>
122
- </FieldGroup>
123
- </FieldSet>
151
+ <Button type="submit" size="lg" class="w-full"
152
+ >{form.actionLabel}</Button
153
+ >
154
+ </FieldGroup>
155
+ </FieldSet>
156
+ </Form>
124
157
  </div>
125
158
  </SectionContainer>
126
159
  </Section>
@@ -1,4 +1,6 @@
1
1
  ---
2
+ import type { HTMLAttributes } from "astro/types"
3
+
2
4
  import { cn } from "@/lib/utils"
3
5
  import { Button } from "@/components/ui/button"
4
6
  import {
@@ -8,13 +10,17 @@ import {
8
10
  FieldLegend,
9
11
  FieldSet,
10
12
  } from "@/components/ui/field"
13
+ import { Form } from "@/components/ui/form"
11
14
  import { Icon } from "@/components/ui/icon"
12
15
  import { Input } from "@/components/ui/input"
13
- import { Section, SectionContainer } from "@/components/ui/section"
16
+ import {
17
+ Section,
18
+ SectionContainer,
19
+ SectionTitle,
20
+ } from "@/components/ui/section"
14
21
  import { Textarea } from "@/components/ui/textarea"
15
22
 
16
- type Props = {
17
- class?: string
23
+ type Props = HTMLAttributes<"section"> & {
18
24
  title: string
19
25
  description: string
20
26
  contactItems: {
@@ -24,6 +30,9 @@ type Props = {
24
30
  href?: string
25
31
  }[]
26
32
  form: {
33
+ id?: string
34
+ action?: string
35
+ method?: "get" | "post"
27
36
  title: string
28
37
  legend: string
29
38
  nameLabel: string
@@ -36,20 +45,26 @@ type Props = {
36
45
  }
37
46
  }
38
47
 
39
- const { class: className, title, description, contactItems, form } = Astro.props
48
+ const {
49
+ class: className,
50
+ title,
51
+ description,
52
+ contactItems,
53
+ form,
54
+ ...props
55
+ } = Astro.props
56
+ const formId = form.id ?? `contact-${crypto.randomUUID()}`
40
57
  ---
41
58
 
42
- <Section class={cn("", className)}>
59
+ <Section class={cn("", className)} {...props}>
43
60
  <SectionContainer
44
61
  class="grid gap-10 lg:grid-cols-[minmax(0,1fr)_22rem] lg:items-start"
45
62
  >
46
63
  <div class="flex flex-col gap-6">
47
64
  <div class="flex flex-col gap-4">
48
- <h2
49
- class="text-foreground text-3xl font-semibold tracking-tight text-balance sm:text-4xl"
50
- >
65
+ <SectionTitle>
51
66
  {title}
52
- </h2>
67
+ </SectionTitle>
53
68
  <p class="text-muted-foreground max-w-xl text-base leading-relaxed">
54
69
  {description}
55
70
  </p>
@@ -58,36 +73,55 @@ const { class: className, title, description, contactItems, form } = Astro.props
58
73
  <div class="mb-6">
59
74
  <h3 class="text-lg font-medium">{form.title}</h3>
60
75
  </div>
61
- <FieldSet>
62
- <FieldLegend class="sr-only">{form.legend}</FieldLegend>
63
- <FieldGroup>
64
- <div class="grid gap-4 md:grid-cols-2">
76
+ <Form id={formId} action={form.action} method={form.method ?? "post"}>
77
+ <FieldSet>
78
+ <FieldLegend class="sr-only">{form.legend}</FieldLegend>
79
+ <FieldGroup>
80
+ <div class="grid gap-4 md:grid-cols-2">
81
+ <Field>
82
+ <FieldLabel for={`${formId}-name`}
83
+ >{form.nameLabel}</FieldLabel
84
+ >
85
+ <Input
86
+ id={`${formId}-name`}
87
+ name="name"
88
+ autocomplete="name"
89
+ required
90
+ placeholder={form.namePlaceholder}
91
+ />
92
+ </Field>
93
+ <Field>
94
+ <FieldLabel for={`${formId}-email`}
95
+ >{form.emailLabel}</FieldLabel
96
+ >
97
+ <Input
98
+ id={`${formId}-email`}
99
+ name="email"
100
+ autocomplete="email"
101
+ required
102
+ type="email"
103
+ placeholder={form.emailPlaceholder}
104
+ />
105
+ </Field>
106
+ </div>
65
107
  <Field>
66
- <FieldLabel for="contact-name-2">{form.nameLabel}</FieldLabel>
67
- <Input id="contact-name-2" placeholder={form.namePlaceholder} />
68
- </Field>
69
- <Field>
70
- <FieldLabel for="contact-email-2">{form.emailLabel}</FieldLabel>
71
- <Input
72
- id="contact-email-2"
73
- type="email"
74
- placeholder={form.emailPlaceholder}
108
+ <FieldLabel for={`${formId}-message`}
109
+ >{form.messageLabel}</FieldLabel
110
+ >
111
+ <Textarea
112
+ id={`${formId}-message`}
113
+ name="message"
114
+ required
115
+ rows={5}
116
+ placeholder={form.messagePlaceholder}
75
117
  />
76
118
  </Field>
77
- </div>
78
- <Field>
79
- <FieldLabel for="contact-message-2"
80
- >{form.messageLabel}</FieldLabel
119
+ <Button type="submit" size="lg" class="w-full"
120
+ >{form.actionLabel}</Button
81
121
  >
82
- <Textarea
83
- id="contact-message-2"
84
- rows={5}
85
- placeholder={form.messagePlaceholder}
86
- />
87
- </Field>
88
- <Button size="lg" class="w-full">{form.actionLabel}</Button>
89
- </FieldGroup>
90
- </FieldSet>
122
+ </FieldGroup>
123
+ </FieldSet>
124
+ </Form>
91
125
  </div>
92
126
  </div>
93
127