tio-design-make-experiments 0.0.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.
- package/ATTRIBUTIONS.md +3 -0
- package/README.md +11 -0
- package/guidelines/Guidelines.md +61 -0
- package/index.html +15 -0
- package/package.json +91 -0
- package/postcss.config.mjs +15 -0
- package/src/app/App.tsx +6 -0
- package/src/app/components/design-system/Buttons.tsx +623 -0
- package/src/app/components/design-system/Cards.tsx +123 -0
- package/src/app/components/design-system/Charts.tsx +135 -0
- package/src/app/components/design-system/ColorPalette.tsx +86 -0
- package/src/app/components/design-system/CopyButton.tsx +102 -0
- package/src/app/components/design-system/Forms.tsx +409 -0
- package/src/app/components/design-system/Icons.tsx +140 -0
- package/src/app/components/design-system/ListItems.tsx +234 -0
- package/src/app/components/design-system/Navigation.tsx +344 -0
- package/src/app/components/design-system/Patterns.tsx +235 -0
- package/src/app/components/design-system/PopoverMenu.tsx +81 -0
- package/src/app/components/design-system/SectionHeader.tsx +22 -0
- package/src/app/components/design-system/Spacing.tsx +109 -0
- package/src/app/components/design-system/StatusIndicators.tsx +194 -0
- package/src/app/components/design-system/Typography.tsx +88 -0
- package/src/app/components/figma/ImageWithFallback.tsx +27 -0
- package/src/app/components/ui/accordion.tsx +66 -0
- package/src/app/components/ui/alert-dialog.tsx +157 -0
- package/src/app/components/ui/alert.tsx +66 -0
- package/src/app/components/ui/aspect-ratio.tsx +11 -0
- package/src/app/components/ui/avatar.tsx +53 -0
- package/src/app/components/ui/badge.tsx +46 -0
- package/src/app/components/ui/breadcrumb.tsx +109 -0
- package/src/app/components/ui/button.tsx +58 -0
- package/src/app/components/ui/calendar.tsx +75 -0
- package/src/app/components/ui/card.tsx +92 -0
- package/src/app/components/ui/carousel.tsx +241 -0
- package/src/app/components/ui/chart.tsx +353 -0
- package/src/app/components/ui/checkbox.tsx +32 -0
- package/src/app/components/ui/collapsible.tsx +33 -0
- package/src/app/components/ui/command.tsx +177 -0
- package/src/app/components/ui/context-menu.tsx +252 -0
- package/src/app/components/ui/dialog.tsx +135 -0
- package/src/app/components/ui/drawer.tsx +132 -0
- package/src/app/components/ui/dropdown-menu.tsx +257 -0
- package/src/app/components/ui/form.tsx +168 -0
- package/src/app/components/ui/hover-card.tsx +44 -0
- package/src/app/components/ui/input-otp.tsx +77 -0
- package/src/app/components/ui/input.tsx +21 -0
- package/src/app/components/ui/label.tsx +24 -0
- package/src/app/components/ui/menubar.tsx +276 -0
- package/src/app/components/ui/navigation-menu.tsx +168 -0
- package/src/app/components/ui/pagination.tsx +127 -0
- package/src/app/components/ui/popover.tsx +48 -0
- package/src/app/components/ui/progress.tsx +31 -0
- package/src/app/components/ui/radio-group.tsx +45 -0
- package/src/app/components/ui/resizable.tsx +56 -0
- package/src/app/components/ui/scroll-area.tsx +58 -0
- package/src/app/components/ui/select.tsx +189 -0
- package/src/app/components/ui/separator.tsx +28 -0
- package/src/app/components/ui/sheet.tsx +139 -0
- package/src/app/components/ui/sidebar.tsx +726 -0
- package/src/app/components/ui/skeleton.tsx +13 -0
- package/src/app/components/ui/slider.tsx +63 -0
- package/src/app/components/ui/sonner.tsx +25 -0
- package/src/app/components/ui/switch.tsx +31 -0
- package/src/app/components/ui/table.tsx +116 -0
- package/src/app/components/ui/tabs.tsx +66 -0
- package/src/app/components/ui/textarea.tsx +18 -0
- package/src/app/components/ui/toggle-group.tsx +73 -0
- package/src/app/components/ui/toggle.tsx +47 -0
- package/src/app/components/ui/tooltip.tsx +61 -0
- package/src/app/components/ui/use-mobile.ts +21 -0
- package/src/app/components/ui/utils.ts +6 -0
- package/src/app/pages/DesignSystem.tsx +189 -0
- package/src/app/pages/Team.tsx +168 -0
- package/src/app/routes.tsx +14 -0
- package/src/assets/6276cd19433d265f363bddc7f52f4937da9b1dd4.png +0 -0
- package/src/assets/9d7a018c9a6938d439d9059f82753d232ce63804.png +0 -0
- package/src/imports/Buttons-3-409.tsx +46 -0
- package/src/imports/Buttons-3-962.tsx +155 -0
- package/src/imports/ButtonsAndActions.tsx +139 -0
- package/src/imports/Dashboard.tsx +1914 -0
- package/src/imports/DesignSystem.tsx +6008 -0
- package/src/imports/Forms.tsx +1088 -0
- package/src/imports/Navigation-17-3259.tsx +564 -0
- package/src/imports/Navigation-18-957.tsx +873 -0
- package/src/imports/Wireframe.tsx +112 -0
- package/src/imports/svg-1ifosis1tx.ts +3 -0
- package/src/imports/svg-5spfd.tsx +1 -0
- package/src/imports/svg-6180by7m37.ts +3 -0
- package/src/imports/svg-guy0p.tsx +1 -0
- package/src/imports/svg-hm2n0.tsx +2 -0
- package/src/imports/svg-j8o95ccqq7.ts +26 -0
- package/src/imports/svg-liuy2nykz3.ts +10 -0
- package/src/imports/svg-pp9c3.tsx +1 -0
- package/src/imports/svg-pr0k9194w9.ts +33 -0
- package/src/imports/svg-umftvfphsk.ts +48 -0
- package/src/imports/svg-vbi95q76mb.ts +23 -0
- package/src/imports/svg-vxjpl.tsx +1 -0
- package/src/imports/svg-wl30wxxv53.ts +3 -0
- package/src/main.tsx +7 -0
- package/src/styles/fonts.css +1 -0
- package/src/styles/forms.css +181 -0
- package/src/styles/header.css +48 -0
- package/src/styles/index.css +7 -0
- package/src/styles/navlinks.css +112 -0
- package/src/styles/popover.css +48 -0
- package/src/styles/tailwind.css +4 -0
- package/src/styles/theme.css +312 -0
- package/vite.config.ts +38 -0
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import { Link, useLocation } from "react-router";
|
|
3
|
+
import svgPaths from "../../imports/svg-umftvfphsk";
|
|
4
|
+
import { imgLogoTestinator } from "../../imports/svg-hm2n0";
|
|
5
|
+
import { ColorPalette } from "../components/design-system/ColorPalette";
|
|
6
|
+
import { Typography } from "../components/design-system/Typography";
|
|
7
|
+
import { Icons } from "../components/design-system/Icons";
|
|
8
|
+
import { Buttons } from "../components/design-system/Buttons";
|
|
9
|
+
import { Cards } from "../components/design-system/Cards";
|
|
10
|
+
import { StatusIndicators } from "../components/design-system/StatusIndicators";
|
|
11
|
+
import { Navigation } from "../components/design-system/Navigation";
|
|
12
|
+
import { ListItems } from "../components/design-system/ListItems";
|
|
13
|
+
import { Charts } from "../components/design-system/Charts";
|
|
14
|
+
import { Patterns } from "../components/design-system/Patterns";
|
|
15
|
+
import { Spacing } from "../components/design-system/Spacing";
|
|
16
|
+
import { Forms } from "../components/design-system/Forms";
|
|
17
|
+
import { PopoverMenu } from "../components/design-system/PopoverMenu";
|
|
18
|
+
|
|
19
|
+
const sections = [
|
|
20
|
+
{ id: "colors", label: "Colors" },
|
|
21
|
+
{ id: "typography", label: "Typography" },
|
|
22
|
+
{ id: "icons", label: "Icons" },
|
|
23
|
+
{ id: "buttons", label: "Buttons" },
|
|
24
|
+
{ id: "navigation", label: "Navigation" },
|
|
25
|
+
{ id: "forms", label: "Forms" },
|
|
26
|
+
{ id: "popover", label: "Popover" },
|
|
27
|
+
{ id: "cards", label: "Cards" },
|
|
28
|
+
{ id: "status", label: "Status" },
|
|
29
|
+
{ id: "lists", label: "List Items" },
|
|
30
|
+
{ id: "charts", label: "Charts" },
|
|
31
|
+
{ id: "patterns", label: "Patterns" },
|
|
32
|
+
{ id: "spacing", label: "Spacing" },
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
export default function DesignSystem() {
|
|
36
|
+
const [activeSection, setActiveSection] = useState("colors");
|
|
37
|
+
const location = useLocation();
|
|
38
|
+
|
|
39
|
+
const scrollToSection = (id: string) => {
|
|
40
|
+
setActiveSection(id);
|
|
41
|
+
const el = document.getElementById(id);
|
|
42
|
+
if (el) {
|
|
43
|
+
el.scrollIntoView({ behavior: "smooth", block: "start" });
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<div className="bg-background min-h-screen font-['Source_Sans_3',sans-serif]">
|
|
49
|
+
{/* Header */}
|
|
50
|
+
<header className="sticky top-0 z-50 header-bar">
|
|
51
|
+
<div className="max-w-[1600px] mx-auto flex items-center h-[70px] px-8 lg:px-12">
|
|
52
|
+
{/* Logo */}
|
|
53
|
+
<Link to="/" className="h-[34px] w-[148px] overflow-clip relative shrink-0 mr-8">
|
|
54
|
+
<div
|
|
55
|
+
className="absolute inset-0 mask-alpha mask-intersect mask-no-clip mask-no-repeat mask-position-[0px_0px] mask-size-[148px_34px]"
|
|
56
|
+
style={{ maskImage: `url('${imgLogoTestinator}')` }}
|
|
57
|
+
>
|
|
58
|
+
<svg className="block size-full" fill="none" preserveAspectRatio="none" viewBox="0 0 147.351 34.0003">
|
|
59
|
+
<path d={svgPaths.pd3f4900} fill="white" />
|
|
60
|
+
<path d={svgPaths.p2ef9e700} fill="white" />
|
|
61
|
+
<path d={svgPaths.p1507e900} fill="white" />
|
|
62
|
+
<path d={svgPaths.p63b5500} fill="white" />
|
|
63
|
+
<path d={svgPaths.p73e5c00} fill="white" />
|
|
64
|
+
<path d={svgPaths.p269eee80} fill="white" />
|
|
65
|
+
<path d={svgPaths.p32f5f900} fill="white" />
|
|
66
|
+
<path d={svgPaths.p166df900} fill="white" />
|
|
67
|
+
<path d={svgPaths.p3af52100} fill="white" />
|
|
68
|
+
<path d={svgPaths.p224ff200} fill="white" />
|
|
69
|
+
<path d={svgPaths.p29a28100} fill="white" />
|
|
70
|
+
<path d={svgPaths.p38feaa80} fill="white" />
|
|
71
|
+
<path d={svgPaths.p1649b700} fill="white" />
|
|
72
|
+
<path d={svgPaths.p5b04f70} fill="white" />
|
|
73
|
+
<path d={svgPaths.pafbcd00} fill="white" />
|
|
74
|
+
<path d={svgPaths.p94ead80} fill="white" />
|
|
75
|
+
<path d={svgPaths.p3e1a5280} fill="white" />
|
|
76
|
+
<path d={svgPaths.p288b2800} fill="#7954FF" />
|
|
77
|
+
<path clipRule="evenodd" d={svgPaths.p1f8b5980} fill="#78EAC1" fillRule="evenodd" />
|
|
78
|
+
</svg>
|
|
79
|
+
</div>
|
|
80
|
+
</Link>
|
|
81
|
+
|
|
82
|
+
<div className="h-8 w-px bg-border mr-6 hidden lg:block" />
|
|
83
|
+
|
|
84
|
+
{/* Page Navigation */}
|
|
85
|
+
<nav className="flex items-center gap-1 mr-6">
|
|
86
|
+
<Link
|
|
87
|
+
to="/"
|
|
88
|
+
className={location.pathname === "/" ? "navlink-active" : "navlink"}
|
|
89
|
+
style={{ fontSize: 14 }}
|
|
90
|
+
>
|
|
91
|
+
<span>Design System</span>
|
|
92
|
+
</Link>
|
|
93
|
+
<Link
|
|
94
|
+
to="/team"
|
|
95
|
+
className={location.pathname === "/team" ? "navlink-active" : "navlink"}
|
|
96
|
+
style={{ fontSize: 14 }}
|
|
97
|
+
>
|
|
98
|
+
<span>Team</span>
|
|
99
|
+
</Link>
|
|
100
|
+
</nav>
|
|
101
|
+
|
|
102
|
+
{/* Section Nav - scrollable on mobile */}
|
|
103
|
+
{location.pathname === "/" && (
|
|
104
|
+
<>
|
|
105
|
+
<div className="h-8 w-px bg-border mr-6 hidden lg:block" />
|
|
106
|
+
<div className="flex-1 overflow-x-auto" style={{ scrollbarWidth: 'none' }}>
|
|
107
|
+
<div className="flex items-center gap-1 min-w-max">
|
|
108
|
+
{sections.map((section) => (
|
|
109
|
+
<button
|
|
110
|
+
key={section.id}
|
|
111
|
+
onClick={() => scrollToSection(section.id)}
|
|
112
|
+
className={`${
|
|
113
|
+
activeSection === section.id ? "tablink-active" : "tablink"
|
|
114
|
+
}`}
|
|
115
|
+
style={{ fontSize: 14 }}
|
|
116
|
+
>
|
|
117
|
+
<span>{section.label}</span>
|
|
118
|
+
</button>
|
|
119
|
+
))}
|
|
120
|
+
</div>
|
|
121
|
+
</div>
|
|
122
|
+
</>
|
|
123
|
+
)}
|
|
124
|
+
</div>
|
|
125
|
+
</header>
|
|
126
|
+
|
|
127
|
+
{/* Main Content */}
|
|
128
|
+
<main className="max-w-[1600px] mx-auto px-8 lg:px-12 py-12">
|
|
129
|
+
{/* Hero */}
|
|
130
|
+
<div className="mb-16">
|
|
131
|
+
<h1 className="font-['Source_Sans_3',sans-serif] text-[40px] text-foreground uppercase tracking-wide" style={{ fontWeight: 300 }}>
|
|
132
|
+
Design System
|
|
133
|
+
</h1>
|
|
134
|
+
<p className="font-['Source_Sans_3',sans-serif] text-muted-foreground mt-2 max-w-2xl">
|
|
135
|
+
A comprehensive reference of all UI components, tokens, and patterns used in the Testinator application.
|
|
136
|
+
Each section documents the visual elements, their variants, and usage context.
|
|
137
|
+
</p>
|
|
138
|
+
<div className="flex items-center gap-2 mt-4">
|
|
139
|
+
<div className="inline-flex items-center justify-center size-[26px] rounded-[6px] bg-muted text-muted-foreground">
|
|
140
|
+
<svg width="14" height="14" viewBox="0 0 14 14" fill="none">
|
|
141
|
+
<rect x="4.5" y="4.5" width="7" height="7" rx="1.5" stroke="currentColor" strokeWidth="1.2" />
|
|
142
|
+
<path d="M9.5 4.5V3C9.5 2.17157 8.82843 1.5 8 1.5H3C2.17157 1.5 1.5 2.17157 1.5 3V8C1.5 8.82843 2.17157 9.5 3 9.5H4.5" stroke="currentColor" strokeWidth="1.2" />
|
|
143
|
+
</svg>
|
|
144
|
+
</div>
|
|
145
|
+
<span className="font-['Source_Sans_3',sans-serif] text-[13px] text-muted-foreground/60">
|
|
146
|
+
Hover over any element to copy its design token
|
|
147
|
+
</span>
|
|
148
|
+
</div>
|
|
149
|
+
</div>
|
|
150
|
+
|
|
151
|
+
{/* Sections */}
|
|
152
|
+
<div className="space-y-20">
|
|
153
|
+
<div id="colors"><ColorPalette /></div>
|
|
154
|
+
<div id="typography"><Typography /></div>
|
|
155
|
+
<div id="icons"><Icons /></div>
|
|
156
|
+
<div id="buttons"><Buttons /></div>
|
|
157
|
+
<div id="navigation"><Navigation /></div>
|
|
158
|
+
<div id="forms"><Forms /></div>
|
|
159
|
+
<div id="popover"><PopoverMenu /></div>
|
|
160
|
+
<div id="cards"><Cards /></div>
|
|
161
|
+
<div id="status"><StatusIndicators /></div>
|
|
162
|
+
<div id="lists"><ListItems /></div>
|
|
163
|
+
<div id="charts"><Charts /></div>
|
|
164
|
+
<div id="patterns"><Patterns /></div>
|
|
165
|
+
<div id="spacing"><Spacing /></div>
|
|
166
|
+
</div>
|
|
167
|
+
|
|
168
|
+
{/* Footer */}
|
|
169
|
+
<div className="mt-20 pt-8 border-t border-border">
|
|
170
|
+
<div className="flex items-center justify-between">
|
|
171
|
+
<p className="font-['Source_Sans_3',sans-serif] text-[13px] text-muted-foreground/60">
|
|
172
|
+
Testinator Design System v1.0
|
|
173
|
+
</p>
|
|
174
|
+
<div className="flex items-center gap-4">
|
|
175
|
+
<div className="flex items-center gap-2">
|
|
176
|
+
<div className="size-3 rounded-full bg-primary" />
|
|
177
|
+
<span className="font-['Source_Sans_3',sans-serif] text-[12px] text-muted-foreground/60">Primary</span>
|
|
178
|
+
</div>
|
|
179
|
+
<div className="flex items-center gap-2">
|
|
180
|
+
<div className="size-3 rounded-full bg-accent" />
|
|
181
|
+
<span className="font-['Source_Sans_3',sans-serif] text-[12px] text-muted-foreground/60">Accent</span>
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
184
|
+
</div>
|
|
185
|
+
</div>
|
|
186
|
+
</main>
|
|
187
|
+
</div>
|
|
188
|
+
);
|
|
189
|
+
}
|
|
@@ -0,0 +1,168 @@
|
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
|
|
3
|
+
export default function Team() {
|
|
4
|
+
const [email, setEmail] = useState("");
|
|
5
|
+
|
|
6
|
+
const testers = [
|
|
7
|
+
{
|
|
8
|
+
id: 1,
|
|
9
|
+
name: "Sarah Johnson",
|
|
10
|
+
role: "Senior QA Engineer",
|
|
11
|
+
tests: 1247,
|
|
12
|
+
successRate: 94,
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
id: 2,
|
|
16
|
+
name: "Michael Chen",
|
|
17
|
+
role: "Test Automation Lead",
|
|
18
|
+
tests: 2103,
|
|
19
|
+
successRate: 96,
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
id: 3,
|
|
23
|
+
name: "Emma Rodriguez",
|
|
24
|
+
role: "QA Analyst",
|
|
25
|
+
tests: 856,
|
|
26
|
+
successRate: 92,
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: 4,
|
|
30
|
+
name: "David Kim",
|
|
31
|
+
role: "Testing Specialist",
|
|
32
|
+
tests: 1432,
|
|
33
|
+
successRate: 95,
|
|
34
|
+
},
|
|
35
|
+
];
|
|
36
|
+
|
|
37
|
+
const handleSubscribe = (e: React.FormEvent) => {
|
|
38
|
+
e.preventDefault();
|
|
39
|
+
console.log("Subscribed:", email);
|
|
40
|
+
setEmail("");
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<div className="bg-background min-h-screen">
|
|
45
|
+
{/* Hero Section */}
|
|
46
|
+
<div className="bg-card border-b border-border">
|
|
47
|
+
<div className="max-w-[1600px] mx-auto px-8 lg:px-12 py-12">
|
|
48
|
+
<h1 className="font-['Source_Sans_3',sans-serif] text-[40px] text-foreground uppercase tracking-wide mb-4" style={{ fontWeight: 300 }}>
|
|
49
|
+
Our Testing Team
|
|
50
|
+
</h1>
|
|
51
|
+
<p className="font-['Source_Sans_3',sans-serif] text-muted-foreground max-w-2xl">
|
|
52
|
+
Meet the experts who ensure quality across all testing scenarios.
|
|
53
|
+
Our dedicated team combines technical expertise with attention to detail.
|
|
54
|
+
</p>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
{/* Main Content */}
|
|
59
|
+
<main className="max-w-[1600px] mx-auto px-8 lg:px-12 py-12">
|
|
60
|
+
{/* Team Members Section */}
|
|
61
|
+
<div className="mb-16">
|
|
62
|
+
<h2 className="font-['Source_Sans_3',sans-serif] text-lg text-foreground uppercase tracking-wider mb-6">
|
|
63
|
+
Team Members
|
|
64
|
+
</h2>
|
|
65
|
+
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
|
|
66
|
+
{testers.map((tester) => (
|
|
67
|
+
<div key={tester.id} className="bg-card rounded-xl p-6 border border-border hover:border-primary transition-all">
|
|
68
|
+
{/* Avatar Circle */}
|
|
69
|
+
<div className="mb-4">
|
|
70
|
+
<div className="size-20 rounded-full bg-secondary flex items-center justify-center">
|
|
71
|
+
<span className="font-['Source_Sans_3',sans-serif] text-2xl text-primary" style={{ fontWeight: 600 }}>
|
|
72
|
+
{tester.name.split(' ').map(n => n[0]).join('')}
|
|
73
|
+
</span>
|
|
74
|
+
</div>
|
|
75
|
+
</div>
|
|
76
|
+
|
|
77
|
+
{/* Info */}
|
|
78
|
+
<h3 className="font-['Source_Sans_3',sans-serif] text-xl text-foreground mb-1" style={{ fontWeight: 300 }}>
|
|
79
|
+
{tester.name}
|
|
80
|
+
</h3>
|
|
81
|
+
<p className="font-['Source_Sans_3',sans-serif] text-sm text-primary uppercase mb-4">
|
|
82
|
+
{tester.role}
|
|
83
|
+
</p>
|
|
84
|
+
|
|
85
|
+
{/* Stats */}
|
|
86
|
+
<div className="space-y-2 pt-4 border-t border-border">
|
|
87
|
+
<div className="flex items-center justify-between">
|
|
88
|
+
<span className="font-['Source_Sans_3',sans-serif] text-xs text-muted-foreground uppercase" style={{ fontWeight: 600 }}>
|
|
89
|
+
Tests Run:
|
|
90
|
+
</span>
|
|
91
|
+
<span className="font-['Source_Sans_3',sans-serif] text-base text-foreground">
|
|
92
|
+
{tester.tests.toLocaleString()}
|
|
93
|
+
</span>
|
|
94
|
+
</div>
|
|
95
|
+
<div className="flex items-center justify-between">
|
|
96
|
+
<span className="font-['Source_Sans_3',sans-serif] text-xs text-muted-foreground uppercase" style={{ fontWeight: 600 }}>
|
|
97
|
+
Success Rate:
|
|
98
|
+
</span>
|
|
99
|
+
<span className="font-['Source_Sans_3',sans-serif] text-base text-foreground">
|
|
100
|
+
{tester.successRate}%
|
|
101
|
+
</span>
|
|
102
|
+
</div>
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
105
|
+
))}
|
|
106
|
+
</div>
|
|
107
|
+
</div>
|
|
108
|
+
|
|
109
|
+
{/* Newsletter Section */}
|
|
110
|
+
<div className="bg-card rounded-xl p-12 border border-border">
|
|
111
|
+
<div className="max-w-2xl mx-auto text-center">
|
|
112
|
+
<h2 className="font-['Source_Sans_3',sans-serif] text-2xl text-foreground uppercase tracking-wide mb-4" style={{ fontWeight: 300 }}>
|
|
113
|
+
Stay Updated
|
|
114
|
+
</h2>
|
|
115
|
+
<p className="font-['Source_Sans_3',sans-serif] text-muted-foreground mb-8">
|
|
116
|
+
Subscribe to our newsletter for the latest testing insights, team updates, and quality assurance best practices.
|
|
117
|
+
</p>
|
|
118
|
+
|
|
119
|
+
<form onSubmit={handleSubscribe} className="flex flex-col sm:flex-row gap-4 max-w-lg mx-auto">
|
|
120
|
+
<div className="flex-1">
|
|
121
|
+
<input
|
|
122
|
+
type="email"
|
|
123
|
+
value={email}
|
|
124
|
+
onChange={(e) => setEmail(e.target.value)}
|
|
125
|
+
placeholder="Enter your email"
|
|
126
|
+
required
|
|
127
|
+
className="w-full h-10 px-4 bg-input-background border border-border rounded-lg text-foreground placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:border-transparent font-['Source_Sans_3',sans-serif]"
|
|
128
|
+
/>
|
|
129
|
+
</div>
|
|
130
|
+
<button type="submit" className="btn-primary">
|
|
131
|
+
Subscribe
|
|
132
|
+
</button>
|
|
133
|
+
</form>
|
|
134
|
+
|
|
135
|
+
<p className="font-['Source_Sans_3',sans-serif] text-xs text-muted-foreground mt-4">
|
|
136
|
+
We respect your privacy. Unsubscribe at any time.
|
|
137
|
+
</p>
|
|
138
|
+
</div>
|
|
139
|
+
</div>
|
|
140
|
+
</main>
|
|
141
|
+
|
|
142
|
+
{/* Floating Chat Button */}
|
|
143
|
+
<button
|
|
144
|
+
className="fixed bottom-8 right-8 size-12 bg-primary rounded-full flex items-center justify-center shadow-lg hover:bg-link-hover transition-all hover:scale-110 z-50"
|
|
145
|
+
aria-label="Open chat"
|
|
146
|
+
>
|
|
147
|
+
<svg width="24" height="24" viewBox="0 0 24 24" fill="none">
|
|
148
|
+
<path
|
|
149
|
+
d="M12 2C6.48 2 2 6.48 2 12C2 13.82 2.55 15.5 3.5 16.89L2.05 21.71C1.97 22.01 2.06 22.33 2.29 22.54C2.43 22.68 2.62 22.75 2.81 22.75C2.9 22.75 2.99 22.73 3.08 22.7L8.11 21.1C9.47 21.94 11.18 22.5 13 22.5C18.52 22.5 23 18.02 23 12.5C23 6.98 18.52 2 12 2ZM12 20C10.42 20 8.94 19.57 7.68 18.84L7.41 18.67L4.07 19.75L5.01 16.59L4.82 16.29C3.98 14.99 3.5 13.53 3.5 12C3.5 7.86 6.86 4.5 11 4.5C15.14 4.5 18.5 7.86 18.5 12C18.5 16.14 15.14 19.5 11 19.5Z"
|
|
150
|
+
fill="currentColor"
|
|
151
|
+
/>
|
|
152
|
+
<path
|
|
153
|
+
d="M8.5 11C8.22 11 8 11.22 8 11.5V12.5C8 12.78 8.22 13 8.5 13C8.78 13 9 12.78 9 12.5V11.5C9 11.22 8.78 11 8.5 11Z"
|
|
154
|
+
fill="currentColor"
|
|
155
|
+
/>
|
|
156
|
+
<path
|
|
157
|
+
d="M12 11C11.72 11 11.5 11.22 11.5 11.5V12.5C11.5 12.78 11.72 13 12 13C12.28 13 12.5 12.78 12.5 12.5V11.5C12.5 11.22 12.28 11 12 11Z"
|
|
158
|
+
fill="currentColor"
|
|
159
|
+
/>
|
|
160
|
+
<path
|
|
161
|
+
d="M15.5 11C15.22 11 15 11.22 15 11.5V12.5C15 12.78 15.22 13 15.5 13C15.78 13 16 12.78 16 12.5V11.5C16 11.22 15.78 11 15.5 11Z"
|
|
162
|
+
fill="currentColor"
|
|
163
|
+
/>
|
|
164
|
+
</svg>
|
|
165
|
+
</button>
|
|
166
|
+
</div>
|
|
167
|
+
);
|
|
168
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { createBrowserRouter } from "react-router";
|
|
2
|
+
import DesignSystem from "./pages/DesignSystem";
|
|
3
|
+
import Team from "./pages/Team";
|
|
4
|
+
|
|
5
|
+
export const router = createBrowserRouter([
|
|
6
|
+
{
|
|
7
|
+
path: "/",
|
|
8
|
+
element: <DesignSystem />,
|
|
9
|
+
},
|
|
10
|
+
{
|
|
11
|
+
path: "/team",
|
|
12
|
+
element: <Team />,
|
|
13
|
+
},
|
|
14
|
+
]);
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import svgPaths from "./svg-1ifosis1tx";
|
|
2
|
+
|
|
3
|
+
function IconsCheckCircleFilled() {
|
|
4
|
+
return (
|
|
5
|
+
<div className="relative shrink-0 size-[20px]" data-name="icons/check-circle-filled">
|
|
6
|
+
<svg className="block size-full" fill="none" preserveAspectRatio="none" viewBox="0 0 20 20">
|
|
7
|
+
<g clipPath="url(#clip0_3_815)" id="icons/check-circle-filled">
|
|
8
|
+
<g id="check-circle-filled" />
|
|
9
|
+
<path d={svgPaths.p2819d400} fill="var(--fill-0, #1D1D1D)" id="Union" />
|
|
10
|
+
</g>
|
|
11
|
+
<defs>
|
|
12
|
+
<clipPath id="clip0_3_815">
|
|
13
|
+
<rect fill="white" height="20" width="20" />
|
|
14
|
+
</clipPath>
|
|
15
|
+
</defs>
|
|
16
|
+
</svg>
|
|
17
|
+
</div>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function IconWrapper() {
|
|
22
|
+
return (
|
|
23
|
+
<div className="content-stretch flex items-center relative shrink-0" data-name="Icon wrapper">
|
|
24
|
+
<IconsCheckCircleFilled />
|
|
25
|
+
</div>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function Button() {
|
|
30
|
+
return (
|
|
31
|
+
<div className="absolute bg-[#78eac1] content-stretch flex gap-[10px] h-[40px] items-center left-[117px] px-[20px] py-[10px] rounded-[50px] top-[132px]" data-name="Button">
|
|
32
|
+
<IconWrapper />
|
|
33
|
+
<div className="flex flex-col font-['Source_Sans_3:Regular',sans-serif] justify-center leading-[0] not-italic relative shrink-0 text-[#1d1d1d] text-[16px] uppercase whitespace-nowrap">
|
|
34
|
+
<p className="leading-[14px]">Button</p>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export default function Buttons() {
|
|
41
|
+
return (
|
|
42
|
+
<div className="bg-[#181818] relative size-full" data-name="Buttons">
|
|
43
|
+
<Button />
|
|
44
|
+
</div>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import svgPaths from "./svg-wl30wxxv53";
|
|
2
|
+
|
|
3
|
+
function IconsCheckCircleFilled() {
|
|
4
|
+
return (
|
|
5
|
+
<div className="relative shrink-0 size-[20px]" data-name="icons/check-circle-filled">
|
|
6
|
+
<svg className="block size-full" fill="none" preserveAspectRatio="none" viewBox="0 0 20 20">
|
|
7
|
+
<g clipPath="url(#clip0_3_815)" id="icons/check-circle-filled">
|
|
8
|
+
<g id="check-circle-filled" />
|
|
9
|
+
<path d={svgPaths.p2819d400} fill="var(--fill-0, #1D1D1D)" id="Union" />
|
|
10
|
+
</g>
|
|
11
|
+
<defs>
|
|
12
|
+
<clipPath id="clip0_3_815">
|
|
13
|
+
<rect fill="white" height="20" width="20" />
|
|
14
|
+
</clipPath>
|
|
15
|
+
</defs>
|
|
16
|
+
</svg>
|
|
17
|
+
</div>
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function IconWrapper() {
|
|
22
|
+
return (
|
|
23
|
+
<div className="content-stretch flex items-center relative shrink-0" data-name="Icon wrapper">
|
|
24
|
+
<IconsCheckCircleFilled />
|
|
25
|
+
</div>
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function Button() {
|
|
30
|
+
return (
|
|
31
|
+
<div className="absolute bg-[#78eac1] content-stretch flex gap-[10px] h-[40px] items-center left-[117px] px-[20px] py-[10px] rounded-[50px] top-[132px]" data-name="Button">
|
|
32
|
+
<IconWrapper />
|
|
33
|
+
<div className="flex flex-col font-['Source_Sans_3:Regular',sans-serif] justify-center leading-[0] not-italic relative shrink-0 text-[#1d1d1d] text-[16px] uppercase whitespace-nowrap">
|
|
34
|
+
<p className="leading-[14px]">Primary</p>
|
|
35
|
+
</div>
|
|
36
|
+
</div>
|
|
37
|
+
);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function IconsCheckCircleFilled1() {
|
|
41
|
+
return (
|
|
42
|
+
<div className="relative shrink-0 size-[20px]" data-name="icons/check-circle-filled">
|
|
43
|
+
<svg className="block size-full" fill="none" preserveAspectRatio="none" viewBox="0 0 20 20">
|
|
44
|
+
<g clipPath="url(#clip0_3_1368)" id="icons/check-circle-filled">
|
|
45
|
+
<g id="check-circle-filled" />
|
|
46
|
+
<path d={svgPaths.p2819d400} fill="var(--fill-0, #78EAC1)" id="Union" />
|
|
47
|
+
</g>
|
|
48
|
+
<defs>
|
|
49
|
+
<clipPath id="clip0_3_1368">
|
|
50
|
+
<rect fill="white" height="20" width="20" />
|
|
51
|
+
</clipPath>
|
|
52
|
+
</defs>
|
|
53
|
+
</svg>
|
|
54
|
+
</div>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function IconWrapper1() {
|
|
59
|
+
return (
|
|
60
|
+
<div className="content-stretch flex items-center relative shrink-0" data-name="Icon wrapper">
|
|
61
|
+
<IconsCheckCircleFilled1 />
|
|
62
|
+
</div>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function Button1() {
|
|
67
|
+
return (
|
|
68
|
+
<div className="absolute content-stretch flex gap-[10px] h-[40px] items-center left-[117px] px-[20px] py-[10px] rounded-[50px] top-[192px]" data-name="Button">
|
|
69
|
+
<div aria-hidden="true" className="absolute border border-[#78eac1] border-solid inset-0 pointer-events-none rounded-[50px]" />
|
|
70
|
+
<IconWrapper1 />
|
|
71
|
+
<p className="font-['Source_Sans_3:Regular',sans-serif] leading-[14px] not-italic relative shrink-0 text-[#78eac1] text-[16px] uppercase">Primary</p>
|
|
72
|
+
</div>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function IconsCheckCircleFilled2() {
|
|
77
|
+
return (
|
|
78
|
+
<div className="relative shrink-0 size-[20px]" data-name="icons/check-circle-filled">
|
|
79
|
+
<svg className="block size-full" fill="none" preserveAspectRatio="none" viewBox="0 0 20 20">
|
|
80
|
+
<g clipPath="url(#clip0_3_1775)" id="icons/check-circle-filled">
|
|
81
|
+
<g id="check-circle-filled" />
|
|
82
|
+
<path d={svgPaths.p2819d400} fill="var(--fill-0, white)" id="Union" />
|
|
83
|
+
</g>
|
|
84
|
+
<defs>
|
|
85
|
+
<clipPath id="clip0_3_1775">
|
|
86
|
+
<rect fill="white" height="20" width="20" />
|
|
87
|
+
</clipPath>
|
|
88
|
+
</defs>
|
|
89
|
+
</svg>
|
|
90
|
+
</div>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function IconWrapper2() {
|
|
95
|
+
return (
|
|
96
|
+
<div className="content-stretch flex items-center relative shrink-0" data-name="Icon wrapper">
|
|
97
|
+
<IconsCheckCircleFilled2 />
|
|
98
|
+
</div>
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function Button2() {
|
|
103
|
+
return (
|
|
104
|
+
<div className="absolute bg-[#7954ff] content-stretch flex gap-[10px] h-[40px] items-center left-[255px] px-[20px] py-[10px] rounded-[50px] top-[132px]" data-name="Button">
|
|
105
|
+
<IconWrapper2 />
|
|
106
|
+
<p className="font-['Source_Sans_3:Regular',sans-serif] leading-[14px] not-italic relative shrink-0 text-[16px] text-white uppercase">Hover</p>
|
|
107
|
+
</div>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function IconsCheckCircleFilled3() {
|
|
112
|
+
return (
|
|
113
|
+
<div className="relative shrink-0 size-[20px]" data-name="icons/check-circle-filled">
|
|
114
|
+
<svg className="block size-full" fill="none" preserveAspectRatio="none" viewBox="0 0 20 20">
|
|
115
|
+
<g clipPath="url(#clip0_3_1775)" id="icons/check-circle-filled">
|
|
116
|
+
<g id="check-circle-filled" />
|
|
117
|
+
<path d={svgPaths.p2819d400} fill="var(--fill-0, white)" id="Union" />
|
|
118
|
+
</g>
|
|
119
|
+
<defs>
|
|
120
|
+
<clipPath id="clip0_3_1775">
|
|
121
|
+
<rect fill="white" height="20" width="20" />
|
|
122
|
+
</clipPath>
|
|
123
|
+
</defs>
|
|
124
|
+
</svg>
|
|
125
|
+
</div>
|
|
126
|
+
);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
function IconWrapper3() {
|
|
130
|
+
return (
|
|
131
|
+
<div className="content-stretch flex items-center relative shrink-0" data-name="Icon wrapper">
|
|
132
|
+
<IconsCheckCircleFilled3 />
|
|
133
|
+
</div>
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
function Button3() {
|
|
138
|
+
return (
|
|
139
|
+
<div className="absolute bg-[#7954ff] content-stretch flex gap-[10px] h-[40px] items-center left-[255px] px-[20px] py-[10px] rounded-[50px] top-[192px]" data-name="Button">
|
|
140
|
+
<IconWrapper3 />
|
|
141
|
+
<p className="font-['Source_Sans_3:Regular',sans-serif] leading-[14px] not-italic relative shrink-0 text-[16px] text-white uppercase">Hover</p>
|
|
142
|
+
</div>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export default function Buttons() {
|
|
147
|
+
return (
|
|
148
|
+
<div className="bg-[#181818] relative size-full" data-name="Buttons">
|
|
149
|
+
<Button />
|
|
150
|
+
<Button1 />
|
|
151
|
+
<Button2 />
|
|
152
|
+
<Button3 />
|
|
153
|
+
</div>
|
|
154
|
+
);
|
|
155
|
+
}
|