@os-legal/ui 0.1.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.
- package/README.md +347 -0
- package/dist/index.d.mts +1959 -0
- package/dist/index.d.ts +1959 -0
- package/dist/index.js +16331 -0
- package/dist/index.mjs +16089 -0
- package/package.json +73 -0
package/README.md
ADDED
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
# OpenContracts Component Library
|
|
2
|
+
|
|
3
|
+
A React component library implementing the OpenContracts design system — built around **transparent infrastructure**, **visible connections**, and **warm precision**.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install github:Open-Source-Legal/OS-Legal-Style
|
|
9
|
+
# or
|
|
10
|
+
yarn add github:Open-Source-Legal/OS-Legal-Style
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or add to your `package.json`:
|
|
14
|
+
|
|
15
|
+
```json
|
|
16
|
+
{
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@opencontracts/ui": "github:Open-Source-Legal/OS-Legal-Style"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Setup
|
|
24
|
+
|
|
25
|
+
### 1. Import Styles
|
|
26
|
+
|
|
27
|
+
Import the combined styles at your app's root:
|
|
28
|
+
|
|
29
|
+
```tsx
|
|
30
|
+
// App.tsx or index.tsx
|
|
31
|
+
import { allStyles } from '@opencontracts/ui';
|
|
32
|
+
|
|
33
|
+
// Inject styles (or use your preferred method)
|
|
34
|
+
const styleEl = document.createElement('style');
|
|
35
|
+
styleEl.textContent = allStyles;
|
|
36
|
+
document.head.appendChild(styleEl);
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
### 2. Add Fonts
|
|
40
|
+
|
|
41
|
+
The design system uses Inter for UI and Georgia for headlines:
|
|
42
|
+
|
|
43
|
+
```html
|
|
44
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
45
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
46
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Usage
|
|
50
|
+
|
|
51
|
+
```tsx
|
|
52
|
+
import { Button, Card, CardHeader, CardBody, SearchBox, StatBlock } from '@opencontracts/ui';
|
|
53
|
+
|
|
54
|
+
function App() {
|
|
55
|
+
return (
|
|
56
|
+
<Card>
|
|
57
|
+
<CardHeader
|
|
58
|
+
title="Contract Analysis"
|
|
59
|
+
subtitle="3 documents reviewed"
|
|
60
|
+
/>
|
|
61
|
+
<CardBody>
|
|
62
|
+
<SearchBox
|
|
63
|
+
placeholder="Search contracts..."
|
|
64
|
+
onSubmit={(value) => console.log(value)}
|
|
65
|
+
/>
|
|
66
|
+
<StatBlock value="142K" label="Annotations" sublabel="community contributed" />
|
|
67
|
+
</CardBody>
|
|
68
|
+
<div style={{ display: 'flex', gap: '8px', marginTop: '16px' }}>
|
|
69
|
+
<Button variant="primary">Accept All</Button>
|
|
70
|
+
<Button variant="secondary">Review</Button>
|
|
71
|
+
</div>
|
|
72
|
+
</Card>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## Components
|
|
78
|
+
|
|
79
|
+
### Layout
|
|
80
|
+
|
|
81
|
+
| Component | Description |
|
|
82
|
+
|-----------|-------------|
|
|
83
|
+
| `AppShell` | Application shell with sidebar, header, and main content |
|
|
84
|
+
| `PageHeader` | Page title with breadcrumbs and actions |
|
|
85
|
+
| `SplitPane` | Resizable split panel layout |
|
|
86
|
+
| `Stack` / `HStack` / `VStack` | Flexbox layout utilities |
|
|
87
|
+
| `ScrollArea` | Custom scrollable container |
|
|
88
|
+
| `Card` | Container with Header, Body, Footer subcomponents |
|
|
89
|
+
| `Sidebar` | Dark navigation sidebar with sections |
|
|
90
|
+
|
|
91
|
+
### Forms
|
|
92
|
+
|
|
93
|
+
| Component | Description |
|
|
94
|
+
|-----------|-------------|
|
|
95
|
+
| `Button` / `IconButton` | Primary, secondary, ghost, danger variants |
|
|
96
|
+
| `Input` | Text input with label, helper text, error states |
|
|
97
|
+
| `Textarea` | Multi-line input with auto-resize |
|
|
98
|
+
| `Select` | Native select with consistent styling |
|
|
99
|
+
| `Checkbox` / `CheckboxGroup` | Checkbox inputs with labels |
|
|
100
|
+
| `Radio` / `RadioGroup` | Radio button inputs |
|
|
101
|
+
| `Toggle` / `Switch` | Toggle switches |
|
|
102
|
+
| `FormField` | Form field wrapper with label and validation |
|
|
103
|
+
| `SearchBox` | Search input with icon and submit button |
|
|
104
|
+
|
|
105
|
+
### Data Display
|
|
106
|
+
|
|
107
|
+
| Component | Description |
|
|
108
|
+
|-----------|-------------|
|
|
109
|
+
| `Avatar` / `AvatarGroup` | User avatars with status indicators |
|
|
110
|
+
| `Chip` / `ChipGroup` | Tags, labels, and filter chips |
|
|
111
|
+
| `StatBlock` / `StatGrid` | Large number stats with labels |
|
|
112
|
+
| `CollectionCard` | List cards with type icons and badges |
|
|
113
|
+
| `ActivityFeed` | Timeline with avatars and actions |
|
|
114
|
+
| `SourceCard` / `Citation` | Document source cards and citations |
|
|
115
|
+
|
|
116
|
+
### Navigation
|
|
117
|
+
|
|
118
|
+
| Component | Description |
|
|
119
|
+
|-----------|-------------|
|
|
120
|
+
| `Tabs` | Tab navigation with panels |
|
|
121
|
+
| `FilterTabs` | Pill-style category filters with counts |
|
|
122
|
+
| `ActionList` | Clickable action items with icons |
|
|
123
|
+
|
|
124
|
+
### Feedback
|
|
125
|
+
|
|
126
|
+
| Component | Description |
|
|
127
|
+
|-----------|-------------|
|
|
128
|
+
| `Toast` / `ToastProvider` | Toast notifications |
|
|
129
|
+
| `Alert` / `Banner` | Alert messages and banners |
|
|
130
|
+
| `Progress` / `ProgressCircle` | Progress indicators |
|
|
131
|
+
| `Spinner` | Loading spinner |
|
|
132
|
+
| `Skeleton` | Loading skeleton placeholders |
|
|
133
|
+
| `EmptyState` | Empty state illustrations |
|
|
134
|
+
|
|
135
|
+
### Overlay
|
|
136
|
+
|
|
137
|
+
| Component | Description |
|
|
138
|
+
|-----------|-------------|
|
|
139
|
+
| `Modal` | Modal dialogs with Header, Body, Footer |
|
|
140
|
+
| `Tooltip` | Hover tooltips |
|
|
141
|
+
| `Popover` | Click-triggered popovers |
|
|
142
|
+
|
|
143
|
+
### Chat & AI
|
|
144
|
+
|
|
145
|
+
| Component | Description |
|
|
146
|
+
|-----------|-------------|
|
|
147
|
+
| `ChatMessage` | Chat message bubbles |
|
|
148
|
+
| `ChatInput` | Chat text input with actions |
|
|
149
|
+
| `ChatContainer` | Chat layout container |
|
|
150
|
+
| `ThinkingBlock` | AI thinking/processing indicator |
|
|
151
|
+
| `TypingIndicator` | Typing animation |
|
|
152
|
+
| `TaskCard` | Task status cards |
|
|
153
|
+
| `ResearchCard` | AI research response cards |
|
|
154
|
+
|
|
155
|
+
### Content
|
|
156
|
+
|
|
157
|
+
| Component | Description |
|
|
158
|
+
|-----------|-------------|
|
|
159
|
+
| `Hero` | Hero sections with search and actions |
|
|
160
|
+
| `SearchInput` | Search with suggestions |
|
|
161
|
+
| `ProjectPicker` | Project selection dropdown |
|
|
162
|
+
| `SourcesPanel` | Sources and files panel |
|
|
163
|
+
|
|
164
|
+
## Component API Examples
|
|
165
|
+
|
|
166
|
+
### SearchBox
|
|
167
|
+
|
|
168
|
+
```tsx
|
|
169
|
+
<SearchBox
|
|
170
|
+
placeholder="Search across all legal knowledge..."
|
|
171
|
+
value={searchValue}
|
|
172
|
+
onChange={(e) => setSearchValue(e.target.value)}
|
|
173
|
+
onSubmit={(value) => handleSearch(value)}
|
|
174
|
+
buttonText="Search"
|
|
175
|
+
size="md" // sm | md | lg
|
|
176
|
+
/>
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### FilterTabs
|
|
180
|
+
|
|
181
|
+
```tsx
|
|
182
|
+
<FilterTabs
|
|
183
|
+
items={[
|
|
184
|
+
{ id: 'all', label: 'All' },
|
|
185
|
+
{ id: 'legislation', label: 'Legislation', count: '2.4K' },
|
|
186
|
+
{ id: 'contracts', label: 'Contracts', count: '12K' },
|
|
187
|
+
]}
|
|
188
|
+
value={activeTab}
|
|
189
|
+
onChange={setActiveTab}
|
|
190
|
+
variant="pill" // pill | underline
|
|
191
|
+
/>
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### StatBlock & StatGrid
|
|
195
|
+
|
|
196
|
+
```tsx
|
|
197
|
+
<StatGrid columns={2}>
|
|
198
|
+
<StatBlock value="23K+" label="Documents" sublabel="across all domains" />
|
|
199
|
+
<StatBlock value="142K" label="Annotations" sublabel="community contributed" />
|
|
200
|
+
</StatGrid>
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
### CollectionCard
|
|
204
|
+
|
|
205
|
+
```tsx
|
|
206
|
+
<CollectionCard
|
|
207
|
+
type="legislation" // legislation | contracts | case-law | knowledge
|
|
208
|
+
badge="Legislation"
|
|
209
|
+
status="Active discussion"
|
|
210
|
+
title="US Federal Code - Annotated"
|
|
211
|
+
description="Complete USC with community annotations..."
|
|
212
|
+
stats={['54 titles', '34.2K annotations', '156 contributors']}
|
|
213
|
+
onClick={() => navigate('/collection/1')}
|
|
214
|
+
/>
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### ActivityFeed
|
|
218
|
+
|
|
219
|
+
```tsx
|
|
220
|
+
<ActivityFeed
|
|
221
|
+
items={[
|
|
222
|
+
{
|
|
223
|
+
id: 1,
|
|
224
|
+
name: 'Sarah Chen',
|
|
225
|
+
initials: 'SC',
|
|
226
|
+
avatarColor: '#3B82F6',
|
|
227
|
+
action: 'annotated',
|
|
228
|
+
target: 'Liability Clause Analysis',
|
|
229
|
+
time: '12m ago',
|
|
230
|
+
},
|
|
231
|
+
]}
|
|
232
|
+
viewAllUrl="/activity"
|
|
233
|
+
viewAllText="View all activity"
|
|
234
|
+
/>
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### ActionList
|
|
238
|
+
|
|
239
|
+
```tsx
|
|
240
|
+
<ActionList
|
|
241
|
+
items={[
|
|
242
|
+
{ id: 1, label: 'Upload document', icon: <UploadIcon /> },
|
|
243
|
+
{ id: 2, label: 'Join project', icon: <JoinIcon /> },
|
|
244
|
+
]}
|
|
245
|
+
variant="card" // default | card
|
|
246
|
+
onItemClick={(item) => console.log(item.label)}
|
|
247
|
+
/>
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Button
|
|
251
|
+
|
|
252
|
+
```tsx
|
|
253
|
+
<Button
|
|
254
|
+
variant="primary" // primary | secondary | ghost | danger
|
|
255
|
+
size="md" // sm | md | lg
|
|
256
|
+
loading={false}
|
|
257
|
+
fullWidth={false}
|
|
258
|
+
leftIcon={<Icon />}
|
|
259
|
+
disabled={false}
|
|
260
|
+
>
|
|
261
|
+
Label
|
|
262
|
+
</Button>
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Card
|
|
266
|
+
|
|
267
|
+
```tsx
|
|
268
|
+
<Card variant="elevated" padding="md">
|
|
269
|
+
<CardHeader
|
|
270
|
+
title="Title"
|
|
271
|
+
subtitle="Subtitle"
|
|
272
|
+
action={<Button size="sm">Action</Button>}
|
|
273
|
+
/>
|
|
274
|
+
<CardBody>Content here</CardBody>
|
|
275
|
+
<CardFooter>Footer actions</CardFooter>
|
|
276
|
+
</Card>
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## Design Principles
|
|
280
|
+
|
|
281
|
+
1. **Structure over decoration** — No heavy borders; shadows define boundaries
|
|
282
|
+
2. **Connections matter** — Visual elements show relationships between documents
|
|
283
|
+
3. **Light touch** — Subtle shadows (0.03-0.06 opacity), never harsh
|
|
284
|
+
4. **Professional precision** — Deep teal accent (`#0F766E`) conveys trust and expertise
|
|
285
|
+
|
|
286
|
+
## Color Palette
|
|
287
|
+
|
|
288
|
+
| Token | Value | Usage |
|
|
289
|
+
|-------|-------|-------|
|
|
290
|
+
| `--oc-accent` | `#0F766E` | Primary actions, active states, links |
|
|
291
|
+
| `--oc-accent-hover` | `#0D9488` | Hover state for accent elements |
|
|
292
|
+
| `--oc-fg-primary` | `#1E293B` | Primary text (slate-800) |
|
|
293
|
+
| `--oc-fg-secondary` | `#475569` | Secondary text (slate-600) |
|
|
294
|
+
| `--oc-fg-tertiary` | `#94A3B8` | Tertiary/muted text (slate-400) |
|
|
295
|
+
| `--oc-bg-canvas` | `#FAFAFA` | Page background |
|
|
296
|
+
| `--oc-bg-surface` | `#FFFFFF` | Card/surface backgrounds |
|
|
297
|
+
| `--oc-bg-sidebar` | `#0F172A` | Dark sidebar background |
|
|
298
|
+
| `--oc-border-default` | `#E2E8F0` | Default borders (slate-200) |
|
|
299
|
+
| `--oc-success` | `#059669` | Success states |
|
|
300
|
+
| `--oc-warning` | `#D97706` | Warning states |
|
|
301
|
+
| `--oc-error` | `#DC2626` | Error states |
|
|
302
|
+
|
|
303
|
+
## Typography
|
|
304
|
+
|
|
305
|
+
- **UI Text**: Inter (400, 500, 600, 700)
|
|
306
|
+
- **Headlines**: Georgia (serif) for editorial feel
|
|
307
|
+
- **Font Sizes**: xs (11px), sm (13px), md (15px), lg (17px), xl (20px)
|
|
308
|
+
|
|
309
|
+
## Spacing & Radius
|
|
310
|
+
|
|
311
|
+
| Token | Value |
|
|
312
|
+
|-------|-------|
|
|
313
|
+
| `--oc-spacing-xs` | 4px |
|
|
314
|
+
| `--oc-spacing-sm` | 8px |
|
|
315
|
+
| `--oc-spacing-md` | 16px |
|
|
316
|
+
| `--oc-spacing-lg` | 24px |
|
|
317
|
+
| `--oc-radius-sm` | 6px |
|
|
318
|
+
| `--oc-radius-md` | 8px |
|
|
319
|
+
| `--oc-radius-lg` | 12px |
|
|
320
|
+
|
|
321
|
+
## TypeScript
|
|
322
|
+
|
|
323
|
+
All components are fully typed. Import types as needed:
|
|
324
|
+
|
|
325
|
+
```tsx
|
|
326
|
+
import type {
|
|
327
|
+
ButtonProps,
|
|
328
|
+
CardProps,
|
|
329
|
+
SearchBoxProps,
|
|
330
|
+
FilterTabsProps,
|
|
331
|
+
CollectionCardProps,
|
|
332
|
+
} from '@opencontracts/ui';
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## Development
|
|
336
|
+
|
|
337
|
+
```bash
|
|
338
|
+
npm run dev # Watch mode
|
|
339
|
+
npm run build # Build library
|
|
340
|
+
npm run storybook # Start Storybook on port 6006
|
|
341
|
+
npm run lint # Run ESLint
|
|
342
|
+
npm run test # Run tests
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
## License
|
|
346
|
+
|
|
347
|
+
MIT © OpenContracts
|