@stackshift-ui/navigation 6.0.3 → 6.0.4

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,252 @@
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 { Text } from "@stackshift-ui/text";
8
+ import React from "react";
9
+ import { NavigationProps, ResponsiveNavLinksProps } from ".";
10
+ import { logoLink } from "./helper";
11
+ import { LabeledRoute, LabeledRouteWithKey, Logo } from "./types";
12
+
13
+ export default function Navigation_C({
14
+ links,
15
+ primaryButton,
16
+ secondaryButton,
17
+ logo,
18
+ }: NavigationProps) {
19
+ const [menu, setMenu] = React.useState(false);
20
+ const showMenu = () => {
21
+ setMenu(prevState => !prevState);
22
+ };
23
+
24
+ return (
25
+ <Section className="bg-background">
26
+ <nav className="relative py-6">
27
+ <Container maxWidth={1280}>
28
+ <Flex align="center">
29
+ <NavLinks links={links} />
30
+ <LogoSection logo={logo} />
31
+ <Buttons primaryButton={primaryButton} secondaryButton={secondaryButton} />
32
+ <MobileMenu showMenu={showMenu} />
33
+ </Flex>
34
+ </Container>
35
+ </nav>
36
+ <ResponsiveNavLinks
37
+ menu={menu}
38
+ showMenu={showMenu}
39
+ links={links}
40
+ primaryButton={primaryButton}
41
+ secondaryButton={secondaryButton}
42
+ />
43
+ </Section>
44
+ );
45
+ }
46
+
47
+ function NavLinks({ links }: { links?: LabeledRouteWithKey[] }) {
48
+ if (!links) return null;
49
+
50
+ return (
51
+ <ul className="hidden lg:flex lg:w-auto lg:items-center lg:space-x-6">
52
+ {links?.map((link, index) => (
53
+ <React.Fragment key={index}>
54
+ {link?.label && <NavItem link={link} />}
55
+ {links.length !== index + 1 ? <NavIcon /> : null}
56
+ </React.Fragment>
57
+ ))}
58
+ </ul>
59
+ );
60
+ }
61
+
62
+ function NavItem({ link }: { link?: LabeledRouteWithKey }) {
63
+ if (!link) return null;
64
+
65
+ return (
66
+ <li>
67
+ <Button
68
+ as="link"
69
+ ariaLabel={link?.label}
70
+ link={link}
71
+ className="text-sm text-gray-500 no-underline hover:text-gray-900">
72
+ {link?.label}
73
+ </Button>
74
+ </li>
75
+ );
76
+ }
77
+
78
+ function NavIcon() {
79
+ return (
80
+ <li className="text-gray-500">
81
+ <svg
82
+ className="w-4 h-4 current-fill"
83
+ xmlns="http://www.w3.org/2000/svg"
84
+ fill="none"
85
+ viewBox="0 0 24 24"
86
+ stroke="currentColor">
87
+ <path
88
+ strokeLinecap="round"
89
+ strokeLinejoin="round"
90
+ strokeWidth="2"
91
+ 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"></path>
92
+ </svg>
93
+ </li>
94
+ );
95
+ }
96
+
97
+ function LogoSection({ logo }: { logo?: Logo }) {
98
+ if (!logo) return null;
99
+
100
+ return (
101
+ <div className="lg:absolute lg:left-1/2 lg:top-1/2 lg:-translate-x-1/2 lg:-translate-y-1/2 lg:transform">
102
+ <Link
103
+ aria-label={`Go to ${logoLink(logo) === "/" ? "home page" : logoLink(logo)}`}
104
+ className="text-3xl font-bold leading-none"
105
+ href={logoLink(logo)}
106
+ target={logo?.linkTarget}
107
+ rel={logo?.linkTarget === "_blank" ? "noopener noreferrer" : ""}>
108
+ <Image
109
+ src={logo?.image}
110
+ alt={logo?.alt ?? "navigation-logo"}
111
+ width={60}
112
+ height={60}
113
+ className="text-3xl font-bold leading-none"
114
+ />
115
+ </Link>
116
+ </div>
117
+ );
118
+ }
119
+
120
+ function Buttons({
121
+ primaryButton,
122
+ secondaryButton,
123
+ }: {
124
+ primaryButton?: LabeledRoute;
125
+ secondaryButton?: LabeledRoute;
126
+ }) {
127
+ return (
128
+ <div className="hidden text-right lg:ml-auto lg:block lg:w-1/3">
129
+ {primaryButton?.label && (
130
+ <Button
131
+ as="link"
132
+ ariaLabel={primaryButton?.label}
133
+ link={primaryButton}
134
+ className="hidden lg:inline-block px-4 py-3 mb-2 text-gray-900 lg:ml-auto lg:mr-3 font-semibold rounded-global bg-secondary hover:bg-secondary/50">
135
+ {primaryButton?.label}
136
+ </Button>
137
+ )}
138
+ {secondaryButton?.label && (
139
+ <Button
140
+ as="link"
141
+ ariaLabel={secondaryButton?.label}
142
+ link={secondaryButton}
143
+ className="hidden lg:inline-block px-4 py-3 mb-2 leading-loose text-center text-white font-semibold bg-primary hover:bg-primary-foreground rounded-global">
144
+ {secondaryButton?.label}
145
+ </Button>
146
+ )}
147
+ </div>
148
+ );
149
+ }
150
+
151
+ function MobileMenu({ showMenu }: { showMenu: () => void }) {
152
+ return (
153
+ <div className="ml-auto lg:hidden">
154
+ <Button
155
+ variant="unstyled"
156
+ as="button"
157
+ ariaLabel="Navigation menu"
158
+ className="flex items-center p-3 navbar-burger text-primary"
159
+ onClick={showMenu}>
160
+ <svg
161
+ className="block w-4 h-4 fill-current"
162
+ viewBox="0 0 20 20"
163
+ xmlns="http://www.w3.org/2000/svg">
164
+ <title>Mobile menu</title>
165
+ <path d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0v-2z"></path>
166
+ </svg>
167
+ </Button>
168
+ </div>
169
+ );
170
+ }
171
+
172
+ function ResponsiveNavLinks({
173
+ menu,
174
+ showMenu,
175
+ links,
176
+ primaryButton,
177
+ secondaryButton,
178
+ }: ResponsiveNavLinksProps) {
179
+ return (
180
+ <div className={`${menu ? null : "hidden"} mobile-nav relative z-50`}>
181
+ <div
182
+ className="fixed inset-0 bg-gray-800 opacity-25 navbar-backdrop"
183
+ onClick={showMenu}></div>
184
+ <nav className="fixed top-0 bottom-0 left-0 flex flex-col w-5/6 max-w-sm px-6 py-6 overflow-y-auto bg-white border-r">
185
+ <div className="flex items-center mb-8">
186
+ <Button
187
+ variant="unstyled"
188
+ as="button"
189
+ ariaLabel="Navigation menu"
190
+ className="navbar-close"
191
+ onClick={showMenu}>
192
+ <svg
193
+ className="w-6 h-6 text-gray-500 cursor-pointer hover:text-gray-500"
194
+ xmlns="http://www.w3.org/2000/svg"
195
+ fill="none"
196
+ viewBox="0 0 24 24"
197
+ stroke="currentColor">
198
+ <path
199
+ strokeLinecap="round"
200
+ strokeLinejoin="round"
201
+ strokeWidth="2"
202
+ d="M6 18L18 6M6 6l12 12"></path>
203
+ </svg>
204
+ </Button>
205
+ </div>
206
+ <div>
207
+ <ul>
208
+ {links &&
209
+ links?.map((link, index) => (
210
+ <li className="mb-1" key={index}>
211
+ <Button
212
+ as="link"
213
+ ariaLabel={link?.label}
214
+ link={link}
215
+ className="block p-4 text-sm font-semibold text-gray-700 no-underline rounded hover:bg-secondary-foreground hover:text-primary">
216
+ {link?.label}
217
+ </Button>
218
+ </li>
219
+ ))}
220
+ </ul>
221
+ </div>
222
+ <div className="mt-auto">
223
+ <div className="pt-6">
224
+ {primaryButton?.label && (
225
+ <Button
226
+ as="link"
227
+ ariaLabel={primaryButton?.label}
228
+ link={primaryButton}
229
+ className="block px-4 py-3 mb-2 text-gray-900 text-center lg:ml-auto lg:mr-3 font-semibold rounded-global bg-secondary hover:bg-secondary/50">
230
+ {primaryButton?.label}
231
+ </Button>
232
+ )}
233
+ {secondaryButton?.label && (
234
+ <Button
235
+ as="link"
236
+ ariaLabel={secondaryButton?.label}
237
+ link={secondaryButton}
238
+ className="block px-4 py-3 mb-2 leading-loose text-center text-white font-semibold bg-primary hover:bg-primary-foreground rounded-global">
239
+ {secondaryButton?.label}
240
+ </Button>
241
+ )}
242
+ </div>
243
+ <Text fontSize="xs" className="my-4 text-center text-gray-700">
244
+ <span>{`© ${new Date().getFullYear()} All rights reserved.`}</span>
245
+ </Text>
246
+ </div>
247
+ </nav>
248
+ </div>
249
+ );
250
+ }
251
+
252
+ export { Navigation_C };
@@ -0,0 +1,252 @@
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 { Text } from "@stackshift-ui/text";
8
+ import React from "react";
9
+ import { NavigationProps, ResponsiveNavLinksProps } from ".";
10
+ import { logoLink } from "./helper";
11
+ import { LabeledRoute, LabeledRouteWithKey, Logo } from "./types";
12
+
13
+ export default function Navigation_D({
14
+ links,
15
+ primaryButton,
16
+ secondaryButton,
17
+ logo,
18
+ }: NavigationProps) {
19
+ const [menu, setMenu] = React.useState(false);
20
+ const showMenu = () => {
21
+ setMenu(prevState => !prevState);
22
+ };
23
+
24
+ return (
25
+ <Section className="bg-background">
26
+ <nav className="relative px-6 py-6">
27
+ <Container maxWidth={1000}>
28
+ <Flex align="center">
29
+ <NavLinks links={links} />
30
+ <LogoSection logo={logo} />
31
+ <Buttons primaryButton={primaryButton} secondaryButton={secondaryButton} />
32
+ <MobileMenu showMenu={showMenu} />
33
+ </Flex>
34
+ </Container>
35
+ </nav>
36
+ <ResponsiveNavLinks
37
+ menu={menu}
38
+ showMenu={showMenu}
39
+ links={links}
40
+ primaryButton={primaryButton}
41
+ secondaryButton={secondaryButton}
42
+ />
43
+ </Section>
44
+ );
45
+ }
46
+
47
+ function NavLinks({ links }: { links?: LabeledRouteWithKey[] }) {
48
+ if (!links) return null;
49
+
50
+ return (
51
+ <ul className="hidden lg:flex lg:w-auto lg:items-center lg:space-x-5">
52
+ {links.map((link, index) => (
53
+ <React.Fragment key={index}>
54
+ {link?.label && <NavItem link={link} />}
55
+ {links.length !== index + 1 && <NavIcon />}
56
+ </React.Fragment>
57
+ ))}
58
+ </ul>
59
+ );
60
+ }
61
+
62
+ function NavItem({ link }: { link?: LabeledRouteWithKey }) {
63
+ if (!link) return null;
64
+
65
+ return (
66
+ <li>
67
+ <Button
68
+ as="link"
69
+ ariaLabel={link?.label}
70
+ link={link}
71
+ className="text-sm text-gray-500 no-underline hover:text-gray-900">
72
+ {link?.label}
73
+ </Button>
74
+ </li>
75
+ );
76
+ }
77
+
78
+ function NavIcon() {
79
+ return (
80
+ <li className="text-gray-500">
81
+ <svg
82
+ className="w-4 h-4 current-fill"
83
+ xmlns="http://www.w3.org/2000/svg"
84
+ fill="none"
85
+ viewBox="0 0 24 24"
86
+ stroke="currentColor">
87
+ <path
88
+ strokeLinecap="round"
89
+ strokeLinejoin="round"
90
+ strokeWidth="2"
91
+ 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"></path>
92
+ </svg>
93
+ </li>
94
+ );
95
+ }
96
+
97
+ function LogoSection({ logo }: { logo?: Logo }) {
98
+ if (!logo) return null;
99
+
100
+ return (
101
+ <div className="lg:absolute lg:left-1/2 lg:top-1/2 lg:-translate-x-1/2 lg:-translate-y-1/2 lg:transform">
102
+ <Link
103
+ aria-label={`Go to ${logoLink(logo) === "/" ? "home page" : logoLink(logo)}`}
104
+ className="text-3xl font-bold leading-none"
105
+ href={logoLink(logo)}
106
+ target={logo?.linkTarget}
107
+ rel={logo?.linkTarget === "_blank" ? "noopener noreferrer" : ""}>
108
+ <Image
109
+ src={logo?.image}
110
+ alt={logo?.alt ?? "navigation-logo"}
111
+ width={100}
112
+ height={100}
113
+ className="text-3xl font-bold leading-none"
114
+ />
115
+ </Link>
116
+ </div>
117
+ );
118
+ }
119
+
120
+ function Buttons({
121
+ primaryButton,
122
+ secondaryButton,
123
+ }: {
124
+ primaryButton?: LabeledRoute;
125
+ secondaryButton?: LabeledRoute;
126
+ }) {
127
+ return (
128
+ <React.Fragment>
129
+ {primaryButton?.label && (
130
+ <Button
131
+ as="link"
132
+ ariaLabel={primaryButton?.label}
133
+ link={primaryButton}
134
+ className="hidden lg:inline-block px-4 py-3 mb-2 text-gray-900 lg:ml-auto lg:mr-3 font-semibold rounded-global bg-secondary hover:bg-secondary/50">
135
+ {primaryButton?.label}
136
+ </Button>
137
+ )}
138
+ {secondaryButton?.label && (
139
+ <Button
140
+ as="link"
141
+ ariaLabel={secondaryButton?.label}
142
+ link={secondaryButton}
143
+ className="hidden lg:inline-block px-4 py-3 mb-2 leading-loose text-center text-white font-semibold bg-primary hover:bg-primary-foreground rounded-global">
144
+ {secondaryButton?.label}
145
+ </Button>
146
+ )}
147
+ </React.Fragment>
148
+ );
149
+ }
150
+
151
+ function MobileMenu({ showMenu }: { showMenu: () => void }) {
152
+ return (
153
+ <div className="ml-auto lg:hidden">
154
+ <Button
155
+ variant="unstyled"
156
+ as="button"
157
+ ariaLabel="Navigation menu"
158
+ className="flex items-center p-3 navbar-burger text-primary"
159
+ onClick={showMenu}>
160
+ <svg
161
+ className="block w-4 h-4 fill-current"
162
+ viewBox="0 0 20 20"
163
+ xmlns="http://www.w3.org/2000/svg">
164
+ <title>Mobile menu</title>
165
+ <path d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0v-2z"></path>
166
+ </svg>
167
+ </Button>
168
+ </div>
169
+ );
170
+ }
171
+
172
+ function ResponsiveNavLinks({
173
+ menu,
174
+ showMenu,
175
+ links,
176
+ primaryButton,
177
+ secondaryButton,
178
+ }: ResponsiveNavLinksProps) {
179
+ return (
180
+ <div className={`${menu ? null : "hidden"} mobile-nav relative z-50`}>
181
+ <div
182
+ className="fixed inset-0 bg-gray-800 opacity-25 navbar-backdrop"
183
+ onClick={showMenu}></div>
184
+ <nav className="fixed top-0 bottom-0 left-0 flex flex-col w-5/6 max-w-sm px-6 py-6 overflow-y-auto bg-white border-r">
185
+ <div className="flex items-center mb-8">
186
+ <Button
187
+ variant="unstyled"
188
+ as="button"
189
+ ariaLabel="Navigation menu"
190
+ className="navbar-close"
191
+ onClick={showMenu}>
192
+ <svg
193
+ className="w-6 h-6 text-gray-500 cursor-pointer hover:text-gray-500"
194
+ xmlns="http://www.w3.org/2000/svg"
195
+ fill="none"
196
+ viewBox="0 0 24 24"
197
+ stroke="currentColor">
198
+ <path
199
+ strokeLinecap="round"
200
+ strokeLinejoin="round"
201
+ strokeWidth="2"
202
+ d="M6 18L18 6M6 6l12 12"></path>
203
+ </svg>
204
+ </Button>
205
+ </div>
206
+ <div>
207
+ <ul>
208
+ {links &&
209
+ links?.map((link, index) => (
210
+ <li className="mb-1" key={index}>
211
+ <Button
212
+ as="link"
213
+ ariaLabel={link?.label}
214
+ link={link}
215
+ className="block p-4 text-sm font-semibold text-gray-700 no-underline rounded hover:bg-secondary-foreground hover:text-primary">
216
+ {link?.label}
217
+ </Button>
218
+ </li>
219
+ ))}
220
+ </ul>
221
+ </div>
222
+ <div className="mt-auto">
223
+ <div className="pt-6">
224
+ {primaryButton?.label && (
225
+ <Button
226
+ as="link"
227
+ ariaLabel={primaryButton?.label}
228
+ link={primaryButton}
229
+ className="block px-4 py-3 mb-2 text-gray-900 text-center lg:ml-auto lg:mr-3 font-semibold rounded-global bg-secondary hover:bg-secondary/50">
230
+ {primaryButton?.label}
231
+ </Button>
232
+ )}
233
+ {secondaryButton?.label && (
234
+ <Button
235
+ as="link"
236
+ ariaLabel={secondaryButton?.label}
237
+ link={secondaryButton}
238
+ className="block px-4 py-3 mb-2 leading-loose text-center text-white font-semibold bg-primary hover:bg-primary-foreground rounded-global">
239
+ {secondaryButton?.label}
240
+ </Button>
241
+ )}
242
+ </div>
243
+ <Text fontSize="xs" muted className="my-4 text-center ">
244
+ <span>{`© ${new Date().getFullYear()} All rights reserved.`}</span>
245
+ </Text>
246
+ </div>
247
+ </nav>
248
+ </div>
249
+ );
250
+ }
251
+
252
+ export { Navigation_D };