@stackshift-ui/footer 6.0.3 → 6.0.5-beta.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.
@@ -0,0 +1,160 @@
1
+ import { Container } from "@stackshift-ui/container";
2
+ import { Flex } from "@stackshift-ui/flex";
3
+ import { Grid } from "@stackshift-ui/grid";
4
+ import { GridItem } from "@stackshift-ui/grid-item";
5
+ import { Image } from "@stackshift-ui/image";
6
+ import { Link } from "@stackshift-ui/link";
7
+ import { Section } from "@stackshift-ui/section";
8
+ import { SocialIcons } from "@stackshift-ui/social-icons";
9
+ import { Text } from "@stackshift-ui/text";
10
+
11
+ import { FooterProps } from ".";
12
+ import { logoLink } from "./helper";
13
+ import { ContactDetails, Logo, SocialLink, Socials } from "./types";
14
+
15
+ export default function Footer_A({ logo, text, contacts, copyright, socialMedia }: FooterProps) {
16
+ return (
17
+ <Section className="py-20 bg-background">
18
+ <Container maxWidth={1000}>
19
+ <Flex wrap className="mb-5 lg:mb-20">
20
+ <LogoSection logo={logo} />
21
+ <TextContainer text={text} />
22
+ <ContactsContainer contacts={contacts} />
23
+ </Flex>
24
+ <Flex justify="between" align="center" className="w-full mx-auto lg:flex">
25
+ <CopyrightContainer copyright={copyright} />
26
+ <SocialMediaContainer socialMedia={socialMedia} />
27
+ </Flex>
28
+ </Container>
29
+ </Section>
30
+ );
31
+ }
32
+
33
+ function LogoSection({ logo }: { logo?: Logo }) {
34
+ if (!logo?.image) return null;
35
+
36
+ return (
37
+ <div className="w-full mb-5 lg:w-1/5">
38
+ <Link
39
+ aria-label={logoLink(logo) === "/" ? "Go to home page" : `Go to ${logoLink(logo)}`}
40
+ className="text-3xl font-bold leading-none"
41
+ href={logoLink(logo)}
42
+ target={logo?.linkTarget}
43
+ rel={logo?.linkTarget === "_blank" ? "noopener noreferrer" : ""}>
44
+ <Image
45
+ className="h-14"
46
+ src={`${logo?.image}`}
47
+ sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
48
+ width={132}
49
+ height={56}
50
+ alt={logo?.alt ?? "footer-logo"}
51
+ />
52
+ </Link>
53
+ </div>
54
+ );
55
+ }
56
+
57
+ function TextContainer({ text }: { text?: string }) {
58
+ if (!text) return null;
59
+
60
+ return (
61
+ <Container className="w-full mb-5 lg:w-1/5" maxWidth={1000}>
62
+ <Text muted className="leading-loose">
63
+ {text}
64
+ </Text>
65
+ </Container>
66
+ );
67
+ }
68
+
69
+ function ContactsContainer({ contacts }: { contacts?: ContactDetails[] }) {
70
+ if (!contacts) return null;
71
+
72
+ return (
73
+ <Container className="w-full mt-1 ml-auto lg:w-1/2" maxWidth={1000}>
74
+ {contacts?.map((contact, index) => (
75
+ <Grid columns={1} gap={4} className="lg:gap-10 md:grid-cols-3" key={index}>
76
+ <GridItem span={1}>
77
+ <Text weight="bold" className="mb-4">
78
+ Address
79
+ </Text>
80
+ <Text muted className="mb-5">
81
+ {contact?.addressInfo}
82
+ </Text>
83
+ </GridItem>
84
+ <GridItem span={1}>
85
+ <Text weight="bold" className="mb-4">
86
+ Email
87
+ </Text>
88
+ <Text muted className="mb-5">
89
+ <a
90
+ href={`mailto:${contact?.emailInfo}`}
91
+ style={{ color: "inherit", textDecoration: "none" }}>
92
+ {contact?.emailInfo}
93
+ </a>
94
+ </Text>
95
+ </GridItem>
96
+ <GridItem span={1}>
97
+ <Text weight="bold" className="mb-4">
98
+ Number
99
+ </Text>
100
+ <Text muted className="mb-5">
101
+ <a
102
+ href={`tel:${contact?.contactInfo}`}
103
+ style={{ color: "inherit", textDecoration: "none" }}>
104
+ {contact?.contactInfo}
105
+ </a>
106
+ </Text>
107
+ </GridItem>
108
+ </Grid>
109
+ ))}
110
+ </Container>
111
+ );
112
+ }
113
+
114
+ function CopyrightContainer({ copyright }: { copyright?: string }) {
115
+ if (!copyright) return null;
116
+
117
+ return (
118
+ <Text muted className="text-sm">
119
+ {copyright}
120
+ </Text>
121
+ );
122
+ }
123
+
124
+ function SocialMediaContainer({ socialMedia }: { socialMedia?: SocialLink[] }) {
125
+ if (!socialMedia) return null;
126
+
127
+ return (
128
+ <Flex wrap className="space-x-2 lg:mx-10 lg:space-x-4">
129
+ {socialMedia?.map((social, index) => <SocialMediaLink social={social} index={index} />)}
130
+ </Flex>
131
+ );
132
+ }
133
+
134
+ function SocialMediaLink({ social, index }: { social?: SocialLink; index?: number }) {
135
+ if (!social?.socialMediaLink) return null;
136
+
137
+ return (
138
+ <Link
139
+ aria-label={social?.socialMedia || social?.socialMediaPlatform || ""}
140
+ className="inline-block p-2 mr-2 rounded"
141
+ target="_blank"
142
+ rel="noopener noreferrer"
143
+ href={social?.socialMediaLink}
144
+ key={index}>
145
+ {social?.socialMediaIcon?.image ? (
146
+ <Image
147
+ className="h-6"
148
+ src={`${social?.socialMediaIcon?.image}`}
149
+ width={24}
150
+ height={24}
151
+ alt={social?.socialMediaIcon?.alt ?? "contact-socialMedia-icon"}
152
+ />
153
+ ) : (
154
+ <SocialIcons social={social?.socialMedia as Socials} />
155
+ )}
156
+ </Link>
157
+ );
158
+ }
159
+
160
+ export { Footer_A };
@@ -0,0 +1,154 @@
1
+ import { Button } from "@stackshift-ui/button";
2
+ import { Container } from "@stackshift-ui/container";
3
+ import { Flex } from "@stackshift-ui/flex";
4
+ import { Image } from "@stackshift-ui/image";
5
+ import { Link } from "@stackshift-ui/link";
6
+ import { Section } from "@stackshift-ui/section";
7
+ import { SocialIcons } from "@stackshift-ui/social-icons";
8
+ import { Text } from "@stackshift-ui/text";
9
+ import React from "react";
10
+
11
+ import { FooterProps } from ".";
12
+ import { logoLink } from "./helper";
13
+ import { LabeledRoute, LabeledRouteWithKey, Logo, SocialLink, Socials } from "./types";
14
+
15
+ export default function Footer_B({ logo, copyright, socialMedia, menu }: FooterProps) {
16
+ return (
17
+ <Section className="py-20 bg-background">
18
+ <Container maxWidth={1280}>
19
+ <Flex wrap align="center" justify="between" className="pb-12 border-b border-gray-100">
20
+ <LogoSection logo={logo} />
21
+ <MenuLists menu={menu} />
22
+ </Flex>
23
+ <Flex wrap align="center" justify="between" className="mt-8">
24
+ <CopyrightContainer copyright={copyright} />
25
+ <SocialMediaContainer socialMedia={socialMedia} />
26
+ </Flex>
27
+ </Container>
28
+ </Section>
29
+ );
30
+ }
31
+
32
+ function LogoSection({ logo }: { logo?: Logo }) {
33
+ if (!logo?.image) return null;
34
+
35
+ return (
36
+ <div className="flex items-end h-full w-full lg:w-1/5">
37
+ <Link
38
+ aria-label={logoLink(logo) === "/" ? "Go to home page" : `Go to ${logoLink(logo)}`}
39
+ className="inline-block text-3xl font-bold leading-none"
40
+ href={logoLink(logo)}
41
+ target={logo?.linkTarget}
42
+ rel={logo?.linkTarget === "_blank" ? "noopener noreferrer" : ""}>
43
+ <Image
44
+ src={logo?.image}
45
+ alt={logo?.alt ?? "footer-logo"}
46
+ width={132}
47
+ height={132}
48
+ className="inline-block text-3xl font-bold leading-none"
49
+ />
50
+ </Link>
51
+ </div>
52
+ );
53
+ }
54
+
55
+ function MenuLists({ menu }: { menu?: LabeledRouteWithKey[] }) {
56
+ if (!menu) return null;
57
+
58
+ return (
59
+ <div className="w-full lg:w-auto">
60
+ <Flex wrap align="center" justify="between" as="ul" className=" mt-8 lg:space-x-5">
61
+ {menu?.map((links, index, { length }) => (
62
+ <React.Fragment key={links?._key || index}>
63
+ <MenuList links={links} />
64
+ {index + 1 !== length ? <MenuSeparatorIcon /> : null}
65
+ </React.Fragment>
66
+ ))}
67
+ </Flex>
68
+ </div>
69
+ );
70
+ }
71
+
72
+ function MenuList({ links, index }: { links?: LabeledRoute; index?: number }) {
73
+ if (!links) return null;
74
+
75
+ return (
76
+ <li className="w-full mb-2 md:mb-0 md:w-auto" key={index}>
77
+ <Button
78
+ as="link"
79
+ link={links}
80
+ className="text-gray-500 no-underline lg:text-sm hover:text-gray-700"
81
+ ariaLabel={links?.label}>
82
+ {links?.label}
83
+ </Button>
84
+ </li>
85
+ );
86
+ }
87
+
88
+ function MenuSeparatorIcon() {
89
+ return (
90
+ <li className="hidden md:block">
91
+ <svg
92
+ className="w-4 h-4 mx-4 text-gray-500"
93
+ xmlns="http://www.w3.org/2000/svg"
94
+ fill="none"
95
+ viewBox="0 0 24 24"
96
+ stroke="currentColor">
97
+ <path
98
+ strokeLinecap="round"
99
+ strokeLinejoin="round"
100
+ strokeWidth="2"
101
+ d="M12 5v.01M12 12v.01M12 19v.01M12 6a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2zm0 7a1 1 0 110-2 1 1 0 010 2z"
102
+ />
103
+ </svg>
104
+ </li>
105
+ );
106
+ }
107
+
108
+ function CopyrightContainer({ copyright }: { copyright?: string }) {
109
+ if (!copyright) return null;
110
+
111
+ return (
112
+ <Text muted className="order-last text-sm ">
113
+ {copyright}
114
+ </Text>
115
+ );
116
+ }
117
+
118
+ function SocialMediaContainer({ socialMedia }: { socialMedia?: SocialLink[] }) {
119
+ if (!socialMedia) return null;
120
+
121
+ return (
122
+ <div className="order-first mb-4 lg:order-last lg:mb-0">
123
+ {socialMedia?.map(social => <SocialMediaLink social={social} />)}
124
+ </div>
125
+ );
126
+ }
127
+
128
+ function SocialMediaLink({ social }: { social?: SocialLink }) {
129
+ if (!social?.socialMediaLink) return null;
130
+
131
+ return (
132
+ <Link
133
+ aria-label={social?.socialMedia || social?.socialMediaPlatform || ""}
134
+ className="inline-block p-2 mr-2 rounded"
135
+ target="_blank"
136
+ rel="noopener noreferrer"
137
+ href={social?.socialMediaLink}
138
+ key={social?._key}>
139
+ {social?.socialMediaIcon?.image ? (
140
+ <Image
141
+ className="h-6"
142
+ src={`${social?.socialMediaIcon?.image}`}
143
+ width={24}
144
+ height={24}
145
+ alt={social?.socialMediaIcon?.alt ?? "contact-socialMedia-icon"}
146
+ />
147
+ ) : (
148
+ <SocialIcons social={social?.socialMedia as Socials} />
149
+ )}
150
+ </Link>
151
+ );
152
+ }
153
+
154
+ export { Footer_B };
@@ -0,0 +1,154 @@
1
+ import { Button } from "@stackshift-ui/button";
2
+ import { Container } from "@stackshift-ui/container";
3
+ import { Flex } from "@stackshift-ui/flex";
4
+ import { Image } from "@stackshift-ui/image";
5
+ import { Link } from "@stackshift-ui/link";
6
+ import { Section } from "@stackshift-ui/section";
7
+ import { SocialIcons } from "@stackshift-ui/social-icons";
8
+ import { Text } from "@stackshift-ui/text";
9
+
10
+ import { FooterProps } from ".";
11
+ import { logoLink } from "./helper";
12
+ import { LabeledRoute, LabeledRouteWithKey, Logo, SocialLink, Socials } from "./types";
13
+
14
+ export default function Footer_C({ logo, menu, copyright, socialMedia }: FooterProps) {
15
+ return (
16
+ <Section className="bg-background">
17
+ <BorderStyle />
18
+ <Container maxWidth={1000}>
19
+ <div className="pt-10 pb-12">
20
+ <Flex
21
+ justify="between"
22
+ align="center"
23
+ className="relative flex-col gap-8 mb-8 md:flex-row lg:border-b lg:border-gray-300 lg:pb-8">
24
+ <CopyrightSection copyright={copyright} />
25
+ <MenuLists menu={menu} />
26
+ <LogoSection logo={logo} />
27
+ </Flex>
28
+ <SocialMediaContainer socialMedia={socialMedia} />
29
+ </div>
30
+ </Container>
31
+ </Section>
32
+ );
33
+ }
34
+
35
+ function CopyrightSection({ copyright }: { copyright?: string }) {
36
+ if (!copyright) return null;
37
+
38
+ return <Text className="w-full text-sm text-center">{copyright}</Text>;
39
+ }
40
+
41
+ function LogoSection({ logo }: { logo?: Logo }) {
42
+ if (!logo?.image) return null;
43
+
44
+ return (
45
+ <div className="w-full text-center">
46
+ <Link
47
+ className="inline-block text-xl font-bold leading-none"
48
+ aria-label={logoLink(logo) === "/" ? "Go to home page" : `Go to ${logoLink(logo)}`}
49
+ href={logoLink(logo)}
50
+ target={logo?.linkTarget}
51
+ rel={logo?.linkTarget === "_blank" ? "noopener noreferrer" : ""}>
52
+ <Image
53
+ src={logo?.image}
54
+ alt={logo?.alt ?? "footer-logo"}
55
+ className="inline-block text-xl font-bold leading-none"
56
+ width={64}
57
+ height={64}
58
+ />
59
+ </Link>
60
+ </div>
61
+ );
62
+ }
63
+
64
+ function MenuLists({ menu }: { menu?: LabeledRouteWithKey[] }) {
65
+ if (!menu) return null;
66
+
67
+ return (
68
+ <div className="mx-auto">
69
+ <Flex
70
+ className="flex-col gap-0 lg:flex-row lg:gap-10"
71
+ as="ul"
72
+ align="center"
73
+ justify="center">
74
+ {menu?.map((links, index) => <MenuList links={links} index={index} />)}
75
+ </Flex>
76
+ </div>
77
+ );
78
+ }
79
+
80
+ function MenuList({ links, index }: { links?: LabeledRoute; index?: number }) {
81
+ if (!links) return null;
82
+
83
+ return (
84
+ <li className="w-full text-center" key={index}>
85
+ <Button
86
+ as="link"
87
+ link={links}
88
+ className="text-sm text-center text-black no-underline hover:text-gray-500 whitespace-nowrap"
89
+ ariaLabel={links?.label}>
90
+ {links?.label}
91
+ </Button>
92
+ </li>
93
+ );
94
+ }
95
+
96
+ function SocialMediaContainer({ socialMedia }: { socialMedia?: SocialLink[] }) {
97
+ if (!socialMedia) return null;
98
+
99
+ return (
100
+ <Flex wrap justify="center" className="space-y-2 sm:space-y-0">
101
+ {socialMedia?.map((social, index) => <SocialMediaLink social={social} index={index} />)}
102
+ </Flex>
103
+ );
104
+ }
105
+
106
+ function SocialMediaLink({ social, index }: { social?: SocialLink; index?: number }) {
107
+ if (!social?.socialMediaLink) return null;
108
+
109
+ return (
110
+ <Link
111
+ aria-label={social?.socialMedia || social?.socialMediaPlatform || ""}
112
+ className="inline-block p-2 mr-2 rounded"
113
+ target="_blank"
114
+ rel="noopener noreferrer"
115
+ href={social?.socialMediaLink}
116
+ key={index}>
117
+ {social?.socialMediaIcon?.image ? (
118
+ <Image
119
+ className="h-6"
120
+ src={`${social?.socialMediaIcon?.image}`}
121
+ width={56}
122
+ height={56}
123
+ alt={social?.socialMediaIcon?.alt ?? "contact-socialMedia-icon"}
124
+ />
125
+ ) : (
126
+ <SocialIcons social={social?.socialMedia as Socials} />
127
+ )}
128
+ </Link>
129
+ );
130
+ }
131
+
132
+ function BorderStyle() {
133
+ return (
134
+ <div className="flex w-full">
135
+ <div className="flex w-1/3">
136
+ <div className="w-1/3 py-1 bg-secondary" />
137
+ <div className="w-1/3 py-1 bg-primary" />
138
+ <div className="w-1/3 py-1 bg-primary" />
139
+ </div>
140
+ <div className="flex w-1/3">
141
+ <div className="w-1/3 py-1 bg-secondary" />
142
+ <div className="w-1/3 py-1 bg-primary" />
143
+ <div className="w-1/3 py-1 bg-primary" />
144
+ </div>
145
+ <div className="flex w-1/3">
146
+ <div className="w-1/3 py-1 bg-secondary" />
147
+ <div className="w-1/3 py-1 bg-primary" />
148
+ <div className="w-1/3 py-1 bg-primary" />
149
+ </div>
150
+ </div>
151
+ );
152
+ }
153
+
154
+ export { Footer_C };
@@ -0,0 +1,154 @@
1
+ import { Button } from "@stackshift-ui/button";
2
+ import { Container } from "@stackshift-ui/container";
3
+ import { Flex } from "@stackshift-ui/flex";
4
+ import { Image } from "@stackshift-ui/image";
5
+ import { Link } from "@stackshift-ui/link";
6
+ import { Section } from "@stackshift-ui/section";
7
+ import { SocialIcons } from "@stackshift-ui/social-icons";
8
+ import { Text } from "@stackshift-ui/text";
9
+
10
+ import { FooterProps } from ".";
11
+ import { logoLink } from "./helper";
12
+ import { Logo, SocialLink, Socials } from "./types";
13
+
14
+ export default function Footer_D({
15
+ logo,
16
+ multipleMenus,
17
+ copyright,
18
+ socialMedia,
19
+ text,
20
+ }: FooterProps) {
21
+ return (
22
+ <Section className="py-20 overflow-hidden bg-background">
23
+ <Container maxWidth={1280}>
24
+ <Flex wrap className="space-y-4 lg:space-y-0">
25
+ <div className="w-full max-w-2xl space-y-4 lg:w-1/4">
26
+ <LogoSection logo={logo} />
27
+ <TextSection text={text} />
28
+ </div>
29
+
30
+ <MenuSection multipleMenus={multipleMenus} />
31
+ <SocialMediaContainer socialMedia={socialMedia} />
32
+ </Flex>
33
+ <CopyrightSection copyright={copyright} />
34
+ </Container>
35
+ </Section>
36
+ );
37
+ }
38
+
39
+ function LogoSection({ logo }: { logo?: Logo }) {
40
+ if (!logo?.image) return null;
41
+
42
+ return (
43
+ <Link
44
+ className="inline-block text-xl font-bold leading-none"
45
+ aria-label={logoLink(logo) === "/" ? "Go to home page" : `Go to ${logoLink(logo)}`}
46
+ href={logoLink(logo)}
47
+ target={logo?.linkTarget}
48
+ rel={logo?.linkTarget === "_blank" ? "noopener noreferrer" : ""}>
49
+ <Image
50
+ className="h-14"
51
+ src={`${logo?.image}`}
52
+ sizes="(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
53
+ width={132}
54
+ height={56}
55
+ alt={logo?.alt ?? "footer-logo"}
56
+ />
57
+ </Link>
58
+ );
59
+ }
60
+
61
+ function TextSection({ text }: { text?: string }) {
62
+ if (!text) return null;
63
+
64
+ return (
65
+ <Text muted className="leading-normal">
66
+ {text}
67
+ </Text>
68
+ );
69
+ }
70
+
71
+ function CopyrightSection({ copyright }: { copyright?: string }) {
72
+ if (!copyright) return null;
73
+
74
+ return <Text className="pt-10 text-sm">{copyright}</Text>;
75
+ }
76
+
77
+ function MenuSection({ multipleMenus }: { multipleMenus?: any[] }) {
78
+ if (!multipleMenus) return null;
79
+
80
+ return (
81
+ <Flex wrap className="flex-grow lg:justify-around" gap={4}>
82
+ {multipleMenus?.map(menu => <MenuLinks key={menu?._key} menu={menu} />)}
83
+ </Flex>
84
+ );
85
+ }
86
+
87
+ // Individual Menu Links Component
88
+ function MenuLinks({ menu }: { menu?: any }) {
89
+ if (!menu) return null;
90
+
91
+ return (
92
+ <div className="w-[200px] flex-none">
93
+ {menu?.title && (
94
+ <Text weight="bold" className="mb-3">
95
+ {menu?.title}
96
+ </Text>
97
+ )}
98
+ {menu?.links?.length > 0 && (
99
+ <Flex as="ul" direction="col" className="space-y-2">
100
+ {menu?.links?.map((link: any) => (
101
+ <li key={link?._key}>
102
+ <Button
103
+ as="link"
104
+ link={link}
105
+ className="text-gray-500 no-underline hover:text-gray-700"
106
+ ariaLabel={link?.label}>
107
+ {link?.label}
108
+ </Button>
109
+ </li>
110
+ ))}
111
+ </Flex>
112
+ )}
113
+ </div>
114
+ );
115
+ }
116
+
117
+ function SocialMediaContainer({ socialMedia }: { socialMedia?: SocialLink[] }) {
118
+ if (!socialMedia) return null;
119
+
120
+ return (
121
+ <Flex className="w-full ml-auto lg:justify-end lg:w-1/6">
122
+ {socialMedia?.map(social => social?.socialMediaLink && <SocialMediaLink social={social} />)}
123
+ </Flex>
124
+ );
125
+ }
126
+
127
+ function SocialMediaLink({ social }: { social?: SocialLink }) {
128
+ if (!social?.socialMediaLink) return null;
129
+
130
+ return (
131
+ <span key={social?._key}>
132
+ <Link
133
+ aria-label={social?.socialMedia || social?.socialMediaPlatform || ""}
134
+ className="inline-block p-2 mr-2 rounded"
135
+ target="_blank"
136
+ rel="noopener noreferrer"
137
+ href={social?.socialMediaLink}>
138
+ {social?.socialMediaIcon?.image ? (
139
+ <Image
140
+ className="h-6"
141
+ src={`${social?.socialMediaIcon?.image}`}
142
+ width={24}
143
+ height={24}
144
+ alt={social?.socialMediaIcon?.alt ?? "contact-socialMedia-icon"}
145
+ />
146
+ ) : (
147
+ <SocialIcons social={social?.socialMedia as Socials} />
148
+ )}
149
+ </Link>
150
+ </span>
151
+ );
152
+ }
153
+
154
+ export { Footer_D };
@@ -0,0 +1,15 @@
1
+ import { Logo } from "../types";
2
+
3
+ // Logo link
4
+ export const logoLink = (logo: Logo) => {
5
+ if (logo?.internalLink && logo?.type === "linkInternal") {
6
+ if (logo?.internalLink?.toLowerCase()?.includes("home")) {
7
+ return "/";
8
+ }
9
+ return `/${logo.internalLink}`;
10
+ } else if (logo?.externalLink && logo?.type === "linkExternal") {
11
+ return logo?.externalLink ?? "/";
12
+ } else {
13
+ return "/";
14
+ }
15
+ };
package/src/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ "use client";
2
+
3
+ // component exports
4
+ export * from "./footer";
5
+ export * from "./footer_a";
6
+ export * from "./footer_b";
7
+ export * from "./footer_c";
8
+ export * from "./footer_d";