@kerfjs/ui 5.0.0-beta.50 → 5.0.0-beta.51
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 +29 -5
- package/ai/compile-time-contracts-v1.json +5 -2
- package/ai/component-catalog-v2.d.ts +19 -1
- package/ai/component-catalog-v2.json +842 -127
- package/ai/component-catalog-v2.schema.json +33 -1
- package/ai/component-catalog.json +603 -126
- package/ai/component-catalog.schema.json +21 -1
- package/ai/public-api-signatures-v1.md +201 -29
- package/ai/skill.md +12 -9
- package/ai/webawesome-jsx-signatures-v1.md +1 -1
- package/analyzer/index.mjs +105 -35
- package/dist/app-tab.js +1 -1
- package/dist/catalog-resources.d.ts +1 -1
- package/dist/catalog.d.ts +28 -5
- package/dist/catalog.js +66 -25
- package/dist/catalog.js.map +1 -1
- package/dist/{chunk-COUPLRZG.js → chunk-5FZZMIMD.js} +3 -3
- package/dist/{chunk-COUPLRZG.js.map → chunk-5FZZMIMD.js.map} +1 -1
- package/dist/{chunk-DARTMI5Z.js → chunk-5PMGQDG7.js} +2 -2
- package/dist/{chunk-DARTMI5Z.js.map → chunk-5PMGQDG7.js.map} +1 -1
- package/dist/{chunk-V6RZWDII.js → chunk-7GUQYHKA.js} +19 -2
- package/dist/chunk-7GUQYHKA.js.map +1 -0
- package/dist/{chunk-ZNZ2JDBW.js → chunk-7IUSV4XG.js} +1 -1
- package/dist/chunk-7IUSV4XG.js.map +1 -0
- package/dist/{chunk-ELRMBQEC.js → chunk-AEPXGCNF.js} +17 -2
- package/dist/chunk-AEPXGCNF.js.map +1 -0
- package/dist/{chunk-5CE64WGC.js → chunk-D547PH4L.js} +3 -3
- package/dist/{chunk-5CE64WGC.js.map → chunk-D547PH4L.js.map} +1 -1
- package/dist/{chunk-S6ZTTTV7.js → chunk-DVZCMMB3.js} +3 -3
- package/dist/{chunk-S6ZTTTV7.js.map → chunk-DVZCMMB3.js.map} +1 -1
- package/dist/chunk-EKYZCRCX.js +256 -0
- package/dist/chunk-EKYZCRCX.js.map +1 -0
- package/dist/{chunk-3V75EQIP.js → chunk-JM53SMVF.js} +3 -3
- package/dist/{chunk-3V75EQIP.js.map → chunk-JM53SMVF.js.map} +1 -1
- package/dist/{chunk-2WMSE4MK.js → chunk-JMGKM7RK.js} +2 -2
- package/dist/{chunk-2WMSE4MK.js.map → chunk-JMGKM7RK.js.map} +1 -1
- package/dist/{chunk-2YOUUEWR.js → chunk-KX7DP2GO.js} +4 -4
- package/dist/{chunk-2YOUUEWR.js.map → chunk-KX7DP2GO.js.map} +1 -1
- package/dist/{chunk-OL4TC3U2.js → chunk-MO56ZZLG.js} +6 -2
- package/dist/chunk-MO56ZZLG.js.map +1 -0
- package/dist/{chunk-OQI7RCRP.js → chunk-MTM43SJO.js} +7 -1
- package/dist/chunk-MTM43SJO.js.map +1 -0
- package/dist/{chunk-ZSYLBVWG.js → chunk-NMGTHYW3.js} +3 -3
- package/dist/{chunk-ZSYLBVWG.js.map → chunk-NMGTHYW3.js.map} +1 -1
- package/dist/{chunk-AQSKJ6U6.js → chunk-NZXWU4R5.js} +21 -2
- package/dist/chunk-NZXWU4R5.js.map +1 -0
- package/dist/{chunk-DJKWFYAA.js → chunk-O3RCCSQJ.js} +3 -3
- package/dist/{chunk-DJKWFYAA.js.map → chunk-O3RCCSQJ.js.map} +1 -1
- package/dist/{chunk-UMGY5JSP.js → chunk-S4QRSBFI.js} +22 -2
- package/dist/chunk-S4QRSBFI.js.map +1 -0
- package/dist/{chunk-KKNK3JUT.js → chunk-UBH743HV.js} +5 -5
- package/dist/chunk-UBH743HV.js.map +1 -0
- package/dist/{chunk-54HM36IQ.js → chunk-ULCDZTWL.js} +2 -2
- package/dist/{chunk-54HM36IQ.js.map → chunk-ULCDZTWL.js.map} +1 -1
- package/dist/{chunk-SIU2AC5W.js → chunk-UPZ6EEJN.js} +3 -3
- package/dist/{chunk-SIU2AC5W.js.map → chunk-UPZ6EEJN.js.map} +1 -1
- package/dist/collapsible-panel.d.ts +1 -1
- package/dist/collapsible-panel.js.map +1 -1
- package/dist/css-values.d.ts +39 -3
- package/dist/css-values.js +1 -1
- package/dist/grid.d.ts +15 -1
- package/dist/grid.js +2 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +19 -19
- package/dist/list-action-row.js +1 -1
- package/dist/list-header.js +1 -1
- package/dist/list-item.js +1 -1
- package/dist/list.d.ts +21 -2
- package/dist/list.js +2 -1
- package/dist/nav-stack.js +1 -1
- package/dist/pane.d.ts +17 -2
- package/dist/pane.js +1 -1
- package/dist/row.d.ts +19 -1
- package/dist/row.js +2 -1
- package/dist/segmented-control.js +1 -1
- package/dist/select.d.ts +13 -3
- package/dist/select.js +1 -1
- package/dist/skeleton.js +1 -1
- package/dist/spacer.js +1 -1
- package/dist/split-view.js +1 -1
- package/dist/state-banner.js +1 -1
- package/dist/styles/catalog/components/catalog-example-stack.css +4 -1
- package/dist/styles/catalog/components/catalog-example.css +145 -0
- package/dist/styles/collapsible-panel.css +132 -4
- package/dist/styles/document.css +23 -0
- package/dist/styles/foundation.css +21 -7
- package/dist/styles/grid.css +10 -0
- package/dist/styles/list-header.css +45 -0
- package/dist/styles/list-inset-control.css +8 -1
- package/dist/styles/list-item.css +6 -0
- package/dist/styles/list.css +11 -0
- package/dist/styles/nav-stack.css +89 -2
- package/dist/styles/pane.css +86 -1
- package/dist/styles/resizable-region.css +93 -5
- package/dist/styles/row.css +10 -0
- package/dist/styles/select.css +39 -4
- package/dist/styles/split-view.css +107 -1
- package/dist/styles/tab-scaffold.css +64 -1
- package/dist/styles/text.css +6 -0
- package/dist/styles/toolbar-control-group.css +90 -11
- package/dist/styles/toolbar-text.css +4 -1
- package/dist/styles/toolbar.css +130 -38
- package/dist/styles/webawesome.css +48 -2
- package/dist/styles/workbench.css +136 -4
- package/dist/text.d.ts +4 -3
- package/dist/text.js +1 -1
- package/dist/toolbar-text.js +1 -1
- package/dist/toolbar.d.ts +24 -3
- package/dist/toolbar.js +1 -1
- package/dist/{types-CzgSrFXP.d.ts → types-CEsieBZi.d.ts} +6 -1
- package/dist/value-table.js +1 -1
- package/dist/wire-resizable-regions.js +1 -1
- package/dist/wire-sidebar.d.ts +18 -3
- package/dist/wire-sidebar.js +95 -14
- package/dist/wire-sidebar.js.map +1 -1
- package/docs/accessibility.md +45 -8
- package/docs/app-layouts.md +73 -0
- package/docs/catalog.md +23 -2
- package/docs/collapsible-panel.md +81 -8
- package/docs/component-contract.md +28 -9
- package/docs/component-integration.md +9 -4
- package/docs/component-selection.md +25 -6
- package/docs/design/templates/list/stack-dark.svg +1 -1
- package/docs/design/templates/list/stack.svg +1 -1
- package/docs/design/templates/list-dark.svg +1 -1
- package/docs/design/templates/list-header/action-dark.svg +1 -1
- package/docs/design/templates/list-header/action.svg +1 -1
- package/docs/design/templates/list-header/count-dark.svg +1 -1
- package/docs/design/templates/list-header/count.svg +1 -1
- package/docs/design/templates/list-header/inline-action-dark.svg +1 -1
- package/docs/design/templates/list-header/inline-action.svg +1 -1
- package/docs/design/templates/list-header/toggle-expanded-dark.svg +1 -1
- package/docs/design/templates/list-header/toggle-expanded.svg +1 -1
- package/docs/design/templates/list-header-dark.svg +1 -1
- package/docs/design/templates/list-header.svg +1 -1
- package/docs/design/templates/list.svg +1 -1
- package/docs/design/templates/state-banner/info-badge-dark.svg +1 -1
- package/docs/design/templates/state-banner/info-badge.svg +1 -1
- package/docs/design/templates/state-banner-dark.svg +1 -1
- package/docs/design/templates/state-banner.svg +1 -1
- package/docs/design/templates/toolbar/title-and-actions-dark.svg +1 -1
- package/docs/design/templates/toolbar/title-and-actions.svg +1 -1
- package/docs/design/templates/toolbar-control-group/with-text-dark.svg +1 -1
- package/docs/design/templates/toolbar-control-group/with-text.svg +1 -1
- package/docs/design/templates/toolbar-control-group-dark.svg +1 -1
- package/docs/design/templates/toolbar-control-group.svg +1 -1
- package/docs/design/templates/toolbar-dark.svg +1 -1
- package/docs/design/templates/toolbar-text/default-dark.svg +1 -1
- package/docs/design/templates/toolbar-text/default.svg +1 -1
- package/docs/design/templates/toolbar-text/large-dark.svg +1 -1
- package/docs/design/templates/toolbar-text/large.svg +1 -1
- package/docs/design/templates/toolbar-text/small-dark.svg +1 -1
- package/docs/design/templates/toolbar-text/small.svg +1 -1
- package/docs/design/templates/toolbar-text-dark.svg +1 -1
- package/docs/design/templates/toolbar-text.svg +1 -1
- package/docs/design/templates/toolbar.svg +1 -1
- package/docs/document-baseline.md +31 -0
- package/docs/layout.md +86 -21
- package/docs/nav-stack.md +8 -0
- package/docs/recipes.md +78 -43
- package/docs/split-view.md +8 -0
- package/docs/tab-scaffold.md +4 -2
- package/docs/type-contracts.md +21 -17
- package/docs/ui-analyzer.md +19 -0
- package/docs/ui-evaluator.md +17 -0
- package/docs/ux-demo.md +4 -4
- package/docs/webawesome-theme.md +20 -2
- package/docs/workbench.md +20 -1
- package/evaluator/index.mjs +73 -8
- package/llms.txt +32 -14
- package/package.json +4 -2
- package/ux-demo/recipes/app-shell.tsx +209 -178
- package/ux-demo/recipes/collapsible-sidebar.tsx +188 -159
- package/ux-demo/recipes/compact-toolbar.tsx +48 -35
- package/ux-demo/recipes/composer-form.tsx +85 -79
- package/ux-demo/recipes/list-detail-dialog.tsx +124 -142
- package/ux-demo/recipes/list-workspace-states.tsx +83 -83
- package/ux-demo/recipes/loaders.ts +5 -2
- package/ux-demo/recipes/loading-inspector.tsx +157 -160
- package/ux-demo/recipes/navigation-sidebar.tsx +111 -109
- package/ux-demo/recipes/navigation-stack.tsx +50 -49
- package/ux-demo/recipes/types.ts +14 -0
- package/ux-demo/recipes/workspace-header.tsx +73 -56
- package/dist/chunk-AQSKJ6U6.js.map +0 -1
- package/dist/chunk-ELRMBQEC.js.map +0 -1
- package/dist/chunk-J3EE6XWD.js +0 -115
- package/dist/chunk-J3EE6XWD.js.map +0 -1
- package/dist/chunk-KKNK3JUT.js.map +0 -1
- package/dist/chunk-OL4TC3U2.js.map +0 -1
- package/dist/chunk-OQI7RCRP.js.map +0 -1
- package/dist/chunk-UMGY5JSP.js.map +0 -1
- package/dist/chunk-V6RZWDII.js.map +0 -1
- package/dist/chunk-ZNZ2JDBW.js.map +0 -1
- package/ux-demo/recipes/app-shell.css +0 -87
- package/ux-demo/recipes/collapsible-sidebar.css +0 -83
- package/ux-demo/recipes/compact-toolbar.css +0 -35
- package/ux-demo/recipes/composer-form.css +0 -19
- package/ux-demo/recipes/list-detail-dialog.css +0 -42
- package/ux-demo/recipes/list-workspace-states.css +0 -30
- package/ux-demo/recipes/loading-inspector.css +0 -7
- package/ux-demo/recipes/navigation-sidebar.css +0 -12
- package/ux-demo/recipes/navigation-stack.css +0 -12
- package/ux-demo/recipes/recipe-root.css +0 -67
- package/ux-demo/recipes/recipe-root.tsx +0 -87
- package/ux-demo/recipes/workspace-header.css +0 -7
package/docs/catalog.md
CHANGED
|
@@ -91,6 +91,18 @@ own overlay implementation.
|
|
|
91
91
|
generated note, then one specimen or one intentionally coupled specimen
|
|
92
92
|
cluster. Use one row per variant/state; do not hand-author the helper's private
|
|
93
93
|
classes.
|
|
94
|
+
- Focused demos do not import local stylesheets, use inline `style`, or invent
|
|
95
|
+
styling-only `demo-*` classes. Prefer a public Kerf component, then a Web
|
|
96
|
+
Awesome surface when Kerf has no equivalent, then ordinary semantic HTML.
|
|
97
|
+
Use `CatalogExample.viewport` for bounded specimen width, height, frame,
|
|
98
|
+
surface, overflow, responsive visibility, and public custom-property values;
|
|
99
|
+
keep those constraints catalog-owned instead of recreating a demo stylesheet.
|
|
100
|
+
Component heights run `short` (220px) through `tall` (360px); frame an app
|
|
101
|
+
shell, whole-screen layout, or other application-sized recipe with
|
|
102
|
+
`height: "app"` (592px), and give its root `fill` rather than a frame `Pane`.
|
|
103
|
+
An app frame stands in for the screen: it is the containing block for
|
|
104
|
+
screen-fixed chrome, so a compact `CollapsiblePanel` overlay, its backdrop,
|
|
105
|
+
and restore controls dock to the frame's edges rather than the page's.
|
|
94
106
|
- The specimen is an immediate child of `CatalogExample`. A focused component
|
|
95
107
|
row should place the component root there, without a decorative card or
|
|
96
108
|
spacing wrapper. A composition row may place the composition root there.
|
|
@@ -143,6 +155,9 @@ from structurally widened or JavaScript objects. Do not copy the helpers'
|
|
|
143
155
|
private `kui-catalog-*` classes into preview markup.
|
|
144
156
|
|
|
145
157
|
The app owns entry ids, `kind`, routing, sources, relationships, and test hooks.
|
|
158
|
+
`Catalog.stageRootAttributes` places app-owned `data-*` state on the
|
|
159
|
+
catalog-owned preview stage without an extra wrapper; `data-catalog-stage`
|
|
160
|
+
remains protected.
|
|
146
161
|
The helpers own their structural markers, label/note anatomy, alignment marker,
|
|
147
162
|
and private classes. Component metadata such as margin/border/padding ownership
|
|
148
163
|
lives in `component-catalog.json`; do not infer or overwrite it from overlay
|
|
@@ -204,7 +219,13 @@ facts that source can prove without guessing at rendered intent:
|
|
|
204
219
|
are not empty, and composition routes do not add redundant skip markers;
|
|
205
220
|
- every `@kerfjs/ui` import is a published package export and relative imports
|
|
206
221
|
do not reach into `ui/src`;
|
|
207
|
-
-
|
|
222
|
+
- focused demos have no relative stylesheet imports, inline style attributes,
|
|
223
|
+
or styling-only `demo-*`, `wa-demo-*`, and token-search class names;
|
|
224
|
+
- demo JSX does not copy private `kui-catalog-*` structural classes;
|
|
225
|
+
- recipe sources (checked by `npm run check:recipes` with the same shared
|
|
226
|
+
analyzer) import no stylesheet other than public `@kerfjs/ui` CSS, set no
|
|
227
|
+
inline style, and name only published layout and Web Awesome classes; each
|
|
228
|
+
recipe declares its catalog frame through an exported `presentation`; and
|
|
208
229
|
- the shell derives both geometry-overlay enablement and documented demo mode
|
|
209
230
|
from the active entry's source and kind.
|
|
210
231
|
|
|
@@ -217,7 +238,7 @@ stage geometry is itself the reviewed specimen. Add the narrow waiver to
|
|
|
217
238
|
[`catalog-conformance-exceptions.json`](../ux-demo/catalog-conformance-exceptions.json)
|
|
218
239
|
with the exact route, source file, stable diagnostic ids, a substantive reason,
|
|
219
240
|
and the reviewing `KF-*` ticket. Only helper/metadata rules are waivable;
|
|
220
|
-
private imports, private markup, empty examples, composition overlay drift, and
|
|
241
|
+
private imports, local styling, private markup, empty examples, composition overlay drift, and
|
|
221
242
|
shell-mode drift always fail. The gate rejects duplicate, malformed, unused,
|
|
222
243
|
and stale exceptions, so delete a waiver when its route adopts the standard
|
|
223
244
|
helpers.
|
|
@@ -37,25 +37,85 @@ Import the panel CSS (`@kerfjs/ui/collapsible-panel.css`) alongside `foundation.
|
|
|
37
37
|
is the app's: put a collapse toggle in the panel's own header and an expand toggle
|
|
38
38
|
somewhere always-visible (a toolbar) so it is reachable while collapsed.
|
|
39
39
|
- **`wireSidebar(root, { panels, deviceClass?, storage? })`** — the interaction
|
|
40
|
-
semantics. Each `panels` entry is
|
|
41
|
-
It:
|
|
40
|
+
semantics. Each `panels` entry is
|
|
41
|
+
`{ id, collapsed, toggleAction, storageKey?, inlineCollapsed? }`. It:
|
|
42
42
|
- **toggles** the panel's `collapsed` signal when any `[data-action=toggleAction]`
|
|
43
43
|
button is clicked, and remembers the trigger;
|
|
44
44
|
- **manages focus** — moves focus into the panel when it opens, and restores it
|
|
45
|
-
to the trigger when it closes
|
|
45
|
+
to the trigger when it closes. When that trigger is the collapse toggle inside
|
|
46
|
+
the now-hidden panel, focus goes to the panel's toggle outside it instead, so
|
|
47
|
+
an app may render its expand toggle only while the panel is collapsed (one
|
|
48
|
+
control per action, as the recipe does);
|
|
46
49
|
- **presents a compact overlay** when `deviceClass.compact` is true (pass a
|
|
47
50
|
`deviceClass()` signal): the open panel floats over the content with a
|
|
48
51
|
dismissable backdrop, Escape and backdrop-click collapse it, and Tab is trapped
|
|
49
|
-
within the panel (the ARIA dialog pattern)
|
|
52
|
+
within the panel (the ARIA dialog pattern). The overlay and its backdrop are
|
|
53
|
+
fixed to the screen; an ancestor that establishes a containing block for
|
|
54
|
+
fixed descendants (such as the catalog's `height: "app"` frame) docks them to
|
|
55
|
+
its edges instead;
|
|
50
56
|
- accepts `compactPresentation: "hidden"` when a compact application replaces
|
|
51
57
|
the panel with different navigation instead of overlaying it;
|
|
58
|
+
- **starts every compact overlay closed** (see
|
|
59
|
+
[Compact initial state](#compact-initial-state));
|
|
52
60
|
- keeps compact overlays exclusive by default, collapsing another open panel
|
|
53
61
|
when a new one opens (`exclusiveCompact: false` opts out);
|
|
54
|
-
- **persists** the collapsed state to `storage` (default
|
|
55
|
-
`storageKey`, seeding the signal on wire-up.
|
|
62
|
+
- **persists** the inline collapsed state to `storage` (default
|
|
63
|
+
`localStorage`) under `storageKey`, seeding the signal on wire-up. An
|
|
64
|
+
overlay's open/closed state is never persisted;
|
|
65
|
+
- **owns the root's `data-collapsible-responsive` / `data-collapsible-overlay`
|
|
66
|
+
attributes and the injected backdrop.** Your app may re-render (and morph)
|
|
67
|
+
the wired root for reasons that never touch a panel signal — a nav
|
|
68
|
+
selection, say — and the morph drops attributes and nodes its template
|
|
69
|
+
doesn't emit. The wire observes the root and re-applies them before the
|
|
70
|
+
next paint, so don't render these attributes yourself.
|
|
56
71
|
|
|
57
72
|
Returns a disposer. Retain it and call it on teardown.
|
|
58
73
|
|
|
74
|
+
## Compact initial state
|
|
75
|
+
|
|
76
|
+
A compact overlay is transient chrome the user summons, like a slide-over
|
|
77
|
+
sidebar on a phone: it covers the content, traps focus, and must be dismissed.
|
|
78
|
+
It therefore opens **only on a user action** (a toggle, or the app setting the
|
|
79
|
+
signal in response to one), never by itself:
|
|
80
|
+
|
|
81
|
+
- **Wire-up on a compact device.** Every panel starts collapsed, whatever its
|
|
82
|
+
signal, `inlineCollapsed`, or stored choice says. No backdrop, focus trap, or
|
|
83
|
+
Escape handling is active until the user opens a panel.
|
|
84
|
+
- **Wide → compact crossing.** Open panels collapse; nothing covers the page.
|
|
85
|
+
- **Compact → wide crossing.** Each panel returns to its remembered inline state
|
|
86
|
+
(open or collapsed), whatever the user did with the overlay meanwhile.
|
|
87
|
+
- **Disposal** hands the inline state back to the signals.
|
|
88
|
+
- **Persistence** records only the inline choice. A stored "open" rail restores
|
|
89
|
+
inline on a wide screen and is remembered, not opened, on a compact one.
|
|
90
|
+
|
|
91
|
+
These presentation changes never move focus, except to rescue focus that a
|
|
92
|
+
collapse would strand inside the hidden panel (it returns to the panel's last
|
|
93
|
+
trigger). `compactPresentation: "hidden"` leaves the signals alone.
|
|
94
|
+
|
|
95
|
+
`wireSidebar` runs after the first render, so an app that seeds an open inline
|
|
96
|
+
default would render the rail open for that first frame on a compact device.
|
|
97
|
+
Seed the signal from the device class instead, and declare the inline default
|
|
98
|
+
with `inlineCollapsed` so a later wide crossing still opens it:
|
|
99
|
+
|
|
100
|
+
```ts
|
|
101
|
+
const device = deviceClass();
|
|
102
|
+
const navCollapsed = signal(device.value.compact);
|
|
103
|
+
// …
|
|
104
|
+
wireSidebar(app, {
|
|
105
|
+
panels: [
|
|
106
|
+
{
|
|
107
|
+
id: "nav",
|
|
108
|
+
collapsed: navCollapsed,
|
|
109
|
+
toggleAction: "toggle-nav",
|
|
110
|
+
inlineCollapsed: false,
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
deviceClass: device,
|
|
114
|
+
});
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
A stored inline choice takes precedence over `inlineCollapsed`.
|
|
118
|
+
|
|
59
119
|
## Example
|
|
60
120
|
|
|
61
121
|
```tsx
|
|
@@ -68,8 +128,10 @@ import {
|
|
|
68
128
|
import { wireSidebar } from "@kerfjs/ui/wire-sidebar";
|
|
69
129
|
import "@kerfjs/ui/collapsible-panel.css";
|
|
70
130
|
|
|
71
|
-
const navCollapsed = signal(false);
|
|
72
131
|
const device = deviceClass();
|
|
132
|
+
// Start collapsed on a compact device; `inlineCollapsed` keeps the open inline
|
|
133
|
+
// default for wide screens.
|
|
134
|
+
const navCollapsed = signal(device.value.compact);
|
|
73
135
|
|
|
74
136
|
const app = document.querySelector("#app")!;
|
|
75
137
|
mount(app, () => (
|
|
@@ -111,12 +173,22 @@ const stop = wireSidebar(app, {
|
|
|
111
173
|
collapsed: navCollapsed,
|
|
112
174
|
toggleAction: "toggle-nav",
|
|
113
175
|
storageKey: "app.nav-collapsed",
|
|
176
|
+
inlineCollapsed: false,
|
|
114
177
|
},
|
|
115
178
|
],
|
|
116
179
|
deviceClass: device,
|
|
117
180
|
});
|
|
118
181
|
```
|
|
119
182
|
|
|
183
|
+
## Safe areas
|
|
184
|
+
|
|
185
|
+
A panel grows by the unsafe inset of the edge it docks to and pads its content
|
|
186
|
+
for every edge it touches except its interior edge. While expanded inline, it
|
|
187
|
+
also clears that edge for its direct flex siblings, so a neighboring pane gains
|
|
188
|
+
the inset when the panel collapses. When you wrap the panel in your own grid
|
|
189
|
+
cell, set `--kui-edge-inset-*: 0px` on the sibling regions yourself (or pass
|
|
190
|
+
`safeAreaEdges` to a sibling `Pane`). See [Choosing an app layout › Safe areas](app-layouts.md#safe-areas).
|
|
191
|
+
|
|
120
192
|
## When to use which
|
|
121
193
|
|
|
122
194
|
- One or two independent rails / a drawer you place yourself → **`CollapsiblePanel` +
|
|
@@ -138,5 +210,6 @@ persistence: [open it](../ux-demo/?component=recipe-collapsible-sidebar) or read
|
|
|
138
210
|
[`recipes.md`](recipes.md#collapsible-sidebar) · [TSX source](../ux-demo/recipes/collapsible-sidebar.tsx).
|
|
139
211
|
It is covered end-to-end across Chromium, Firefox, and WebKit by
|
|
140
212
|
`tests/browser/collapsible-sidebar-recipe.spec.ts` (collapse/expand, focus
|
|
141
|
-
move/restore, the compact overlay + Escape/backdrop dismiss,
|
|
213
|
+
move/restore, the compact overlay + Escape/backdrop dismiss, the Tab trap, and
|
|
214
|
+
the compact initial state across first load and wide/compact crossings),
|
|
142
215
|
alongside the component/wire unit tests.
|
|
@@ -36,6 +36,19 @@ bounded `items[].property` form. Consumer catalogs can publish the same facts;
|
|
|
36
36
|
ESLint, `kerf-ui-analyze`, and `kerf-ui-doctor` then issue the same stable
|
|
37
37
|
`KUI-L013`–`KUI-L017` feedback for application and third-party components.
|
|
38
38
|
|
|
39
|
+
`wiring.stateAttributes` lists the **wiring-owned state attributes**: the
|
|
40
|
+
`data-*` attributes a wiring helper writes at runtime, such as
|
|
41
|
+
`data-handle-inset` and `data-resizing`, which `wireResizableRegions` puts on a
|
|
42
|
+
`ResizableRegion`. Each entry names the attribute, the element that carries it
|
|
43
|
+
(`on`), the `helper` that writes it, and what it means. An application must not
|
|
44
|
+
render, remove, or treat these attributes as its own state; tools use the list
|
|
45
|
+
to tell them apart from app-authored attributes. They are declared once, on the
|
|
46
|
+
helper's wiring item in the v1 catalog, and v2 flattens them. `check:catalog`
|
|
47
|
+
reads each `wire*` helper's source and fails when its declarations differ from
|
|
48
|
+
the `data-*` attributes it actually writes. First-party entries always carry
|
|
49
|
+
the list, empty when their helpers write none; it is optional in extension
|
|
50
|
+
catalogs.
|
|
51
|
+
|
|
39
52
|
The generator starts with permissive defaults. An `any` mode records that the
|
|
40
53
|
catalog has no defensible prohibition; it does not claim every composition is
|
|
41
54
|
recommended. Objective rules live in
|
|
@@ -306,8 +319,10 @@ props. Its opaque string brand improves authoring correctness; it is not a CSS
|
|
|
306
319
|
sanitizer or security boundary.
|
|
307
320
|
`Row.flex` and `List.flex` likewise accept their boolean default, finite keywords, or `CssFlex`
|
|
308
321
|
from `flex(grow, shrink, basis)`. `Skeleton` width/height use `CssSize`, radius
|
|
309
|
-
uses `CssLength`, and `SelectChoice.color` uses `
|
|
310
|
-
`
|
|
322
|
+
uses `CssLength`, and `SelectChoice.color` uses `CssForegroundColor` from
|
|
323
|
+
`uiColor()` with a foreground token such as `success-on-quiet`, or from
|
|
324
|
+
`foregroundColorVar()`. Fill tokens such as `success` are pale background tints
|
|
325
|
+
and do not type-check there. Never exchange these property grammars. List rows expose
|
|
311
326
|
`className`, public tokens, and semantic props instead of unrestricted `style`
|
|
312
327
|
declarations.
|
|
313
328
|
`.kui-content` gives major children 24px vertical separation.
|
|
@@ -329,18 +344,22 @@ breakpoint; do not hide the group with an application class. Reach for
|
|
|
329
344
|
a Web Awesome feature, chiefly the `slot="trigger"` button of a `wa-dropdown`
|
|
330
345
|
popup menu. For a compact mixed-content group, set `nestedDropdown`; a
|
|
331
346
|
text-and-caret trigger grows to its intrinsic width while an icon-only trigger
|
|
332
|
-
can remain square.
|
|
347
|
+
can remain square. A compact icon `<button>` is a 32px circle, so a selected
|
|
348
|
+
compact segment never becomes an oval. An icon-only `Select` joins a group as
|
|
349
|
+
one more segment with its siblings' inset, radius, hover, and focus ring; only a
|
|
350
|
+
lone Select grows the group to its icon-and-caret pill. Set `menuInset` to configure the dropdown menu surface
|
|
333
351
|
without application `::part(menu)` CSS. Compact mixed controls retain the standard
|
|
334
352
|
item padding, omit an internal separator, and let the raised selected item paint
|
|
335
|
-
over the outer border instead of shrinking to an inset highlight. The
|
|
336
|
-
trigger
|
|
337
|
-
|
|
338
|
-
raise `--kui-toolbar-dropdown-trigger-width` for longer localized copy.
|
|
353
|
+
over the outer border instead of shrinking to an inset highlight. The Web
|
|
354
|
+
Awesome trigger's shadow base owns max-content sizing, so icons, localized text,
|
|
355
|
+
and the shadow caret determine the width without a fixed host measurement.
|
|
339
356
|
The enclosing `Toolbar` owns zone alignment and responsive topology: use
|
|
340
357
|
`centerAlign="stretch"` when the center group should consume its track, and
|
|
341
|
-
choose `responsive="stack"` with `responsiveAt="compact" | "narrow"
|
|
358
|
+
choose `responsive="stack"` with `responsiveAt="compact" | "narrow"`,
|
|
359
|
+
`responsive="wrap"` for a heading whose title must stay whole, or
|
|
342
360
|
`responsive="center-priority"` instead of selecting its zone classes from a
|
|
343
|
-
parent stylesheet.
|
|
361
|
+
parent stylesheet. No policy clips an action: the trailing zone, and a stacked
|
|
362
|
+
center zone, wrap whole groups onto another row.
|
|
344
363
|
`ListHeader` similarly separates its dormant title and
|
|
345
364
|
optional count or badge from its optional 44px action. Use the mutually
|
|
346
365
|
exclusive `count`/`countLabel` pair for non-negative safe-integer section
|
|
@@ -45,9 +45,11 @@ Run `npm run check:change` after changing a public component. It synchronizes
|
|
|
45
45
|
both catalog projections, declarations, AI signatures, and compatibility
|
|
46
46
|
digests; names every checked-in projection changed by that synchronization;
|
|
47
47
|
runs the catalog/component contracts, unit coverage, consumer bundle tests,
|
|
48
|
-
source and packed type contracts;
|
|
49
|
-
the
|
|
50
|
-
|
|
48
|
+
source and packed type contracts; rebuilds the package and production catalog
|
|
49
|
+
through the same `demo:bundle` script `npm run demo:build` uses; and reports
|
|
50
|
+
the exact gzip byte delta from the last reviewed baseline. Every step runs on
|
|
51
|
+
the Node that invoked it, so `check:change` and `demo:build` measure the same
|
|
52
|
+
bytes. The broader `npm run check` remains the release gate.
|
|
51
53
|
|
|
52
54
|
Intentional bundle changes use the same workflow with an explicit review
|
|
53
55
|
reason:
|
|
@@ -59,5 +61,8 @@ npm run check:change -- --update-bundle-budget \
|
|
|
59
61
|
|
|
60
62
|
That mode writes `demo-bundle-budget.json`, records the previous and new exact
|
|
61
63
|
measurements and budgets with the reason and timestamp, and rounds the total
|
|
62
|
-
budget to the next 100 bytes.
|
|
64
|
+
budget to the next 100 bytes. Gzip output depends on the zlib bundled with
|
|
65
|
+
Node, so reviewed baselines are recorded on the repository's pinned Node major
|
|
66
|
+
(`.nvmrc`, also CI's version): an update on another major is refused, and a
|
|
67
|
+
plain check on one prints a warning. Do not edit the budget or add a history comment
|
|
63
68
|
by hand.
|
|
@@ -27,6 +27,12 @@ CSS".
|
|
|
27
27
|
|
|
28
28
|
## Foundation tokens
|
|
29
29
|
|
|
30
|
+
Import the opt-in `@kerfjs/ui/document.css` baseline when the application wants
|
|
31
|
+
Kerf UI to own global box sizing, body typography/colors, plain-link color, and
|
|
32
|
+
the definite full-height chain. Put `.kui-app-root` on the one direct mount
|
|
33
|
+
container only for a full-height shell; ordinary flowing pages can omit it. See
|
|
34
|
+
[Document baseline](document-baseline.md).
|
|
35
|
+
|
|
30
36
|
Import `@kerfjs/ui/foundation.css` when application-owned composition CSS needs
|
|
31
37
|
the same semantic typography, spacing, device breakpoints, geometry, radii,
|
|
32
38
|
colors, focus ring, or shadows as Kerf components. Its complete supported
|
|
@@ -73,12 +79,17 @@ expressions fail during typechecking rather than in the browser.
|
|
|
73
79
|
Other CSS-valued props use distinct contracts: `Spacer.width` and
|
|
74
80
|
`Spacer.height` take `UiSpaceName | CssLength`; `flex()` creates `CssFlex` for
|
|
75
81
|
`Row.flex`, `Grid.flex`, and `List.flex`; `Skeleton` dimensions take typed lengths (plus finite intrinsic
|
|
76
|
-
keywords for width/height); and `
|
|
77
|
-
`
|
|
82
|
+
keywords for width/height); and `SelectChoice.color` takes a
|
|
83
|
+
`CssForegroundColor` from `uiColor()` with a foreground token (`*-on-*`, a text
|
|
84
|
+
role, or a `*-text` alias) or from `foregroundColorVar()`. The bare `success`,
|
|
85
|
+
`warning`, `danger`, `pop`, and `accent` tokens are quiet fills, not
|
|
86
|
+
foregrounds, and are rejected there; `colorVar()` returns a plain `CssColor`.
|
|
87
|
+
Do not substitute one brand for another. Row components
|
|
78
88
|
have no declaration-string `style` prop; use `className`, documented public
|
|
79
89
|
tokens, and semantic component props. Catalog media queries remain strings and
|
|
80
90
|
semantic pixel measurements remain numbers because those are different APIs.
|
|
81
|
-
The corresponding public builders are `flex`, `uiColor`,
|
|
91
|
+
The corresponding public builders are `flex`, `uiColor`, `colorVar`, and
|
|
92
|
+
`foregroundColorVar`.
|
|
82
93
|
|
|
83
94
|
## Production recipes
|
|
84
95
|
|
|
@@ -127,13 +138,13 @@ an upstream component or recipe request.
|
|
|
127
138
|
| Application toolbar or heading — `Toolbar` | Leading identity, optional centered content, and trailing controls form one horizontal app bar or a page/panel/dialog heading. | Do not add bespoke heading geometry or a private wrapper; use the same zone contract everywhere. | Put identity/title text directly in a zone as `ToolbarText`; group controls and icon tiles in `ToolbarControlGroup`. | Actions, command availability, responsive relocation, state, and supporting copy below a heading. | `@kerfjs/ui/toolbar` | [Toolbar composition](../README.md#component-subpaths) |
|
|
128
139
|
| Toolbar control cluster — `ToolbarControlGroup`, `ToolbarActionLink` | Related toolbar buttons, semantic links, compact/tight controls, avatar actions, or a dropdown trigger/menu surface need one configured chrome contract. | Do not use it merely to align unrelated controls. Do not restyle anchors or dropdown parts in application CSS; use `ToolbarActionLink`, `overflow`, and `menuInset`. Web Awesome `wa-button-group` is only for an exceptional grouped-action contract. | Delegate child actions; use `ToolbarActionLink` for native navigation, `overflow="scroll"` for bounded action rows, and `menuInset` for dropdown surface padding. Use `avatarImage` instead of inserting an `img`; use `SegmentedControl` for an exclusive choice. | Actions, destinations, pressed/expanded state, content, and policy. | `@kerfjs/ui/toolbar-control-group` | [Component ownership](./component-contract.md#ownership-boundaries) |
|
|
129
140
|
| Floating controls over content — `FloatingToolbar` | A small cluster of controls (e.g. a drawer restore) must float over scrolling content — distinct and forced-dark — inside a positioned container. | Do not use it for a primary page or panel toolbar (use `Toolbar`), or for anything that must sit above dialogs/overlays — it is not top-layer. | Compose `ToolbarControlGroup`s and delegate their actions; the app owns visibility and position. | Controls, visibility, and position. | `@kerfjs/ui/floating-toolbar` | [Component subpaths](../README.md#component-subpaths) |
|
|
130
|
-
| Toolbar identity text — `ToolbarText` | A toolbar needs extra-large (page/panel title), large, default, or compact textual identity. | Plain text is not a heading by default; when a title needs heading semantics pass `headingLevel`.
|
|
131
|
-
| Semantic
|
|
141
|
+
| Toolbar identity text — `ToolbarText` | A toolbar needs extra-large (page/panel title), large, default, or compact textual identity. | Plain text is not a heading by default; when a title needs heading semantics pass `headingLevel`. Sizes below `xlarge` are intentionally quiet identity text with no tone option — do not use them as a normal-color subsection title; use `Text` with an `h2`–`h6` variant, or `ListHeader` for a list section. | Optional `headingLevel` for `role="heading"` + `aria-level`. Defaults to one line, ellipsized when it does not fit; `wrap` flows onto multiple lines, `ellipsis` toggles the trailing …, and `maxLines` caps a wrap. | Text, heading level, overflow behavior, and responsive priority. | `@kerfjs/ui/toolbar-text` | [Toolbar composition](../README.md#component-subpaths) |
|
|
142
|
+
| Semantic block or inline text — `Text` | Ordinary application copy needs native `h1`–`h6` or `p` semantics plus standard geometry, or inline secondary copy needs a native `span` without box geometry. | Do not choose heading levels for appearance alone or recreate muted, error, small, or code utility classes. Use `ToolbarText` for toolbar identity/title content and `ListInsetText` when list-aligned prose needs full margin/border/padding geometry. | Omit `variant` for the default `p`, choose `h1`–`h6` from the document outline, or choose `span` inside a row, label, or table cell. Independently compose `tone="quiet | danger"`, `size="compact"`, and `font="monospace"`; ordinary native global, `data-_`, and `aria-_` attributes pass through. | Copy, localization, semantic variant, presentation roles, and document heading hierarchy. | `@kerfjs/ui/text` | [Text](./layout.md#text) |
|
|
132
143
|
| Vertical stack — `List` | Rows, sections, or arbitrary components need a consistent vertical stretch layout, optional standard/custom gap, flex growth, one vertical scroll owner, or edge dividers. | It is layout-only and does not provide `ul`/`ol` semantics. Do not nest scroll owners or use it when a horizontal layout is required. | Choose `gap`, `flex`, `scrollable`, and canonical `dividerSides` (`t`, `r`, `b`, `l` combinations in that order); bound the block size when scrolling. | Child semantics/content, containing height, and which optional layout behaviors apply. | `@kerfjs/ui/list` | [Pane geometry](../README.md#pane-and-content-geometry) |
|
|
133
144
|
| Equal-width columns — `Grid` | A fixed positive number of sibling columns must divide the available width evenly, including when child content has different intrinsic widths. | Do not use it for intrinsic, asymmetric, spanning, auto-fit, or masonry tracks; use application-owned CSS grid. Do not use it for a user-operable separator; use `ResizableRegion`. | Choose `columns`, a typed `gap`, and optional typed `flex`; preserve source order when the app changes the count responsively. | Child semantics/content, the column count and responsive policy, and typed gap/flex choices. | `@kerfjs/ui/grid` | [Grid](./layout.md#grid) |
|
|
134
145
|
| Navigation row — `ListItem` | A pane or navigation area needs a selectable, disabled, dormant-trailing, or multiline action row. | Do not put a control in `trailing`; use `ListActionRow` when the trailing region must be independently interactive. Use an `<a>` for navigation that must retain link behavior, a native `<button>` for an ordinary action, or implement the complete ARIA menu widget. | Delegate its `data-action`; compose inside a `.kui-content` section. Put domain event/drop metadata in `rootAttributes` rather than adding wrapper markup. The rounded root clips overflowing descendants; set `multiline` when the primary label should wrap. | Routing, selection, permissions, copy, action handling, and domain `data-*` values. | `@kerfjs/ui/list-item` | [Pane geometry](../README.md#pane-and-content-geometry) |
|
|
135
146
|
| Navigation row with trailing action — `ListActionRow` | A full-width row needs a selectable primary action and an independently focusable trailing action. | Use `ListItem` when trailing content is dormant metadata. Do not put controls inside the row's `label`, `icon`, or `trailingActionIcon` SafeHtml slots. Do not use `AppTab` outside tablist semantics or `ToolbarControlGroup` outside a toolbar. | Delegate both action strings; update controlled selection and any popover/context-menu state in the app. | Routing, selection, both action policies, domain metadata, and popover/context-menu behavior. | `@kerfjs/ui/list-action-row` | [Accessibility](./accessibility.md#listactionrow) |
|
|
136
|
-
| Navigation section heading — `ListHeader` | A menu section needs a full-width label, semantic count, non-count badge, logical-end action, or real disclosure state. | Do not concatenate counts into `label` or put numeric content in `badge`; use `count` with the localized full phrase in `countLabel`. Do not add a disclosure arrow to navigation that reveals nothing.
|
|
147
|
+
| Navigation section heading — `ListHeader` | A menu section needs a full-width label, semantic count, non-count badge, logical-end action, or real disclosure state. | Do not concatenate counts into `label` or put numeric content in `badge`; use `count` with the localized full phrase in `countLabel`. Do not add a disclosure arrow to navigation that reveals nothing. Keep its 44px hit target; do not resize its 36px square. Do not use it as a page, panel, or dialog title; use a heading `Toolbar`. | Delegate its optional action; the app controls expanded state and revealed content. Toggle mode supplies `DisclosureArrow` unless `actionIcon` replaces it. Use `triggerAttributes` only for domain `data-*` or a native popover relationship. | Section organization, valid count and localized count label, disclosure state and content, non-count badge content, popover target behavior, and policy. | `@kerfjs/ui/list-header` | [Pane geometry](../README.md#pane-and-content-geometry) |
|
|
137
148
|
| Inset self-bordered control — `ListInsetControl` | A control that owns its own border and padding but no outer margin (a search input, a `SegmentedControl`) must line up inside a `.kui-content` list with the standard 8px inline margins and stretch to fill the row. | Do not wrap a `.kui-content-item` or a `ListItem`/`ListHeader` that already owns its inline margin — that double-insets it. Do not add ad-hoc `margin`/`padding` around a bare control to align it; use this instead. | Place the self-bordered control(s) as children; they stretch to fill. It applies only the inline margin, flex stretch, and 8px gap — the child owns its own border and padding. | The control(s), their state, and action wiring. | `@kerfjs/ui/list-inset-control` | [Pane geometry](../README.md#component-subpaths) |
|
|
138
149
|
| Inset bare text — `ListInsetText` | A plain string or inline content with no margin, border, or padding of its own must sit in a `.kui-content` list with its text edge aligned to the bordered items around it. | Do not use it to wrap a component that already owns content-item geometry (`ListItem`, `StateBanner`, a `.kui-content-item`) — that double-insets it. Do not hand-roll the 8px margin / 1px border / 8px padding. | Pass the text or inline `SafeHtml` as children; it supplies the 8px inline margin, 1px transparent border, and 8px padding so the text edge lands at the standard 17px inset. Pass `horizontalOnly` to keep that horizontal inset but drop the vertical margin, border, and padding for tight text layout. | The text, copy, and localization. | `@kerfjs/ui/list-inset-text` | [Pane geometry](../README.md#component-subpaths) |
|
|
139
150
|
| Application column — `Pane` | A sidebar, main area, inspector, or dialog needs shared vertical header/content/footer organization, one scroll owner, and optional edge separators. | Do not pad the pane shell, wrap child-owned geometry in competing insets, invent unrelated centered measures, or leave an icon-only rail for a hidden pane. | Import `Pane`, use `children` for its homogeneous primary content and the named `SafeHtml` prop slots `header`/`footer` for optional fixed chrome, then opt into only the needed logical-edge separators; add `.kui-content-item` as needed. A visible pane owns collapse in its toolbar; move a hidden inline-start pane's restore control to the main toolbar leading edge and an inline-end pane's restore control to its trailing edge. | Layout hierarchy, reading width, responsive relocation, pane visibility state, slot semantics, labels, and separator placement. | `@kerfjs/ui/pane` | [Pane anatomy](./layout.md#anatomy) |
|
|
@@ -164,6 +175,14 @@ an upstream component or recipe request.
|
|
|
164
175
|
- `TabBar` changes tabpanels and supports overflow/reorder; `SegmentedControl` chooses among a few compact views; `Select` handles a longer value list.
|
|
165
176
|
- `StateBanner` persists beside affected work; `EmptyState` replaces absent content; `wa-callout` is contextual ecosystem content; `wa-toast` and `wa-toast-item` are transient and must not carry the only copy of important state.
|
|
166
177
|
- `ResizableRegion` is an interactive controlled pane. `Grid` is the right answer for static equal-width columns; application CSS grid remains the answer for asymmetric or intrinsic tracks.
|
|
178
|
+
- A `ResizableRegion`'s content spans the whole region, like its separator. Give
|
|
179
|
+
it one child — normally a `Pane` — and that child fills the region, so the
|
|
180
|
+
pane reaches the region's far edge and owns scrolling for long content.
|
|
181
|
+
Several children stack at their natural height. Do not size the child with
|
|
182
|
+
application `height` rules. While expanded, slide-motion content follows the
|
|
183
|
+
region's actual track, so a region its parent clamps (a `max-width`, a narrow
|
|
184
|
+
container) never shows content past its separator; the fixed expanded size
|
|
185
|
+
applies only while the collapsed content slides out.
|
|
167
186
|
- A `ResizableRegion` overlay automatically clamps both its track and fixed-size
|
|
168
187
|
animated content to the responsive overlay maximum. Set the policy and maximum
|
|
169
188
|
on the component instead of adding application descendant width/height fixes.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 230" width="420" height="230"><defs><clipPath id="cp0"><rect x="29" y="34.5" width="81.8" height="15"/></clipPath><clipPath id="ct1"><rect x="29" y="34.5" width="81.8" height="15"/></clipPath><clipPath id="ct2"><rect x="118.8" y="
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 230" width="420" height="230"><defs><clipPath id="cp0"><rect x="29" y="34.5" width="81.8" height="15"/></clipPath><clipPath id="ct1"><rect x="29" y="34.5" width="81.8" height="15"/></clipPath><clipPath id="ct2"><rect x="118.8" y="33" width="9.3" height="18"/></clipPath><clipPath id="cp3"><rect x="28" y="72" width="324" height="44"/></clipPath><clipPath id="ov4"><rect x="29" y="73" width="322" height="42" rx="11"/></clipPath><clipPath id="cp5"><rect x="37" y="85" width="18" height="18"/></clipPath><clipPath id="cp7"><rect x="63" y="85" width="272" height="18"/></clipPath><clipPath id="ov8"><rect x="63" y="85" width="272" height="18" rx="0"/></clipPath><clipPath id="ct9"><rect x="63" y="85" width="272" height="18"/></clipPath><clipPath id="cp10"><rect x="28" y="124" width="324" height="44"/></clipPath><clipPath id="ov11"><rect x="29" y="125" width="322" height="42" rx="11"/></clipPath><clipPath id="cp12"><rect x="37" y="137" width="18" height="18"/></clipPath><clipPath id="cp14"><rect x="63" y="137" width="272" height="18"/></clipPath><clipPath id="ov15"><rect x="63" y="137" width="272" height="18" rx="0"/></clipPath><clipPath id="ct16"><rect x="63" y="137" width="272" height="18"/></clipPath></defs><rect x="28.5" y="20.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp0)"><g clip-path="url(#ct1)"><text x="29" y="46.5" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="650" fill="rgb(174,174,178)">WORKSPACE</text></g></g><text x="118.81" y="48" font-family="system-ui, "-apple-system", sans-serif" font-size="16" fill="rgb(174,174,178)">2</text><g clip-path="url(#cp3)"><rect x="28" y="72" width="324" height="44" rx="12" fill="rgb(40,57,66)"/><rect x="28.5" y="72.5" width="323" height="43" rx="11.5" fill="none" stroke="rgb(53,92,109)" stroke-width="1"/><g clip-path="url(#ov4)"><g clip-path="url(#cp5)"><g color="rgb(245, 245, 247)"><clipPath id="svgic6"><rect x="37" y="85" width="18" height="18"/></clipPath><g clip-path="url(#svgic6)"><g transform="matrix(.75 0 0 .75 37 85)"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M5.5 5.1 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.4-6.9A2 2 0 0 0 16.8 4H7.2a2 2 0 0 0-1.7 1.1" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp7)"><g clip-path="url(#ov8)"><text x="63" y="100" font-family="system-ui, "-apple-system", sans-serif" font-size="16" font-weight="650" fill="rgb(245,245,247)">Inbox</text></g></g></g></g><g clip-path="url(#cp10)"><rect x="28.5" y="124.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#ov11)"><g clip-path="url(#cp12)"><g color="rgb(245, 245, 247)"><clipPath id="svgic13"><rect x="37" y="137" width="18" height="18"/></clipPath><g clip-path="url(#svgic13)"><g transform="matrix(.75 0 0 .75 37 137)"><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.7-.9l-.8-1.2A2 2 0 0 0 7.9 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp14)"><g clip-path="url(#ov15)"><text x="63" y="152" font-family="system-ui, "-apple-system", sans-serif" font-size="16" fill="rgb(245,245,247)">Projects</text></g></g></g></g></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 230" width="420" height="230"><defs><clipPath id="cp0"><rect x="29" y="34.5" width="81.8" height="15"/></clipPath><clipPath id="ct1"><rect x="29" y="34.5" width="81.8" height="15"/></clipPath><clipPath id="ct2"><rect x="118.8" y="
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 230" width="420" height="230"><defs><clipPath id="cp0"><rect x="29" y="34.5" width="81.8" height="15"/></clipPath><clipPath id="ct1"><rect x="29" y="34.5" width="81.8" height="15"/></clipPath><clipPath id="ct2"><rect x="118.8" y="33" width="9.3" height="18"/></clipPath><clipPath id="cp3"><rect x="28" y="72" width="324" height="44"/></clipPath><clipPath id="ov4"><rect x="29" y="73" width="322" height="42" rx="11"/></clipPath><clipPath id="cp5"><rect x="37" y="85" width="18" height="18"/></clipPath><clipPath id="cp7"><rect x="63" y="85" width="272" height="18"/></clipPath><clipPath id="ov8"><rect x="63" y="85" width="272" height="18" rx="0"/></clipPath><clipPath id="ct9"><rect x="63" y="85" width="272" height="18"/></clipPath><clipPath id="cp10"><rect x="28" y="124" width="324" height="44"/></clipPath><clipPath id="ov11"><rect x="29" y="125" width="322" height="42" rx="11"/></clipPath><clipPath id="cp12"><rect x="37" y="137" width="18" height="18"/></clipPath><clipPath id="cp14"><rect x="63" y="137" width="272" height="18"/></clipPath><clipPath id="ov15"><rect x="63" y="137" width="272" height="18" rx="0"/></clipPath><clipPath id="ct16"><rect x="63" y="137" width="272" height="18"/></clipPath></defs><rect x="28.5" y="20.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp0)"><g clip-path="url(#ct1)"><text x="29" y="46.5" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="650" fill="rgb(110,110,115)">WORKSPACE</text></g></g><text x="118.81" y="48" font-family="system-ui, "-apple-system", sans-serif" font-size="16" fill="rgb(110,110,115)">2</text><g clip-path="url(#cp3)"><rect x="28" y="72" width="324" height="44" rx="12" fill="rgb(214,236,255)"/><rect x="28.5" y="72.5" width="323" height="43" rx="11.5" fill="none" stroke="rgb(166,213,255)" stroke-width="1"/><g clip-path="url(#ov4)"><g clip-path="url(#cp5)"><g color="rgb(29, 29, 31)"><clipPath id="svgic6"><rect x="37" y="85" width="18" height="18"/></clipPath><g clip-path="url(#svgic6)"><g transform="matrix(.75 0 0 .75 37 85)"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M5.5 5.1 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.4-6.9A2 2 0 0 0 16.8 4H7.2a2 2 0 0 0-1.7 1.1" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp7)"><g clip-path="url(#ov8)"><text x="63" y="100" font-family="system-ui, "-apple-system", sans-serif" font-size="16" font-weight="650" fill="rgb(29,29,31)">Inbox</text></g></g></g></g><g clip-path="url(#cp10)"><rect x="28.5" y="124.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#ov11)"><g clip-path="url(#cp12)"><g color="rgb(29, 29, 31)"><clipPath id="svgic13"><rect x="37" y="137" width="18" height="18"/></clipPath><g clip-path="url(#svgic13)"><g transform="matrix(.75 0 0 .75 37 137)"><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.7-.9l-.8-1.2A2 2 0 0 0 7.9 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(29, 29, 31)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#cp14)"><g clip-path="url(#ov15)"><text x="63" y="152" font-family="system-ui, "-apple-system", sans-serif" font-size="16" fill="rgb(29,29,31)">Projects</text></g></g></g></g></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 452 512" width="452" height="512"><defs><clipPath id="cp0"><rect x="16" y="38" width="420" height="230"/></clipPath><clipPath id="cp1"><rect x="16" y="306" width="420" height="190"/></clipPath><clipPath id="ct2"><rect x="16" y="16" width="420" height="22"/></clipPath><clipPath id="irc3"><rect x="16" y="38" width="420" height="230" rx="0"/></clipPath><clipPath id="ct5"><rect x="16" y="284" width="420" height="22"/></clipPath><clipPath id="irc6"><rect x="16" y="306" width="420" height="190" rx="0"/></clipPath></defs><rect x="0" y="0" width="452" height="512" rx="0" fill="rgb(28,28,30)"/><text x="16" y="28" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="600" fill="rgb(174,174,178)">Standard gap and four dividers</text><g clip-path="url(#cp0)"><g clip-path="url(#irc3)"><clipPath id="svgimg4vclip"><rect x="16" y="38" width="420" height="230"/></clipPath><g clip-path="url(#svgimg4vclip)"><g transform="translate(16 38)"><defs><clipPath id="svgimg4cp0"><rect x="29" y="34.5" width="81.8" height="15"/></clipPath><clipPath id="svgimg4ct1"><rect x="29" y="34.5" width="81.8" height="15"/></clipPath><clipPath id="svgimg4ct2"><rect x="118.8" y="31.2" width="21.6" height="21.6"/></clipPath><clipPath id="svgimg4cp3"><rect x="28" y="72" width="324" height="44"/></clipPath><clipPath id="svgimg4ov4"><rect x="29" y="73" width="322" height="42" rx="11"/></clipPath><clipPath id="svgimg4cp5"><rect x="37" y="85" width="18" height="18"/></clipPath><clipPath id="svgimg4cp7"><rect x="63" y="85" width="272" height="18"/></clipPath><clipPath id="svgimg4ov8"><rect x="63" y="85" width="272" height="18" rx="0"/></clipPath><clipPath id="svgimg4ct9"><rect x="63" y="85" width="272" height="18"/></clipPath><clipPath id="svgimg4cp10"><rect x="28" y="124" width="324" height="44"/></clipPath><clipPath id="svgimg4ov11"><rect x="29" y="125" width="322" height="42" rx="11"/></clipPath><clipPath id="svgimg4cp12"><rect x="37" y="137" width="18" height="18"/></clipPath><clipPath id="svgimg4cp14"><rect x="63" y="137" width="272" height="18"/></clipPath><clipPath id="svgimg4ov15"><rect x="63" y="137" width="272" height="18" rx="0"/></clipPath><clipPath id="svgimg4ct16"><rect x="63" y="137" width="272" height="18"/></clipPath></defs><rect x="28.5" y="20.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg4cp0)"><g clip-path="url(#svgimg4ct1)"><text x="29" y="46.5" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="650" fill="rgb(174,174,178)">WORKSPACE</text></g></g><rect x="118.8" y="31.2" width="21.6" height="21.6" rx="10.8" fill="rgb(17,17,19)"/><text x="126.33" y="46" font-family="system-ui, "-apple-system", sans-serif" font-size="10" font-weight="700" fill="rgb(174,174,178)">2</text><g clip-path="url(#svgimg4cp3)"><rect x="28" y="72" width="324" height="44" rx="12" fill="rgb(40,57,66)"/><rect x="28.5" y="72.5" width="323" height="43" rx="11.5" fill="none" stroke="rgb(53,92,109)" stroke-width="1"/><g clip-path="url(#svgimg4ov4)"><g clip-path="url(#svgimg4cp5)"><g color="rgb(245, 245, 247)"><clipPath id="svgimg4svgic6"><rect x="37" y="85" width="18" height="18"/></clipPath><g clip-path="url(#svgimg4svgic6)"><g transform="matrix(.75 0 0 .75 37 85)"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M5.5 5.1 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.4-6.9A2 2 0 0 0 16.8 4H7.2a2 2 0 0 0-1.7 1.1" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#svgimg4cp7)"><g clip-path="url(#svgimg4ov8)"><text x="63" y="100" font-family="system-ui, "-apple-system", sans-serif" font-size="16" font-weight="650" fill="rgb(245,245,247)">Inbox</text></g></g></g></g><g clip-path="url(#svgimg4cp10)"><rect x="28.5" y="124.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg4ov11)"><g clip-path="url(#svgimg4cp12)"><g color="rgb(245, 245, 247)"><clipPath id="svgimg4svgic13"><rect x="37" y="137" width="18" height="18"/></clipPath><g clip-path="url(#svgimg4svgic13)"><g transform="matrix(.75 0 0 .75 37 137)"><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.7-.9l-.8-1.2A2 2 0 0 0 7.9 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#svgimg4cp14)"><g clip-path="url(#svgimg4ov15)"><text x="63" y="152" font-family="system-ui, "-apple-system", sans-serif" font-size="16" fill="rgb(245,245,247)">Projects</text></g></g></g></g></g></g></g></g><text x="16" y="296" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="600" fill="rgb(174,174,178)">Compact, no gap</text><g clip-path="url(#cp1)"><g clip-path="url(#irc6)"><clipPath id="svgimg7vclip"><rect x="16" y="306" width="420" height="190"/></clipPath><g clip-path="url(#svgimg7vclip)"><g transform="translate(16 306)"><defs><clipPath id="svgimg7cp0"><rect x="28" y="20" width="324" height="44"/></clipPath><clipPath id="svgimg7ov1"><rect x="29" y="21" width="322" height="42" rx="11"/></clipPath><clipPath id="svgimg7cp2"><rect x="37" y="33" width="18" height="18"/></clipPath><clipPath id="svgimg7cp4"><rect x="63" y="33" width="272" height="18"/></clipPath><clipPath id="svgimg7ov5"><rect x="63" y="33" width="272" height="18" rx="0"/></clipPath><clipPath id="svgimg7ct6"><rect x="63" y="33" width="272" height="18"/></clipPath><clipPath id="svgimg7cp7"><rect x="28" y="64" width="324" height="44"/></clipPath><clipPath id="svgimg7ov8"><rect x="29" y="65" width="322" height="42" rx="11"/></clipPath><clipPath id="svgimg7cp9"><rect x="37" y="77" width="18" height="18"/></clipPath><clipPath id="svgimg7cp11"><rect x="63" y="77" width="272" height="18"/></clipPath><clipPath id="svgimg7ov12"><rect x="63" y="77" width="272" height="18" rx="0"/></clipPath><clipPath id="svgimg7ct13"><rect x="63" y="77" width="272" height="18"/></clipPath></defs><g clip-path="url(#svgimg7cp0)"><rect x="28.5" y="20.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg7ov1)"><g clip-path="url(#svgimg7cp2)"><g color="rgb(245, 245, 247)"><clipPath id="svgimg7svgic3"><rect x="37" y="33" width="18" height="18"/></clipPath><g clip-path="url(#svgimg7svgic3)"><g transform="matrix(.75 0 0 .75 37 33)"><path d="M11.5 2.3a.5.5 0 0 1 1 0L14.8 7a2 2 0 0 0 1.6 1l5.1.8a.5.5 0 0 1 .3.9l-3.7 3.6a2 2 0 0 0-.6 2l.9 5a.5.5 0 0 1-.8.6L13 18.6a2 2 0 0 0-2 0L6.4 21a.5.5 0 0 1-.8-.6l1-5a2 2 0 0 0-.7-2L2.2 9.8a.5.5 0 0 1 .3-1l5.1-.7A2 2 0 0 0 9.2 7Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#svgimg7cp4)"><g clip-path="url(#svgimg7ov5)"><text x="63" y="48" font-family="system-ui, "-apple-system", sans-serif" font-size="16" fill="rgb(245,245,247)">Priority</text></g></g></g></g><g clip-path="url(#svgimg7cp7)"><rect x="28.5" y="64.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg7ov8)"><g clip-path="url(#svgimg7cp9)"><g color="rgb(245, 245, 247)"><clipPath id="svgimg7svgic10"><rect x="37" y="77" width="18" height="18"/></clipPath><g clip-path="url(#svgimg7svgic10)"><g transform="matrix(.75 0 0 .75 37 77)"><path d="M3 5z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M3 12z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M3 19z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M8 5h13" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M8 12h13" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M8 19h13" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#svgimg7cp11)"><g clip-path="url(#svgimg7ov12)"><text x="63" y="92" font-family="system-ui, "-apple-system", sans-serif" font-size="16" fill="rgb(245,245,247)">All work</text></g></g></g></g></g></g></g></g></svg>
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 452 512" width="452" height="512"><defs><clipPath id="cp0"><rect x="16" y="38" width="420" height="230"/></clipPath><clipPath id="cp1"><rect x="16" y="306" width="420" height="190"/></clipPath><clipPath id="ct2"><rect x="16" y="16" width="420" height="22"/></clipPath><clipPath id="irc3"><rect x="16" y="38" width="420" height="230" rx="0"/></clipPath><clipPath id="ct5"><rect x="16" y="284" width="420" height="22"/></clipPath><clipPath id="irc6"><rect x="16" y="306" width="420" height="190" rx="0"/></clipPath></defs><rect x="0" y="0" width="452" height="512" rx="0" fill="rgb(28,28,30)"/><text x="16" y="28" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="600" fill="rgb(174,174,178)">Standard gap and four dividers</text><g clip-path="url(#cp0)"><g clip-path="url(#irc3)"><clipPath id="svgimg4vclip"><rect x="16" y="38" width="420" height="230"/></clipPath><g clip-path="url(#svgimg4vclip)"><g transform="translate(16 38)"><defs><clipPath id="svgimg4cp0"><rect x="29" y="34.5" width="81.8" height="15"/></clipPath><clipPath id="svgimg4ct1"><rect x="29" y="34.5" width="81.8" height="15"/></clipPath><clipPath id="svgimg4ct2"><rect x="118.8" y="33" width="9.3" height="18"/></clipPath><clipPath id="svgimg4cp3"><rect x="28" y="72" width="324" height="44"/></clipPath><clipPath id="svgimg4ov4"><rect x="29" y="73" width="322" height="42" rx="11"/></clipPath><clipPath id="svgimg4cp5"><rect x="37" y="85" width="18" height="18"/></clipPath><clipPath id="svgimg4cp7"><rect x="63" y="85" width="272" height="18"/></clipPath><clipPath id="svgimg4ov8"><rect x="63" y="85" width="272" height="18" rx="0"/></clipPath><clipPath id="svgimg4ct9"><rect x="63" y="85" width="272" height="18"/></clipPath><clipPath id="svgimg4cp10"><rect x="28" y="124" width="324" height="44"/></clipPath><clipPath id="svgimg4ov11"><rect x="29" y="125" width="322" height="42" rx="11"/></clipPath><clipPath id="svgimg4cp12"><rect x="37" y="137" width="18" height="18"/></clipPath><clipPath id="svgimg4cp14"><rect x="63" y="137" width="272" height="18"/></clipPath><clipPath id="svgimg4ov15"><rect x="63" y="137" width="272" height="18" rx="0"/></clipPath><clipPath id="svgimg4ct16"><rect x="63" y="137" width="272" height="18"/></clipPath></defs><rect x="28.5" y="20.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg4cp0)"><g clip-path="url(#svgimg4ct1)"><text x="29" y="46.5" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="650" fill="rgb(174,174,178)">WORKSPACE</text></g></g><text x="118.81" y="48" font-family="system-ui, "-apple-system", sans-serif" font-size="16" fill="rgb(174,174,178)">2</text><g clip-path="url(#svgimg4cp3)"><rect x="28" y="72" width="324" height="44" rx="12" fill="rgb(40,57,66)"/><rect x="28.5" y="72.5" width="323" height="43" rx="11.5" fill="none" stroke="rgb(53,92,109)" stroke-width="1"/><g clip-path="url(#svgimg4ov4)"><g clip-path="url(#svgimg4cp5)"><g color="rgb(245, 245, 247)"><clipPath id="svgimg4svgic6"><rect x="37" y="85" width="18" height="18"/></clipPath><g clip-path="url(#svgimg4svgic6)"><g transform="matrix(.75 0 0 .75 37 85)"><polyline points="22 12 16 12 14 15 10 15 8 12 2 12" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M5.5 5.1 2 12v6a2 2 0 0 0 2 2h16a2 2 0 0 0 2-2v-6l-3.4-6.9A2 2 0 0 0 16.8 4H7.2a2 2 0 0 0-1.7 1.1" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#svgimg4cp7)"><g clip-path="url(#svgimg4ov8)"><text x="63" y="100" font-family="system-ui, "-apple-system", sans-serif" font-size="16" font-weight="650" fill="rgb(245,245,247)">Inbox</text></g></g></g></g><g clip-path="url(#svgimg4cp10)"><rect x="28.5" y="124.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg4ov11)"><g clip-path="url(#svgimg4cp12)"><g color="rgb(245, 245, 247)"><clipPath id="svgimg4svgic13"><rect x="37" y="137" width="18" height="18"/></clipPath><g clip-path="url(#svgimg4svgic13)"><g transform="matrix(.75 0 0 .75 37 137)"><path d="M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.7-.9l-.8-1.2A2 2 0 0 0 7.9 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#svgimg4cp14)"><g clip-path="url(#svgimg4ov15)"><text x="63" y="152" font-family="system-ui, "-apple-system", sans-serif" font-size="16" fill="rgb(245,245,247)">Projects</text></g></g></g></g></g></g></g></g><text x="16" y="296" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="600" fill="rgb(174,174,178)">Compact, no gap</text><g clip-path="url(#cp1)"><g clip-path="url(#irc6)"><clipPath id="svgimg7vclip"><rect x="16" y="306" width="420" height="190"/></clipPath><g clip-path="url(#svgimg7vclip)"><g transform="translate(16 306)"><defs><clipPath id="svgimg7cp0"><rect x="28" y="20" width="324" height="44"/></clipPath><clipPath id="svgimg7ov1"><rect x="29" y="21" width="322" height="42" rx="11"/></clipPath><clipPath id="svgimg7cp2"><rect x="37" y="33" width="18" height="18"/></clipPath><clipPath id="svgimg7cp4"><rect x="63" y="33" width="272" height="18"/></clipPath><clipPath id="svgimg7ov5"><rect x="63" y="33" width="272" height="18" rx="0"/></clipPath><clipPath id="svgimg7ct6"><rect x="63" y="33" width="272" height="18"/></clipPath><clipPath id="svgimg7cp7"><rect x="28" y="64" width="324" height="44"/></clipPath><clipPath id="svgimg7ov8"><rect x="29" y="65" width="322" height="42" rx="11"/></clipPath><clipPath id="svgimg7cp9"><rect x="37" y="77" width="18" height="18"/></clipPath><clipPath id="svgimg7cp11"><rect x="63" y="77" width="272" height="18"/></clipPath><clipPath id="svgimg7ov12"><rect x="63" y="77" width="272" height="18" rx="0"/></clipPath><clipPath id="svgimg7ct13"><rect x="63" y="77" width="272" height="18"/></clipPath></defs><g clip-path="url(#svgimg7cp0)"><rect x="28.5" y="20.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg7ov1)"><g clip-path="url(#svgimg7cp2)"><g color="rgb(245, 245, 247)"><clipPath id="svgimg7svgic3"><rect x="37" y="33" width="18" height="18"/></clipPath><g clip-path="url(#svgimg7svgic3)"><g transform="matrix(.75 0 0 .75 37 33)"><path d="M11.5 2.3a.5.5 0 0 1 1 0L14.8 7a2 2 0 0 0 1.6 1l5.1.8a.5.5 0 0 1 .3.9l-3.7 3.6a2 2 0 0 0-.6 2l.9 5a.5.5 0 0 1-.8.6L13 18.6a2 2 0 0 0-2 0L6.4 21a.5.5 0 0 1-.8-.6l1-5a2 2 0 0 0-.7-2L2.2 9.8a.5.5 0 0 1 .3-1l5.1-.7A2 2 0 0 0 9.2 7Z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#svgimg7cp4)"><g clip-path="url(#svgimg7ov5)"><text x="63" y="48" font-family="system-ui, "-apple-system", sans-serif" font-size="16" fill="rgb(245,245,247)">Priority</text></g></g></g></g><g clip-path="url(#svgimg7cp7)"><rect x="28.5" y="64.5" width="323" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#svgimg7ov8)"><g clip-path="url(#svgimg7cp9)"><g color="rgb(245, 245, 247)"><clipPath id="svgimg7svgic10"><rect x="37" y="77" width="18" height="18"/></clipPath><g clip-path="url(#svgimg7svgic10)"><g transform="matrix(.75 0 0 .75 37 77)"><path d="M3 5z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M3 12z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M3 19z" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M8 5h13" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M8 12h13" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M8 19h13" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(245, 245, 247)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g clip-path="url(#svgimg7cp11)"><g clip-path="url(#svgimg7ov12)"><text x="63" y="92" font-family="system-ui, "-apple-system", sans-serif" font-size="16" fill="rgb(245,245,247)">All work</text></g></g></g></g></g></g></g></g></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 92" width="420" height="92"><defs><clipPath id="cp0"><rect x="29" y="34.5" width="104.6" height="15"/></clipPath><clipPath id="ct1"><rect x="29" y="34.5" width="104.6" height="15"/></clipPath><clipPath id="cp2"><rect x="
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 92" width="420" height="92"><defs><clipPath id="cp0"><rect x="29" y="34.5" width="104.6" height="15"/></clipPath><clipPath id="ct1"><rect x="29" y="34.5" width="104.6" height="15"/></clipPath><clipPath id="cp2"><rect x="361" y="33" width="18" height="18"/></clipPath></defs><rect x="28.5" y="20.5" width="315" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp0)"><g clip-path="url(#ct1)"><text x="29" y="46.5" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="650" fill="rgb(174,174,178)">TEAM MEMBERS</text></g></g><rect x="352.5" y="24.5" width="35" height="35" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp2)"><g color="rgb(174, 174, 178)"><clipPath id="svgic3"><rect x="361" y="33" width="18" height="18"/></clipPath><g clip-path="url(#svgic3)"><g transform="matrix(.75 0 0 .75 361 33)"><path d="M5 12h14" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M12 5v14" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(174, 174, 178)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g data-domotion-pseudo-source="blink-pseudo-fragment-v1" data-domotion-pseudo="::before" data-domotion-pseudo-owner="source-fragments"><g/></g></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 92" width="420" height="92"><defs><clipPath id="cp0"><rect x="29" y="34.5" width="104.6" height="15"/></clipPath><clipPath id="ct1"><rect x="29" y="34.5" width="104.6" height="15"/></clipPath><clipPath id="cp2"><rect x="
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 92" width="420" height="92"><defs><clipPath id="cp0"><rect x="29" y="34.5" width="104.6" height="15"/></clipPath><clipPath id="ct1"><rect x="29" y="34.5" width="104.6" height="15"/></clipPath><clipPath id="cp2"><rect x="361" y="33" width="18" height="18"/></clipPath></defs><rect x="28.5" y="20.5" width="315" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp0)"><g clip-path="url(#ct1)"><text x="29" y="46.5" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="650" fill="rgb(110,110,115)">TEAM MEMBERS</text></g></g><rect x="352.5" y="24.5" width="35" height="35" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp2)"><g color="rgb(110, 110, 115)"><clipPath id="svgic3"><rect x="361" y="33" width="18" height="18"/></clipPath><g clip-path="url(#svgic3)"><g transform="matrix(.75 0 0 .75 361 33)"><path d="M5 12h14" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/><path d="M12 5v14" style="marker:none;vector-effect:none;color-interpolation:srgb" fill="none" stroke="rgb(110, 110, 115)" stroke-width="2px" stroke-dasharray="none" stroke-linecap="round" stroke-linejoin="round" stroke-opacity="1" fill-opacity="1" opacity="1"/></g></g></g></g><g data-domotion-pseudo-source="blink-pseudo-fragment-v1" data-domotion-pseudo="::before" data-domotion-pseudo-owner="source-fragments"><g/></g></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 92" width="420" height="92"><defs><clipPath id="cp0"><rect x="29" y="34.5" width="95" height="15"/></clipPath><clipPath id="ct1"><rect x="29" y="34.5" width="95" height="15"/></clipPath><clipPath id="ct2"><rect x="132" y="
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 92" width="420" height="92"><defs><clipPath id="cp0"><rect x="29" y="34.5" width="95" height="15"/></clipPath><clipPath id="ct1"><rect x="29" y="34.5" width="95" height="15"/></clipPath><clipPath id="ct2"><rect x="132" y="33" width="16.5" height="18"/></clipPath></defs><rect x="28.5" y="20.5" width="363" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp0)"><g clip-path="url(#ct1)"><text x="29" y="46.5" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="650" fill="rgb(174,174,178)">OPEN TICKETS</text></g></g><text x="132.05" y="48" font-family="system-ui, "-apple-system", sans-serif" font-size="16" fill="rgb(174,174,178)">12</text></svg>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 92" width="420" height="92"><defs><clipPath id="cp0"><rect x="29" y="34.5" width="95" height="15"/></clipPath><clipPath id="ct1"><rect x="29" y="34.5" width="95" height="15"/></clipPath><clipPath id="ct2"><rect x="132" y="
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 420 92" width="420" height="92"><defs><clipPath id="cp0"><rect x="29" y="34.5" width="95" height="15"/></clipPath><clipPath id="ct1"><rect x="29" y="34.5" width="95" height="15"/></clipPath><clipPath id="ct2"><rect x="132" y="33" width="16.5" height="18"/></clipPath></defs><rect x="28.5" y="20.5" width="363" height="43" rx="11.5" fill="none" stroke="rgba(0,0,0,0)" stroke-width="1"/><g clip-path="url(#cp0)"><g clip-path="url(#ct1)"><text x="29" y="46.5" font-family="system-ui, "-apple-system", sans-serif" font-size="12" font-weight="650" fill="rgb(110,110,115)">OPEN TICKETS</text></g></g><text x="132.05" y="48" font-family="system-ui, "-apple-system", sans-serif" font-size="16" fill="rgb(110,110,115)">12</text></svg>
|