@notionhive/footers 0.1.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 (197) hide show
  1. package/bin/footers.js +16 -0
  2. package/category.config.json +7 -0
  3. package/package.json +24 -0
  4. package/registry/footer-01.json +6 -0
  5. package/registry/footer-02.json +9 -0
  6. package/registry/footer-03.json +9 -0
  7. package/registry/footer-04.json +9 -0
  8. package/registry/footer-05.json +9 -0
  9. package/registry/footer-06.json +7 -0
  10. package/registry/footer-07.json +9 -0
  11. package/registry/footer-08.json +9 -0
  12. package/registry/footer-09.json +9 -0
  13. package/registry/footer-10.json +9 -0
  14. package/registry/footer-11.json +7 -0
  15. package/registry/footer-12.json +9 -0
  16. package/registry/footer-13.json +9 -0
  17. package/registry/footer-14.json +9 -0
  18. package/registry/footer-15.json +9 -0
  19. package/registry/footer-16.json +9 -0
  20. package/registry/footer-17.json +9 -0
  21. package/registry/footer-18.json +9 -0
  22. package/registry/footer-19.json +9 -0
  23. package/registry/footer-20.json +9 -0
  24. package/registry/footer-21.json +9 -0
  25. package/registry/footer-22.json +9 -0
  26. package/registry/footer-23.json +9 -0
  27. package/registry/footer-24.json +9 -0
  28. package/registry/footer-25.json +9 -0
  29. package/registry/footer-26.json +9 -0
  30. package/registry/footer-27.json +9 -0
  31. package/registry/footer-28.json +9 -0
  32. package/registry/footer-29.json +6 -0
  33. package/registry/footer-30.json +6 -0
  34. package/registry/index.json +263 -0
  35. package/templates/components/atoms/SafeImage/SafeImage.jsx +101 -0
  36. package/templates/components/atoms/SafeImage/index.js +1 -0
  37. package/templates/components/organisms/Footer01/Footer01.jsx +142 -0
  38. package/templates/components/organisms/Footer01/Footer01.propTypes.js +110 -0
  39. package/templates/components/organisms/Footer01/index.js +1 -0
  40. package/templates/components/organisms/Footer02/Footer02.jsx +136 -0
  41. package/templates/components/organisms/Footer02/Footer02.propTypes.js +112 -0
  42. package/templates/components/organisms/Footer02/index.js +1 -0
  43. package/templates/components/organisms/Footer03/Footer03.jsx +162 -0
  44. package/templates/components/organisms/Footer03/Footer03.propTypes.js +73 -0
  45. package/templates/components/organisms/Footer03/index.js +1 -0
  46. package/templates/components/organisms/Footer04/Footer04.jsx +128 -0
  47. package/templates/components/organisms/Footer04/Footer04.propTypes.js +93 -0
  48. package/templates/components/organisms/Footer04/index.js +1 -0
  49. package/templates/components/organisms/Footer05/Footer05.jsx +101 -0
  50. package/templates/components/organisms/Footer05/Footer05.propTypes.js +42 -0
  51. package/templates/components/organisms/Footer05/index.js +1 -0
  52. package/templates/components/organisms/Footer06/Footer06.jsx +170 -0
  53. package/templates/components/organisms/Footer06/Footer06.propTypes.js +53 -0
  54. package/templates/components/organisms/Footer06/index.js +1 -0
  55. package/templates/components/organisms/Footer07/Footer07.jsx +253 -0
  56. package/templates/components/organisms/Footer07/Footer07.propTypes.js +83 -0
  57. package/templates/components/organisms/Footer07/index.js +1 -0
  58. package/templates/components/organisms/Footer08/Footer08.jsx +183 -0
  59. package/templates/components/organisms/Footer08/Footer08.propTypes.js +92 -0
  60. package/templates/components/organisms/Footer08/index.js +1 -0
  61. package/templates/components/organisms/Footer09/Footer09.jsx +199 -0
  62. package/templates/components/organisms/Footer09/Footer09.propTypes.js +76 -0
  63. package/templates/components/organisms/Footer09/index.js +1 -0
  64. package/templates/components/organisms/Footer10/Footer10.jsx +172 -0
  65. package/templates/components/organisms/Footer10/Footer10.propTypes.js +38 -0
  66. package/templates/components/organisms/Footer10/index.js +1 -0
  67. package/templates/components/organisms/Footer11/Footer11.jsx +107 -0
  68. package/templates/components/organisms/Footer11/Footer11.propTypes.js +64 -0
  69. package/templates/components/organisms/Footer11/index.js +1 -0
  70. package/templates/components/organisms/Footer12/Footer12.jsx +122 -0
  71. package/templates/components/organisms/Footer12/Footer12.propTypes.js +94 -0
  72. package/templates/components/organisms/Footer12/index.js +1 -0
  73. package/templates/components/organisms/Footer13/Footer13.jsx +156 -0
  74. package/templates/components/organisms/Footer13/Footer13.propTypes.js +80 -0
  75. package/templates/components/organisms/Footer13/index.js +1 -0
  76. package/templates/components/organisms/Footer14/Footer14.jsx +157 -0
  77. package/templates/components/organisms/Footer14/Footer14.propTypes.js +60 -0
  78. package/templates/components/organisms/Footer14/index.js +1 -0
  79. package/templates/components/organisms/Footer15/Footer15.jsx +184 -0
  80. package/templates/components/organisms/Footer15/Footer15.propTypes.js +58 -0
  81. package/templates/components/organisms/Footer15/index.js +1 -0
  82. package/templates/components/organisms/Footer16/Footer16.jsx +87 -0
  83. package/templates/components/organisms/Footer16/Footer16.propTypes.js +73 -0
  84. package/templates/components/organisms/Footer16/index.js +1 -0
  85. package/templates/components/organisms/Footer17/Footer17.jsx +176 -0
  86. package/templates/components/organisms/Footer17/Footer17.propTypes.js +117 -0
  87. package/templates/components/organisms/Footer17/index.js +1 -0
  88. package/templates/components/organisms/Footer18/Footer18.jsx +236 -0
  89. package/templates/components/organisms/Footer18/Footer18.propTypes.js +92 -0
  90. package/templates/components/organisms/Footer18/index.js +1 -0
  91. package/templates/components/organisms/Footer19/Footer19.jsx +287 -0
  92. package/templates/components/organisms/Footer19/Footer19.propTypes.js +116 -0
  93. package/templates/components/organisms/Footer19/index.js +1 -0
  94. package/templates/components/organisms/Footer20/Footer20.jsx +201 -0
  95. package/templates/components/organisms/Footer20/Footer20.propTypes.js +70 -0
  96. package/templates/components/organisms/Footer20/index.js +1 -0
  97. package/templates/components/organisms/Footer21/Footer21.jsx +134 -0
  98. package/templates/components/organisms/Footer21/Footer21.propTypes.js +122 -0
  99. package/templates/components/organisms/Footer21/index.js +1 -0
  100. package/templates/components/organisms/Footer22/Footer22.jsx +136 -0
  101. package/templates/components/organisms/Footer22/Footer22.propTypes.js +58 -0
  102. package/templates/components/organisms/Footer22/index.js +1 -0
  103. package/templates/components/organisms/Footer23/Footer23.jsx +177 -0
  104. package/templates/components/organisms/Footer23/Footer23.propTypes.js +97 -0
  105. package/templates/components/organisms/Footer23/index.js +1 -0
  106. package/templates/components/organisms/Footer24/Footer24.jsx +192 -0
  107. package/templates/components/organisms/Footer24/Footer24.propTypes.js +132 -0
  108. package/templates/components/organisms/Footer24/index.js +1 -0
  109. package/templates/components/organisms/Footer25/Footer25.jsx +135 -0
  110. package/templates/components/organisms/Footer25/Footer25.propTypes.js +124 -0
  111. package/templates/components/organisms/Footer25/index.js +1 -0
  112. package/templates/components/organisms/Footer26/Footer26.jsx +167 -0
  113. package/templates/components/organisms/Footer26/Footer26.propTypes.js +54 -0
  114. package/templates/components/organisms/Footer26/index.js +1 -0
  115. package/templates/components/organisms/Footer27/Footer27.jsx +171 -0
  116. package/templates/components/organisms/Footer27/Footer27.propTypes.js +105 -0
  117. package/templates/components/organisms/Footer27/index.js +1 -0
  118. package/templates/components/organisms/Footer28/Footer28.jsx +98 -0
  119. package/templates/components/organisms/Footer28/Footer28.propTypes.js +96 -0
  120. package/templates/components/organisms/Footer28/index.js +1 -0
  121. package/templates/components/organisms/Footer29/Footer29.jsx +118 -0
  122. package/templates/components/organisms/Footer29/Footer29.propTypes.js +68 -0
  123. package/templates/components/organisms/Footer29/index.js +1 -0
  124. package/templates/components/organisms/Footer30/Footer30.jsx +92 -0
  125. package/templates/components/organisms/Footer30/Footer30.propTypes.js +51 -0
  126. package/templates/components/organisms/Footer30/index.js +1 -0
  127. package/templates/public/footer/footer02/payment-01.png +0 -0
  128. package/templates/public/footer/footer02/payment-02.png +0 -0
  129. package/templates/public/footer/footer02/payment-03.png +0 -0
  130. package/templates/public/footer/footer02/payment-04.png +0 -0
  131. package/templates/public/footer/footer02/payment-05.png +0 -0
  132. package/templates/public/footer/footer02/payment-06.png +0 -0
  133. package/templates/public/footer/footer02/payment-07.png +0 -0
  134. package/templates/public/footer/footer02/payment-08.png +0 -0
  135. package/templates/public/footer/footer02/payment-09.svg +5 -0
  136. package/templates/public/footer/footer02/payment-10.svg +11 -0
  137. package/templates/public/footer/footer02/payment-11.svg +22 -0
  138. package/templates/public/footer/footer02/payment-12.svg +25 -0
  139. package/templates/public/footer/footer02/payment-13.svg +10 -0
  140. package/templates/public/footer/footer02/payment-14.svg +36 -0
  141. package/templates/public/footer/footer02/payment-15.svg +18 -0
  142. package/templates/public/footer/footer02/payment-sprite-01.png +0 -0
  143. package/templates/public/footer/footer02/payment-sprite-02.png +0 -0
  144. package/templates/public/footer/footer02/payment-sprite-03.png +0 -0
  145. package/templates/public/footer/footer02/payment-sprite-04.png +0 -0
  146. package/templates/public/footer/footer02/payment-sprite-05.png +0 -0
  147. package/templates/public/footer/footer02/payment-sprite-06.png +0 -0
  148. package/templates/public/footer/footer03/logo-mask.png +0 -0
  149. package/templates/public/footer/footer03/logo.png +0 -0
  150. package/templates/public/footer/footer04/logo.svg +45 -0
  151. package/templates/public/footer/footer05/brand-watermark.png +0 -0
  152. package/templates/public/footer/footer07/logo.png +0 -0
  153. package/templates/public/footer/footer07/watch-hero.png +0 -0
  154. package/templates/public/footer/footer07/watch-overlay.png +0 -0
  155. package/templates/public/footer/footer08/logo.png +0 -0
  156. package/templates/public/footer/footer08/logo.svg +3 -0
  157. package/templates/public/footer/footer09/logo.svg +13 -0
  158. package/templates/public/footer/footer10/hero-image.png +0 -0
  159. package/templates/public/footer/footer10/hero-mask-download.svg +3 -0
  160. package/templates/public/footer/footer10/hero-mask.svg +3 -0
  161. package/templates/public/footer/footer12/logo-icon.svg +3 -0
  162. package/templates/public/footer/footer12/refugee-logo.png +0 -0
  163. package/templates/public/footer/footer13/logo.png +0 -0
  164. package/templates/public/footer/footer14/logo.png +0 -0
  165. package/templates/public/footer/footer15/logo.svg +19 -0
  166. package/templates/public/footer/footer16/logo.svg +6 -0
  167. package/templates/public/footer/footer17/logo-left.svg +11 -0
  168. package/templates/public/footer/footer17/logo-right.svg +36 -0
  169. package/templates/public/footer/footer18/logo.png +108 -0
  170. package/templates/public/footer/footer18/logo.svg +108 -0
  171. package/templates/public/footer/footer19/logo.png +0 -0
  172. package/templates/public/footer/footer19/payment-bkash.png +0 -0
  173. package/templates/public/footer/footer19/payment-mastercard.svg +12 -0
  174. package/templates/public/footer/footer19/payment-nagad.png +0 -0
  175. package/templates/public/footer/footer19/payment-nexus.png +0 -0
  176. package/templates/public/footer/footer19/payment-rocket.png +0 -0
  177. package/templates/public/footer/footer19/payment-upay.png +0 -0
  178. package/templates/public/footer/footer19/payment-visa.svg +6 -0
  179. package/templates/public/footer/footer20/bg.png +0 -0
  180. package/templates/public/footer/footer20/logo.png +0 -0
  181. package/templates/public/footer/footer21/logo.png +0 -0
  182. package/templates/public/footer/footer22/logo-icon.svg +10 -0
  183. package/templates/public/footer/footer22/logo-name.svg +5 -0
  184. package/templates/public/footer/footer22/logo-tagline.svg +5 -0
  185. package/templates/public/footer/footer23/logo-icon.svg +10 -0
  186. package/templates/public/footer/footer23/logo-name.svg +20 -0
  187. package/templates/public/footer/footer23/logo-tagline.svg +17 -0
  188. package/templates/public/footer/footer24/logo.svg +46 -0
  189. package/templates/public/footer/footer24/map.png +0 -0
  190. package/templates/public/footer/footer25/logo-icon.svg +15 -0
  191. package/templates/public/footer/footer25/logo-text.svg +42 -0
  192. package/templates/public/footer/footer25/map-pin.svg +7 -0
  193. package/templates/public/footer/footer25/map.png +0 -0
  194. package/templates/public/footer/footer26/logo-jpl.svg +5 -0
  195. package/templates/public/footer/footer26/logo.png +0 -0
  196. package/templates/public/footer/footer27/logo.png +0 -0
  197. package/templates/public/footer/footer28/logo.png +0 -0
