@febkosq8/arc 0.3.0 → 0.7.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.
Files changed (47) hide show
  1. package/README.md +69 -5
  2. package/components/index.css +319 -114
  3. package/dist/arc.js +1758 -0
  4. package/dist/avatar.d.ts +18 -0
  5. package/dist/button-double-click.d.ts +18 -0
  6. package/dist/button-group.d.ts +8 -0
  7. package/dist/button-long-press.d.ts +20 -0
  8. package/dist/button.d.ts +21 -0
  9. package/dist/card.d.ts +17 -0
  10. package/dist/date-handler.d.ts +13 -0
  11. package/dist/divider.d.ts +2 -0
  12. package/dist/dropdown-multi.d.ts +16 -0
  13. package/dist/dropdown.d.ts +19 -0
  14. package/dist/error-text.d.ts +5 -0
  15. package/dist/grid-loader.d.ts +14 -0
  16. package/dist/hash-navigation.d.ts +34 -0
  17. package/dist/index.d.ts +47 -0
  18. package/dist/input-timestamp.d.ts +7 -0
  19. package/dist/input.d.ts +19 -0
  20. package/dist/label-field.d.ts +9 -0
  21. package/dist/menu.d.ts +29 -0
  22. package/dist/modal.d.ts +15 -0
  23. package/dist/pill-link.d.ts +8 -0
  24. package/dist/pill.d.ts +5 -0
  25. package/dist/preview-card.d.ts +14 -0
  26. package/dist/select.d.ts +18 -0
  27. package/dist/switch.d.ts +10 -0
  28. package/dist/table.d.ts +30 -0
  29. package/dist/tag.d.ts +6 -0
  30. package/dist/text-link.d.ts +6 -0
  31. package/dist/theme-switcher.d.ts +5 -0
  32. package/dist/typing-animation.d.ts +23 -0
  33. package/package.json +51 -35
  34. package/.prettierrc +0 -8
  35. package/components/button.tsx +0 -42
  36. package/components/card.tsx +0 -32
  37. package/components/index.ts +0 -8
  38. package/components/input.tsx +0 -21
  39. package/components/menu.tsx +0 -80
  40. package/components/pill.tsx +0 -20
  41. package/components/switch.tsx +0 -82
  42. package/components/text-area.tsx +0 -21
  43. package/components/theme-switcher.tsx +0 -81
  44. package/eslint.config.mjs +0 -36
  45. package/index.html +0 -11
  46. package/tsconfig.json +0 -27
  47. package/vite.config.ts +0 -37
