@pienter/ui 0.11.0 → 0.14.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/CHANGELOG.md +96 -0
- package/CONVENTIONS.md +17 -0
- package/components/form/block-editor/BlockEditor.vue +61 -44
- package/components/form/block-editor/block-editor.css +11 -0
- package/components/form/checkbox/Checkbox.vue +23 -7
- package/components/form/checkbox/checkbox.css +12 -0
- package/components/form/combobox/Combobox.vue +9 -2
- package/components/form/date-input/DateInput.vue +5 -0
- package/components/form/form/Form.vue +5 -2
- package/components/form/number-field/NumberField.vue +8 -3
- package/components/form/number-field/number-field.css +6 -0
- package/components/form/radio-group/RadioGroup.vue +23 -1
- package/components/form/radio-group/radio-group.css +9 -0
- package/components/form/record-form/RecordFields.vue +40 -2
- package/components/form/record-form/RecordForm.vue +7 -1
- package/components/form/record-form/record-form.css +14 -0
- package/components/form/record-form/types.ts +6 -0
- package/components/form/select/Select.vue +32 -6
- package/components/form/select/select.css +5 -0
- package/components/form/switch/Switch.vue +23 -7
- package/components/form/switch/switch.css +8 -0
- package/components/form/tags-input/TagsInput.vue +11 -5
- package/components/form/tags-input/tags-input.css +5 -0
- package/components/form/text-input/TextInput.vue +6 -1
- package/components/form/textarea/Textarea.vue +6 -1
- package/components/form/textarea/textarea.css +7 -0
- package/components/layout/app-layout/app-layout.css +15 -13
- package/components/layout/record-layout/Panel.vue +44 -0
- package/components/layout/record-layout/RecordLayout.vue +35 -0
- package/components/layout/record-layout/record-layout.css +94 -0
- package/components/navigation/tabs/tabs.css +2 -0
- package/icons/index.ts +4 -0
- package/icons/sidebar-left.ts +1 -0
- package/icons/sidebar-right.ts +1 -0
- package/package.json +3 -1
- package/styles/4-components/form-field.css +7 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<section class="pui-panel">
|
|
3
|
+
<header v-if="title || description" class="pui-panel__header">
|
|
4
|
+
<component
|
|
5
|
+
:is="`h${level}`"
|
|
6
|
+
v-if="title"
|
|
7
|
+
:id="titleId"
|
|
8
|
+
class="pui-panel__title"
|
|
9
|
+
>{{ title }}</component
|
|
10
|
+
>
|
|
11
|
+
<p v-if="description" class="pui-panel__description">
|
|
12
|
+
{{ description }}
|
|
13
|
+
</p>
|
|
14
|
+
</header>
|
|
15
|
+
<slot />
|
|
16
|
+
</section>
|
|
17
|
+
</template>
|
|
18
|
+
|
|
19
|
+
<script setup lang="ts">
|
|
20
|
+
withDefaults(
|
|
21
|
+
defineProps<{
|
|
22
|
+
title?: string;
|
|
23
|
+
description?: string;
|
|
24
|
+
/** Heading level of the title: `2` under a page heading, `3` under another section. */
|
|
25
|
+
level?: 2 | 3;
|
|
26
|
+
/** `id` for the title element, so the panel or a landmark can reference it through `aria-labelledby`. */
|
|
27
|
+
titleId?: string;
|
|
28
|
+
}>(),
|
|
29
|
+
{
|
|
30
|
+
title: undefined,
|
|
31
|
+
description: undefined,
|
|
32
|
+
level: 2,
|
|
33
|
+
titleId: undefined,
|
|
34
|
+
},
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
defineSlots<{
|
|
38
|
+
default?: () => unknown;
|
|
39
|
+
}>();
|
|
40
|
+
</script>
|
|
41
|
+
|
|
42
|
+
<style>
|
|
43
|
+
@import './record-layout.css';
|
|
44
|
+
</style>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="pui-record-layout">
|
|
3
|
+
<aside
|
|
4
|
+
v-if="$slots.sidebar"
|
|
5
|
+
class="pui-record-layout__sidebar"
|
|
6
|
+
:aria-labelledby="sidebarLabelledby"
|
|
7
|
+
>
|
|
8
|
+
<slot name="sidebar" />
|
|
9
|
+
</aside>
|
|
10
|
+
<div class="pui-record-layout__main">
|
|
11
|
+
<slot />
|
|
12
|
+
</div>
|
|
13
|
+
</div>
|
|
14
|
+
</template>
|
|
15
|
+
|
|
16
|
+
<script setup lang="ts">
|
|
17
|
+
withDefaults(
|
|
18
|
+
defineProps<{
|
|
19
|
+
/** `id` of the sidebar's heading; names the `<aside>` landmark through `aria-labelledby`. */
|
|
20
|
+
sidebarLabelledby?: string;
|
|
21
|
+
}>(),
|
|
22
|
+
{
|
|
23
|
+
sidebarLabelledby: undefined,
|
|
24
|
+
},
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
defineSlots<{
|
|
28
|
+
sidebar?: () => unknown;
|
|
29
|
+
default?: () => unknown;
|
|
30
|
+
}>();
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<style>
|
|
34
|
+
@import './record-layout.css';
|
|
35
|
+
</style>
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
@layer components {
|
|
2
|
+
.pui-record-layout {
|
|
3
|
+
display: grid;
|
|
4
|
+
grid-template-columns:
|
|
5
|
+
minmax(0, var(--space-sidebar-width))
|
|
6
|
+
minmax(0, 1fr);
|
|
7
|
+
gap: var(--space-m);
|
|
8
|
+
align-items: start;
|
|
9
|
+
min-inline-size: 0;
|
|
10
|
+
|
|
11
|
+
@media (max-width: 56em) {
|
|
12
|
+
grid-template-columns: minmax(0, 1fr);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
.pui-record-layout__sidebar {
|
|
17
|
+
min-inline-size: 0;
|
|
18
|
+
|
|
19
|
+
& .pui-panel {
|
|
20
|
+
--pui-record-fields-columns: minmax(0, 1fr);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/* Same layer as record-details.css, so this has to outrank its field rule. */
|
|
24
|
+
& .pui-record-details .pui-record-details__field {
|
|
25
|
+
grid-template-columns: minmax(0, 1fr);
|
|
26
|
+
gap: var(--space-3xs);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
@media (min-width: 24em) and (max-width: 56em) {
|
|
30
|
+
& .pui-panel {
|
|
31
|
+
--pui-record-fields-columns: repeat(2, minmax(0, 1fr));
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.pui-record-layout__main {
|
|
37
|
+
display: grid;
|
|
38
|
+
gap: var(--space-s);
|
|
39
|
+
min-inline-size: 0;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.pui-panel {
|
|
43
|
+
--pui-record-fields-columns: minmax(0, 1fr);
|
|
44
|
+
|
|
45
|
+
display: grid;
|
|
46
|
+
gap: var(--space-s);
|
|
47
|
+
min-inline-size: 0;
|
|
48
|
+
padding: var(--space-m);
|
|
49
|
+
border: var(--stroke-sm) solid var(--border-clr-subtle);
|
|
50
|
+
border-radius: var(--radius-md);
|
|
51
|
+
background: var(--bg-clr-surface);
|
|
52
|
+
|
|
53
|
+
&[hidden] {
|
|
54
|
+
display: none;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
& .pui-field:has(textarea) {
|
|
58
|
+
grid-column: 1 / -1;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/* An editable block list draws its own boxes and needs the width for
|
|
62
|
+
* its controls; a read-only one is content and keeps the panel. */
|
|
63
|
+
&:has(> .pui-block-editor:not([data-readonly='true'])) {
|
|
64
|
+
padding: var(--space-2xs) 0 0;
|
|
65
|
+
border: 0;
|
|
66
|
+
background: transparent;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
@media (min-width: 48em) {
|
|
70
|
+
--pui-record-fields-columns: repeat(2, minmax(0, 1fr));
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@media (max-width: 56em) {
|
|
74
|
+
padding: var(--space-s);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
.pui-panel__header {
|
|
79
|
+
display: grid;
|
|
80
|
+
gap: var(--space-3xs);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.pui-panel__title {
|
|
84
|
+
margin: 0;
|
|
85
|
+
font-size: var(--step-0);
|
|
86
|
+
font-weight: var(--fw-semibold);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.pui-panel__description {
|
|
90
|
+
margin: 0;
|
|
91
|
+
font-size: var(--step--1);
|
|
92
|
+
color: var(--text-clr-muted);
|
|
93
|
+
}
|
|
94
|
+
}
|
package/icons/index.ts
CHANGED
|
@@ -41,6 +41,8 @@ import send from './send.js';
|
|
|
41
41
|
import settings from './settings.js';
|
|
42
42
|
import tool from './tool.js';
|
|
43
43
|
import trash from './trash.js';
|
|
44
|
+
import sidebarLeft from './sidebar-left.js';
|
|
45
|
+
import sidebarRight from './sidebar-right.js';
|
|
44
46
|
|
|
45
47
|
export const icons = {
|
|
46
48
|
info: info,
|
|
@@ -86,6 +88,8 @@ export const icons = {
|
|
|
86
88
|
settings: settings,
|
|
87
89
|
tool: tool,
|
|
88
90
|
trash: trash,
|
|
91
|
+
'sidebar-left': sidebarLeft,
|
|
92
|
+
'sidebar-right': sidebarRight,
|
|
89
93
|
} as const;
|
|
90
94
|
|
|
91
95
|
export type IconName = keyof typeof icons;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="var(--pui-icon-clr, currentColor)" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24"><rect width="18" height="18" x="3" y="3" rx="2" ry="2"/><path d="M9 3v18"/></svg>';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none" stroke="var(--pui-icon-clr, currentColor)" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" viewBox="0 0 24 24"><rect width="18" height="18" x="3" y="3" rx="2" ry="2"/><path d="M15 3v18"/></svg>';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pienter/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Shared Pienter UI components, styles, icons, and browser utilities.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -64,6 +64,8 @@
|
|
|
64
64
|
"./components/Collapsible.vue": "./components/layout/collapsible/Collapsible.vue",
|
|
65
65
|
"./components/AppLayout.vue": "./components/layout/app-layout/AppLayout.vue",
|
|
66
66
|
"./components/PageHeader.vue": "./components/layout/page-header/PageHeader.vue",
|
|
67
|
+
"./components/Panel.vue": "./components/layout/record-layout/Panel.vue",
|
|
68
|
+
"./components/RecordLayout.vue": "./components/layout/record-layout/RecordLayout.vue",
|
|
67
69
|
"./components/Separator.vue": "./components/layout/separator/Separator.vue",
|
|
68
70
|
"./components/Table.vue": "./components/layout/table/Table.vue",
|
|
69
71
|
"./components/TableRow.vue": "./components/layout/table/TableRow.vue",
|
|
@@ -96,6 +96,13 @@
|
|
|
96
96
|
cursor: not-allowed;
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
/* `data-readonly="true"`: same border, text and focus ring as the
|
|
100
|
+
* default state on a muted surface; the control stays in the tab order. */
|
|
101
|
+
.pui-field[data-readonly='true'] .pui-input,
|
|
102
|
+
.pui-field[data-readonly='true'] .pui-textarea {
|
|
103
|
+
background: var(--bg-clr-surface-2);
|
|
104
|
+
}
|
|
105
|
+
|
|
99
106
|
.pui-field[data-status='error'] .pui-input,
|
|
100
107
|
.pui-field[data-status='error'] .pui-textarea {
|
|
101
108
|
border-color: var(--border-clr-danger);
|