@allbluecn/web-app 0.17.0 → 0.17.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/package.json +1 -1
  2. package/src/components/landing/landing-page.tsx +20 -0
  3. package/src/lib/changelog/sdk-versions.ts +1 -1
  4. package/src/paraglide/README.md +1 -1
  5. package/src/paraglide/messages/_index.js +0 -48
  6. package/src/paraglide/messages/en.js +0 -15
  7. package/src/paraglide/messages/zh.js +0 -15
  8. package/src/routes/_nav/prd/index.tsx +1 -1
  9. package/src/routes/_nav/tags/index.tsx +1 -1
  10. package/src/routes/_public/index/route.tsx +2 -6
  11. package/src/server/middlewares/paraglide-locale.ts +39 -0
  12. package/src/start.ts +4 -1
  13. package/src/styles/globals.css +2 -3
  14. package/src/__tests__/bench/baselines/format-timestamp.json +0 -44
  15. package/src/assets/logo/logo.tsx +0 -70
  16. package/src/components/shadcn-space/animations/marquee.tsx +0 -139
  17. package/src/components/shadcn-space/blocks/about-us-01/about-us.tsx +0 -136
  18. package/src/components/shadcn-space/blocks/about-us-01/index.tsx +0 -62
  19. package/src/components/shadcn-space/blocks/cta-01/cta.tsx +0 -74
  20. package/src/components/shadcn-space/blocks/faq-01/faq.tsx +0 -100
  21. package/src/components/shadcn-space/blocks/footer-01/footer.tsx +0 -232
  22. package/src/components/shadcn-space/blocks/hero-01/brand-slider.tsx +0 -79
  23. package/src/components/shadcn-space/blocks/hero-01/header.tsx +0 -272
  24. package/src/components/shadcn-space/blocks/hero-01/hero.tsx +0 -111
  25. package/src/components/shadcn-space/blocks/hero-01/index.tsx +0 -127
  26. package/src/components/shadcn-space/blocks/portfolio-01/portfolio.tsx +0 -149
  27. package/src/components/shadcn-space/blocks/pricing-01/pricing.tsx +0 -187
  28. package/src/components/shadcn-space/blocks/pricing-02/pricing.tsx +0 -213
  29. package/src/components/shadcn-space/blocks/services-01/services.tsx +0 -178
  30. package/src/components/shadcn-space/blocks/team-01/team.tsx +0 -166
