@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,171 @@
1
+ "use client";
2
+
3
+ import SafeImage from "../../atoms/SafeImage";
4
+ import {
5
+ footer27DefaultProps,
6
+ footer27PropTypes,
7
+ } from "./Footer27.propTypes";
8
+
9
+ function FacebookIcon({ className = "" }) {
10
+ return (
11
+ <svg viewBox="0 0 18 18" fill="currentColor" aria-hidden="true" className={className}>
12
+ <path d="M10 2H8a3 3 0 00-3 3v2H3v3h2v5h3v-5h2.5l.5-3H8V5c0-.55.45-1 1-1h1V2h-1z" />
13
+ </svg>
14
+ );
15
+ }
16
+
17
+ function LinkedinIcon({ className = "" }) {
18
+ return (
19
+ <svg viewBox="0 0 18 18" fill="currentColor" aria-hidden="true" className={className}>
20
+ <rect x="2" y="6" width="3" height="10" />
21
+ <circle cx="3.5" cy="3.5" r="1.5" />
22
+ <path d="M8 6h2.5v1.2c.5-.9 1.4-1.4 2.5-1.4 2.5 0 2.8 1.6 2.8 3.7V16H13v-4c0-1 0-2-1.3-2-1.3 0-1.2 1.5-1.2 1.5V16H8V6z" />
23
+ </svg>
24
+ );
25
+ }
26
+
27
+ function TwitterIcon({ className = "" }) {
28
+ return (
29
+ <svg viewBox="0 0 18 18" fill="currentColor" aria-hidden="true" className={className}>
30
+ <path d="M13.5 3h2.1l-4.6 5.3 5.4 6.7h-4.2l-3.3-4.3-3.8 4.3H3.3l4.9-5.6L3 3h4.3l3 4 3.5-4h2.7z" />
31
+ </svg>
32
+ );
33
+ }
34
+
35
+ function YoutubeIcon({ className = "" }) {
36
+ return (
37
+ <svg viewBox="0 0 18 18" fill="currentColor" aria-hidden="true" className={className}>
38
+ <path d="M16.2 4.8a1.8 1.8 0 00-1.3-1.3C13.5 3 9 3 9 3s-4.5 0-5.9.5A1.8 1.8 0 001.8 4.8 18 18 0 001.5 9a18 18 0 00.3 4.2 1.8 1.8 0 001.3 1.3C4.5 15 9 15 9 15s4.5 0 5.9-.5a1.8 1.8 0 001.3-1.3A18 18 0 0016.5 9a18 18 0 00-.3-4.2zM7.5 11.8V6.2L12 9l-4.5 2.8z" />
39
+ </svg>
40
+ );
41
+ }
42
+
43
+ const SOCIAL_ICONS = {
44
+ facebook: FacebookIcon,
45
+ linkedin: LinkedinIcon,
46
+ twitter: TwitterIcon,
47
+ youtube: YoutubeIcon,
48
+ };
49
+
50
+ function LinkColumn({ column }) {
51
+ return (
52
+ <div className="flex min-w-0 flex-1 flex-col gap-6">
53
+ <p className="text-xl font-medium leading-[1.4] text-white md:text-2xl">{column.title}</p>
54
+ <ul className="flex flex-col gap-4">
55
+ {column.links.map((link) => (
56
+ <li key={link.label}>
57
+ <a
58
+ href={link.href ?? "#"}
59
+ className="text-base leading-[1.6] text-white/80 transition-colors duration-200 ease-out hover:text-white focus-visible:outline-2 focus-visible:outline-offset-2"
60
+ >
61
+ {link.label}
62
+ </a>
63
+ </li>
64
+ ))}
65
+ </ul>
66
+ </div>
67
+ );
68
+ }
69
+
70
+ /**
71
+ * Footer27 — PCS Group dark services footer.
72
+ * Figma node 32:20799 at 1920px.
73
+ */
74
+ export function Footer27({
75
+ logoSrc = footer27DefaultProps.logoSrc,
76
+ logoAlt = footer27DefaultProps.logoAlt,
77
+ tagline = footer27DefaultProps.tagline,
78
+ contactBlocks = footer27DefaultProps.contactBlocks,
79
+ linkColumns = footer27DefaultProps.linkColumns,
80
+ socialButtons = footer27DefaultProps.socialButtons,
81
+ copyright = footer27DefaultProps.copyright,
82
+ legalLinks = footer27DefaultProps.legalLinks,
83
+ className = "",
84
+ }) {
85
+ const [servicesColumn, aboutColumn, quickLinksColumn] = linkColumns;
86
+
87
+ return (
88
+ <footer
89
+ className={["relative w-full overflow-hidden bg-[#141418]", className]
90
+ .filter(Boolean)
91
+ .join(" ")}
92
+ data-footer="footer27"
93
+ >
94
+ <div className="mx-auto flex w-full max-w-[1920px] flex-col gap-16 px-4 pb-5 pt-16 sm:px-6 md:px-10 lg:gap-20 lg:px-10 lg:pt-[100px] xl:px-10">
95
+ <div className="flex flex-col gap-12 xl:flex-row xl:justify-between">
96
+ <div className="flex max-w-md flex-col gap-10 pr-0 xl:max-w-[553px] xl:pr-8">
97
+ <div className="flex flex-col gap-8">
98
+ <SafeImage
99
+ src={logoSrc}
100
+ alt={logoAlt}
101
+ width={91}
102
+ height={48}
103
+ className="h-auto w-[91px]"
104
+ />
105
+ <p className="max-w-[355px] text-lg leading-[1.6] text-white/80">{tagline}</p>
106
+ </div>
107
+ <div className="flex flex-col gap-5">
108
+ {contactBlocks.map((block) => (
109
+ <div key={block.title} className="flex flex-col gap-2.5">
110
+ <p className="text-lg font-medium leading-[1.2] text-white">{block.title}</p>
111
+ <div className="text-base leading-[1.6] text-white/80">
112
+ {block.lines.map((line) => (
113
+ <p key={line}>{line}</p>
114
+ ))}
115
+ </div>
116
+ </div>
117
+ ))}
118
+ </div>
119
+ </div>
120
+
121
+ <div className="grid flex-1 grid-cols-1 gap-10 sm:grid-cols-2 xl:grid-cols-3 xl:gap-8">
122
+ {servicesColumn ? <LinkColumn column={servicesColumn} /> : null}
123
+ <div className="flex flex-col gap-12">
124
+ {aboutColumn ? <LinkColumn column={aboutColumn} /> : null}
125
+ <div className="flex flex-col gap-6">
126
+ <p className="text-xl font-medium leading-[1.4] text-white md:text-2xl">
127
+ Follow us
128
+ </p>
129
+ <div className="flex flex-wrap items-center gap-0.5">
130
+ {socialButtons.map((social) => {
131
+ const Icon = SOCIAL_ICONS[social.icon] ?? FacebookIcon;
132
+ return (
133
+ <a
134
+ key={social.label}
135
+ href={social.href ?? "#"}
136
+ aria-label={social.label}
137
+ className="rounded-full p-2.5 text-white transition-colors duration-200 ease-out hover:bg-white/10 focus-visible:outline-2 focus-visible:outline-offset-2"
138
+ >
139
+ <Icon className="size-[18px]" />
140
+ </a>
141
+ );
142
+ })}
143
+ </div>
144
+ </div>
145
+ </div>
146
+ {quickLinksColumn ? <LinkColumn column={quickLinksColumn} /> : null}
147
+ </div>
148
+ </div>
149
+
150
+ <div className="flex flex-col gap-4 border-t border-white/10 py-[18px] sm:flex-row sm:items-center sm:justify-between">
151
+ <p className="text-base leading-[1.6] text-white/80 opacity-80">{copyright}</p>
152
+ <div className="flex flex-wrap items-center gap-5">
153
+ {legalLinks.map((link) => (
154
+ <a
155
+ key={link.label}
156
+ href={link.href ?? "#"}
157
+ className="text-base leading-[1.6] text-white/80 opacity-80 transition-colors duration-200 ease-out hover:text-white focus-visible:outline-2 focus-visible:outline-offset-2"
158
+ >
159
+ {link.label}
160
+ </a>
161
+ ))}
162
+ </div>
163
+ </div>
164
+ </div>
165
+ </footer>
166
+ );
167
+ }
168
+
169
+ Footer27.propTypes = footer27PropTypes;
170
+
171
+ export default Footer27;
@@ -0,0 +1,105 @@
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
+ const contactBlockShape = PropTypes.shape({
14
+ title: PropTypes.string.isRequired,
15
+ lines: PropTypes.arrayOf(PropTypes.string),
16
+ });
17
+
18
+ const socialShape = PropTypes.shape({
19
+ label: PropTypes.string.isRequired,
20
+ href: PropTypes.string,
21
+ icon: PropTypes.oneOf(["facebook", "instagram", "youtube", "linkedin", "twitter"]),
22
+ });
23
+
24
+ export const footer27PropTypes = {
25
+ logoSrc: PropTypes.string,
26
+ logoAlt: PropTypes.string,
27
+ tagline: PropTypes.string,
28
+ contactBlocks: PropTypes.arrayOf(contactBlockShape),
29
+ linkColumns: PropTypes.arrayOf(columnShape),
30
+ socialButtons: PropTypes.arrayOf(socialShape),
31
+ copyright: PropTypes.string,
32
+ legalLinks: PropTypes.arrayOf(linkShape),
33
+ className: PropTypes.string,
34
+ };
35
+
36
+ export const footer27DefaultProps = {
37
+ logoSrc: "/footer/footer27/logo.png",
38
+ logoAlt: "PCS Group",
39
+ tagline: "Making people and places the best they can be.",
40
+ contactBlocks: [
41
+ {
42
+ title: "Corporate Office",
43
+ lines: ["House# 07, Road #3/A, Block- J, Baridhara, Dhaka- 1212, Bangladesh 1212"],
44
+ },
45
+ {
46
+ title: "Phone",
47
+ lines: ["+8801911978049,", "+8801914067771"],
48
+ },
49
+ {
50
+ title: "Email",
51
+ lines: ["md.anisur.rahman@pcs.com.bd"],
52
+ },
53
+ ],
54
+ linkColumns: [
55
+ {
56
+ title: "Services",
57
+ links: [
58
+ { label: "Cleaning Services", href: "#" },
59
+ { label: "Payroll Management", href: "#" },
60
+ { label: "Care Giver", href: "#" },
61
+ { label: "Pest Control", href: "#" },
62
+ { label: "Feminine Hygiene", href: "#" },
63
+ { label: "Baby Sitting", href: "#" },
64
+ { label: "Driver", href: "#" },
65
+ { label: "Office Staff", href: "#" },
66
+ { label: "Security Services", href: "#" },
67
+ { label: "Home Deep Cleaning", href: "#" },
68
+ { label: "Carpet Cleaning", href: "#" },
69
+ { label: "External Glass Cleaning", href: "#" },
70
+ ],
71
+ },
72
+ {
73
+ title: "About Us",
74
+ links: [
75
+ { label: "Who We Are", href: "#" },
76
+ { label: "Leadership Team", href: "#" },
77
+ { label: "Sustainability & Innovation", href: "#" },
78
+ { label: "Corporate Social Responsibility (CSR)", href: "#" },
79
+ ],
80
+ },
81
+ {
82
+ title: "Quick Links",
83
+ links: [
84
+ { label: "Technology", href: "#" },
85
+ { label: "ESG", href: "#" },
86
+ { label: "Leadership Team", href: "#" },
87
+ { label: "Careers", href: "#" },
88
+ { label: "News & Insights", href: "#" },
89
+ { label: "Contact Us", href: "#" },
90
+ ],
91
+ },
92
+ ],
93
+ socialButtons: [
94
+ { label: "Facebook", href: "#", icon: "facebook" },
95
+ { label: "LinkedIn", href: "#", icon: "linkedin" },
96
+ { label: "X", href: "#", icon: "twitter" },
97
+ { label: "YouTube", href: "#", icon: "youtube" },
98
+ ],
99
+ copyright: "© 2025 PCS Group. All rights reserved | Site by: Notionhive",
100
+ legalLinks: [
101
+ { label: "Privacy Policy", href: "#" },
102
+ { label: "Terms & Conditions", href: "#" },
103
+ ],
104
+ className: "",
105
+ };
@@ -0,0 +1 @@
1
+ export { Footer27, default } from "./Footer27";
@@ -0,0 +1,98 @@
1
+ "use client";
2
+
3
+ import SafeImage from "../../atoms/SafeImage";
4
+ import {
5
+ footer28DefaultProps,
6
+ footer28PropTypes,
7
+ } from "./Footer28.propTypes";
8
+
9
+ function LinkColumn({ column }) {
10
+ return (
11
+ <div className="flex min-w-0 flex-col gap-6 xl:gap-[30px]">
12
+ <p className="text-lg font-semibold leading-none text-[#00a3b5] xl:text-xl">
13
+ {column.title}
14
+ </p>
15
+ <ul className="flex flex-col gap-2.5">
16
+ {column.links.map((link) => (
17
+ <li key={link.label}>
18
+ <a
19
+ href={link.href ?? "#"}
20
+ className="text-base font-medium leading-6 text-black transition-colors duration-200 ease-out hover:text-[#00a3b5] focus-visible:outline-2 focus-visible:outline-offset-2"
21
+ >
22
+ {link.label}
23
+ </a>
24
+ </li>
25
+ ))}
26
+ </ul>
27
+ </div>
28
+ );
29
+ }
30
+
31
+ function ContactBlock({ block }) {
32
+ return (
33
+ <div className="flex flex-col gap-4">
34
+ <p className="text-lg font-semibold leading-none text-[#00a3b5] xl:text-xl">
35
+ {block.title}
36
+ </p>
37
+ <div className="text-base font-medium leading-6 text-black">
38
+ {block.lines.map((line) => (
39
+ <p key={line}>{line}</p>
40
+ ))}
41
+ </div>
42
+ </div>
43
+ );
44
+ }
45
+
46
+ /**
47
+ * Footer28 — Refugee 613 teal-accent footer.
48
+ * Figma node 32:20800 at 1920px.
49
+ */
50
+ export function Footer28({
51
+ linkColumns = footer28DefaultProps.linkColumns,
52
+ logoSrc = footer28DefaultProps.logoSrc,
53
+ logoAlt = footer28DefaultProps.logoAlt,
54
+ location = footer28DefaultProps.location,
55
+ contact = footer28DefaultProps.contact,
56
+ copyright = footer28DefaultProps.copyright,
57
+ className = "",
58
+ }) {
59
+ return (
60
+ <footer
61
+ className={["relative w-full overflow-hidden border-t-4 border-[#00a3b5] bg-white", className]
62
+ .filter(Boolean)
63
+ .join(" ")}
64
+ data-footer="footer28"
65
+ >
66
+ <div className="mx-auto flex w-full max-w-[1920px] flex-col gap-12 px-4 py-10 sm:px-6 md:px-10 lg:gap-[50px] lg:px-20 lg:py-[66px] xl:px-[120px]">
67
+ <div className="grid grid-cols-1 gap-10 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4 xl:grid-cols-6 xl:justify-between">
68
+ {linkColumns.map((column) => (
69
+ <LinkColumn key={column.title} column={column} />
70
+ ))}
71
+ </div>
72
+
73
+ <div className="h-px w-full bg-black/10" />
74
+
75
+ <div className="flex flex-col gap-8 lg:flex-row lg:items-center lg:justify-between">
76
+ <div className="flex flex-col gap-8 sm:flex-row sm:items-center xl:gap-[95px]">
77
+ <SafeImage
78
+ src={logoSrc}
79
+ alt={logoAlt}
80
+ width={194}
81
+ height={50}
82
+ className="h-auto w-[194px] max-w-full"
83
+ />
84
+ <div className="flex flex-col gap-8 sm:flex-row xl:gap-[150px]">
85
+ <ContactBlock block={location} />
86
+ <ContactBlock block={contact} />
87
+ </div>
88
+ </div>
89
+ <p className="text-base font-medium leading-6 text-black">{copyright}</p>
90
+ </div>
91
+ </div>
92
+ </footer>
93
+ );
94
+ }
95
+
96
+ Footer28.propTypes = footer28PropTypes;
97
+
98
+ export default Footer28;
@@ -0,0 +1,96 @@
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
+ const contactBlockShape = PropTypes.shape({
14
+ title: PropTypes.string.isRequired,
15
+ lines: PropTypes.arrayOf(PropTypes.string),
16
+ });
17
+
18
+ export const footer28PropTypes = {
19
+ linkColumns: PropTypes.arrayOf(columnShape),
20
+ logoSrc: PropTypes.string,
21
+ logoAlt: PropTypes.string,
22
+ location: contactBlockShape,
23
+ contact: contactBlockShape,
24
+ copyright: PropTypes.string,
25
+ className: PropTypes.string,
26
+ };
27
+
28
+ export const footer28DefaultProps = {
29
+ linkColumns: [
30
+ {
31
+ title: "About R613",
32
+ links: [
33
+ { label: "Who We Are", href: "#" },
34
+ { label: "Our Approach", href: "#" },
35
+ { label: "Our Impact", href: "#" },
36
+ { label: "Partners & Network", href: "#" },
37
+ ],
38
+ },
39
+ {
40
+ title: "Programs",
41
+ links: [
42
+ { label: "Connectors Program", href: "#" },
43
+ { label: "CIIRC Initiative", href: "#" },
44
+ { label: "Community Programs", href: "#" },
45
+ { label: "Advocacy & Systems Change", href: "#" },
46
+ ],
47
+ },
48
+ {
49
+ title: "Resources",
50
+ links: [
51
+ { label: "Newcomer Multilingual Info Bank", href: "#" },
52
+ { label: "Guides & Toolkits", href: "#" },
53
+ { label: "Latest Insights & Updates", href: "#" },
54
+ ],
55
+ },
56
+ {
57
+ title: "Get Involved",
58
+ links: [
59
+ { label: "Become a Connector", href: "#" },
60
+ { label: "Volunteer Opportunities", href: "#" },
61
+ { label: "Attend an Event", href: "#" },
62
+ { label: "Partner With Us", href: "#" },
63
+ ],
64
+ },
65
+ {
66
+ title: "Quick link",
67
+ links: [
68
+ { label: "Donate Now", href: "#" },
69
+ { label: "Contact Us", href: "#" },
70
+ { label: "Privacy Policy", href: "#" },
71
+ ],
72
+ },
73
+ {
74
+ title: "Socials",
75
+ links: [
76
+ { label: "Facebook", href: "#" },
77
+ { label: "Twitter", href: "#" },
78
+ { label: "YouTube", href: "#" },
79
+ { label: "LinkedIn", href: "#" },
80
+ { label: "Instagram", href: "#" },
81
+ ],
82
+ },
83
+ ],
84
+ logoSrc: "/footer/footer28/logo.png",
85
+ logoAlt: "Refugee 613",
86
+ location: {
87
+ title: "Location",
88
+ lines: ["945 Wellington St W Ottawa", "ON K1Y 2X5 Canada"],
89
+ },
90
+ contact: {
91
+ title: "Contact Us",
92
+ lines: ["+8802-58952280", "info@refugee613.ca"],
93
+ },
94
+ copyright: "© 2025 Refugee 613. All Rights Reserved",
95
+ className: "",
96
+ };
@@ -0,0 +1 @@
1
+ export { Footer28, default } from "./Footer28";
@@ -0,0 +1,118 @@
1
+ "use client";
2
+
3
+ import {
4
+ footer29DefaultProps,
5
+ footer29PropTypes,
6
+ } from "./Footer29.propTypes";
7
+
8
+ function LinkColumn({ column }) {
9
+ return (
10
+ <div className="flex min-w-0 flex-1 flex-col gap-8">
11
+ <p className="text-xl font-medium leading-[1.4] tracking-[-0.48px] text-white md:text-2xl">
12
+ {column.title}
13
+ </p>
14
+ <ul className="flex flex-col gap-4">
15
+ {column.links.map((link) => (
16
+ <li key={link.label}>
17
+ <a
18
+ href={link.href ?? "#"}
19
+ className="text-base font-light leading-[1.4] tracking-[-0.32px] text-white/70 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
+ * Footer29 — Sandbay dark newsletter footer with wordmark.
32
+ * Figma node 32:21079 at 1920px.
33
+ */
34
+ export function Footer29({
35
+ newsletterTitle = footer29DefaultProps.newsletterTitle,
36
+ newsletterDescription = footer29DefaultProps.newsletterDescription,
37
+ email = footer29DefaultProps.email,
38
+ onEmailChange,
39
+ onNewsletterSubmit,
40
+ submitLabel = footer29DefaultProps.submitLabel,
41
+ copyright = footer29DefaultProps.copyright,
42
+ linkColumns = footer29DefaultProps.linkColumns,
43
+ brandWordmark = footer29DefaultProps.brandWordmark,
44
+ className = "",
45
+ }) {
46
+ const handleSubmit = (event) => {
47
+ event.preventDefault();
48
+ onNewsletterSubmit?.(event);
49
+ };
50
+
51
+ return (
52
+ <footer
53
+ className={["relative w-full overflow-hidden bg-[#200006]", className]
54
+ .filter(Boolean)
55
+ .join(" ")}
56
+ data-footer="footer29"
57
+ >
58
+ <div className="mx-auto flex w-full max-w-[1920px] flex-col items-center gap-12 px-4 pt-16 sm:px-6 md:gap-16 md:px-10 lg:gap-[60px] lg:px-20 lg:pt-[140px] xl:px-[120px]">
59
+ <div className="flex w-full flex-col gap-12 xl:flex-row xl:justify-center">
60
+ <div className="flex w-full max-w-[543px] flex-col gap-8">
61
+ <div className="flex flex-col gap-4">
62
+ <p className="text-xl font-medium leading-[1.4] tracking-[-0.48px] text-white md:text-2xl">
63
+ {newsletterTitle}
64
+ </p>
65
+ <p className="text-base font-light leading-[1.4] tracking-[-0.32px] text-white/70 opacity-80">
66
+ {newsletterDescription}
67
+ </p>
68
+ </div>
69
+
70
+ <form
71
+ onSubmit={handleSubmit}
72
+ className="flex h-14 w-full items-center justify-between rounded-[110px] bg-white/10 py-2.5 pl-6 pr-1"
73
+ >
74
+ <label htmlFor="footer29-email" className="sr-only">
75
+ Email
76
+ </label>
77
+ <input
78
+ id="footer29-email"
79
+ type="email"
80
+ value={email}
81
+ onChange={onEmailChange}
82
+ placeholder="Email"
83
+ className="min-w-0 flex-1 bg-transparent text-sm font-light tracking-[-0.28px] text-white/70 placeholder:text-white/60 focus:outline-none"
84
+ />
85
+ <button
86
+ type="submit"
87
+ className="shrink-0 rounded-[120px] bg-[#fbe8e8] px-6 py-3 text-base tracking-[-0.32px] text-[#410000] transition-colors duration-200 ease-out hover:opacity-90 focus-visible:outline-2 focus-visible:outline-offset-2 sm:px-8"
88
+ >
89
+ {submitLabel}
90
+ </button>
91
+ </form>
92
+
93
+ <p className="text-base font-light leading-[1.4] tracking-[-0.32px] text-white/60">
94
+ {copyright}
95
+ </p>
96
+ </div>
97
+
98
+ <div className="grid flex-1 grid-cols-1 gap-8 sm:grid-cols-2 xl:grid-cols-4">
99
+ {linkColumns.map((column) => (
100
+ <LinkColumn key={column.title} column={column} />
101
+ ))}
102
+ </div>
103
+ </div>
104
+
105
+ <p
106
+ className="pointer-events-none w-full select-none overflow-hidden text-center text-[clamp(4rem,28vw,570px)] leading-none tracking-[-0.04em] text-[#ff0033] opacity-50"
107
+ aria-hidden="true"
108
+ >
109
+ {brandWordmark}
110
+ </p>
111
+ </div>
112
+ </footer>
113
+ );
114
+ }
115
+
116
+ Footer29.propTypes = footer29PropTypes;
117
+
118
+ export default Footer29;
@@ -0,0 +1,68 @@
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 footer29PropTypes = {
14
+ newsletterTitle: PropTypes.string,
15
+ newsletterDescription: PropTypes.string,
16
+ email: PropTypes.string,
17
+ onEmailChange: PropTypes.func,
18
+ onNewsletterSubmit: PropTypes.func,
19
+ submitLabel: PropTypes.string,
20
+ copyright: PropTypes.string,
21
+ linkColumns: PropTypes.arrayOf(columnShape),
22
+ brandWordmark: PropTypes.string,
23
+ className: PropTypes.string,
24
+ };
25
+
26
+ export const footer29DefaultProps = {
27
+ newsletterTitle: "Get our Weekly Newsletter",
28
+ newsletterDescription:
29
+ "Curated insights on privacy, comfort, and timeless design—delivered once a week.",
30
+ email: "",
31
+ submitLabel: "Get updates",
32
+ copyright: "© 2026 Sandbay. All Rights Reserved.",
33
+ linkColumns: [
34
+ {
35
+ title: "Contact",
36
+ links: [
37
+ { label: "info@sandbay.com", href: "mailto:info@sandbay.com" },
38
+ { label: "+66 61 340 80 23", href: "tel:+66613408023" },
39
+ ],
40
+ },
41
+ {
42
+ title: "Quick Links",
43
+ links: [
44
+ { label: "Rooms & Suites", href: "#" },
45
+ { label: "About Sandbay", href: "#" },
46
+ { label: "Gallery", href: "#" },
47
+ ],
48
+ },
49
+ {
50
+ title: "Follow us",
51
+ links: [
52
+ { label: "Linkedin", href: "#" },
53
+ { label: "Instagram", href: "#" },
54
+ { label: "X", href: "#" },
55
+ ],
56
+ },
57
+ {
58
+ title: "Legal",
59
+ links: [
60
+ { label: "Privacy Policy", href: "#" },
61
+ { label: "Terms of Conditions", href: "#" },
62
+ { label: "Instagram", href: "#" },
63
+ ],
64
+ },
65
+ ],
66
+ brandWordmark: "Sandbay",
67
+ className: "",
68
+ };
@@ -0,0 +1 @@
1
+ export { Footer29, default } from "./Footer29";