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,123 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import svgPaths from "../../../imports/svg-umftvfphsk";
|
|
3
|
+
import { SectionHeader } from "./SectionHeader";
|
|
4
|
+
import { CopyButton } from "./CopyButton";
|
|
5
|
+
|
|
6
|
+
export function Cards() {
|
|
7
|
+
return (
|
|
8
|
+
<section>
|
|
9
|
+
<SectionHeader
|
|
10
|
+
title="Cards"
|
|
11
|
+
description="Card containers used for grouping related content"
|
|
12
|
+
/>
|
|
13
|
+
|
|
14
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
15
|
+
{/* Basic Card */}
|
|
16
|
+
<div>
|
|
17
|
+
<p className="font-['Source_Sans_3',sans-serif] text-xs text-muted-foreground uppercase tracking-wider mb-3">
|
|
18
|
+
Basic Card
|
|
19
|
+
</p>
|
|
20
|
+
<div className="group/card bg-card rounded-xl p-8 relative">
|
|
21
|
+
<div className="absolute top-2 right-2 opacity-0 group-hover/card:opacity-100 transition-opacity">
|
|
22
|
+
<CopyButton token="bg-card rounded-xl p-8" />
|
|
23
|
+
</div>
|
|
24
|
+
<p className="font-['Source_Sans_3',sans-serif] text-lg text-foreground uppercase" style={{ fontWeight: 300 }}>
|
|
25
|
+
Card Title
|
|
26
|
+
</p>
|
|
27
|
+
<div className="h-5" />
|
|
28
|
+
<p className="font-['Source_Sans_3',sans-serif] text-sm text-muted-foreground">
|
|
29
|
+
Card content goes here. Uses background #1D1D1D with 15px border radius and 30px padding.
|
|
30
|
+
</p>
|
|
31
|
+
</div>
|
|
32
|
+
</div>
|
|
33
|
+
|
|
34
|
+
{/* Card with Header */}
|
|
35
|
+
<div>
|
|
36
|
+
<p className="font-['Source_Sans_3',sans-serif] text-xs text-muted-foreground uppercase tracking-wider mb-3">
|
|
37
|
+
Session Details Card
|
|
38
|
+
</p>
|
|
39
|
+
<div className="group/card bg-card rounded-xl p-8 relative">
|
|
40
|
+
<div className="absolute top-2 right-12 opacity-0 group-hover/card:opacity-100 transition-opacity z-10">
|
|
41
|
+
<CopyButton token="bg-card rounded-xl p-8 | header: text-lg uppercase | title: text-2xl" />
|
|
42
|
+
</div>
|
|
43
|
+
<div className="flex items-start justify-between">
|
|
44
|
+
<div>
|
|
45
|
+
<p className="font-['Source_Sans_3',sans-serif] text-lg text-foreground uppercase" style={{ fontWeight: 300 }}>
|
|
46
|
+
Session Details
|
|
47
|
+
</p>
|
|
48
|
+
<div className="h-1" />
|
|
49
|
+
<p className="font-['Source_Sans_3',sans-serif] text-2xl text-foreground" style={{ fontWeight: 300 }}>
|
|
50
|
+
Test session title
|
|
51
|
+
</p>
|
|
52
|
+
</div>
|
|
53
|
+
<button className="btn-icon">
|
|
54
|
+
<svg width="20" height="20" viewBox="0 0 20 20" fill="none">
|
|
55
|
+
<path d={svgPaths.p5e64f80} fill="currentColor" />
|
|
56
|
+
</svg>
|
|
57
|
+
</button>
|
|
58
|
+
</div>
|
|
59
|
+
<div className="h-4" />
|
|
60
|
+
<div className="flex flex-wrap gap-x-12 gap-y-2 text-muted-foreground">
|
|
61
|
+
<div className="flex gap-5 items-center">
|
|
62
|
+
<span className="font-['Source_Sans_3',sans-serif] text-xs uppercase" style={{ fontWeight: 600 }}>Created on:</span>
|
|
63
|
+
<span className="font-['Source_Sans_3',sans-serif] text-base">2025-07-23 19:11</span>
|
|
64
|
+
</div>
|
|
65
|
+
<div className="flex gap-5 items-center">
|
|
66
|
+
<span className="font-['Source_Sans_3',sans-serif] text-xs uppercase" style={{ fontWeight: 600 }}>Status:</span>
|
|
67
|
+
<span className="font-['Source_Sans_3',sans-serif] text-base text-foreground">draft</span>
|
|
68
|
+
</div>
|
|
69
|
+
</div>
|
|
70
|
+
</div>
|
|
71
|
+
</div>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
{/* XL Buttons */}
|
|
75
|
+
<div className="mt-8">
|
|
76
|
+
<p className="font-['Source_Sans_3',sans-serif] text-xs text-muted-foreground uppercase tracking-wider mb-3">
|
|
77
|
+
XL Buttons
|
|
78
|
+
</p>
|
|
79
|
+
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
|
80
|
+
{/* Create New Session Card */}
|
|
81
|
+
<div className="group/card relative">
|
|
82
|
+
<button className="btn-xl-outline w-full">
|
|
83
|
+
<div className="pb-4">
|
|
84
|
+
<svg width="60" height="60" viewBox="0 0 60 60" fill="none">
|
|
85
|
+
<g clipPath="url(#clip_plus_action)">
|
|
86
|
+
<path d={svgPaths.p2455100} fill="currentColor" />
|
|
87
|
+
</g>
|
|
88
|
+
<defs>
|
|
89
|
+
<clipPath id="clip_plus_action"><rect fill="white" height="60" width="60" /></clipPath>
|
|
90
|
+
</defs>
|
|
91
|
+
</svg>
|
|
92
|
+
</div>
|
|
93
|
+
<span>Create New Test Session</span>
|
|
94
|
+
</button>
|
|
95
|
+
<div className="absolute top-2 right-2 opacity-0 group-hover/card:opacity-100 transition-opacity z-10">
|
|
96
|
+
<CopyButton token="btn-xl-outline" />
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
|
|
100
|
+
{/* Placeholder for other action cards */}
|
|
101
|
+
<div className="group/card relative">
|
|
102
|
+
<button className="btn-xl-filled w-full">
|
|
103
|
+
<div className="pb-4">
|
|
104
|
+
<svg width="60" height="60" viewBox="0 0 60 60" fill="none">
|
|
105
|
+
<g clipPath="url(#clip_test_action)">
|
|
106
|
+
<path d={svgPaths.p2af2dd00} fill="currentColor" />
|
|
107
|
+
</g>
|
|
108
|
+
<defs>
|
|
109
|
+
<clipPath id="clip_test_action"><rect fill="white" height="60" width="60" /></clipPath>
|
|
110
|
+
</defs>
|
|
111
|
+
</svg>
|
|
112
|
+
</div>
|
|
113
|
+
<span>Start test</span>
|
|
114
|
+
</button>
|
|
115
|
+
<div className="absolute top-2 right-2 opacity-0 group-hover/card:opacity-100 transition-opacity z-10">
|
|
116
|
+
<CopyButton token="btn-xl-filled" />
|
|
117
|
+
</div>
|
|
118
|
+
</div>
|
|
119
|
+
</div>
|
|
120
|
+
</div>
|
|
121
|
+
</section>
|
|
122
|
+
);
|
|
123
|
+
}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import svgPaths from "../../../imports/svg-umftvfphsk";
|
|
3
|
+
import { SectionHeader } from "./SectionHeader";
|
|
4
|
+
import { CopyButton } from "./CopyButton";
|
|
5
|
+
|
|
6
|
+
export function Charts() {
|
|
7
|
+
return (
|
|
8
|
+
<section>
|
|
9
|
+
<SectionHeader
|
|
10
|
+
title="Charts & Data Visualization"
|
|
11
|
+
description="Donut charts, line charts, and data nodes"
|
|
12
|
+
/>
|
|
13
|
+
|
|
14
|
+
<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
|
|
15
|
+
{/* Donut Chart */}
|
|
16
|
+
<div>
|
|
17
|
+
<p className="font-['Source_Sans_3',sans-serif] text-xs text-muted-foreground uppercase tracking-wider mb-3">
|
|
18
|
+
Donut Chart (Large)
|
|
19
|
+
</p>
|
|
20
|
+
<div className="group/chart bg-card rounded-xl p-8 flex flex-col items-center relative">
|
|
21
|
+
<div className="absolute top-2 right-2 opacity-0 group-hover/chart:opacity-100 transition-opacity z-10">
|
|
22
|
+
<CopyButton token="donut: 180x180 | ring: var(--secondary) | segments: var(--chart-1/2/3) | center: text-6xl" />
|
|
23
|
+
</div>
|
|
24
|
+
<div className="relative size-[180px] flex items-center justify-center">
|
|
25
|
+
{/* Base ring */}
|
|
26
|
+
<svg className="absolute inset-0" viewBox="0 0 180 180" fill="none">
|
|
27
|
+
<path clipRule="evenodd" d={svgPaths.p3f48ef30} fill="var(--secondary)" fillRule="evenodd" />
|
|
28
|
+
</svg>
|
|
29
|
+
{/* Color segments */}
|
|
30
|
+
<svg className="absolute inset-0" viewBox="0 0 180 180" fill="none">
|
|
31
|
+
<mask height="180" id="mask_donut_demo" maskUnits="userSpaceOnUse" style={{ maskType: "alpha" }} width="180" x="0" y="0">
|
|
32
|
+
<path clipRule="evenodd" d={svgPaths.p3f48ef30} fill="var(--secondary)" fillRule="evenodd" />
|
|
33
|
+
</mask>
|
|
34
|
+
<g mask="url(#mask_donut_demo)">
|
|
35
|
+
<rect fill="var(--chart-2)" height="90" width="90" x="90" />
|
|
36
|
+
<rect fill="var(--chart-3)" height="90" width="90" x="90" y="90" />
|
|
37
|
+
<rect fill="var(--chart-1)" height="90" width="90" y="90" />
|
|
38
|
+
</g>
|
|
39
|
+
</svg>
|
|
40
|
+
{/* Center content */}
|
|
41
|
+
<div className="relative z-10 text-center">
|
|
42
|
+
<p className="font-['Source_Sans_3',sans-serif] text-6xl text-foreground leading-10" style={{ fontWeight: 300 }}>999</p>
|
|
43
|
+
<p className="font-['Source_Sans_3',sans-serif] text-xs text-muted-foreground mt-2.5">Total check executions</p>
|
|
44
|
+
</div>
|
|
45
|
+
</div>
|
|
46
|
+
<div className="h-5" />
|
|
47
|
+
{/* Legend */}
|
|
48
|
+
<div className="flex gap-2.5 items-center justify-center">
|
|
49
|
+
{[
|
|
50
|
+
{ color: "var(--chart-1)", label: "12 passed" },
|
|
51
|
+
{ color: "var(--chart-2)", label: "12 failed" },
|
|
52
|
+
{ color: "var(--chart-3)", label: "12 blocked" },
|
|
53
|
+
].map((item) => (
|
|
54
|
+
<div key={item.label} className="flex items-center gap-1.5">
|
|
55
|
+
<svg width="5" height="5" viewBox="0 0 5 5" fill="none">
|
|
56
|
+
<circle cx="2.5" cy="2.5" r="2.5" fill={item.color} />
|
|
57
|
+
</svg>
|
|
58
|
+
<span className="font-['Source_Sans_3',sans-serif] text-xs text-muted-foreground">{item.label}</span>
|
|
59
|
+
</div>
|
|
60
|
+
))}
|
|
61
|
+
</div>
|
|
62
|
+
</div>
|
|
63
|
+
</div>
|
|
64
|
+
|
|
65
|
+
{/* Line Chart Data Points */}
|
|
66
|
+
<div>
|
|
67
|
+
<p className="font-['Source_Sans_3',sans-serif] text-xs text-muted-foreground uppercase tracking-wider mb-3">
|
|
68
|
+
Line Chart Data Nodes
|
|
69
|
+
</p>
|
|
70
|
+
<div className="group/chart bg-card rounded-xl p-8 relative">
|
|
71
|
+
<div className="absolute top-2 right-2 opacity-0 group-hover/chart:opacity-100 transition-opacity z-10">
|
|
72
|
+
<CopyButton token="data-nodes: circle 10x10 | colors: var(--chart-1/2/3) | labels: text-xs text-muted-foreground" />
|
|
73
|
+
</div>
|
|
74
|
+
<p className="font-['Source_Sans_3',sans-serif] text-lg text-foreground uppercase mb-5" style={{ fontWeight: 300 }}>
|
|
75
|
+
Test Session Results
|
|
76
|
+
</p>
|
|
77
|
+
{/* Data columns */}
|
|
78
|
+
<div className="flex items-end justify-between px-4">
|
|
79
|
+
{[
|
|
80
|
+
{ passed: 5, blocked: 3, failed: 0 },
|
|
81
|
+
{ passed: 7, blocked: 4, failed: 2 },
|
|
82
|
+
{ passed: 6, blocked: 4, failed: 0 },
|
|
83
|
+
{ passed: 9, blocked: 3, failed: 2 },
|
|
84
|
+
{ passed: 8, blocked: 3, failed: 0 },
|
|
85
|
+
{ passed: 5, blocked: 4, failed: 0 },
|
|
86
|
+
{ passed: 5, blocked: 4, failed: 0 },
|
|
87
|
+
].map((col, i) => (
|
|
88
|
+
<div key={i} className="flex flex-col items-center gap-2">
|
|
89
|
+
<div className="flex flex-col items-center gap-1">
|
|
90
|
+
<span className="font-['Source_Sans_3',sans-serif] text-sm text-foreground">{col.passed}</span>
|
|
91
|
+
<svg width="10" height="10" viewBox="0 0 10 10" fill="none">
|
|
92
|
+
<circle cx="5" cy="5" r="5" fill="var(--chart-1)" />
|
|
93
|
+
</svg>
|
|
94
|
+
</div>
|
|
95
|
+
<div className="flex flex-col items-center gap-1">
|
|
96
|
+
<span className="font-['Source_Sans_3',sans-serif] text-sm text-foreground">{col.blocked}</span>
|
|
97
|
+
<svg width="10" height="10" viewBox="0 0 10 10" fill="none">
|
|
98
|
+
<circle cx="5" cy="5" r="5" fill="var(--chart-3)" />
|
|
99
|
+
</svg>
|
|
100
|
+
</div>
|
|
101
|
+
<div className="flex flex-col items-center gap-1">
|
|
102
|
+
<span className="font-['Source_Sans_3',sans-serif] text-sm text-foreground">{col.failed}</span>
|
|
103
|
+
<svg width="10" height="10" viewBox="0 0 10 10" fill="none">
|
|
104
|
+
<circle cx="5" cy="5" r="5" fill="var(--chart-2)" />
|
|
105
|
+
</svg>
|
|
106
|
+
</div>
|
|
107
|
+
<div className="mt-2 text-center">
|
|
108
|
+
<p className="font-['Source_Sans_3',sans-serif] text-xs text-muted-foreground">19-09</p>
|
|
109
|
+
<p className="font-['Source_Sans_3',sans-serif] text-xs text-muted-foreground">10:00</p>
|
|
110
|
+
</div>
|
|
111
|
+
</div>
|
|
112
|
+
))}
|
|
113
|
+
</div>
|
|
114
|
+
<div className="h-5" />
|
|
115
|
+
{/* Legend */}
|
|
116
|
+
<div className="flex gap-2.5 items-center justify-center">
|
|
117
|
+
{[
|
|
118
|
+
{ color: "var(--chart-5)", label: "passed" },
|
|
119
|
+
{ color: "var(--chart-2)", label: "failed" },
|
|
120
|
+
{ color: "var(--chart-3)", label: "blocked" },
|
|
121
|
+
].map((item) => (
|
|
122
|
+
<div key={item.label} className="flex items-center gap-1.5">
|
|
123
|
+
<svg width="5" height="5" viewBox="0 0 5 5" fill="none">
|
|
124
|
+
<circle cx="2.5" cy="2.5" r="2.5" fill={item.color} />
|
|
125
|
+
</svg>
|
|
126
|
+
<span className="font-['Source_Sans_3',sans-serif] text-xs text-muted-foreground">{item.label}</span>
|
|
127
|
+
</div>
|
|
128
|
+
))}
|
|
129
|
+
</div>
|
|
130
|
+
</div>
|
|
131
|
+
</div>
|
|
132
|
+
</div>
|
|
133
|
+
</section>
|
|
134
|
+
);
|
|
135
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { SectionHeader } from "./SectionHeader";
|
|
3
|
+
import { CopyButton } from "./CopyButton";
|
|
4
|
+
|
|
5
|
+
const colors = [
|
|
6
|
+
{
|
|
7
|
+
group: "Backgrounds",
|
|
8
|
+
items: [
|
|
9
|
+
{ name: "Background", value: "#181818", css: "--background" },
|
|
10
|
+
{ name: "Card", value: "#1D1D1D", css: "--card" },
|
|
11
|
+
{ name: "Secondary", value: "#262626", css: "--secondary" },
|
|
12
|
+
{ name: "Muted", value: "#2E2E2E", css: "--muted" },
|
|
13
|
+
],
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
group: "Brand",
|
|
17
|
+
items: [
|
|
18
|
+
{ name: "Primary (Teal)", value: "#78EAC1", css: "--primary" },
|
|
19
|
+
{ name: "Accent (Purple)", value: "#7954FF", css: "--accent" },
|
|
20
|
+
],
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
group: "Status",
|
|
24
|
+
items: [
|
|
25
|
+
{ name: "Passed / Success", value: "#33BA9E", css: "--chart-1" },
|
|
26
|
+
{ name: "Failed / Error", value: "#FF3131", css: "--destructive" },
|
|
27
|
+
{ name: "Blocked / Warning", value: "#F48D21", css: "--chart-3" },
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
group: "Text",
|
|
32
|
+
items: [
|
|
33
|
+
{ name: "Primary Text", value: "#FFFFFF", css: "--foreground" },
|
|
34
|
+
{ name: "Muted Text", value: "#888888", css: "--muted-foreground" },
|
|
35
|
+
{ name: "Subtle Text", value: "#595959", css: "n/a" },
|
|
36
|
+
],
|
|
37
|
+
},
|
|
38
|
+
];
|
|
39
|
+
|
|
40
|
+
export function ColorPalette() {
|
|
41
|
+
return (
|
|
42
|
+
<section>
|
|
43
|
+
<SectionHeader
|
|
44
|
+
title="Color Palette"
|
|
45
|
+
description="Core colors used throughout the application"
|
|
46
|
+
/>
|
|
47
|
+
<div className="space-y-8">
|
|
48
|
+
{colors.map((group) => (
|
|
49
|
+
<div key={group.group}>
|
|
50
|
+
<p className="font-['Source_Sans_3',sans-serif] text-[14px] text-[#888] uppercase tracking-wider mb-4">
|
|
51
|
+
{group.group}
|
|
52
|
+
</p>
|
|
53
|
+
<div className="grid grid-cols-2 sm:grid-cols-3 md:grid-cols-4 lg:grid-cols-5 gap-4">
|
|
54
|
+
{group.items.map((color) => (
|
|
55
|
+
<div key={color.name} className="space-y-2">
|
|
56
|
+
<div
|
|
57
|
+
className="group/swatch h-20 rounded-[10px] border border-[#2e2e2e] relative"
|
|
58
|
+
style={{ backgroundColor: color.value }}
|
|
59
|
+
>
|
|
60
|
+
<div className="absolute top-1.5 right-1.5 opacity-0 group-hover/swatch:opacity-100 transition-opacity flex gap-1">
|
|
61
|
+
<CopyButton token={color.value} />
|
|
62
|
+
{color.css !== "n/a" && <CopyButton token={`var(${color.css})`} />}
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
<p className="font-['Source_Sans_3',sans-serif] text-[14px] text-white">
|
|
66
|
+
{color.name}
|
|
67
|
+
</p>
|
|
68
|
+
<div className="flex items-center gap-1.5">
|
|
69
|
+
<p className="font-['Source_Sans_3',sans-serif] text-[12px] text-[#888] font-mono">
|
|
70
|
+
{color.value}
|
|
71
|
+
</p>
|
|
72
|
+
{color.css !== "n/a" && (
|
|
73
|
+
<span className="font-['Source_Sans_3',sans-serif] text-[11px] text-[#555] font-mono">
|
|
74
|
+
{color.css}
|
|
75
|
+
</span>
|
|
76
|
+
)}
|
|
77
|
+
</div>
|
|
78
|
+
</div>
|
|
79
|
+
))}
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
))}
|
|
83
|
+
</div>
|
|
84
|
+
</section>
|
|
85
|
+
);
|
|
86
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import React, { useState, useCallback } from "react";
|
|
2
|
+
|
|
3
|
+
interface CopyButtonProps {
|
|
4
|
+
token: string;
|
|
5
|
+
className?: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function CopyButton({ token, className = "" }: CopyButtonProps) {
|
|
9
|
+
const [copied, setCopied] = useState(false);
|
|
10
|
+
|
|
11
|
+
const handleCopy = useCallback(
|
|
12
|
+
async (e: React.MouseEvent) => {
|
|
13
|
+
e.stopPropagation();
|
|
14
|
+
try {
|
|
15
|
+
await navigator.clipboard.writeText(token);
|
|
16
|
+
setCopied(true);
|
|
17
|
+
setTimeout(() => setCopied(false), 1500);
|
|
18
|
+
} catch {
|
|
19
|
+
// Fallback
|
|
20
|
+
const textarea = document.createElement("textarea");
|
|
21
|
+
textarea.value = token;
|
|
22
|
+
document.body.appendChild(textarea);
|
|
23
|
+
textarea.select();
|
|
24
|
+
document.execCommand("copy");
|
|
25
|
+
document.body.removeChild(textarea);
|
|
26
|
+
setCopied(true);
|
|
27
|
+
setTimeout(() => setCopied(false), 1500);
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
[token]
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<button
|
|
35
|
+
onClick={handleCopy}
|
|
36
|
+
title={copied ? "Copied!" : `Copy: ${token}`}
|
|
37
|
+
className={`inline-flex items-center justify-center size-[26px] rounded-[6px] cursor-pointer transition-all ${
|
|
38
|
+
copied
|
|
39
|
+
? "bg-chart-1/20 text-chart-1"
|
|
40
|
+
: "bg-muted text-muted-foreground hover:text-foreground hover:bg-muted/80"
|
|
41
|
+
} ${className}`}
|
|
42
|
+
>
|
|
43
|
+
{copied ? (
|
|
44
|
+
<svg width="14" height="14" viewBox="0 0 14 14" fill="none">
|
|
45
|
+
<path
|
|
46
|
+
d="M2.5 7.5L5.5 10.5L11.5 3.5"
|
|
47
|
+
stroke="currentColor"
|
|
48
|
+
strokeWidth="1.5"
|
|
49
|
+
strokeLinecap="round"
|
|
50
|
+
strokeLinejoin="round"
|
|
51
|
+
/>
|
|
52
|
+
</svg>
|
|
53
|
+
) : (
|
|
54
|
+
<svg width="14" height="14" viewBox="0 0 14 14" fill="none">
|
|
55
|
+
<rect
|
|
56
|
+
x="4.5"
|
|
57
|
+
y="4.5"
|
|
58
|
+
width="7"
|
|
59
|
+
height="7"
|
|
60
|
+
rx="1.5"
|
|
61
|
+
stroke="currentColor"
|
|
62
|
+
strokeWidth="1.2"
|
|
63
|
+
/>
|
|
64
|
+
<path
|
|
65
|
+
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"
|
|
66
|
+
stroke="currentColor"
|
|
67
|
+
strokeWidth="1.2"
|
|
68
|
+
/>
|
|
69
|
+
</svg>
|
|
70
|
+
)}
|
|
71
|
+
</button>
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
interface CopyTokenWrapperProps {
|
|
76
|
+
token: string;
|
|
77
|
+
children: React.ReactNode;
|
|
78
|
+
className?: string;
|
|
79
|
+
inline?: boolean;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function CopyTokenWrapper({
|
|
83
|
+
token,
|
|
84
|
+
children,
|
|
85
|
+
className = "",
|
|
86
|
+
inline = false,
|
|
87
|
+
}: CopyTokenWrapperProps) {
|
|
88
|
+
return (
|
|
89
|
+
<div
|
|
90
|
+
className={`group/copy relative ${inline ? "inline-flex items-center" : ""} ${className}`}
|
|
91
|
+
>
|
|
92
|
+
{children}
|
|
93
|
+
<div
|
|
94
|
+
className={`opacity-0 group-hover/copy:opacity-100 transition-opacity ${
|
|
95
|
+
inline ? "ml-1.5" : "absolute top-1 right-1"
|
|
96
|
+
}`}
|
|
97
|
+
>
|
|
98
|
+
<CopyButton token={token} />
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
);
|
|
102
|
+
}
|