@@ -1,136 +0,0 @@
1
- // SPDX-License-Identifier: AGPL-3.0-or-later
2
- // AllBlue - 理想之海
3
- // Copyright (C) 2026 AllBlue Contributors
4
- //
5
- // This program is free software: you can redistribute it and/or modify
6
- // it under the terms of the GNU Affero General Public License as published by
7
- // the Free Software Foundation, either version 3 of the License, or
8
- // (at your option) any later version.
9
- //
10
- // This program is distributed in the hope that it will be useful,
11
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- // GNU Affero General Public License for more details.
14
- //
15
- // You should have received a copy of the GNU Affero General Public License
16
- // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
-
18
- import { cn } from "@/lib/utils";
19
- import { LucideIcon, Plus } from "lucide-react";
20
- import { useEffect, useRef } from "react";
21
- import { m, useSpring, useTransform, useInView } from "motion/react";
22
- type aboutusData = {
23
- icon: LucideIcon;
24
- title: string;
25
- color: string;
26
- }[];
27
- type statisticsCounter = {
28
- title: string;
29
- count: number;
30
- }[];
31
- const AnimatedCounter = ({
32
- value,
33
- isInView,
34
- }: {
35
- value: number;
36
- isInView: boolean;
37
- }) => {
38
- const springValue = useSpring(0, {
39
- bounce: 0,
40
- duration: 2000,
41
- });
42
- const displayValue = useTransform(springValue, (current) =>
43
- Math.round(current)
44
- );
45
- useEffect(() => {
46
- if (isInView) {
47
- springValue.set(value);
48
- }
49
- }, [isInView, value, springValue]);
50
- return <m.span>{displayValue}</m.span>;
51
- };
52
- const AboutUs = ({
53
- aboutusData,
54
- statisticsCounter,
55
- }: {
56
- aboutusData: aboutusData;
57
- statisticsCounter: statisticsCounter;
58
- }) => {
59
- const statsRef = useRef(null);
60
- const isInView = useInView(statsRef, { once: true, margin: "-100px" });
61
- return (
62
- <section className="lg:py-20 sm:py-16 py-8">
63
- <div className="mx-auto max-w-7xl px-4 sm:px-6 lg:px-16">
64
- <div className="flex flex-col items-center justify-center gap-8 md:gap-16">
65
- <m.div
66
- initial={{ y: -40, opacity: 0 }}
67
- whileInView={{ y: 0, opacity: 1 }}
68
- viewport={{ once: true }}
69
- transition={{
70
- duration: 0.8,
71
- ease: [0.21, 0.47, 0.32, 0.98],
72
- }}
73
- className="flex flex-col items-center justify-center gap-4"
74
- >
75
- <h2 className="text-3xl sm:text-4xl lg:text-5xl font-medium text-foreground text-center tracking-tight">
76
- Crafting exceptional, well experienced & technology driven
77
- strategies to drive impactful results with
78
- </h2>
79
- <div className="flex flex-wrap items-center justify-center gap-x-2 gap-y-4">
80
- {aboutusData.map((item, index) => (
81
- <div
82
- key={index}
83
- className={cn(
84
- "flex items-center gap-3 px-6 py-2 rounded-full",
85
- item.color
86
- )}
87
- >
88
- <item.icon className="w-6 h-6 sm:w-8 sm:h-8 lg:w-10 lg:h-10" />
89
- <span
90
- className={cn(
91
- "text-4xl font-normal",
92
- "font-serif"
93
- )}
94
- >
95
- {item.title}
96
- </span>
97
- </div>
98
- ))}
99
- </div>
100
- </m.div>
101
- <div
102
- ref={statsRef}
103
- className="w-full grid grid-cols-1 sm:grid-cols-3 gap-1 sm:gap-0"
104
- >
105
- {statisticsCounter?.map((value, index) => {
106
- return (
107
- <div
108
- key={index}
109
- className="relative px-6 py-5 sm:py-10 gap-3 flex flex-col items-center justify-center"
110
- >
111
- {index !== 0 && (
112
- <div className="hidden sm:block absolute left-0 top-1/2 -translate-y-1/2 w-px h-40 bg-border" />
113
- )}
114
- <div className="flex gap-0 sm:gap-2 text-6xl sm:text-7xl md:text-8xl lg:text-9xl font-medium">
115
- <Plus
116
- strokeWidth={3.5}
117
- className="w-6 h-6 sm:w-8 sm:h-8 lg:w-12 lg:h-12"
118
- />
119
- <AnimatedCounter
120
- value={value.count}
121
- isInView={isInView}
122
- />
123
- </div>
124
- <p className="text-base font-normal text-muted-foreground text-center">
125
- {value.title}
126
- </p>
127
- </div>
128
- );
129
- })}
130
- </div>
131
- </div>
132
- </div>
133
- </section>
134
- );
135
- };
136
- export default AboutUs;
@@ -1,62 +0,0 @@
1
- // SPDX-License-Identifier: AGPL-3.0-or-later
2
- // AllBlue - 理想之海
3
- // Copyright (C) 2026 AllBlue Contributors
4
- //
5
- // This program is free software: you can redistribute it and/or modify
6
- // it under the terms of the GNU Affero General Public License as published by
7
- // the Free Software Foundation, either version 3 of the License, or
8
- // (at your option) any later version.
9
- //
10
- // This program is distributed in the hope that it will be useful,
11
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- // GNU Affero General Public License for more details.
14
- //
15
- // You should have received a copy of the GNU Affero General Public License
16
- // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
-
18
- import AboutUs from "@/components/shadcn-space/blocks/about-us-01/about-us";
19
- import { Target, WandSparkles, Zap } from "lucide-react";
20
-
21
- const aboutusData = [
22
- {
23
- icon: WandSparkles,
24
- title: "Creativity",
25
- color: "bg-blue-500/10 text-blue-500"
26
- },
27
- {
28
- icon: Zap,
29
- title: "Innovation",
30
- color: "bg-teal-400/10 text-teal-400"
31
- },
32
- {
33
- icon: Target,
34
- title: "Strategy",
35
- color: "bg-orange-400/10 text-orange-400"
36
- }
37
- ];
38
-
39
- const statisticsCounter = [
40
- {
41
- title: "Total Projects Completed",
42
- count: 40
43
- },
44
- {
45
- title: "Years of Experience",
46
- count: 15
47
- },
48
- {
49
- title: "Design Awards",
50
- count: 12
51
- },
52
- ]
53
-
54
- const AboutAndStats01 = () => {
55
- return (
56
- <>
57
- <AboutUs aboutusData={aboutusData} statisticsCounter={statisticsCounter} />
58
- </>
59
- );
60
- };
61
-
62
- export default AboutAndStats01;
@@ -1,74 +0,0 @@
1
- // SPDX-License-Identifier: AGPL-3.0-or-later
2
- // AllBlue - 理想之海
3
- // Copyright (C) 2026 AllBlue Contributors
4
- //
5
- // This program is free software: you can redistribute it and/or modify
6
- // it under the terms of the GNU Affero General Public License as published by
7
- // the Free Software Foundation, either version 3 of the License, or
8
- // (at your option) any later version.
9
- //
10
- // This program is distributed in the hope that it will be useful,
11
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- // GNU Affero General Public License for more details.
14
- //
15
- // You should have received a copy of the GNU Affero General Public License
16
- // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
-
18
- import { useRef } from "react";
19
- import { m } from "motion/react";
20
- import { Button } from "@/components/ui/button";
21
- import { ArrowUpRight } from "lucide-react";
22
-
23
- type CTAProps = {
24
- className?: string;
25
- };
26
-
27
- const CTA = ({ className }: CTAProps) => {
28
- const ref = useRef(null);
29
-
30
- const bottomAnimation = {
31
- initial: { y: "5%", opacity: 0 },
32
- animate: { y: 0, opacity: 1 },
33
- transition: { duration: 1, delay: 0.8 },
34
- };
35
-
36
- return (
37
- <section>
38
- <div className="sm:py-20 py-8">
39
- <div className="max-w-7xl mx-auto sm:px-16 px-4">
40
- <div
41
- ref={ref}
42
- className="relative overflow-hidden min-h-96 flex items-center justify-center px-6 border border-border rounded-3xl before:absolute before:w-full before:h-4/5 before:bg-linear-to-r before:from-sky-100 before:from-15% before:via-white before:via-55% before:to-amber-100 before:to-90% before:rounded-full before:top-24 before:blur-3xl before:-z-10 dark:before:from-sky-400/10 dark:before:from-40% dark:before:via-black dark:before:via-55% dark:before:to-amber-300/10 dark:before:to-60% dark:before:rounded-full dark:before:-z-10"
43
- >
44
- <m.div
45
- {...bottomAnimation}
46
- className="flex flex-col gap-6 items-center mx-auto"
47
- >
48
- <div className="flex flex-col gap-3 items-center text-center">
49
- <h2 className="text-3xl md:text-5xl font-medium">
50
- Innovative solutions for bold brands
51
- </h2>
52
- <p className="max-w-2xl mx-auto">
53
- Looking to elevate your brand? We craft immersive experiences
54
- that captivate, engage, and make your business unforgettable
55
- in every interaction.
56
- </p>
57
- </div>
58
- <Button className="relative text-sm font-medium rounded-full h-12 p-1 ps-6 pe-14 group transition-all duration-500 hover:ps-14 hover:pe-6 w-fit overflow-hidden hover:bg-primary/80 cursor-pointer">
59
- <span className="relative z-10 transition-all duration-500">
60
- Let's craft together
61
- </span>
62
- <div className="absolute right-1 w-10 h-10 bg-background text-foreground rounded-full flex items-center justify-center transition-all duration-500 group-hover:right-[calc(100%-44px)] group-hover:rotate-45">
63
- <ArrowUpRight size={16} />
64
- </div>
65
- </Button>
66
- </m.div>
67
- </div>
68
- </div>
69
- </div>
70
- </section>
71
- );
72
- };
73
-
74
- export default CTA;
@@ -1,100 +0,0 @@
1
- // SPDX-License-Identifier: AGPL-3.0-or-later
2
- // AllBlue - 理想之海
3
- // Copyright (C) 2026 AllBlue Contributors
4
- //
5
- // This program is free software: you can redistribute it and/or modify
6
- // it under the terms of the GNU Affero General Public License as published by
7
- // the Free Software Foundation, either version 3 of the License, or
8
- // (at your option) any later version.
9
- //
10
- // This program is distributed in the hope that it will be useful,
11
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- // GNU Affero General Public License for more details.
14
- //
15
- // You should have received a copy of the GNU Affero General Public License
16
- // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
-
18
- import {
19
- Accordion,
20
- AccordionContent,
21
- AccordionItem,
22
- AccordionTrigger,
23
- } from "@/components/ui/accordion";
24
- import { Badge } from "@/components/ui/badge";
25
- import { PlusIcon } from "lucide-react";
26
- import { cn } from "@/lib/utils";
27
-
28
- const FAQ_DATA = [
29
- {
30
- question: "What services does Shadcn Space offer?",
31
- answer:
32
- "We offer a wide range of services including web development, app development, and digital marketing.",
33
- },
34
- {
35
- question: "How long does a typical project take?",
36
- answer:
37
- "The time it takes to complete a project depends on the complexity of the project and the scope of the work.",
38
- },
39
- {
40
- question: "How is pricing structured at Awake Agency?",
41
- answer:
42
- "Pricing is based on the complexity of the project and the scope of the work.",
43
- },
44
- {
45
- question: "Do you offer ongoing support after project completion?",
46
- answer:
47
- "Absolutely! We offer comprehensive post-launch support to ensure a seamless implementation and provide ongoing maintenance packages tailored to clients who need regular updates or technical assistance. Our commitment doesn’t end at launch — we’re here to help you every step of the way.",
48
- },
49
- {
50
- question: "How often will I receive updates on my project?",
51
- answer:
52
- "We provide updates on a regular basis to ensure that your project is running smoothly and that you are aware of any changes or updates to the project.",
53
- },
54
- ];
55
-
56
- export default function Faq() {
57
- return (
58
- <section>
59
- <div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 xl:py-24 py-8 flex flex-col gap-16">
60
- <div className="flex flex-col gap-4 items-center animate-in fade-in slide-in-from-top-10 duration-1000 delay-100 ease-in-out fill-mode-both">
61
- <Badge
62
- variant="outline"
63
- className="text-sm h-auto py-1 px-3 border-0 outline outline-border"
64
- >
65
- FAQs
66
- </Badge>
67
- <h2 className="text-5xl font-medium text-center max-w-lg">
68
- Got questions? We’ve got answers ready
69
- </h2>
70
- </div>
71
- <div>
72
- <Accordion className="w-full flex flex-col gap-6">
73
- {FAQ_DATA.map((faq, index) => (
74
- <AccordionItem
75
- key={`item-${index}`}
76
- value={`item-${index}`}
77
- className={cn(
78
- "p-6 border border-border rounded-2xl flex flex-col gap-3 group/item data-[open]:bg-accent transition-colors animate-in fade-in slide-in-from-bottom-8 duration-700 fill-mode-both",
79
- index === 0 && "delay-100",
80
- index === 1 && "delay-200",
81
- index === 2 && "delay-300",
82
- index === 3 && "delay-400",
83
- index === 4 && "delay-500",
84
- )}
85
- >
86
- <AccordionTrigger className="p-0 text-xl font-medium hover:no-underline **:data-[slot=accordion-trigger-icon]:hidden cursor-pointer">
87
- {faq.question}
88
- <PlusIcon className="w-6 h-6 shrink-0 transition-transform duration-200 group-aria-expanded/accordion-trigger:rotate-45" />
89
- </AccordionTrigger>
90
- <AccordionContent className="p-0 text-muted-foreground text-base">
91
- {faq.answer}
92
- </AccordionContent>
93
- </AccordionItem>
94
- ))}
95
- </Accordion>
96
- </div>
97
- </div>
98
- </section>
99
- );
100
- }
@@ -1,232 +0,0 @@
1
- // SPDX-License-Identifier: AGPL-3.0-or-later
2
- // AllBlue - 理想之海
3
- // Copyright (C) 2026 AllBlue Contributors
4
- //
5
- // This program is free software: you can redistribute it and/or modify
6
- // it under the terms of the GNU Affero General Public License as published by
7
- // the Free Software Foundation, either version 3 of the License, or
8
- // (at your option) any later version.
9
- //
10
- // This program is distributed in the hope that it will be useful,
11
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- // GNU Affero General Public License for more details.
14
- //
15
- // You should have received a copy of the GNU Affero General Public License
16
- // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
-
18
- import Logo from "@/assets/logo/logo";
19
- import { Separator } from "@/components/ui/separator";
20
-
21
- const TwitterIcon = () => (
22
- <svg width="20" height="20" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
23
- <path d="M11.791 2.188 8.46 5.996 5.58 2.188H1.408l4.984 6.518-4.723 5.399H3.69l3.646-4.166 3.187 4.166h4.068l-5.196-6.87 4.417-5.047zm-.71 10.707L3.77 3.335h1.2l7.23 9.56z" fill="currentColor" />
24
- </svg>
25
- );
26
-
27
- const LinkedinIcon = () => (
28
- <svg width="20" height="20" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
29
- <g clipPath="url(#footer01-linkedin-clip)">
30
- <path d="M13.633 13.633h-2.37V9.92c0-.885-.017-2.025-1.234-2.025-1.235 0-1.424.965-1.424 1.96v3.778h-2.37V5.998H8.51v1.043h.031a2.5 2.5 0 0 1 2.246-1.233c2.403 0 2.846 1.58 2.846 3.637zM3.56 4.954a1.376 1.376 0 1 1 0-2.751 1.376 1.376 0 0 1 0 2.751m1.185 8.679H2.372V5.998h2.373zM14.815.001H1.18A1.17 1.17 0 0 0 0 1.154v13.691A1.17 1.17 0 0 0 1.18 16h13.635A1.17 1.17 0 0 0 16 14.845V1.153A1.17 1.17 0 0 0 14.815 0" fill="currentColor" />
31
- </g>
32
- <defs>
33
- <clipPath id="footer01-linkedin-clip">
34
- <path d="M0 0h16v16H0z" />
35
- </clipPath>
36
- </defs>
37
- </svg>
38
- );
39
-
40
- const DribbbleIcon = () => (
41
- <svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
42
- <g clipPath="url(#footer01-dribbble-clip)">
43
- <path d="M15.942 4.242C12.683 7.617 8.333 8.7 1.874 9.117m16.25 1.583c-5.517-1.175-10.117.833-13.65 5.267M7.133 2.292c3.642 5 5 7.85 6.667 14.766M18.333 10a8.333 8.333 0 1 1-16.666 0 8.333 8.333 0 0 1 16.666 0" stroke="currentColor" strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" />
44
- </g>
45
- <defs>
46
- <clipPath id="footer01-dribbble-clip">
47
- <path fill="currentColor" d="M0 0h20v20H0z" />
48
- </clipPath>
49
- </defs>
50
- </svg>
51
- );
52
-
53
- const InstagramIcon = () => (
54
- <svg width="20" height="20" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
55
- <g clipPath="url(#footer01-instagram-clip)">
56
- <path d="M12 2.162c3.204 0 3.584.012 4.849.07 1.17.054 1.805.249 2.228.413.56.218.96.478 1.38.898s.68.82.898 1.38c.164.423.36 1.058.413 2.228.058 1.265.07 1.645.07 4.849s-.012 3.584-.07 4.849c-.053 1.17-.249 1.805-.413 2.228a3.7 3.7 0 0 1-.898 1.38c-.42.42-.82.68-1.38.898-.423.164-1.058.36-2.228.413-1.265.058-1.645.07-4.849.07s-3.584-.012-4.849-.07c-1.17-.053-1.805-.249-2.228-.413a3.7 3.7 0 0 1-1.38-.898c-.42-.42-.68-.82-.898-1.38-.164-.423-.36-1.058-.413-2.228-.058-1.265-.07-1.645-.07-4.849s.012-3.584.07-4.849c.054-1.17.249-1.805.413-2.228.218-.56.478-.96.898-1.38s.82-.68 1.38-.898c.423-.164 1.058-.36 2.228-.413 1.265-.058 1.645-.07 4.849-.07M12 0C8.741 0 8.332.014 7.052.072 5.775.131 4.902.333 4.14.63a5.9 5.9 0 0 0-2.126 1.384A5.9 5.9 0 0 0 .63 4.14c-.297.763-.5 1.635-.558 2.912C.014 8.332 0 8.741 0 12s.014 3.668.072 4.948c.059 1.277.261 2.15.558 2.912.307.79.717 1.459 1.384 2.126A5.9 5.9 0 0 0 4.14 23.37c.763.297 1.635.5 2.912.558C8.332 23.986 8.741 24 12 24s3.668-.014 4.948-.072c1.277-.059 2.15-.261 2.912-.558a5.9 5.9 0 0 0 2.126-1.384 5.9 5.9 0 0 0 1.384-2.126c.297-.763.5-1.635.558-2.912.058-1.28.072-1.689.072-4.948s-.014-3.668-.072-4.948c-.059-1.277-.261-2.15-.558-2.912a5.9 5.9 0 0 0-1.384-2.126A5.9 5.9 0 0 0 19.86.63c-.763-.297-1.635-.5-2.912-.558C15.668.014 15.259 0 12 0m0 5.838a6.162 6.162 0 1 0 0 12.324 6.162 6.162 0 0 0 0-12.324M12 16a4 4 0 1 1 0-8 4 4 0 0 1 0 8m7.846-10.406a1.44 1.44 0 1 1-2.88 0 1.44 1.44 0 0 1 2.88 0" fill="currentColor" />
57
- </g>
58
- <defs>
59
- <clipPath id="footer01-instagram-clip">
60
- <path fill="currentColor" d="M0 0h24v24H0z" />
61
- </clipPath>
62
- </defs>
63
- </svg>
64
- );
65
-
66
- type FooterData = {
67
- title: string;
68
- links: {
69
- title: string;
70
- href: string;
71
- }[];
72
- };
73
-
74
- const footerSections: FooterData[] = [
75
- {
76
- title: "Sitemap",
77
- links: [
78
- {
79
- title: "Contact us",
80
- href: "#",
81
- },
82
- {
83
- title: "About us",
84
- href: "#",
85
- },
86
- {
87
- title: "Work",
88
- href: "#",
89
- },
90
- {
91
- title: "Services",
92
- href: "#",
93
- },
94
- {
95
- title: "Pricing",
96
- href: "#",
97
- },
98
- ],
99
- },
100
- {
101
- title: "Other Pages",
102
- links: [
103
- {
104
- title: "Error 404",
105
- href: "#",
106
- },
107
- {
108
- title: "Terms & Conditions",
109
- href: "#",
110
- },
111
- {
112
- title: "Privacy Policy",
113
- href: "#",
114
- },
115
- ],
116
- },
117
- ];
118
-
119
- const Footer = () => {
120
- return (
121
- <footer className="py-10">
122
- <div className="max-w-7xl xl:px-16 lg:px-8 px-4 mx-auto">
123
- <div className="flex flex-col gap-6 sm:gap-12">
124
- <div className="py-12 grid grid-cols-2 sm:grid-cols-4 md:grid-cols-7 lg:grid-cols-12 gap-x-8 gap-y-10 px-6 xl:px-0">
125
- <div className="col-span-full lg:col-span-4">
126
- <div className="flex flex-col gap-6 animate-in fade-in slide-in-from-bottom-10 duration-1000 delay-100 ease-in-out fill-mode-both">
127
- {/* Logo */}
128
- <a href="#">
129
- <Logo />
130
- </a>
131
-
132
- <p className="text-base font-normal text-muted-foreground">
133
- Empowering businesses with innovative solutions. Let's create
134
- something amazing together.
135
- </p>
136
-
137
- {/* social links */}
138
- <div className="flex items-center gap-4">
139
- <a
140
- href="#"
141
- className="text-muted-foreground hover:text-foreground"
142
- >
143
- <TwitterIcon />
144
- </a>
145
- <a
146
- href="#"
147
- className="text-muted-foreground hover:text-foreground"
148
- >
149
- <LinkedinIcon />
150
- </a>
151
- <a
152
- href="#"
153
- className="text-muted-foreground hover:text-foreground"
154
- >
155
- <DribbbleIcon />
156
- </a>
157
- <a
158
- href="#"
159
- className="text-muted-foreground hover:text-foreground"
160
- >
161
- <InstagramIcon />
162
- </a>
163
- </div>
164
- </div>
165
- </div>
166
-
167
- <div className="col-span-1 lg:block hidden"></div>
168
-
169
- {footerSections.map(({ title, links }, index) => (
170
- <div key={index} className="col-span-2">
171
- <div className="flex flex-col gap-4 animate-in fade-in slide-in-from-bottom-10 duration-1000 delay-100 ease-in-out fill-mode-both">
172
- <p className="text-base font-medium text-foreground">
173
- {title}
174
- </p>
175
- <ul className="flex flex-col gap-3">
176
- {links.map(({ title, href }) => (
177
- <li key={title}>
178
- <a
179
- href={href}
180
- className="text-base font-normal text-muted-foreground hover:text-foreground"
181
- >
182
- {title}
183
- </a>
184
- </li>
185
- ))}
186
- </ul>
187
- </div>
188
- </div>
189
- ))}
190
-
191
- <div className="col-span-3">
192
- <div className="flex flex-col gap-4 animate-in fade-in slide-in-from-bottom-10 duration-1000 delay-100 ease-in-out fill-mode-both">
193
- <p className="text-base font-medium text-foreground">
194
- Contact Details
195
- </p>
196
- <ul className="flex flex-col gap-3">
197
- <li>
198
- <p className="text-base font-normal text-muted-foreground">
199
- 81 Rivington Street London EC2A 3AY
200
- </p>
201
- </li>
202
- <li>
203
- <a
204
- href="mailto:contact@example.com"
205
- className="text-base font-normal text-muted-foreground hover:text-foreground"
206
- >
207
- hello@shadcnspace.com
208
- </a>
209
- </li>
210
- <li>
211
- <a
212
- href="tel:+01051923556"
213
- className="text-base font-normal text-muted-foreground hover:text-foreground"
214
- >
215
- 0105 192 3556
216
- </a>
217
- </li>
218
- </ul>
219
- </div>
220
- </div>
221
- </div>
222
- <Separator orientation="horizontal" />
223
- <p className="text-sm font-normal text-muted-foreground text-center animate-in fade-in slide-in-from-bottom-10 duration-1000 delay-100 ease-in-out fill-mode-both">
224
- ©2026 Shadcn Space. All Rights Reserved
225
- </p>
226
- </div>
227
- </div>
228
- </footer>
229
- );
230
- };
231
-
232
- export default Footer;
@@ -1,79 +0,0 @@
1
- // SPDX-License-Identifier: AGPL-3.0-or-later
2
- // AllBlue - 理想之海
3
- // Copyright (C) 2026 AllBlue Contributors
4
- //
5
- // This program is free software: you can redistribute it and/or modify
6
- // it under the terms of the GNU Affero General Public License as published by
7
- // the Free Software Foundation, either version 3 of the License, or
8
- // (at your option) any later version.
9
- //
10
- // This program is distributed in the hope that it will be useful,
11
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- // GNU Affero General Public License for more details.
14
- //
15
- // You should have received a copy of the GNU Affero General Public License
16
- // along with this program. If not, see <https://www.gnu.org/licenses/>.
17
-
18
- import { Marquee } from "@/components/shadcn-space/animations/marquee";
19
- import { m } from "motion/react";
20
-
21
- export interface BrandList {
22
- image: string;
23
- name: string;
24
- lightimg: string;
25
- }
26
-
27
- function BrandSlider({ brandList }: { brandList: BrandList[] }) {
28
- return (
29
- <section>
30
- <div className="py-6 md:py-10">
31
- <div className="mx-auto max-w-6xl">
32
- <m.div
33
- initial={{ opacity: 0, y: 32 }}
34
- whileInView={{ opacity: 1, y: 0 }}
35
- viewport={{ once: true }}
36
- transition={{ duration: 1, delay: 0.6 }}
37
- className="flex flex-col gap-3"
38
- >
39
- <div className="flex justify-center text-center py-3 md:py-4 relative">
40
- <div className="flex items-center justify-center gap-4">
41
- <div className="hidden md:block h-0.5 w-40 bg-linear-to-l from-muted-foreground to-white dark:from-muted-foreground dark:to-transparent opacity-20" />
42
- <p className="text-sm font-normal sm:px-2 px-10 text-muted-foreground text-center">
43
- Loved by 1000+ big and small brands around the worlds
44
- </p>
45
- <div className="hidden md:block h-0.5 w-40 bg-linear-to-r from-muted-foreground to-white dark:from-muted-foreground dark:to-transparent opacity-20" />
46
- </div>
47
- </div>
48
- {brandList && brandList.length > 0 && (
49
- <div className="py-4">
50
- <Marquee pauseOnHover className="[--duration:20s] p-0">
51
- {brandList.map((brand, index) => (
52
- <div key={index}>
53
- <img
54
- src={brand.image}
55
- alt={brand.name}
56
- width={144}
57
- height={32}
58
- className="w-36 h-8 mr-6 lg:mr-20 dark:hidden"
59
- />
60
- <img
61
- src={brand.lightimg}
62
- alt={brand.name}
63
- width={144}
64
- height={32}
65
- className="hidden dark:block w-36 h-8 mr-12 lg:mr-20"
66
- />
67
- </div>
68
- ))}
69
- </Marquee>
70
- </div>
71
- )}
72
- </m.div>
73
- </div>
74
- </div>
75
- </section>
76
- );
77
- }
78
-
79
- export default BrandSlider;