@@ -0,0 +1,162 @@
1
+ "use client";
2
+
3
+ import { useState } from "react";
4
+ import { SafeImage } from "../../atoms/SafeImage";
5
+ import {
6
+ footer03DefaultProps,
7
+ footer03PropTypes,
8
+ } from "./Footer03.propTypes";
9
+
10
+ function ArrowIcon({ className = "" }) {
11
+ return (
12
+ <svg viewBox="0 0 24 24" fill="none" aria-hidden="true" className={className}>
13
+ <path
14
+ d="M5 12h14M13 6l6 6-6 6"
15
+ stroke="currentColor"
16
+ strokeWidth="1.5"
17
+ strokeLinecap="round"
18
+ strokeLinejoin="round"
19
+ />
20
+ </svg>
21
+ );
22
+ }
23
+
24
+ function LinkColumn({ column }) {
25
+ return (
26
+ <div className="flex min-w-0 flex-col gap-6">
27
+ <p className="text-sm font-medium uppercase tracking-wide text-white">{column.title}</p>
28
+ <ul className="flex flex-col gap-2 sm:gap-3">
29
+ {column.links.map((link) => (
30
+ <li key={link.label}>
31
+ <a
32
+ href={link.href ?? "#"}
33
+ className="text-sm text-white/80 transition-colors duration-200 ease-out hover:text-white focus-visible:outline-2 focus-visible:outline-offset-2"
34
+ >
35
+ {link.label}
36
+ </a>
37
+ </li>
38
+ ))}
39
+ </ul>
40
+ </div>
41
+ );
42
+ }
43
+
44
+ /**
45
+ * Footer03 — Mir Ceramic dark green footer with newsletter.
46
+ * Figma node 32:19379 at 1920px.
47
+ */
48
+ export function Footer03({
49
+ phone = footer03DefaultProps.phone,
50
+ email: controlledEmail,
51
+ address = footer03DefaultProps.address,
52
+ linkColumns = footer03DefaultProps.linkColumns,
53
+ newsletterPlaceholder = footer03DefaultProps.newsletterPlaceholder,
54
+ newsletterCaption = footer03DefaultProps.newsletterCaption,
55
+ onEmailChange,
56
+ onNewsletterSubmit,
57
+ copyright = footer03DefaultProps.copyright,
58
+ privacyHref = footer03DefaultProps.privacyHref,
59
+ termsHref = footer03DefaultProps.termsHref,
60
+ className = "",
61
+ }) {
62
+ const [internalEmail, setInternalEmail] = useState("");
63
+ const email = controlledEmail ?? internalEmail;
64
+
65
+ const handleEmailChange = (event) => {
66
+ onEmailChange?.(event.target.value);
67
+ if (controlledEmail === undefined) setInternalEmail(event.target.value);
68
+ };
69
+
70
+ const handleSubmit = (event) => {
71
+ event.preventDefault();
72
+ onNewsletterSubmit?.(email);
73
+ };
74
+
75
+ return (
76
+ <footer
77
+ className={["relative w-full overflow-hidden bg-[#0d1912]", className]
78
+ .filter(Boolean)
79
+ .join(" ")}
80
+ data-footer="footer03"
81
+ >
82
+ <div className="mx-auto flex w-full max-w-[1920px] flex-col gap-10 px-4 py-12 sm:px-6 md:gap-12 md:px-10 lg:px-20 xl:gap-[60px] xl:px-[80px] xl:pt-[140px]">
83
+ <div className="flex flex-col gap-10 lg:flex-row lg:items-start lg:justify-between xl:gap-16">
84
+ <div className="flex max-w-md flex-col gap-8 xl:max-w-[470px] xl:gap-[60px]">
85
+ <SafeImage
86
+ src="/footer/footer03/logo.png"
87
+ alt="Mir Ceramic"
88
+ width={120}
89
+ height={80}
90
+ className="h-12 w-auto sm:h-16 sm:w-[120px]"
91
+ />
92
+ <div className="flex flex-col gap-4 text-sm text-white/80 sm:gap-5 sm:text-base">
93
+ <a
94
+ href={`tel:${phone.replace(/\s/g, "")}`}
95
+ className="transition-colors duration-200 ease-out hover:text-white focus-visible:outline-2 focus-visible:outline-offset-2"
96
+ >
97
+ {phone}
98
+ </a>
99
+ <a
100
+ href="mailto:sales.info@mirceramic.com"
101
+ className="transition-colors duration-200 ease-out hover:text-white focus-visible:outline-2 focus-visible:outline-offset-2"
102
+ >
103
+ sales.info@mirceramic.com
104
+ </a>
105
+ <p>{address}</p>
106
+ </div>
107
+ </div>
108
+
109
+ <div className="grid grid-cols-1 gap-8 sm:grid-cols-2 lg:grid-cols-4 lg:gap-10 xl:gap-12">
110
+ {linkColumns.map((column) => (
111
+ <LinkColumn key={column.title} column={column} />
112
+ ))}
113
+ <div className="flex flex-col gap-6 sm:gap-8">
114
+ <p className="text-sm font-medium uppercase tracking-wide text-white">newsletter</p>
115
+ <form onSubmit={handleSubmit} className="flex flex-col gap-2">
116
+ <div className="flex items-center gap-4 border-b border-white/20 py-4">
117
+ <input
118
+ type="email"
119
+ value={email}
120
+ onChange={handleEmailChange}
121
+ placeholder={newsletterPlaceholder}
122
+ className="min-w-0 flex-1 bg-transparent text-xs font-medium uppercase tracking-widest text-white/70 outline-none placeholder:text-white/60"
123
+ />
124
+ <button
125
+ type="submit"
126
+ aria-label="Subscribe"
127
+ className="shrink-0 text-white transition-opacity duration-200 ease-out hover:opacity-80 focus-visible:outline-2 focus-visible:outline-offset-2"
128
+ >
129
+ <ArrowIcon className="size-6" />
130
+ </button>
131
+ </div>
132
+ <p className="text-sm text-white/70">{newsletterCaption}</p>
133
+ </form>
134
+ </div>
135
+ </div>
136
+ </div>
137
+
138
+ <div className="flex flex-col gap-5 border-t border-white/20 pt-5 sm:flex-row sm:items-center sm:justify-between">
139
+ <p className="text-sm text-white/60">{copyright}</p>
140
+ <div className="flex flex-wrap gap-6 text-sm text-white/60 sm:gap-10">
141
+ <a
142
+ href={privacyHref ?? "#"}
143
+ className="transition-colors duration-200 ease-out hover:text-white focus-visible:outline-2 focus-visible:outline-offset-2"
144
+ >
145
+ Privacy Policy
146
+ </a>
147
+ <a
148
+ href={termsHref ?? "#"}
149
+ className="transition-colors duration-200 ease-out hover:text-white focus-visible:outline-2 focus-visible:outline-offset-2"
150
+ >
151
+ Terms & Condition
152
+ </a>
153
+ </div>
154
+ </div>
155
+ </div>
156
+ </footer>
157
+ );
158
+ }
159
+
160
+ Footer03.propTypes = footer03PropTypes;
161
+
162
+ export default Footer03;
@@ -0,0 +1,73 @@
1
+ import PropTypes from "prop-types";
2
+
3
+ const linkShape = PropTypes.shape({
4
+ label: PropTypes.string.isRequired,
5
+ href: PropTypes.string,
6
+ });
7
+
8
+ const columnShape = PropTypes.shape({
9
+ title: PropTypes.string.isRequired,
10
+ links: PropTypes.arrayOf(linkShape),
11
+ });
12
+
13
+ export const footer03PropTypes = {
14
+ phone: PropTypes.string,
15
+ email: PropTypes.string,
16
+ address: PropTypes.string,
17
+ linkColumns: PropTypes.arrayOf(columnShape),
18
+ newsletterPlaceholder: PropTypes.string,
19
+ newsletterCaption: PropTypes.string,
20
+ onEmailChange: PropTypes.func,
21
+ onNewsletterSubmit: PropTypes.func,
22
+ copyright: PropTypes.string,
23
+ privacyHref: PropTypes.string,
24
+ termsHref: PropTypes.string,
25
+ className: PropTypes.string,
26
+ };
27
+
28
+ export const footer03DefaultProps = {
29
+ phone: "+8801713-296300",
30
+ email: "",
31
+ address:
32
+ "Red Crescent Borak Tower (Level-7) 37/3/A, Eskaton Garden Road, Dhaka-1000, Bangladesh.",
33
+ linkColumns: [
34
+ {
35
+ title: "Products",
36
+ links: [
37
+ { label: "Floor Tiles", href: "#" },
38
+ { label: "Wall Tiles", href: "#" },
39
+ { label: "Stair Tiles", href: "#" },
40
+ { label: "Parking & Rooftop Tiles", href: "#" },
41
+ { label: "Outdoor Tiles", href: "#" },
42
+ { label: "Commercial", href: "#" },
43
+ ],
44
+ },
45
+ {
46
+ title: "Quick Links",
47
+ links: [
48
+ { label: "Catalogue", href: "#" },
49
+ { label: "Store Locator", href: "#" },
50
+ { label: "About Us", href: "#" },
51
+ { label: "Career", href: "#" },
52
+ { label: "Blog", href: "#" },
53
+ { label: "Contact us", href: "#" },
54
+ ],
55
+ },
56
+ {
57
+ title: "Follow us",
58
+ links: [
59
+ { label: "Linkedin", href: "#" },
60
+ { label: "Instagram", href: "#" },
61
+ { label: "Whatsapp", href: "#" },
62
+ ],
63
+ },
64
+ ],
65
+ newsletterPlaceholder: "Email",
66
+ newsletterCaption: "Get our weekly newsletter",
67
+ onEmailChange: undefined,
68
+ onNewsletterSubmit: undefined,
69
+ copyright: "© 2026 Mir Ceramic. All rights reserved",
70
+ privacyHref: "#",
71
+ termsHref: "#",
72
+ className: "",
73
+ };
@@ -0,0 +1 @@
1
+ export { Footer03, default } from "./Footer03";
@@ -0,0 +1,128 @@
1
+ "use client";
2
+
3
+ import { useState } from "react";
4
+ import { SafeImage } from "../../atoms/SafeImage";
5
+ import {
6
+ footer04DefaultProps,
7
+ footer04PropTypes,
8
+ } from "./Footer04.propTypes";
9
+
10
+ function LinkColumn({ column }) {
11
+ return (
12
+ <div className="flex min-w-0 flex-col gap-8 sm:gap-10 xl:gap-[50px]">
13
+ <p className="text-base text-white">{column.title}</p>
14
+ <ul className="flex flex-col gap-2">
15
+ {column.links.map((link) => (
16
+ <li key={link.label}>
17
+ <a
18
+ href={link.href ?? "#"}
19
+ className="text-base text-[#97989f] transition-colors duration-200 ease-out hover:text-white focus-visible:outline-2 focus-visible:outline-offset-2"
20
+ >
21
+ {link.label}
22
+ </a>
23
+ </li>
24
+ ))}
25
+ </ul>
26
+ </div>
27
+ );
28
+ }
29
+
30
+ /**
31
+ * Footer04 — Platform One dark newsletter + multi-column footer.
32
+ * Figma node 32:19446 at 1920px.
33
+ */
34
+ export function Footer04({
35
+ description = footer04DefaultProps.description,
36
+ emailPlaceholder = footer04DefaultProps.emailPlaceholder,
37
+ submitLabel = footer04DefaultProps.submitLabel,
38
+ newsletterCaption = footer04DefaultProps.newsletterCaption,
39
+ email: controlledEmail,
40
+ onEmailChange,
41
+ onNewsletterSubmit,
42
+ linkColumns = footer04DefaultProps.linkColumns,
43
+ copyright = footer04DefaultProps.copyright,
44
+ siteByLabel = footer04DefaultProps.siteByLabel,
45
+ siteByHref = footer04DefaultProps.siteByHref,
46
+ className = "",
47
+ }) {
48
+ const [internalEmail, setInternalEmail] = useState("");
49
+ const email = controlledEmail ?? internalEmail;
50
+
51
+ const handleEmailChange = (event) => {
52
+ onEmailChange?.(event.target.value);
53
+ if (controlledEmail === undefined) setInternalEmail(event.target.value);
54
+ };
55
+
56
+ const handleSubmit = (event) => {
57
+ event.preventDefault();
58
+ onNewsletterSubmit?.(email);
59
+ };
60
+
61
+ return (
62
+ <footer
63
+ className={["relative w-full overflow-hidden bg-[#020617]", className]
64
+ .filter(Boolean)
65
+ .join(" ")}
66
+ data-footer="footer04"
67
+ >
68
+ <div className="mx-auto flex w-full max-w-[1920px] flex-col gap-10 px-4 py-12 sm:px-6 md:px-10 lg:gap-14 lg:px-20 lg:py-20 xl:gap-[60px] xl:px-[160px] xl:pt-[100px]">
69
+ <div className="flex flex-col gap-10 lg:flex-row lg:items-start lg:justify-between lg:gap-16">
70
+ <div className="flex max-w-lg flex-col gap-5">
71
+ <SafeImage
72
+ src="/footer/footer04/logo.svg"
73
+ alt="Platform One"
74
+ width={388}
75
+ height={64}
76
+ className="h-10 w-auto sm:h-12 md:h-16 md:max-w-[388px]"
77
+ />
78
+ <p className="text-base tracking-wide text-[#c8c9cd]">{description}</p>
79
+ </div>
80
+
81
+ <form onSubmit={handleSubmit} className="flex w-full max-w-lg flex-col gap-2.5">
82
+ <input
83
+ type="email"
84
+ value={email}
85
+ onChange={handleEmailChange}
86
+ placeholder={emailPlaceholder}
87
+ className="w-full rounded-full bg-[#343744] px-5 py-3.5 text-base text-[#97989f] outline-none transition-colors duration-200 ease-out placeholder:text-[#97989f] focus-visible:ring-2 focus-visible:ring-white/30"
88
+ />
89
+ <button
90
+ type="submit"
91
+ className="w-full rounded-full bg-white px-8 py-5 text-base font-medium text-black transition-opacity duration-200 ease-out hover:opacity-90 focus-visible:outline-2 focus-visible:outline-offset-2"
92
+ >
93
+ {submitLabel}
94
+ </button>
95
+ <p className="text-base text-[#c8c9cd]">{newsletterCaption}</p>
96
+ </form>
97
+ </div>
98
+
99
+ <div className="h-px w-full bg-[#343744]/60" />
100
+
101
+ <div className="grid grid-cols-2 gap-8 sm:grid-cols-3 lg:grid-cols-6 lg:gap-6 xl:justify-between">
102
+ {linkColumns.map((column) => (
103
+ <LinkColumn key={column.title} column={column} />
104
+ ))}
105
+ </div>
106
+
107
+ <div className="h-px w-full bg-[#343744]/60" />
108
+
109
+ <div className="flex flex-col gap-3 text-sm text-[#97989f] sm:flex-row sm:items-center sm:justify-between sm:text-base">
110
+ <p>{copyright}</p>
111
+ <p>
112
+ Site by{" "}
113
+ <a
114
+ href={siteByHref ?? "#"}
115
+ className="text-[#e1e2e3] underline transition-colors duration-200 ease-out hover:text-white focus-visible:outline-2 focus-visible:outline-offset-2"
116
+ >
117
+ {siteByLabel}
118
+ </a>
119
+ </p>
120
+ </div>
121
+ </div>
122
+ </footer>
123
+ );
124
+ }
125
+
126
+ Footer04.propTypes = footer04PropTypes;
127
+
128
+ export default Footer04;
@@ -0,0 +1,93 @@
1
+ import PropTypes from "prop-types";
2
+
3
+ const linkShape = PropTypes.shape({
4
+ label: PropTypes.string.isRequired,
5
+ href: PropTypes.string,
6
+ });
7
+
8
+ const columnShape = PropTypes.shape({
9
+ title: PropTypes.string.isRequired,
10
+ links: PropTypes.arrayOf(linkShape),
11
+ });
12
+
13
+ export const footer04PropTypes = {
14
+ description: PropTypes.string,
15
+ emailPlaceholder: PropTypes.string,
16
+ submitLabel: PropTypes.string,
17
+ newsletterCaption: PropTypes.string,
18
+ email: PropTypes.string,
19
+ onEmailChange: PropTypes.func,
20
+ onNewsletterSubmit: PropTypes.func,
21
+ linkColumns: PropTypes.arrayOf(columnShape),
22
+ copyright: PropTypes.string,
23
+ siteByLabel: PropTypes.string,
24
+ siteByHref: PropTypes.string,
25
+ className: PropTypes.string,
26
+ };
27
+
28
+ export const footer04DefaultProps = {
29
+ description:
30
+ "Experience Intelligence that drives meaningful change. Trusted by global brands to deliver human-centered insights that scale.",
31
+ emailPlaceholder: "E-mail Address",
32
+ submitLabel: "Unlock Exclusive CX Trends",
33
+ newsletterCaption:
34
+ "Join CX leaders and industry innovators. Get the latest insights, trends, and best practices delivered straight to your inbox.",
35
+ email: "",
36
+ linkColumns: [
37
+ {
38
+ title: "Services",
39
+ links: [
40
+ { label: "Customer Experience", href: "#" },
41
+ { label: "Insight Communities", href: "#" },
42
+ { label: "Market Insights", href: "#" },
43
+ { label: "Syndicated Research", href: "#" },
44
+ { label: "Behavioural Tracking", href: "#" },
45
+ ],
46
+ },
47
+ {
48
+ title: "Resources",
49
+ links: [
50
+ { label: "Insights", href: "#" },
51
+ { label: "Webinars", href: "#" },
52
+ { label: "Press Releases", href: "#" },
53
+ { label: "Podcasts", href: "#" },
54
+ ],
55
+ },
56
+ {
57
+ title: "Company",
58
+ links: [
59
+ { label: "About Platform One", href: "#" },
60
+ { label: "Life at Platform One", href: "#" },
61
+ { label: "Careers", href: "#" },
62
+ ],
63
+ },
64
+ {
65
+ title: "Legal",
66
+ links: [
67
+ { label: "Privacy Policy", href: "#" },
68
+ { label: "Terms & Conditions", href: "#" },
69
+ { label: "Sitemap", href: "#" },
70
+ ],
71
+ },
72
+ {
73
+ title: "Connect",
74
+ links: [
75
+ { label: "Book a Demo", href: "#" },
76
+ { label: "Partner With Us", href: "#" },
77
+ ],
78
+ },
79
+ {
80
+ title: "Socials",
81
+ links: [
82
+ { label: "X (Twitter)", href: "#" },
83
+ { label: "LinkedIn", href: "#" },
84
+ { label: "Facebook", href: "#" },
85
+ { label: "Instagram", href: "#" },
86
+ ],
87
+ },
88
+ ],
89
+ copyright: "© 2025 Platform One. All rights reserved.",
90
+ siteByLabel: "Notionhive",
91
+ siteByHref: "#",
92
+ className: "",
93
+ };
@@ -0,0 +1 @@
1
+ export { Footer04, default } from "./Footer04";
@@ -0,0 +1,101 @@
1
+ "use client";
2
+
3
+ import { SafeImage } from "../../atoms/SafeImage";
4
+ import {
5
+ footer05DefaultProps,
6
+ footer05PropTypes,
7
+ } from "./Footer05.propTypes";
8
+
9
+ /**
10
+ * Footer05 — M&U Group minimal nav footer with brand watermark.
11
+ * Figma node 32:20210 at 1920px.
12
+ */
13
+ export function Footer05({
14
+ navLinks = footer05DefaultProps.navLinks,
15
+ contactLabel = footer05DefaultProps.contactLabel,
16
+ contactHref = footer05DefaultProps.contactHref,
17
+ copyright = footer05DefaultProps.copyright,
18
+ socialLinks = footer05DefaultProps.socialLinks,
19
+ privacyHref = footer05DefaultProps.privacyHref,
20
+ className = "",
21
+ }) {
22
+ return (
23
+ <footer
24
+ className={["relative w-full min-h-[580px] overflow-hidden bg-[#fffbf5]", className]
25
+ .filter(Boolean)
26
+ .join(" ")}
27
+ data-footer="footer05"
28
+ >
29
+ <div
30
+ className="pointer-events-none absolute inset-x-0 bottom-0 h-[581px] bg-gradient-to-b from-[rgba(95,204,29,0)] via-[rgba(95,204,29,0.45)] to-[#5fcc1d] opacity-100 blur-[26px]"
31
+ aria-hidden="true"
32
+ />
33
+ <div className="pointer-events-none absolute inset-x-0 bottom-0 h-16 bg-[#5fcc1d]" aria-hidden="true" />
34
+ <div className="pointer-events-none absolute bottom-[64px] left-1/2 h-[min(723px,55vh)] w-[min(1914px,100%)] -translate-x-1/2 opacity-20">
35
+ <SafeImage
36
+ src="/footer/footer05/brand-watermark.png"
37
+ alt=""
38
+ fill
39
+ className="object-contain object-bottom"
40
+ />
41
+ </div>
42
+
43
+ <div className="relative mx-auto w-full max-w-[1920px] px-4 pb-20 pt-16 sm:px-6 md:px-10 lg:px-20 xl:px-[80px] xl:pb-24 xl:pt-[180px]">
44
+ <div className="mx-auto w-full max-w-[1760px]">
45
+ <div className="flex flex-col gap-0 border-t border-[#141313]/10 py-8 sm:flex-row sm:items-center sm:justify-between xl:py-8">
46
+ <nav className="flex flex-wrap items-center gap-6 text-xl text-[#141313]">
47
+ {navLinks.map((link) => (
48
+ <a
49
+ key={link.label}
50
+ href={link.href ?? "#"}
51
+ className={[
52
+ "transition-colors duration-200 ease-out hover:text-[#141313] focus-visible:outline-2 focus-visible:outline-offset-2",
53
+ link.active ? "text-[#141313]" : "text-[#141313]/50",
54
+ ].join(" ")}
55
+ >
56
+ {link.label}
57
+ </a>
58
+ ))}
59
+ </nav>
60
+ <a
61
+ href={contactHref ?? "#"}
62
+ className="mt-4 flex w-max flex-col items-end sm:mt-0"
63
+ >
64
+ <span className="text-xl text-[#141313] transition-colors duration-200 ease-out hover:opacity-70">
65
+ {contactLabel}
66
+ </span>
67
+ <span className="mt-0.5 block h-0.5 w-full bg-[#141313]" />
68
+ </a>
69
+ </div>
70
+
71
+ <div className="relative flex min-h-[92px] flex-col items-center justify-center gap-6 border-t border-[#141313]/10 py-6 lg:block lg:py-0">
72
+ <p className="text-center text-xl leading-7 text-[#141313]/70 lg:absolute lg:left-0 lg:top-[31px] lg:text-left">
73
+ {copyright}
74
+ </p>
75
+ <nav className="flex flex-wrap justify-center gap-6 text-xl text-[#141313]/50 lg:absolute lg:left-1/2 lg:top-[33px] lg:-translate-x-1/2">
76
+ {socialLinks.map((link) => (
77
+ <a
78
+ key={link.label}
79
+ href={link.href ?? "#"}
80
+ className="transition-colors duration-200 ease-out hover:text-[#141313] focus-visible:outline-2 focus-visible:outline-offset-2"
81
+ >
82
+ {link.label}
83
+ </a>
84
+ ))}
85
+ </nav>
86
+ <a
87
+ href={privacyHref ?? "#"}
88
+ className="text-center text-xl leading-7 text-[#141313]/70 underline transition-colors duration-200 ease-out hover:text-[#141313] focus-visible:outline-2 focus-visible:outline-offset-2 lg:absolute lg:right-0 lg:top-[31px]"
89
+ >
90
+ Privacy Policy
91
+ </a>
92
+ </div>
93
+ </div>
94
+ </div>
95
+ </footer>
96
+ );
97
+ }
98
+
99
+ Footer05.propTypes = footer05PropTypes;
100
+
101
+ export default Footer05;
@@ -0,0 +1,42 @@
1
+ import PropTypes from "prop-types";
2
+
3
+ const linkShape = PropTypes.shape({
4
+ label: PropTypes.string.isRequired,
5
+ href: PropTypes.string,
6
+ active: PropTypes.bool,
7
+ });
8
+
9
+ const socialShape = PropTypes.shape({
10
+ label: PropTypes.string.isRequired,
11
+ href: PropTypes.string,
12
+ });
13
+
14
+ export const footer05PropTypes = {
15
+ navLinks: PropTypes.arrayOf(linkShape),
16
+ contactLabel: PropTypes.string,
17
+ contactHref: PropTypes.string,
18
+ copyright: PropTypes.string,
19
+ socialLinks: PropTypes.arrayOf(socialShape),
20
+ privacyHref: PropTypes.string,
21
+ className: PropTypes.string,
22
+ };
23
+
24
+ export const footer05DefaultProps = {
25
+ navLinks: [
26
+ { label: "Home", href: "#", active: true },
27
+ { label: "About", href: "#" },
28
+ { label: "Compliance", href: "#" },
29
+ { label: "Sustainability", href: "#" },
30
+ ],
31
+ contactLabel: "Contact",
32
+ contactHref: "#",
33
+ copyright: "© 2026 M&U Group. All Rights Reserved.",
34
+ socialLinks: [
35
+ { label: "Facebook", href: "#" },
36
+ { label: "LinkedIn", href: "#" },
37
+ { label: "Instagram", href: "#" },
38
+ { label: "Twitter (X)", href: "#" },
39
+ ],
40
+ privacyHref: "#",
41
+ className: "",
42
+ };
@@ -0,0 +1 @@
1
+ export { Footer05, default } from "./Footer05";