package/README.md CHANGED
@@ -1,5 +1,69 @@
1
- # ARC
2
-
3
- This is a component library that will be used in all of my projects.
4
-
5
- Not something I would recommend using in your projects, but feel free to take a look at the code.
1
+ <div align="center">
2
+ <h1>Arc</h1>
3
+ <p>A collection of reusable React components and interaction patterns for the interfaces I build.</p>
4
+ <p>
5
+ <a href="https://www.npmjs.com/package/@febkosq8/arc">
6
+ <img alt="NPM Version" src="https://img.shields.io/npm/v/%40febkosq8%2Farc">
7
+ </a>
8
+ <a href="https://www.npmjs.com/package/@febkosq8/arc">
9
+ <img alt="NPM Downloads" src="https://img.shields.io/npm/dm/%40febkosq8%2Farc">
10
+ </a>
11
+ </p>
12
+ </div>
13
+
14
+ ---
15
+
16
+ Arc is a React + Tailwind CSS component library that brings together the UI building blocks I reuse across my projects. It focuses on practical components, consistent styling, and small interaction details, while leaving page layout and product decisions to the application.
17
+
18
+ 👉 **[Explore the components in Storybook](https://arc.febkosq8.me/)** 👈
19
+
20
+ ## Features
21
+
22
+ - **Reusable UI building blocks:** Buttons, inputs, cards, menus, dropdowns, selects, switches, tags, modals, and more.
23
+ - **Interaction-focused components:** Long-press and double-click buttons, preview cards, typing animation, a configurable grid loader, and hash navigation helpers.
24
+ - **Themed styling:** Built with React and Tailwind CSS, with shared design tokens and light and dark theme styles.
25
+ - **Composable components:** Use the components as parts of your interface without handing over control of your page layout.
26
+ - **Interactive examples:** Browse component examples and states in [Storybook](https://arc.febkosq8.me/).
27
+
28
+ ## Installation
29
+
30
+ ```bash
31
+ npm install @febkosq8/arc
32
+ # or
33
+ pnpm add @febkosq8/arc
34
+ ```
35
+
36
+ ## Usage
37
+
38
+ Import Arc's stylesheet from your application CSS:
39
+
40
+ ```css
41
+ @import "@febkosq8/arc/styles.css";
42
+ ```
43
+
44
+ Arc's stylesheet registers its compiled components with Tailwind CSS v4, so their utility classes are generated automatically without an application-level `@source` directive.
45
+
46
+ Import components from the package:
47
+
48
+ ```tsx
49
+ import { Button, GridLoader } from "@febkosq8/arc";
50
+
51
+ export function Example() {
52
+ return (
53
+ <>
54
+ <Button>Save</Button>
55
+ <GridLoader rows={3} columns={3} label="Saving" />
56
+ </>
57
+ );
58
+ }
59
+ ```
60
+
61
+ ## Explore the project
62
+
63
+ - [Live Storybook](https://arc.febkosq8.me/)
64
+ - [npm package](https://www.npmjs.com/package/@febkosq8/arc)
65
+ - [GitHub repository](https://github.com/febkosq8/arc)
66
+ - [Component source](./components/)
67
+ - [Storybook stories](./stories/)
68
+
69
+ Arc is primarily built to meet my own projects' needs. It's shared publicly for anyone who might find the code useful, but it isn't intended as a polished, general-purpose replacement for a larger UI framework.
@@ -1,114 +1,319 @@
1
- @tailwind base;
2
- @tailwind components;
3
- @tailwind utilities;
4
-
5
- @layer base {
6
- :root {
7
- --background: 0 0% 96%;
8
- --foreground: 20 14.3% 4.1%;
9
- --card: 0 0% 100%;
10
- --card-foreground: 20 14.3% 4.1%;
11
- --popover: 0 0% 100%;
12
- --popover-foreground: 20 14.3% 4.1%;
13
- --primary: 24.6 95% 53.1%;
14
- --primary-foreground: 60 9.1% 97.8%;
15
- --secondary: 60 4.8% 95.9%;
16
- --secondary-foreground: 24 9.8% 10%;
17
- --muted: 60 4.8% 95.9%;
18
- --muted-foreground: 25 5.3% 44.7%;
19
- --accent: 60 4.8% 95.9%;
20
- --accent-foreground: 24 9.8% 10%;
21
- --destructive: 0 84.2% 60.2%;
22
- --destructive-foreground: 60 9.1% 97.8%;
23
- --border: 20 5.9% 90%;
24
- --input: 20 5.9% 90%;
25
- --ring: 24.6 95% 53.1%;
26
- --radius: 1rem;
27
- }
28
-
29
- .dark {
30
- --background: 20 14.3% 4.1%;
31
- --foreground: 60 9.1% 97.8%;
32
- --card: 20 14.3% 4.1%;
33
- --card-foreground: 60 9.1% 97.8%;
34
- --popover: 20 14.3% 4.1%;
35
- --popover-foreground: 60 9.1% 97.8%;
36
- --primary: 20.5 90.2% 48.2%;
37
- --primary-foreground: 60 9.1% 97.8%;
38
- --secondary: 12 6.5% 15.1%;
39
- --secondary-foreground: 60 9.1% 97.8%;
40
- --muted: 12 6.5% 15.1%;
41
- --muted-foreground: 24 5.4% 63.9%;
42
- --accent: 12 6.5% 15.1%;
43
- --accent-foreground: 60 9.1% 97.8%;
44
- --destructive: 0 72.2% 50.6%;
45
- --destructive-foreground: 60 9.1% 97.8%;
46
- --border: 12 6.5% 15.1%;
47
- --input: 12 6.5% 15.1%;
48
- --ring: 20.5 90.2% 48.2%;
49
- }
50
- }
51
-
52
- @layer base {
53
- * {
54
- @apply border-border;
55
- }
56
- body {
57
- @apply bg-background text-foreground;
58
- }
59
- }
60
-
61
- @layer components {
62
- .typography-heading-1 {
63
- @apply scroll-m-20 text-4xl font-extrabold tracking-tight lg:text-5xl;
64
- }
65
- .typography-heading-2 {
66
- @apply scroll-m-20 border-b pb-2 text-3xl font-semibold tracking-tight transition-colors first:mt-0;
67
- }
68
- .typography-heading-3 {
69
- @apply scroll-m-20 text-2xl font-semibold tracking-tight;
70
- }
71
- .typography-heading-4 {
72
- @apply scroll-m-20 text-xl font-semibold tracking-tight;
73
- }
74
- .typography-paragraph {
75
- @apply leading-7 [&:not(:first-child)]:mt-6;
76
- }
77
- .typography-lead {
78
- @apply text-xl text-muted-foreground;
79
- }
80
- .typography-large {
81
- @apply text-lg font-semibold;
82
- }
83
- .typography-small {
84
- @apply text-sm font-medium leading-none;
85
- }
86
- .typography-muted {
87
- @apply text-sm text-muted-foreground;
88
- }
89
- }
90
-
91
- /* Style for the scrollbar */
92
- ::-webkit-scrollbar {
93
- width: 10px;
94
- }
95
-
96
- /* Track */
97
- ::-webkit-scrollbar-track {
98
- background: hsl(var(--background));
99
- }
100
-
101
- /* Handle */
102
- ::-webkit-scrollbar-thumb {
103
- background: hsl(var(--primary));
104
- border-radius: 5px;
105
- }
106
-
107
- /* Handle on hover */
108
- ::-webkit-scrollbar-thumb:hover {
109
- background: hsl(var(--primary));
110
- }
111
-
112
- * {
113
- @apply scroll-smooth;
114
- }
1
+ @import "tailwindcss";
2
+ @source "../dist/arc.js";
3
+
4
+ @custom-variant dark (&:where(.dark, .dark *));
5
+
6
+ @property --double-click-progress {
7
+ syntax: "<number>";
8
+ inherits: false;
9
+ initial-value: 100;
10
+ }
11
+
12
+ @keyframes double-click-countdown {
13
+ from {
14
+ --double-click-progress: 100;
15
+ }
16
+ to {
17
+ --double-click-progress: 0;
18
+ }
19
+ }
20
+
21
+ .arc-double-click-progress-ring {
22
+ -webkit-mask:
23
+ linear-gradient(#000 0 0) content-box,
24
+ linear-gradient(#000 0 0);
25
+ -webkit-mask-composite: xor;
26
+ mask:
27
+ linear-gradient(#000 0 0) content-box,
28
+ linear-gradient(#000 0 0);
29
+ mask-composite: exclude;
30
+ }
31
+
32
+ @keyframes arc-grid-loader-pulse {
33
+ 0%,
34
+ 100% {
35
+ transform: scale(0.45);
36
+ opacity: 0.8;
37
+ }
38
+ 50% {
39
+ transform: scale(1);
40
+ opacity: 1;
41
+ }
42
+ }
43
+
44
+ .arc-grid-loader__cell {
45
+ background-color: color-mix(in srgb, var(--color-primary) 85%, var(--color-primary-foreground) 15%);
46
+ color: var(--color-foreground);
47
+ animation: arc-grid-loader-pulse 1.2s ease-in-out infinite;
48
+ }
49
+
50
+ .arc-grid-loader__cell--diamond {
51
+ clip-path: polygon(50% 0, 100% 50%, 50% 100%, 0 50%);
52
+ }
53
+
54
+ .arc-grid-loader__cell--star {
55
+ clip-path: polygon(50% 0, 61% 35%, 98% 35%, 68% 57%, 79% 94%, 50% 71%, 21% 94%, 32% 57%, 2% 35%, 39% 35%);
56
+ }
57
+
58
+ .arc-grid-loader__cell--heart {
59
+ clip-path: polygon(
60
+ 50% 94%,
61
+ 8% 54%,
62
+ 2% 39%,
63
+ 5% 24%,
64
+ 16% 13%,
65
+ 30% 12%,
66
+ 42% 21%,
67
+ 50% 33%,
68
+ 58% 21%,
69
+ 70% 12%,
70
+ 84% 13%,
71
+ 95% 24%,
72
+ 98% 39%,
73
+ 92% 54%
74
+ );
75
+ }
76
+
77
+ .arc-grid-loader__cell--hexagon {
78
+ clip-path: polygon(25% 4%, 75% 4%, 100% 50%, 75% 96%, 25% 96%, 0 50%);
79
+ }
80
+
81
+ @media (prefers-reduced-motion: reduce) {
82
+ .arc-grid-loader__cell {
83
+ animation: none;
84
+ opacity: 1;
85
+ }
86
+ }
87
+
88
+ .arc-pill:hover,
89
+ .arc-pill-link:hover {
90
+ border-color: var(--color-border);
91
+ background-color: color-mix(in srgb, var(--color-background) 94%, var(--color-foreground) 6%) !important;
92
+ }
93
+
94
+ .dark .arc-pill:hover,
95
+ .dark .arc-pill-link:hover {
96
+ border-color: var(--color-primary);
97
+ background-color: color-mix(in srgb, var(--color-background) 88%, var(--color-primary) 12%) !important;
98
+ }
99
+
100
+ .arc-menu-content {
101
+ background-color: color-mix(in srgb, var(--color-background) 92%, var(--color-foreground) 8%);
102
+ }
103
+
104
+ .arc-theme-switcher .arc-menu-content [data-highlighted] {
105
+ border-color: transparent !important;
106
+ }
107
+
108
+ .arc-menu-content [data-highlighted] {
109
+ background-color: color-mix(in srgb, var(--color-background) 94%, var(--color-foreground) 6%) !important;
110
+ color: var(--color-primary) !important;
111
+ }
112
+
113
+ .dark .arc-menu-content [data-highlighted] {
114
+ background-color: color-mix(in srgb, var(--color-background) 88%, var(--color-primary) 12%) !important;
115
+ }
116
+
117
+ .arc-menu-content [data-highlighted] {
118
+ border-color: var(--color-border) !important;
119
+ }
120
+
121
+ .dark .arc-menu-content [data-highlighted] {
122
+ border-color: var(--color-primary) !important;
123
+ }
124
+
125
+ @layer base {
126
+ :root {
127
+ --background: 220 14% 94%;
128
+ --foreground: 220 20% 12%;
129
+ --card: 0 0% 98%;
130
+ --card-foreground: 220 20% 12%;
131
+ --popover: 0 0% 98%;
132
+ --popover-foreground: 220 20% 12%;
133
+ --primary: 24.6 95% 53.1%;
134
+ --primary-foreground: 60 9.1% 97.8%;
135
+ --secondary: 220 14% 90%;
136
+ --secondary-foreground: 220 20% 12%;
137
+ --muted: 220 14% 90%;
138
+ --muted-foreground: 220 10% 40%;
139
+ --accent: 220 14% 90%;
140
+ --accent-foreground: 220 20% 12%;
141
+ --destructive: 0 84.2% 60.2%;
142
+ --destructive-foreground: 60 9.1% 97.8%;
143
+ --success: 142 71% 45%;
144
+ --success-foreground: 144 70% 98%;
145
+ --warning: 38 92% 50%;
146
+ --warning-foreground: 24 10% 10%;
147
+ --border: 220 10% 82%;
148
+ --input: 220 10% 82%;
149
+ --ring: 24.6 95% 53.1%;
150
+ --radius: 1rem;
151
+ }
152
+
153
+ .dark {
154
+ --background: 220 15% 14%;
155
+ --foreground: 60 9.1% 97.8%;
156
+ --card: 220 15% 18%;
157
+ --card-foreground: 60 9.1% 97.8%;
158
+ --popover: 220 15% 22%;
159
+ --popover-foreground: 60 9.1% 97.8%;
160
+ --primary: 20.5 90.2% 48.2%;
161
+ --primary-foreground: 60 9.1% 97.8%;
162
+ --secondary: 12 6.5% 15.1%;
163
+ --secondary-foreground: 60 9.1% 97.8%;
164
+ --muted: 12 6.5% 15.1%;
165
+ --muted-foreground: 24 5.4% 63.9%;
166
+ --accent: 12 6.5% 15.1%;
167
+ --accent-foreground: 60 9.1% 97.8%;
168
+ --destructive: 0 72.2% 50.6%;
169
+ --destructive-foreground: 60 9.1% 97.8%;
170
+ --success: 142 70% 45%;
171
+ --success-foreground: 144 70% 98%;
172
+ --warning: 38 92% 50%;
173
+ --warning-foreground: 24 10% 10%;
174
+ --border: 12 6.5% 25.1%;
175
+ --input: 12 6.5% 25.1%;
176
+ --ring: 20.5 90.2% 48.2%;
177
+ }
178
+ }
179
+
180
+ @theme inline {
181
+ --color-background: hsl(var(--background));
182
+ --color-foreground: hsl(var(--foreground));
183
+ --color-card: hsl(var(--card));
184
+ --color-card-foreground: hsl(var(--card-foreground));
185
+ --color-popover: hsl(var(--popover));
186
+ --color-popover-foreground: hsl(var(--popover-foreground));
187
+ --color-primary: hsl(var(--primary));
188
+ --color-primary-foreground: hsl(var(--primary-foreground));
189
+ --color-secondary: hsl(var(--secondary));
190
+ --color-secondary-foreground: hsl(var(--secondary-foreground));
191
+ --color-muted: hsl(var(--muted));
192
+ --color-muted-foreground: hsl(var(--muted-foreground));
193
+ --color-accent: hsl(var(--accent));
194
+ --color-accent-foreground: hsl(var(--accent-foreground));
195
+ --color-destructive: hsl(var(--destructive));
196
+ --color-destructive-foreground: hsl(var(--destructive-foreground));
197
+ --color-success: hsl(var(--success));
198
+ --color-success-foreground: hsl(var(--success-foreground));
199
+ --color-warning: hsl(var(--warning));
200
+ --color-warning-foreground: hsl(var(--warning-foreground));
201
+ --color-border: hsl(var(--border));
202
+ --color-input: hsl(var(--input));
203
+ --color-ring: hsl(var(--ring));
204
+ }
205
+
206
+ @layer base {
207
+ * {
208
+ @apply border-border;
209
+ }
210
+ body {
211
+ @apply bg-background text-foreground;
212
+ }
213
+ }
214
+
215
+ @layer components {
216
+ .typography-heading-1 {
217
+ @apply text-4xl font-extrabold tracking-tight;
218
+ }
219
+ .typography-heading-2 {
220
+ @apply pb-2 text-3xl font-bold tracking-tight transition-colors;
221
+ }
222
+ .typography-heading-3 {
223
+ @apply text-2xl font-semibold tracking-tight;
224
+ }
225
+ .typography-heading-4 {
226
+ @apply text-xl font-semibold tracking-tight;
227
+ }
228
+ .typography-paragraph {
229
+ @apply leading-7;
230
+ }
231
+ .typography-lead {
232
+ @apply text-xl text-muted-foreground;
233
+ }
234
+ .typography-large {
235
+ @apply text-lg font-semibold;
236
+ }
237
+ .typography-small {
238
+ @apply text-sm leading-none font-medium;
239
+ }
240
+ .typography-muted {
241
+ @apply text-sm text-muted-foreground;
242
+ }
243
+
244
+ .arc-card-cursor-border {
245
+ --card-pointer-x: 50%;
246
+ --card-pointer-y: 50%;
247
+ }
248
+
249
+ .arc-card-cursor-border::before {
250
+ position: absolute;
251
+ opacity: 0;
252
+ z-index: 20;
253
+ -webkit-mask:
254
+ linear-gradient(#000 0 0) content-box,
255
+ linear-gradient(#000 0 0);
256
+ -webkit-mask-composite: xor;
257
+ mask:
258
+ linear-gradient(#000 0 0) content-box,
259
+ linear-gradient(#000 0 0);
260
+ mask-composite: exclude;
261
+ transition: opacity 300ms ease-out;
262
+ inset: 0;
263
+ border-radius: inherit;
264
+ background: radial-gradient(
265
+ 300px circle at var(--card-pointer-x) var(--card-pointer-y),
266
+ color-mix(in srgb, var(--primary) 55%, var(--foreground)),
267
+ transparent 68%
268
+ );
269
+ padding: 1px;
270
+ pointer-events: none;
271
+ content: "";
272
+ }
273
+
274
+ @media (hover: hover) {
275
+ .arc-card-cursor-border:hover::before {
276
+ opacity: 1;
277
+ }
278
+ }
279
+
280
+ .typography-heading-2:first-child {
281
+ margin-top: 0;
282
+ }
283
+
284
+ .typography-paragraph:not(:first-child) {
285
+ margin-top: 1.5rem;
286
+ }
287
+ }
288
+
289
+ @media (min-width: 64rem) {
290
+ .typography-heading-1 {
291
+ font-size: var(--text-5xl);
292
+ line-height: var(--text-5xl--line-height);
293
+ }
294
+ }
295
+
296
+ /* Style for the scrollbar */
297
+ ::-webkit-scrollbar {
298
+ width: 10px;
299
+ }
300
+
301
+ /* Track */
302
+ ::-webkit-scrollbar-track {
303
+ background: var(--color-background);
304
+ }
305
+
306
+ /* Handle */
307
+ ::-webkit-scrollbar-thumb {
308
+ border-radius: 5px;
309
+ background: var(--color-primary);
310
+ }
311
+
312
+ /* Handle on hover */
313
+ ::-webkit-scrollbar-thumb:hover {
314
+ background: var(--color-primary);
315
+ }
316
+
317
+ * {
318
+ @apply scroll-smooth;
319
+ }