@studiocms/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 +21 -0
- package/README.md +564 -0
- package/package.json +49 -0
- package/src/components/BaseHead.astro +22 -0
- package/src/components/Button.astro +338 -0
- package/src/components/Card.astro +62 -0
- package/src/components/Center.astro +16 -0
- package/src/components/Checkbox.astro +180 -0
- package/src/components/Divider.astro +39 -0
- package/src/components/Dropdown/Dropdown.astro +253 -0
- package/src/components/Dropdown/dropdown.ts +170 -0
- package/src/components/Dropdown/index.ts +2 -0
- package/src/components/Input.astro +93 -0
- package/src/components/Modal/Modal.astro +164 -0
- package/src/components/Modal/index.ts +2 -0
- package/src/components/Modal/modal.ts +129 -0
- package/src/components/RadioGroup.astro +175 -0
- package/src/components/Row.astro +38 -0
- package/src/components/SearchSelect.astro +430 -0
- package/src/components/Select.astro +334 -0
- package/src/components/Sidebar/Double.astro +91 -0
- package/src/components/Sidebar/Single.astro +42 -0
- package/src/components/Sidebar/helpers.ts +133 -0
- package/src/components/Sidebar/index.ts +3 -0
- package/src/components/Textarea.astro +102 -0
- package/src/components/ThemeToggle.astro +40 -0
- package/src/components/Toast/Toaster.astro +330 -0
- package/src/components/Toast/index.ts +2 -0
- package/src/components/Toast/toast.ts +16 -0
- package/src/components/Toggle.astro +146 -0
- package/src/components/User.astro +68 -0
- package/src/components/index.ts +25 -0
- package/src/components.ts +24 -0
- package/src/css/colors.css +106 -0
- package/src/css/global.css +2 -0
- package/src/css/resets.css +55 -0
- package/src/env.d.ts +15 -0
- package/src/icons/Checkmark.astro +13 -0
- package/src/icons/ChevronUpDown.astro +13 -0
- package/src/icons/User.astro +13 -0
- package/src/icons/X-Mark.astro +13 -0
- package/src/layouts/RootLayout.astro +34 -0
- package/src/layouts/index.ts +2 -0
- package/src/layouts.ts +1 -0
- package/src/types/index.ts +11 -0
- package/src/utils/Icon.astro +41 -0
- package/src/utils/ThemeHelper.ts +127 -0
- package/src/utils/colors.ts +1 -0
- package/src/utils/generateID.ts +5 -0
- package/src/utils/headers.ts +190 -0
- package/src/utils/iconStrings.ts +29 -0
- package/src/utils/iconType.ts +3 -0
- package/src/utils/index.ts +1 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 StudioCMS - Louis Escher
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,564 @@
|
|
|
1
|
+
# @studiocms/ui
|
|
2
|
+
|
|
3
|
+
This is the UI library that we use to build StudioCMS.
|
|
4
|
+
|
|
5
|
+
All of these components can be tested [here](https://ui-testing.studiocms.dev).
|
|
6
|
+
|
|
7
|
+
## Components & how to use them
|
|
8
|
+
All components are exported from `@studiocms/ui/components`.
|
|
9
|
+
|
|
10
|
+
### Button
|
|
11
|
+
A simple button component. Use it like this:
|
|
12
|
+
|
|
13
|
+
```html
|
|
14
|
+
<Button>Hello World!</Button>
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
You can pass the following props:
|
|
18
|
+
```ts
|
|
19
|
+
type Props = {
|
|
20
|
+
as?: As; // What the button should be rendered as. Set to "a" for an anchor tag, etc.
|
|
21
|
+
size?: 'sm' | 'md' | 'lg';
|
|
22
|
+
fullWidth?: boolean; // Make the button take up full width
|
|
23
|
+
color?: 'default' | 'primary' | 'success' | 'warning' | 'danger';
|
|
24
|
+
variant?: 'solid' | 'outlined' | 'flat';
|
|
25
|
+
class?: string;
|
|
26
|
+
disabled?: boolean;
|
|
27
|
+
// Note: you can pass all other HTML attributes and they will be applied.
|
|
28
|
+
};
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Card
|
|
32
|
+
A simple card component with support for a header and footer. Use it like this:
|
|
33
|
+
```html
|
|
34
|
+
<Card>
|
|
35
|
+
<div slot="header">Header Content</div>
|
|
36
|
+
<div>Body Content</div> <!-- No slot definition needed for the body! -->
|
|
37
|
+
<div slot="footer">Footer Content</div>
|
|
38
|
+
</Card>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
You can pass the following props:
|
|
42
|
+
```ts
|
|
43
|
+
type Props = {
|
|
44
|
+
as?: As;
|
|
45
|
+
class?: string;
|
|
46
|
+
fullWidth?: boolean;
|
|
47
|
+
fullHeight?: boolean;
|
|
48
|
+
};
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Center
|
|
52
|
+
A component that automatically centers all of it's content. Use it like this:
|
|
53
|
+
```html
|
|
54
|
+
<Center>Content in here will be centered!</Center>
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Checkbox
|
|
58
|
+
A checkbox component. Use it like this:
|
|
59
|
+
```html
|
|
60
|
+
<Checkbox
|
|
61
|
+
label="Label"
|
|
62
|
+
/>
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
You can pass the following props:
|
|
66
|
+
```ts
|
|
67
|
+
type Props = {
|
|
68
|
+
label: string;
|
|
69
|
+
size?: 'sm' | 'md' | 'lg';
|
|
70
|
+
color?: 'default' | 'primary' | 'success' | 'warning' | 'danger';
|
|
71
|
+
defaultChecked?: boolean;
|
|
72
|
+
disabled?: boolean;
|
|
73
|
+
name?: string; // If you want to use this in forms. If unset, a name will be auto-generated.
|
|
74
|
+
isRequired?: boolean;
|
|
75
|
+
};
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Divider
|
|
79
|
+
A simple divider. Use it like this:
|
|
80
|
+
```html
|
|
81
|
+
<Divider>Divider Label</Divider>
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Dropdown
|
|
85
|
+
A dropdown component. Use it like this:
|
|
86
|
+
```html
|
|
87
|
+
<Dropdown
|
|
88
|
+
options={[
|
|
89
|
+
{ label: 'Option 1', value: 'opt-1' },
|
|
90
|
+
{ label: 'Option 2', value: 'opt-2' },
|
|
91
|
+
]}
|
|
92
|
+
id='dropdown'
|
|
93
|
+
>
|
|
94
|
+
<div slot="icon-start"><!-- Icon goes here --></div>
|
|
95
|
+
<div>Your Trigger goes here!</div>
|
|
96
|
+
<div slot="icon-end"><!-- Icon goes here --></div>
|
|
97
|
+
</Dropdown>
|
|
98
|
+
```
|
|
99
|
+
**This component needs a helper to function.** Add it in a script tag:
|
|
100
|
+
```html
|
|
101
|
+
<script>
|
|
102
|
+
import { DropdownHelper } from "@studiocms/ui/components";
|
|
103
|
+
|
|
104
|
+
const dropdown1 = new DropdownHelper('dropdown-1');
|
|
105
|
+
dropdown1.registerClickCallback((value) => {
|
|
106
|
+
// "value" will be what you put in the options.
|
|
107
|
+
// When an option is clicked, it will supply its value here
|
|
108
|
+
console.log(value);
|
|
109
|
+
});
|
|
110
|
+
</script>
|
|
111
|
+
```
|
|
112
|
+
You can pass the following props:
|
|
113
|
+
```ts
|
|
114
|
+
type Option = {
|
|
115
|
+
label: string;
|
|
116
|
+
value: string;
|
|
117
|
+
disabled?: boolean;
|
|
118
|
+
color?: 'default' | 'primary' | 'success' | 'warning' | 'danger';
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
type Props = {
|
|
122
|
+
id: string;
|
|
123
|
+
options: Option[];
|
|
124
|
+
disabled?: boolean;
|
|
125
|
+
align?: 'start' | 'center' | 'end';
|
|
126
|
+
triggerOn?: 'left' | 'right' | 'both';
|
|
127
|
+
};
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
### Input
|
|
131
|
+
A text input. Use it like this:
|
|
132
|
+
```html
|
|
133
|
+
<Input />
|
|
134
|
+
```
|
|
135
|
+
You can pass the following props:
|
|
136
|
+
```ts
|
|
137
|
+
type Props = {
|
|
138
|
+
label?: string;
|
|
139
|
+
type?: 'text' | 'password';
|
|
140
|
+
placeholder?: string;
|
|
141
|
+
isRequired?: boolean;
|
|
142
|
+
name?: string;
|
|
143
|
+
disabled?: boolean;
|
|
144
|
+
defaultValue?: string;
|
|
145
|
+
class?: string;
|
|
146
|
+
};
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### Modal
|
|
150
|
+
A modal component with form support. Use it like this:
|
|
151
|
+
```html
|
|
152
|
+
<Modal id="modal">
|
|
153
|
+
<!-- This component has a header slot! Use it like this: -->
|
|
154
|
+
<h2 slot="header">Header content</h2>
|
|
155
|
+
<div>Modal content</div>
|
|
156
|
+
</Modal>
|
|
157
|
+
<Button id="modal-trigger">Open Modal</Button>
|
|
158
|
+
```
|
|
159
|
+
**This component needs a helper to function.** Add it in a script tag:
|
|
160
|
+
```html
|
|
161
|
+
<script>
|
|
162
|
+
import { ModalHelper } from "@studiocms/ui/components";
|
|
163
|
+
|
|
164
|
+
const modal = new ModalHelper('modal');
|
|
165
|
+
modal.bindTrigger('modal-trigger');
|
|
166
|
+
</script>
|
|
167
|
+
```
|
|
168
|
+
You can make the modal a form and also display "confirm" and "cancel" buttons individually:
|
|
169
|
+
```html
|
|
170
|
+
<Modal id="modal" isForm buttons={['confirm', 'cancel']}>
|
|
171
|
+
<h2 slot="header">Header content</h2>
|
|
172
|
+
<div>Modal content</div>
|
|
173
|
+
</Modal>
|
|
174
|
+
<Button id="modal-trigger">Open Modal</Button>
|
|
175
|
+
```
|
|
176
|
+
*Note: The order in which you supply the buttons does not change the buttons order in the modal.*
|
|
177
|
+
|
|
178
|
+
After adding a button, you can register a callback that will be fired when a button is clicked. If you made the modal a form, this will also give you a way to access the form data:
|
|
179
|
+
```html
|
|
180
|
+
<script>
|
|
181
|
+
import { ModalHelper } from "@studiocms/ui/components";
|
|
182
|
+
|
|
183
|
+
const modal = new ModalHelper('modal');
|
|
184
|
+
modal.bindTrigger('modal-trigger');
|
|
185
|
+
|
|
186
|
+
// The cancel callback will not be supplied the formData, even if you made the modal a form.
|
|
187
|
+
modal.registerCancelCallback(() => {
|
|
188
|
+
// Your cancellation logic
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// formData will be undefined unless you set the isForm prop!
|
|
192
|
+
modal.registerConfirmCallback((formData) => {
|
|
193
|
+
// Your confirmation logic
|
|
194
|
+
});
|
|
195
|
+
</script>
|
|
196
|
+
```
|
|
197
|
+
You can pass the following props:
|
|
198
|
+
```ts
|
|
199
|
+
type Props = {
|
|
200
|
+
id: string;
|
|
201
|
+
size?: 'sm' | 'md' | 'lg';
|
|
202
|
+
dismissable?: boolean;
|
|
203
|
+
buttons?: ('confirm' | 'cancel')[];
|
|
204
|
+
isForm?: boolean;
|
|
205
|
+
};
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### RadioGroup
|
|
209
|
+
A radio group. Use it like this:
|
|
210
|
+
```html
|
|
211
|
+
<RadioGroup
|
|
212
|
+
label="Label"
|
|
213
|
+
options={[
|
|
214
|
+
{ label: "Option 1", value: "opt-1" },
|
|
215
|
+
{ label: "Option 2", value: "opt-2" },
|
|
216
|
+
{ label: "Option 3", value: "opt-3" }
|
|
217
|
+
]}
|
|
218
|
+
/>
|
|
219
|
+
```
|
|
220
|
+
You can pass the following props:
|
|
221
|
+
```ts
|
|
222
|
+
type Option = {
|
|
223
|
+
label: string;
|
|
224
|
+
value: string;
|
|
225
|
+
disabled?: boolean;
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
type Props = {
|
|
229
|
+
label: string;
|
|
230
|
+
options: Option[];
|
|
231
|
+
color?: 'default' | 'primary' | 'success' | 'warning' | 'danger';
|
|
232
|
+
defaultValue?: string; // Needs to be the value of an option!
|
|
233
|
+
disabled?: boolean;
|
|
234
|
+
name?: string;
|
|
235
|
+
isRequired?: boolean;
|
|
236
|
+
horizontal?: boolean;
|
|
237
|
+
class?: string;
|
|
238
|
+
};
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Row
|
|
242
|
+
A simple row component, essentially a flex div to wrap stuff in. Use it like this:
|
|
243
|
+
```html
|
|
244
|
+
<Row>
|
|
245
|
+
<Button>These two will be...</Button>
|
|
246
|
+
<Button>in a row!</Button>
|
|
247
|
+
</Row>
|
|
248
|
+
```
|
|
249
|
+
You can pass the following props:
|
|
250
|
+
```ts
|
|
251
|
+
type Props = {
|
|
252
|
+
alignCenter?: boolean;
|
|
253
|
+
gapSize?: 'sm' | 'md' | 'lg';
|
|
254
|
+
};
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Select
|
|
258
|
+
A select component. Use it like this:
|
|
259
|
+
```html
|
|
260
|
+
<Select
|
|
261
|
+
label='Select'
|
|
262
|
+
options={[
|
|
263
|
+
{ label: "Option 1", value: "opt-1" },
|
|
264
|
+
{ label: "Option 2", value: "opt-2" },
|
|
265
|
+
{ label: "Option 3", value: "opt-3" },
|
|
266
|
+
]}
|
|
267
|
+
/>
|
|
268
|
+
```
|
|
269
|
+
You can pass the following props:
|
|
270
|
+
```ts
|
|
271
|
+
type Option = {
|
|
272
|
+
label: string;
|
|
273
|
+
value: string;
|
|
274
|
+
disabled?: boolean;
|
|
275
|
+
};
|
|
276
|
+
|
|
277
|
+
type Props = {
|
|
278
|
+
label?: string;
|
|
279
|
+
defaultValue?: string;
|
|
280
|
+
class?: string;
|
|
281
|
+
name?: string;
|
|
282
|
+
isRequired?: boolean;
|
|
283
|
+
options: Option[];
|
|
284
|
+
disabled?: boolean;
|
|
285
|
+
fullWidth?: boolean;
|
|
286
|
+
};
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
### Sidebar
|
|
290
|
+
The sidebar comes in two flavors: single and double. **Each requires a helper and functions slightly differently.** We recommend you use these in a layout. If you do, make sure to make the sidebar's parent a flex-div with `flex-direction: row` and set it to `height: 100vh` or `height: 100dvh`. The sidebar might not work correctly otherwise.
|
|
291
|
+
|
|
292
|
+
#### Single Sidebar
|
|
293
|
+
The layout of your page should look similar to this:
|
|
294
|
+
```html
|
|
295
|
+
<main>
|
|
296
|
+
<Sidebar>
|
|
297
|
+
Sidebar Content (anchor tags etc.)
|
|
298
|
+
</Sidebar>
|
|
299
|
+
<div class="content">
|
|
300
|
+
<!--
|
|
301
|
+
This will be the trigger for your sidebar.
|
|
302
|
+
You can use whatever you want here, like an icon.
|
|
303
|
+
We recommend placing this in the upper left corner of the screen.
|
|
304
|
+
-->
|
|
305
|
+
<Button id='sidebar-toggle'>
|
|
306
|
+
Sidebar toggle.
|
|
307
|
+
</Button>
|
|
308
|
+
|
|
309
|
+
<slot /> <!-- The slot for your content -->
|
|
310
|
+
</div>
|
|
311
|
+
</main>
|
|
312
|
+
<style>
|
|
313
|
+
.main {
|
|
314
|
+
width: 100vw;
|
|
315
|
+
height: 100vh;
|
|
316
|
+
overflow: hidden;
|
|
317
|
+
display: flex;
|
|
318
|
+
flex-direction: row;
|
|
319
|
+
align-items: center;
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
.content {
|
|
323
|
+
width: 100%;
|
|
324
|
+
height: 100%;
|
|
325
|
+
display: flex;
|
|
326
|
+
align-items: center;
|
|
327
|
+
justify-content: center;
|
|
328
|
+
text-align: center;
|
|
329
|
+
position: relative;
|
|
330
|
+
}
|
|
331
|
+
</style>
|
|
332
|
+
<script>
|
|
333
|
+
import { SingleSidebarHelper } from "@studiocms/ui/components";
|
|
334
|
+
|
|
335
|
+
// Use the ID of your trigger here!
|
|
336
|
+
new SingleSidebarHelper('sidebar-toggle');
|
|
337
|
+
</script>
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
We recommend you use the same button to both show and hide the sidebar, and that you hide it on devides with a screen size larger than `840px`.
|
|
341
|
+
|
|
342
|
+
If needed, it is possible to register elements to open / close the sidebar manually:
|
|
343
|
+
```html
|
|
344
|
+
<script>
|
|
345
|
+
import { SingleSidebarHelper } from "@studiocms/ui/components";
|
|
346
|
+
|
|
347
|
+
const sidebar = new SingleSidebarHelper();
|
|
348
|
+
|
|
349
|
+
// Use the IDs of the respective elements here:
|
|
350
|
+
sidebar.hideSidebarOnClick('another-elements-id');
|
|
351
|
+
sidebar.showSidebarOnClick('another-elements-id');
|
|
352
|
+
</script>
|
|
353
|
+
```
|
|
354
|
+
You can even just use the barebones function calls if you need to close the sidebar programatically:
|
|
355
|
+
```html
|
|
356
|
+
<script>
|
|
357
|
+
import { SingleSidebarHelper } from "@studiocms/ui/components";
|
|
358
|
+
|
|
359
|
+
const sidebar = new SingleSidebarHelper();
|
|
360
|
+
|
|
361
|
+
sidebar.hideSidebar();
|
|
362
|
+
sidebar.showSidebar();
|
|
363
|
+
</script>
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
#### Double Sidebar
|
|
367
|
+
When using the double sidebar, the layout of your page should look similar to this:
|
|
368
|
+
```html
|
|
369
|
+
<main class="main">
|
|
370
|
+
<DoubleSidebar>
|
|
371
|
+
<div slot="outer" class="outer">
|
|
372
|
+
<Button id='to-inner'>
|
|
373
|
+
To Inner Sidebar
|
|
374
|
+
</Button>
|
|
375
|
+
</div>
|
|
376
|
+
<div slot="inner">
|
|
377
|
+
<Button id='to-outer'>
|
|
378
|
+
To Outer Sidebar
|
|
379
|
+
</Button>
|
|
380
|
+
<Button id='to-content'>
|
|
381
|
+
To Content
|
|
382
|
+
</Button>
|
|
383
|
+
</div>
|
|
384
|
+
</DoubleSidebar>
|
|
385
|
+
<div class="content">
|
|
386
|
+
<Button id='sidebar-toggle'>
|
|
387
|
+
Sidebar toggle.
|
|
388
|
+
</Button>
|
|
389
|
+
<slot />
|
|
390
|
+
</div>
|
|
391
|
+
</main>
|
|
392
|
+
<style>
|
|
393
|
+
.main {
|
|
394
|
+
width: 100vw;
|
|
395
|
+
height: 100vh;
|
|
396
|
+
overflow: hidden;
|
|
397
|
+
display: flex;
|
|
398
|
+
flex-direction: row;
|
|
399
|
+
align-items: center;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
.content {
|
|
403
|
+
width: 100%;
|
|
404
|
+
height: 100%;
|
|
405
|
+
display: flex;
|
|
406
|
+
align-items: center;
|
|
407
|
+
justify-content: center;
|
|
408
|
+
text-align: center;
|
|
409
|
+
}
|
|
410
|
+
</style>
|
|
411
|
+
<script>
|
|
412
|
+
import { DoubleSidebarHelper } from "@studiocms/ui/components";
|
|
413
|
+
|
|
414
|
+
// The helper. Pass in the initial sidebar trigger id and the
|
|
415
|
+
// id for the button to switch from inner to outer sidebar on
|
|
416
|
+
// mobile devices.
|
|
417
|
+
const dbsb = new DoubleSidebarHelper('sidebar-toggle', 'to-outer');
|
|
418
|
+
|
|
419
|
+
// The id for the element to show the inner sidebar when clicked.
|
|
420
|
+
// Should be used when the user is currently on the outer sidebar
|
|
421
|
+
// and needs to switch to the inner.
|
|
422
|
+
dbsb.showInnerOnClick('to-inner');
|
|
423
|
+
|
|
424
|
+
// The id for the element to show the content on click. Should
|
|
425
|
+
// be used from the inner sidebar when the user wants to see the
|
|
426
|
+
// page content.
|
|
427
|
+
dbsb.showContentOnClick('to-content');
|
|
428
|
+
</script>
|
|
429
|
+
```
|
|
430
|
+
The double sidebar, like the single sidebar, supports individual function calls to show and hide the outer or inner navbars programatically:
|
|
431
|
+
|
|
432
|
+
```html
|
|
433
|
+
<script>
|
|
434
|
+
import { DoubleSidebarHelper } from "@studiocms/ui/components";
|
|
435
|
+
|
|
436
|
+
const sidebar = new DoubleSidebarHelper('sidebar-toggle', 'to-outer');
|
|
437
|
+
|
|
438
|
+
sidebar.hideSidebar();
|
|
439
|
+
sidebar.showInnerSidebar();
|
|
440
|
+
sidebar.showOuterSidebar();
|
|
441
|
+
</script>
|
|
442
|
+
```
|
|
443
|
+
*Note: The API (especially for the double sidebar) is highly likely to change to make it easier to use.*
|
|
444
|
+
|
|
445
|
+
### Textarea
|
|
446
|
+
A simple textarea component. Use it like this:
|
|
447
|
+
```html
|
|
448
|
+
<Textarea />
|
|
449
|
+
```
|
|
450
|
+
You can pass the following props:
|
|
451
|
+
```ts
|
|
452
|
+
type Props = {
|
|
453
|
+
label?: string;
|
|
454
|
+
placeholder?: string;
|
|
455
|
+
isRequired?: boolean;
|
|
456
|
+
fullWidth?: boolean;
|
|
457
|
+
resize?: boolean;
|
|
458
|
+
name?: string;
|
|
459
|
+
disabled?: boolean;
|
|
460
|
+
defaultValue?: string;
|
|
461
|
+
};
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### Toast
|
|
465
|
+
A component and helper for toasts. Use the component like this *(we recommend placing it in a layout)*:
|
|
466
|
+
```html
|
|
467
|
+
<Toaster />
|
|
468
|
+
```
|
|
469
|
+
You can pass the following props to the `<Toaster />` component:
|
|
470
|
+
```ts
|
|
471
|
+
type Props = {
|
|
472
|
+
position?:
|
|
473
|
+
| 'top-left'
|
|
474
|
+
| 'top-right'
|
|
475
|
+
| 'top-center'
|
|
476
|
+
| 'bottom-left'
|
|
477
|
+
| 'bottom-right'
|
|
478
|
+
| 'bottom-center';
|
|
479
|
+
class?: string;
|
|
480
|
+
duration?: number;
|
|
481
|
+
expand?: boolean;
|
|
482
|
+
closeButton?: boolean;
|
|
483
|
+
offset?: number;
|
|
484
|
+
gap?: number;
|
|
485
|
+
};
|
|
486
|
+
```
|
|
487
|
+
**This component needs a helper to function.** You can create toasts from a script tag:
|
|
488
|
+
```html
|
|
489
|
+
<script>
|
|
490
|
+
import { toast } from '@studiocms/ui/components';
|
|
491
|
+
|
|
492
|
+
toast({
|
|
493
|
+
title: "Toast Title",
|
|
494
|
+
type: 'info',
|
|
495
|
+
});
|
|
496
|
+
</script>
|
|
497
|
+
```
|
|
498
|
+
Only a title and a type are required to create a toast. However, you can pass the following options to customize it a little more:
|
|
499
|
+
```ts
|
|
500
|
+
type Props = {
|
|
501
|
+
title: string;
|
|
502
|
+
type: 'success' | 'warning' | 'danger' | 'info';
|
|
503
|
+
description?: string;
|
|
504
|
+
duration?: number;
|
|
505
|
+
closeButton?: boolean;
|
|
506
|
+
persistent?: boolean; // When set to true, you MUST set "closeButton" to true as well.
|
|
507
|
+
};
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
### Toggle
|
|
511
|
+
A toggle component, essentially a checkbox with different design. Use it like this:
|
|
512
|
+
```html
|
|
513
|
+
<Toggle label='Label' />
|
|
514
|
+
```
|
|
515
|
+
You can pass the following props:
|
|
516
|
+
```ts
|
|
517
|
+
type Props = {
|
|
518
|
+
label: string;
|
|
519
|
+
size?: 'sm' | 'md' | 'lg';
|
|
520
|
+
color?: 'default' | 'primary' | 'success' | 'warning' | 'danger';
|
|
521
|
+
defaultChecked?: boolean;
|
|
522
|
+
disabled?: boolean;
|
|
523
|
+
name?: string;
|
|
524
|
+
isRequired?: boolean;
|
|
525
|
+
};
|
|
526
|
+
```
|
|
527
|
+
|
|
528
|
+
### User
|
|
529
|
+
A helper to display a user. Use it like this:
|
|
530
|
+
```html
|
|
531
|
+
<User
|
|
532
|
+
name="Louis Escher"
|
|
533
|
+
description='UI/UX & Developer'
|
|
534
|
+
/>
|
|
535
|
+
```
|
|
536
|
+
Optionally, you can pass an avatar to be shown instead of the default placeholder, and also pass a class name for the container:
|
|
537
|
+
```html
|
|
538
|
+
<User
|
|
539
|
+
name='Louis Escher'
|
|
540
|
+
description='UI/UX & Developer'
|
|
541
|
+
avatar='https://avatars.githubusercontent.com/u/66965600?v=4'
|
|
542
|
+
class="mt-4"
|
|
543
|
+
/>
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
## Planned
|
|
547
|
+
|
|
548
|
+
### Based on popover API
|
|
549
|
+
- Tooltips based on popover & anchor positioning API (not supported at time of writing, needs a custom solution)
|
|
550
|
+
- Date Picker
|
|
551
|
+
|
|
552
|
+
### Loading Stuff
|
|
553
|
+
- Skeleton
|
|
554
|
+
- Spinners
|
|
555
|
+
|
|
556
|
+
### Other Stuff
|
|
557
|
+
- Image dropzone
|
|
558
|
+
|
|
559
|
+
### Otter Stuff
|
|
560
|
+
- Markdown editor (WYSIWYG (thanks Otter <3))
|
|
561
|
+
|
|
562
|
+
### Maybe's
|
|
563
|
+
- Implement tailwind's prose
|
|
564
|
+
- Maybe starlight props.css
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@studiocms/ui",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "The UI library for StudioCMS. Includes the layouts & components we use to build StudioCMS.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/withstudiocms/ui.git"
|
|
8
|
+
},
|
|
9
|
+
"author": {
|
|
10
|
+
"name": "Louis Escher",
|
|
11
|
+
"url": "https://studiocms.dev"
|
|
12
|
+
},
|
|
13
|
+
"contributors": [
|
|
14
|
+
"louisescher"
|
|
15
|
+
],
|
|
16
|
+
"keywords": [
|
|
17
|
+
"astro-studiocms",
|
|
18
|
+
"cms",
|
|
19
|
+
"studiocms"
|
|
20
|
+
],
|
|
21
|
+
"homepage": "https://ui.studiocms.dev",
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
},
|
|
25
|
+
"sideEffects": false,
|
|
26
|
+
"files": [
|
|
27
|
+
"src"
|
|
28
|
+
],
|
|
29
|
+
"license": "MIT",
|
|
30
|
+
"type": "module",
|
|
31
|
+
"exports": {
|
|
32
|
+
"./components": "./src/components.ts",
|
|
33
|
+
"./layouts": "./src/layouts.ts",
|
|
34
|
+
"./css/*": "./src/css/*",
|
|
35
|
+
"./utils/*": "./src/utils/*",
|
|
36
|
+
"./types": "./src/types/index.ts"
|
|
37
|
+
},
|
|
38
|
+
"dependencies": {
|
|
39
|
+
"@fontsource-variable/onest": "5.1.0",
|
|
40
|
+
"@iconify/utils": "^2.1.33",
|
|
41
|
+
"@iconify-json/heroicons": "^1.2.1"
|
|
42
|
+
},
|
|
43
|
+
"peerDependencies": {
|
|
44
|
+
"astro": "^4.5 || ^5.0.0-beta.0"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"typescript": "^5.7.2"
|
|
48
|
+
}
|
|
49
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { type HeadConfig, createHead, headDefaults } from '../utils/headers';
|
|
3
|
+
|
|
4
|
+
export interface Props {
|
|
5
|
+
title: string;
|
|
6
|
+
description: string;
|
|
7
|
+
headers?: HeadConfig | undefined;
|
|
8
|
+
image?: string | undefined;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
const { title, description, image, headers: userHeaders } = Astro.props;
|
|
12
|
+
|
|
13
|
+
const canonicalURL = Astro.site ? new URL(Astro.url.pathname, Astro.site) : undefined;
|
|
14
|
+
|
|
15
|
+
// This should probably be removed from the UI lib at some point
|
|
16
|
+
const defaultHeaders = headDefaults(title, description, Astro, image, canonicalURL);
|
|
17
|
+
|
|
18
|
+
const head = createHead(defaultHeaders, userHeaders || []);
|
|
19
|
+
---
|
|
20
|
+
{head.map(({ tag: Tag, attrs, content }) => (
|
|
21
|
+
<Tag {...attrs} set:html={content} />
|
|
22
|
+
))}
|