@danieljoffe/shared-ui 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/LICENSE.md +117 -0
- package/README.md +373 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5360 -0
- package/dist/lib/Alert.d.ts +13 -0
- package/dist/lib/Alert.d.ts.map +1 -0
- package/dist/lib/AspectRatio.d.ts +8 -0
- package/dist/lib/AspectRatio.d.ts.map +1 -0
- package/dist/lib/Avatar.d.ts +11 -0
- package/dist/lib/Avatar.d.ts.map +1 -0
- package/dist/lib/Badge.d.ts +12 -0
- package/dist/lib/Badge.d.ts.map +1 -0
- package/dist/lib/Breadcrumb.d.ts +12 -0
- package/dist/lib/Breadcrumb.d.ts.map +1 -0
- package/dist/lib/Button.d.ts +23 -0
- package/dist/lib/Button.d.ts.map +1 -0
- package/dist/lib/CTACard.d.ts +10 -0
- package/dist/lib/CTACard.d.ts.map +1 -0
- package/dist/lib/Card.d.ts +39 -0
- package/dist/lib/Card.d.ts.map +1 -0
- package/dist/lib/Checkbox.d.ts +8 -0
- package/dist/lib/Checkbox.d.ts.map +1 -0
- package/dist/lib/Container.d.ts +10 -0
- package/dist/lib/Container.d.ts.map +1 -0
- package/dist/lib/Divider.d.ts +11 -0
- package/dist/lib/Divider.d.ts.map +1 -0
- package/dist/lib/Dropdown.d.ts +17 -0
- package/dist/lib/Dropdown.d.ts.map +1 -0
- package/dist/lib/FormFieldError.d.ts +6 -0
- package/dist/lib/FormFieldError.d.ts.map +1 -0
- package/dist/lib/Grid.d.ts +26 -0
- package/dist/lib/Grid.d.ts.map +1 -0
- package/dist/lib/GridBg.d.ts +7 -0
- package/dist/lib/GridBg.d.ts.map +1 -0
- package/dist/lib/Heading.d.ts +12 -0
- package/dist/lib/Heading.d.ts.map +1 -0
- package/dist/lib/Input.d.ts +12 -0
- package/dist/lib/Input.d.ts.map +1 -0
- package/dist/lib/Kbd.d.ts +8 -0
- package/dist/lib/Kbd.d.ts.map +1 -0
- package/dist/lib/Loading.d.ts +12 -0
- package/dist/lib/Loading.d.ts.map +1 -0
- package/dist/lib/Modal.d.ts +18 -0
- package/dist/lib/Modal.d.ts.map +1 -0
- package/dist/lib/PageContainer.d.ts +22 -0
- package/dist/lib/PageContainer.d.ts.map +1 -0
- package/dist/lib/PageLayout.d.ts +14 -0
- package/dist/lib/PageLayout.d.ts.map +1 -0
- package/dist/lib/Pagination.d.ts +11 -0
- package/dist/lib/Pagination.d.ts.map +1 -0
- package/dist/lib/ProgressBar.d.ts +15 -0
- package/dist/lib/ProgressBar.d.ts.map +1 -0
- package/dist/lib/Section.d.ts +23 -0
- package/dist/lib/Section.d.ts.map +1 -0
- package/dist/lib/SectionLabel.d.ts +9 -0
- package/dist/lib/SectionLabel.d.ts.map +1 -0
- package/dist/lib/Select.d.ts +17 -0
- package/dist/lib/Select.d.ts.map +1 -0
- package/dist/lib/Sidebar.d.ts +20 -0
- package/dist/lib/Sidebar.d.ts.map +1 -0
- package/dist/lib/Skeleton.d.ts +11 -0
- package/dist/lib/Skeleton.d.ts.map +1 -0
- package/dist/lib/Spacer.d.ts +8 -0
- package/dist/lib/Spacer.d.ts.map +1 -0
- package/dist/lib/Spinner.d.ts +13 -0
- package/dist/lib/Spinner.d.ts.map +1 -0
- package/dist/lib/Stack.d.ts +18 -0
- package/dist/lib/Stack.d.ts.map +1 -0
- package/dist/lib/StatsCard.d.ts +16 -0
- package/dist/lib/StatsCard.d.ts.map +1 -0
- package/dist/lib/StructuredData.d.ts +5 -0
- package/dist/lib/StructuredData.d.ts.map +1 -0
- package/dist/lib/Switch.d.ts +13 -0
- package/dist/lib/Switch.d.ts.map +1 -0
- package/dist/lib/Table.d.ts +25 -0
- package/dist/lib/Table.d.ts.map +1 -0
- package/dist/lib/Tabs.d.ts +17 -0
- package/dist/lib/Tabs.d.ts.map +1 -0
- package/dist/lib/Text.d.ts +12 -0
- package/dist/lib/Text.d.ts.map +1 -0
- package/dist/lib/Textarea.d.ts +10 -0
- package/dist/lib/Textarea.d.ts.map +1 -0
- package/dist/lib/ThemeProvider.d.ts +14 -0
- package/dist/lib/ThemeProvider.d.ts.map +1 -0
- package/dist/lib/ThemeToggle.d.ts +2 -0
- package/dist/lib/ThemeToggle.d.ts.map +1 -0
- package/dist/lib/Toast.d.ts +18 -0
- package/dist/lib/Toast.d.ts.map +1 -0
- package/dist/lib/Tooltip.d.ts +13 -0
- package/dist/lib/Tooltip.d.ts.map +1 -0
- package/dist/lib/index.d.ts +89 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/styles/formStyles.d.ts +42 -0
- package/dist/lib/styles/formStyles.d.ts.map +1 -0
- package/dist/lib/styles/semanticVariants.d.ts +22 -0
- package/dist/lib/styles/semanticVariants.d.ts.map +1 -0
- package/dist/lib/types.d.ts +3 -0
- package/dist/lib/types.d.ts.map +1 -0
- package/dist/lib/utils/ErrorBoundary.d.ts +21 -0
- package/dist/lib/utils/ErrorBoundary.d.ts.map +1 -0
- package/dist/lib/utils/ModalErrorBoundary.d.ts +21 -0
- package/dist/lib/utils/ModalErrorBoundary.d.ts.map +1 -0
- package/dist/lib/utils/cn.d.ts +3 -0
- package/dist/lib/utils/cn.d.ts.map +1 -0
- package/dist/lib/utils/index.d.ts +5 -0
- package/dist/lib/utils/index.d.ts.map +1 -0
- package/dist/lib/utils/validateProps.d.ts +6 -0
- package/dist/lib/utils/validateProps.d.ts.map +1 -0
- package/dist/test-setup.d.ts +1 -0
- package/dist/test-setup.d.ts.map +1 -0
- package/package.json +79 -0
- package/src/styles/indigo-theme.css +322 -0
- package/src/styles/preview.scss +4 -0
- package/src/styles/pyre-storybook-preview.css +50 -0
- package/src/styles/pyre-theme.css +346 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
# Functional Source License, Version 1.1, MIT Future License
|
|
2
|
+
|
|
3
|
+
## Abbreviation
|
|
4
|
+
|
|
5
|
+
FSL-1.1-MIT
|
|
6
|
+
|
|
7
|
+
## Notice
|
|
8
|
+
|
|
9
|
+
Copyright 2026 Daniel Joffe
|
|
10
|
+
|
|
11
|
+
## Terms and Conditions
|
|
12
|
+
|
|
13
|
+
### Licensor ("We")
|
|
14
|
+
|
|
15
|
+
The party offering the Software under these Terms and Conditions.
|
|
16
|
+
|
|
17
|
+
### The Software
|
|
18
|
+
|
|
19
|
+
The "Software" is each version of the software that we make available
|
|
20
|
+
under these Terms and Conditions, as indicated by our inclusion of these
|
|
21
|
+
Terms and Conditions with the Software.
|
|
22
|
+
|
|
23
|
+
### License Grant
|
|
24
|
+
|
|
25
|
+
Subject to your compliance with this License Grant and the Patents,
|
|
26
|
+
Redistribution and Trademark clauses below, we hereby grant you the right
|
|
27
|
+
to use, copy, modify, create derivative works, publish, and redistribute
|
|
28
|
+
the Software, in whole or in part, solely for any Permitted Purpose.
|
|
29
|
+
|
|
30
|
+
### Permitted Purpose
|
|
31
|
+
|
|
32
|
+
A Permitted Purpose is any purpose other than a Competing Use. A
|
|
33
|
+
Competing Use means making the Software available to others in a
|
|
34
|
+
commercial product or service that:
|
|
35
|
+
|
|
36
|
+
1. substitutes for the Software;
|
|
37
|
+
|
|
38
|
+
2. substitutes for any other product or service we offer using the
|
|
39
|
+
Software that exists as of the date we make the Software available; or
|
|
40
|
+
|
|
41
|
+
3. offers the same or substantially similar functionality as the Software.
|
|
42
|
+
|
|
43
|
+
Permitted Purposes specifically include using the Software:
|
|
44
|
+
|
|
45
|
+
1. for your internal use and access;
|
|
46
|
+
|
|
47
|
+
2. for non-commercial education;
|
|
48
|
+
|
|
49
|
+
3. for non-commercial research; and
|
|
50
|
+
|
|
51
|
+
4. in connection with professional services that you provide to a
|
|
52
|
+
licensee using the Software in accordance with these Terms and
|
|
53
|
+
Conditions.
|
|
54
|
+
|
|
55
|
+
### Patents
|
|
56
|
+
|
|
57
|
+
To the extent your use for a Permitted Purpose would necessarily infringe
|
|
58
|
+
our patents, the license grant above includes a license under our patents.
|
|
59
|
+
If you make a claim against any party that the Software infringes or
|
|
60
|
+
contributes to the infringement of any patent, then your patent license
|
|
61
|
+
to the Software ends immediately.
|
|
62
|
+
|
|
63
|
+
### Redistribution
|
|
64
|
+
|
|
65
|
+
The Terms and Conditions apply to all copies, modifications and
|
|
66
|
+
derivatives of the Software.
|
|
67
|
+
|
|
68
|
+
If you redistribute any copies, modifications or derivatives of the
|
|
69
|
+
Software, you must include a copy of or a link to these Terms and
|
|
70
|
+
Conditions and not remove any copyright notices provided in or with the
|
|
71
|
+
Software.
|
|
72
|
+
|
|
73
|
+
### Disclaimer
|
|
74
|
+
|
|
75
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND WITHOUT WARRANTIES OF ANY KIND,
|
|
76
|
+
INCLUDING WITHOUT LIMITATION WARRANTIES OF MERCHANTABILITY, FITNESS FOR
|
|
77
|
+
A PARTICULAR PURPOSE, NON-INFRINGEMENT AND TITLE.
|
|
78
|
+
|
|
79
|
+
OUR TOTAL LIABILITY TO YOU FOR ANY DAMAGES ARISING OUT OF OR RELATED TO
|
|
80
|
+
THIS AGREEMENT IS LIMITED TO US$500.
|
|
81
|
+
|
|
82
|
+
WE WILL NOT BE LIABLE TO YOU FOR ANY LOST PROFITS, REVENUES, OR DATA, OR
|
|
83
|
+
FOR CONSEQUENTIAL, INDIRECT, SPECIAL, INCIDENTAL, OR PUNITIVE DAMAGES.
|
|
84
|
+
|
|
85
|
+
### Trademarks
|
|
86
|
+
|
|
87
|
+
Except for displaying the License Details and identifying us as the
|
|
88
|
+
origin of the Software, you have no right under these Terms and
|
|
89
|
+
Conditions to use our trademarks, trade names, service marks or product
|
|
90
|
+
names.
|
|
91
|
+
|
|
92
|
+
## Grant of Future License
|
|
93
|
+
|
|
94
|
+
We hereby irrevocably grant you an additional license to use the Software
|
|
95
|
+
under the MIT license that is effective on the second anniversary of the
|
|
96
|
+
date we make the Software available. On or after that date, you may use
|
|
97
|
+
the Software under the MIT license, in which case the following will
|
|
98
|
+
apply:
|
|
99
|
+
|
|
100
|
+
> Permission is hereby granted, free of charge, to any person obtaining a
|
|
101
|
+
> copy of this software and associated documentation files (the
|
|
102
|
+
> "Software"), to deal in the Software without restriction, including
|
|
103
|
+
> without limitation the rights to use, copy, modify, merge, publish,
|
|
104
|
+
> distribute, sublicense, and/or sell copies of the Software, and to
|
|
105
|
+
> permit persons to whom the Software is furnished to do so, subject to
|
|
106
|
+
> the following conditions:
|
|
107
|
+
>
|
|
108
|
+
> The above copyright notice and this permission notice shall be included
|
|
109
|
+
> in all copies or substantial portions of the Software.
|
|
110
|
+
>
|
|
111
|
+
> THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
|
112
|
+
> OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
113
|
+
> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
114
|
+
> IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
115
|
+
> CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
116
|
+
> TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
117
|
+
> SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
# @danieljoffe/shared-ui
|
|
2
|
+
|
|
3
|
+
A React component library built with Tailwind CSS 4. Provides 40+ accessible, theme-aware UI primitives designed for the danieljoffe.com ecosystem.
|
|
4
|
+
|
|
5
|
+
**Live component catalog**: [ui.danieljoffe.com](https://ui.danieljoffe.com) (Storybook)
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @danieljoffe/shared-ui
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Peer dependencies
|
|
14
|
+
|
|
15
|
+
| Package | Version | Required |
|
|
16
|
+
| -------------- | ----------- | --------------------------------- |
|
|
17
|
+
| `react` | `^19.0.0` | Yes |
|
|
18
|
+
| `react-dom` | `^19.0.0` | Yes |
|
|
19
|
+
| `tailwindcss` | `^4.0.0` | Yes |
|
|
20
|
+
| `lucide-react` | `>=0.400.0` | Yes (icons in various components) |
|
|
21
|
+
|
|
22
|
+
### Bundled dependencies
|
|
23
|
+
|
|
24
|
+
These are included in the package and do not need to be installed separately:
|
|
25
|
+
|
|
26
|
+
- `clsx` — conditional class construction
|
|
27
|
+
- `tailwind-merge` — Tailwind class deduplication
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install react react-dom tailwindcss lucide-react
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Quick start
|
|
34
|
+
|
|
35
|
+
```tsx
|
|
36
|
+
import { Button } from '@danieljoffe/shared-ui';
|
|
37
|
+
// Or use deep imports for tree-shaking:
|
|
38
|
+
import { Button } from '@danieljoffe/shared-ui/Button';
|
|
39
|
+
|
|
40
|
+
export default function App() {
|
|
41
|
+
return (
|
|
42
|
+
<Button variant='primary' size='md'>
|
|
43
|
+
Get Started
|
|
44
|
+
</Button>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Theme setup
|
|
50
|
+
|
|
51
|
+
Import the theme CSS to get design tokens (colors, spacing, typography, shadows, animations):
|
|
52
|
+
|
|
53
|
+
```css
|
|
54
|
+
/* In your global CSS or Tailwind entry point */
|
|
55
|
+
@import '@danieljoffe/shared-ui/styles/theme.css';
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
The theme file is **self-contained** with no external imports. It uses Tailwind CSS 4's `@theme` directive so every token is available as both a CSS custom property and a Tailwind utility class (e.g., `bg-brand-500`, `text-text-secondary`, `shadow-md`).
|
|
59
|
+
|
|
60
|
+
> **oklch color space** -- Brand colors use `oklch()` for perceptually uniform lightness across the scale. Semantic surface/text/status colors use hex or `rgba` for maximum browser compatibility.
|
|
61
|
+
|
|
62
|
+
### Consumer setup (Tailwind CSS 4)
|
|
63
|
+
|
|
64
|
+
```css
|
|
65
|
+
/* app/globals.css */
|
|
66
|
+
@import 'tailwindcss';
|
|
67
|
+
@import '@danieljoffe/shared-ui/styles/theme.css';
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
That single import gives you every token below. No `tailwind.config` changes are needed in Tailwind CSS 4 -- the `@theme` directive registers tokens automatically.
|
|
71
|
+
|
|
72
|
+
### Integration paths
|
|
73
|
+
|
|
74
|
+
| Approach | When to use | How |
|
|
75
|
+
| ---------------------- | ---------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
76
|
+
| **Full adoption** | New apps built on shared-ui | Import `theme.css` as shown above. All tokens, base styles, dark mode, and keyframes are active. |
|
|
77
|
+
| **Selective adoption** | Existing apps with their own theme | Copy individual `@theme` token groups into your own CSS. Or import `theme.css` and override specific variables in a subsequent `@theme` block. |
|
|
78
|
+
|
|
79
|
+
To override tokens selectively:
|
|
80
|
+
|
|
81
|
+
```css
|
|
82
|
+
@import '@danieljoffe/shared-ui/styles/theme.css';
|
|
83
|
+
|
|
84
|
+
@theme {
|
|
85
|
+
--color-brand-500: oklch(0.6 0.2 280); /* shift brand toward purple */
|
|
86
|
+
--font-sans: 'Geist', ui-sans-serif, system-ui, sans-serif;
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Full token reference
|
|
91
|
+
|
|
92
|
+
#### Radius
|
|
93
|
+
|
|
94
|
+
| Token | Value | Tailwind class |
|
|
95
|
+
| --------------- | ---------- | -------------- |
|
|
96
|
+
| `--radius-sm` | `0.375rem` | `rounded-sm` |
|
|
97
|
+
| `--radius-md` | `0.5rem` | `rounded-md` |
|
|
98
|
+
| `--radius-lg` | `0.75rem` | `rounded-lg` |
|
|
99
|
+
| `--radius-xl` | `1rem` | `rounded-xl` |
|
|
100
|
+
| `--radius-full` | `9999px` | `rounded-full` |
|
|
101
|
+
|
|
102
|
+
#### Typography
|
|
103
|
+
|
|
104
|
+
| Token | Value | Tailwind class |
|
|
105
|
+
| ------------- | ----------------------------------------------- | -------------- |
|
|
106
|
+
| `--font-sans` | `'Inter', ui-sans-serif, system-ui, sans-serif` | `font-sans` |
|
|
107
|
+
| `--font-mono` | `'JetBrains Mono', ui-monospace, monospace` | `font-mono` |
|
|
108
|
+
|
|
109
|
+
#### Shadows
|
|
110
|
+
|
|
111
|
+
| Token | Light mode | Dark mode | Tailwind class |
|
|
112
|
+
| ------------- | --------------------------------------------------------------------- | ------------------------------------------------------------------- | -------------- |
|
|
113
|
+
| `--shadow-xs` | `0 1px 2px rgba(0,0,0,0.04)` | `0 1px 2px rgba(0,0,0,0.2)` | `shadow-xs` |
|
|
114
|
+
| `--shadow-sm` | `0 1px 3px rgba(0,0,0,0.06), 0 1px 2px rgba(0,0,0,0.04)` | `0 1px 3px rgba(0,0,0,0.3), 0 1px 2px rgba(0,0,0,0.2)` | `shadow-sm` |
|
|
115
|
+
| `--shadow-md` | `0 4px 6px -1px rgba(0,0,0,0.07), 0 2px 4px -2px rgba(0,0,0,0.05)` | `0 4px 6px -1px rgba(0,0,0,0.3), 0 2px 4px -2px rgba(0,0,0,0.2)` | `shadow-md` |
|
|
116
|
+
| `--shadow-lg` | `0 10px 15px -3px rgba(0,0,0,0.08), 0 4px 6px -4px rgba(0,0,0,0.04)` | `0 10px 15px -3px rgba(0,0,0,0.4), 0 4px 6px -4px rgba(0,0,0,0.2)` | `shadow-lg` |
|
|
117
|
+
| `--shadow-xl` | `0 20px 25px -5px rgba(0,0,0,0.08), 0 8px 10px -6px rgba(0,0,0,0.04)` | `0 20px 25px -5px rgba(0,0,0,0.4), 0 8px 10px -6px rgba(0,0,0,0.2)` | `shadow-xl` |
|
|
118
|
+
|
|
119
|
+
#### Animations
|
|
120
|
+
|
|
121
|
+
| Token | Value | Tailwind class |
|
|
122
|
+
| -------------------------- | --------------------------------------- | ------------------------ |
|
|
123
|
+
| `--animate-fade-in` | `fade-in 0.2s ease-out` | `animate-fade-in` |
|
|
124
|
+
| `--animate-slide-up` | `slide-up 0.2s ease-out` | `animate-slide-up` |
|
|
125
|
+
| `--animate-slide-down` | `slide-down 0.15s ease-out` | `animate-slide-down` |
|
|
126
|
+
| `--animate-slide-out-down` | `slide-out-down 0.15s ease-in forwards` | `animate-slide-out-down` |
|
|
127
|
+
| `--animate-scale-in` | `scale-in 0.15s ease-out` | `animate-scale-in` |
|
|
128
|
+
|
|
129
|
+
Additional keyframes defined (usable in custom animations): `bounceSubtle`, `pulseSlow`.
|
|
130
|
+
|
|
131
|
+
#### Colors -- Brand (blue-indigo, oklch hue 250)
|
|
132
|
+
|
|
133
|
+
| Token | Value | Tailwind class |
|
|
134
|
+
| ------------------- | ---------------------- | ------------------------------------ |
|
|
135
|
+
| `--color-brand-50` | `oklch(0.97 0.01 250)` | `bg-brand-50`, `text-brand-50`, etc. |
|
|
136
|
+
| `--color-brand-100` | `oklch(0.93 0.03 250)` | `bg-brand-100` |
|
|
137
|
+
| `--color-brand-200` | `oklch(0.87 0.06 250)` | `bg-brand-200` |
|
|
138
|
+
| `--color-brand-300` | `oklch(0.78 0.1 250)` | `bg-brand-300` |
|
|
139
|
+
| `--color-brand-400` | `oklch(0.68 0.15 250)` | `bg-brand-400` |
|
|
140
|
+
| `--color-brand-500` | `oklch(0.54 0.19 250)` | `bg-brand-500` |
|
|
141
|
+
| `--color-brand-600` | `oklch(0.5 0.19 250)` | `bg-brand-600` |
|
|
142
|
+
| `--color-brand-700` | `oklch(0.43 0.17 250)` | `bg-brand-700` |
|
|
143
|
+
| `--color-brand-800` | `oklch(0.37 0.14 250)` | `bg-brand-800` |
|
|
144
|
+
| `--color-brand-900` | `oklch(0.3 0.1 250)` | `bg-brand-900` |
|
|
145
|
+
| `--color-brand-950` | `oklch(0.22 0.08 250)` | `bg-brand-950` |
|
|
146
|
+
|
|
147
|
+
#### Colors -- Semantic surface
|
|
148
|
+
|
|
149
|
+
| Token | Light | Dark | Tailwind class |
|
|
150
|
+
| --------------------------- | ----------------- | ----------------- | ---------------------- |
|
|
151
|
+
| `--color-surface` | `#ffffff` | `#0f1117` | `bg-surface` |
|
|
152
|
+
| `--color-surface-secondary` | `#f9fafb` | `#161922` | `bg-surface-secondary` |
|
|
153
|
+
| `--color-surface-tertiary` | `#f3f4f6` | `#1e2130` | `bg-surface-tertiary` |
|
|
154
|
+
| `--color-surface-elevated` | `#ffffff` | `#1a1d2b` | `bg-surface-elevated` |
|
|
155
|
+
| `--color-surface-overlay` | `rgba(0,0,0,0.5)` | `rgba(0,0,0,0.7)` | `bg-surface-overlay` |
|
|
156
|
+
|
|
157
|
+
#### Colors -- Semantic border
|
|
158
|
+
|
|
159
|
+
| Token | Light | Dark | Tailwind class |
|
|
160
|
+
| -------------------------- | ---------------------- | --------- | ------------------------- |
|
|
161
|
+
| `--color-border` | `#e5e7eb` | `#2a2d3a` | `border-border` |
|
|
162
|
+
| `--color-border-secondary` | `#d1d5db` | `#3a3d4a` | `border-border-secondary` |
|
|
163
|
+
| `--color-border-focus` | `oklch(0.54 0.19 250)` | _(same)_ | `outline-border-focus` |
|
|
164
|
+
|
|
165
|
+
#### Colors -- Semantic text
|
|
166
|
+
|
|
167
|
+
| Token | Light | Dark | Tailwind class |
|
|
168
|
+
| ------------------------ | --------------------- | --------- | --------------------- |
|
|
169
|
+
| `--color-text-primary` | `#111827` | `#f1f5f9` | `text-text-primary` |
|
|
170
|
+
| `--color-text-secondary` | `#6b7280` | `#94a3b8` | `text-text-secondary` |
|
|
171
|
+
| `--color-text-tertiary` | `#9ca3af` | `#64748b` | `text-text-tertiary` |
|
|
172
|
+
| `--color-text-inverse` | `#ffffff` | `#0f1117` | `text-text-inverse` |
|
|
173
|
+
| `--color-text-brand` | `oklch(0.5 0.19 250)` | _(same)_ | `text-text-brand` |
|
|
174
|
+
|
|
175
|
+
#### Colors -- Status
|
|
176
|
+
|
|
177
|
+
| Token | Light | Dark | Tailwind class |
|
|
178
|
+
| ----------------------- | --------- | --------- | ---------------------------- |
|
|
179
|
+
| `--color-success` | `#10b981` | _(same)_ | `text-success`, `bg-success` |
|
|
180
|
+
| `--color-success-light` | `#ecfdf5` | `#052e16` | `bg-success-light` |
|
|
181
|
+
| `--color-warning` | `#f59e0b` | _(same)_ | `text-warning`, `bg-warning` |
|
|
182
|
+
| `--color-warning-light` | `#fffbeb` | `#451a03` | `bg-warning-light` |
|
|
183
|
+
| `--color-error` | `#ef4444` | _(same)_ | `text-error`, `bg-error` |
|
|
184
|
+
| `--color-error-light` | `#fef2f2` | `#450a0a` | `bg-error-light` |
|
|
185
|
+
| `--color-info` | `#2563eb` | _(same)_ | `text-info`, `bg-info` |
|
|
186
|
+
| `--color-info-light` | `#eff6ff` | `#172554` | `bg-info-light` |
|
|
187
|
+
|
|
188
|
+
### Dark mode
|
|
189
|
+
|
|
190
|
+
Dark mode is handled via `.dark` class overrides in the same theme file. The `ThemeProvider` component toggles the `.dark` class on `<html>`. The theme file also registers a custom variant:
|
|
191
|
+
|
|
192
|
+
```css
|
|
193
|
+
@custom-variant dark (&:is(.dark *));
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
This means you can use `dark:` prefix in Tailwind classes (e.g., `dark:bg-surface-secondary`) and they will activate when `.dark` is present on an ancestor element.
|
|
197
|
+
|
|
198
|
+
### Base styles
|
|
199
|
+
|
|
200
|
+
The theme file includes an `@layer base` block that sets:
|
|
201
|
+
|
|
202
|
+
- Default border and outline colors on all elements
|
|
203
|
+
- Body background, text color, font-family, and line-height
|
|
204
|
+
- Heading typography (h1-h6) with balanced text wrapping and tight letter-spacing
|
|
205
|
+
- Code element styling using `font-mono` with brand-colored background
|
|
206
|
+
- Table and list resets
|
|
207
|
+
- Scrollbar styling (WebKit)
|
|
208
|
+
- `prefers-reduced-motion` support (disables animations automatically)
|
|
209
|
+
|
|
210
|
+
### Experimental color schemes
|
|
211
|
+
|
|
212
|
+
The `styles/` directory also contains three SCSS-based color scheme variants. These are **experimental** and use a different variable convention from the main `theme.css` (e.g., `--accent`, `--background` instead of `--color-brand-*`, `--color-surface`). They are not currently exported in `package.json` and are not intended for consumer use:
|
|
213
|
+
|
|
214
|
+
| Scheme | Directory | Accent color |
|
|
215
|
+
| ------------ | ---------------------- | ------------ |
|
|
216
|
+
| Deep Teal | `styles/deep-teal/` | `#0d7377` |
|
|
217
|
+
| Muted Violet | `styles/muted-violet/` | `#6b5b95` |
|
|
218
|
+
| Warm Gold | `styles/warm-gold/` | `#9a6c18` |
|
|
219
|
+
|
|
220
|
+
Each includes a `default.scss` (light) and `dark.scss` file.
|
|
221
|
+
|
|
222
|
+
## Component catalog
|
|
223
|
+
|
|
224
|
+
### Typography
|
|
225
|
+
|
|
226
|
+
| Component | Description | Key props |
|
|
227
|
+
| ----------- | ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
228
|
+
| **Heading** | Semantic headings with predefined variants | `variant`: `hero`, `detail`, `subtitle`, `section`, `cardTitle`, `component`, `mdxH1`-`mdxH4`. `as`: override element (`h1`-`h6`, `p`) |
|
|
229
|
+
| **Text** | Body text with semantic variants | `variant`: `body`, `bodyLg`, `subtitle`, `cardDescription`, `detail`, `label`, `meta`, `caption`, `helper`, `error`. `as`: override element (`p`, `span`, `div`, `label`) |
|
|
230
|
+
|
|
231
|
+
### Layout
|
|
232
|
+
|
|
233
|
+
| Component | Description | Key props |
|
|
234
|
+
| ----------------------- | ------------------------------------------ | -------------------------------------- |
|
|
235
|
+
| **Container** | Max-width centered container | `size`: `sm`, `md`, `lg`, `xl`, `full` |
|
|
236
|
+
| **Grid** / **GridItem** | CSS Grid wrapper | `cols`, `gap`, `responsive` |
|
|
237
|
+
| **PageContainer** | Page-level wrapper with consistent padding | `wide` |
|
|
238
|
+
| **PageLayout** | Full page layout with sections | `wide` |
|
|
239
|
+
| **Section** | Semantic section with spacing | `id`, `className` |
|
|
240
|
+
| **SectionLabel** | Section header with icon + label | `icon`, `label` |
|
|
241
|
+
| **Spacer** | Vertical/horizontal spacing | `size`: `xs`-`xl` |
|
|
242
|
+
| **Stack** | Flex stack (vertical/horizontal) | `direction`, `gap`, `align`, `justify` |
|
|
243
|
+
| **Sidebar** | Navigation sidebar | `items`, `activeItem` |
|
|
244
|
+
|
|
245
|
+
### Data display
|
|
246
|
+
|
|
247
|
+
| Component | Description | Key props |
|
|
248
|
+
| ---------------------------------------------------------------------------- | ------------------------------------------- | ----------------------------------------------------------------------------------- |
|
|
249
|
+
| **Avatar** | User avatar with fallback | `src`, `alt`, `size` |
|
|
250
|
+
| **Badge** | Status/category label | `variant`: `default`, `brand`, `brand-solid`, `success`, `warning`, `error`, `info` |
|
|
251
|
+
| **Breadcrumb** | Navigation breadcrumb trail | `items: BreadcrumbItem[]` |
|
|
252
|
+
| **Card** / **CardHeader** / **CardTitle** / **CardContent** / **CardFooter** | Composable card | Standard card sections |
|
|
253
|
+
| **CTACard** | Call-to-action card with heading and action | `title`, `description`, `action` |
|
|
254
|
+
| **Divider** | Horizontal rule with optional label | `label` |
|
|
255
|
+
| **Kbd** | Keyboard shortcut display | `children` (key text) |
|
|
256
|
+
| **Pagination** | Page navigation controls | `currentPage`, `totalPages`, `onPageChange` |
|
|
257
|
+
| **ProgressBar** | Progress indicator | `value`, `max`, `variant` |
|
|
258
|
+
| **Skeleton** | Loading placeholder | `width`, `height`, `variant`: `text`, `circular`, `rectangular` |
|
|
259
|
+
| **StatsCard** | Metric display card | `label`, `value`, `subtitle`, `trend` |
|
|
260
|
+
| **StructuredData** | JSON-LD script injection | `data` |
|
|
261
|
+
| **Table** | Data table with sorting | `columns: Column[]`, `data`, `sortable` |
|
|
262
|
+
| **Tabs** | Tab navigation | `tabs: Tab[]`, `activeTab`, `onTabChange` |
|
|
263
|
+
| **Tooltip** | Hover tooltip | `content`, `position` |
|
|
264
|
+
|
|
265
|
+
### Forms
|
|
266
|
+
|
|
267
|
+
| Component | Description | Key props |
|
|
268
|
+
| ------------------ | ------------------------------ | ----------------------------------------------------------------------------------------- |
|
|
269
|
+
| **Button** | Button with variants and sizes | `variant`: `primary`, `secondary`, `ghost`, `outline`, `danger`. `size`: `sm`, `md`, `lg` |
|
|
270
|
+
| **Checkbox** | Checkbox input | `checked`, `onChange`, `label` |
|
|
271
|
+
| **FormFieldError** | Validation error message | `message`, `id` (for `aria-describedby`) |
|
|
272
|
+
| **Input** | Text input with label/error | `label`, `error`, `helper` |
|
|
273
|
+
| **Select** | Select dropdown | `options: SelectOption[]`, `label`, `error` |
|
|
274
|
+
| **Switch** | Toggle switch | `checked`, `onChange`, `label` |
|
|
275
|
+
| **Textarea** | Multi-line text input | `label`, `error`, `helper` |
|
|
276
|
+
|
|
277
|
+
### Feedback
|
|
278
|
+
|
|
279
|
+
| Component | Description | Key props |
|
|
280
|
+
| -------------------------------- | ------------------------- | --------------------------------------------------------------------- |
|
|
281
|
+
| **Alert** | Contextual alert banner | `variant`: `info`, `success`, `warning`, `error`. `title`, `children` |
|
|
282
|
+
| **Dropdown** | Action menu | `items: DropdownItem[]`, `trigger` |
|
|
283
|
+
| **Loading** | Full-area loading spinner | `message` |
|
|
284
|
+
| **Modal** | Dialog overlay | `open`, `onClose`, `title` |
|
|
285
|
+
| **Spinner** | Inline loading indicator | `size`: `sm`, `md`, `lg` |
|
|
286
|
+
| **ToastProvider** / **useToast** | Toast notification system | `toast({ variant, title, description })` |
|
|
287
|
+
|
|
288
|
+
### Theming
|
|
289
|
+
|
|
290
|
+
| Component | Description | Key props |
|
|
291
|
+
| -------------------------------- | ----------------------------- | ------------------------------------------ |
|
|
292
|
+
| **ThemeProvider** / **useTheme** | Theme context provider | Wraps app, provides `theme`, `toggleTheme` |
|
|
293
|
+
| **ThemeToggle** | Dark/light mode toggle button | Uses `useTheme` internally |
|
|
294
|
+
|
|
295
|
+
### Decorative
|
|
296
|
+
|
|
297
|
+
| Component | Description | Key props |
|
|
298
|
+
| --------------- | ---------------------------- | ----------- |
|
|
299
|
+
| **AspectRatio** | Fixed aspect ratio container | `ratio` |
|
|
300
|
+
| **GridBg** | Decorative grid background | `className` |
|
|
301
|
+
|
|
302
|
+
## Utilities
|
|
303
|
+
|
|
304
|
+
| Export | Description |
|
|
305
|
+
| ----------------------------- | -------------------------------------------------------- |
|
|
306
|
+
| `cn(...classes)` | Tailwind-aware class merging (`clsx` + `tailwind-merge`) |
|
|
307
|
+
| `validateProps(props, rules)` | Runtime prop validation helper |
|
|
308
|
+
| `ErrorBoundary` | React error boundary component |
|
|
309
|
+
| `ModalErrorBoundary` | Error boundary scoped to modals |
|
|
310
|
+
|
|
311
|
+
## TypeScript
|
|
312
|
+
|
|
313
|
+
All components export their prop types (e.g., `ButtonProps`, `AlertProps`). The library is built with `exactOptionalPropertyTypes` compatibility.
|
|
314
|
+
|
|
315
|
+
```tsx
|
|
316
|
+
import type { ButtonProps, ButtonVariant } from '@danieljoffe/shared-ui';
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
## Tree-shaking
|
|
320
|
+
|
|
321
|
+
Use deep imports for optimal bundle size:
|
|
322
|
+
|
|
323
|
+
```tsx
|
|
324
|
+
// Only bundles Button code:
|
|
325
|
+
import { Button } from '@danieljoffe/shared-ui/Button';
|
|
326
|
+
|
|
327
|
+
// Bundles everything (barrel import):
|
|
328
|
+
import { Button } from '@danieljoffe/shared-ui';
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
## React 19 ref pattern
|
|
332
|
+
|
|
333
|
+
Components accept `ref` as a regular prop — `forwardRef` is not used. This is the React 19 pattern:
|
|
334
|
+
|
|
335
|
+
```tsx
|
|
336
|
+
import { useRef } from 'react';
|
|
337
|
+
import { Input } from '@danieljoffe/shared-ui/Input';
|
|
338
|
+
|
|
339
|
+
function MyForm() {
|
|
340
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
341
|
+
return <Input ref={inputRef} label='Name' />;
|
|
342
|
+
}
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
## Constraints
|
|
346
|
+
|
|
347
|
+
- **No Next.js APIs**: This library depends only on React and Tailwind CSS. Components requiring `next/link`, `next/image`, `useRouter`, etc. belong in the consuming app's `components/kit/` directory.
|
|
348
|
+
- **No framework-specific code**: Components work in any React 19+ environment with Tailwind CSS 4.
|
|
349
|
+
|
|
350
|
+
## Development
|
|
351
|
+
|
|
352
|
+
```bash
|
|
353
|
+
# Run unit tests
|
|
354
|
+
pnpm nx test @danieljoffe/shared-ui
|
|
355
|
+
|
|
356
|
+
# Start Storybook
|
|
357
|
+
pnpm nx storybook @danieljoffe/shared-ui
|
|
358
|
+
|
|
359
|
+
# Build library
|
|
360
|
+
pnpm nx build @danieljoffe/shared-ui
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
## Contributing
|
|
364
|
+
|
|
365
|
+
This library lives in the [danieljoffe.com monorepo](https://github.com/danieljoffe/danieljoffe.com) at `libs/shared/ui/`. See the root `CLAUDE.md` for conventions around the Rule of Three, component patterns, and the shared-ui boundary.
|
|
366
|
+
|
|
367
|
+
## License
|
|
368
|
+
|
|
369
|
+
[FSL-1.1-MIT](./LICENSE.md) — Functional Source License 1.1 with MIT Future License.
|
|
370
|
+
|
|
371
|
+
The Functional Source License grants permission to use, copy, modify, and redistribute the software for any purpose except a Competing Use (a commercial product or service that substitutes for this library or anything we offer using it). Two years after each release, that release automatically re-licenses under the MIT License. Read the [LICENSE](./LICENSE.md) for the full terms.
|
|
372
|
+
|
|
373
|
+
Practical translation: you can use, fork, and self-host this library freely for personal, internal, educational, or non-competing-commercial work. If you'd like to use it inside a competing commercial offering, [open an issue](https://github.com/danieljoffe/danieljoffe.com/issues) — there's almost certainly a path that works for both of us.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAC"}
|