@panphora/bevel 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +16 -0
- package/README.md +226 -0
- package/bevel-fonts.css +16 -0
- package/bevel.css +3075 -0
- package/bevel.js +2126 -0
- package/dist/react/components/activity-feed.d.ts +89 -0
- package/dist/react/components/activity-feed.js +54 -0
- package/dist/react/components/alert-dialog.d.ts +14 -0
- package/dist/react/components/alert-dialog.js +19 -0
- package/dist/react/components/app-shell.d.ts +98 -0
- package/dist/react/components/app-shell.js +86 -0
- package/dist/react/components/app-toolbar.d.ts +19 -0
- package/dist/react/components/app-toolbar.js +22 -0
- package/dist/react/components/avatar-group.d.ts +67 -0
- package/dist/react/components/avatar-group.js +49 -0
- package/dist/react/components/badge-and-pill.d.ts +34 -0
- package/dist/react/components/badge-and-pill.js +12 -0
- package/dist/react/components/breadcrumbs.d.ts +56 -0
- package/dist/react/components/breadcrumbs.js +44 -0
- package/dist/react/components/bulk-bar.d.ts +22 -0
- package/dist/react/components/bulk-bar.js +59 -0
- package/dist/react/components/button.d.ts +15 -0
- package/dist/react/components/button.js +20 -0
- package/dist/react/components/callout-and-hint.d.ts +17 -0
- package/dist/react/components/callout-and-hint.js +8 -0
- package/dist/react/components/checkbox.d.ts +5 -0
- package/dist/react/components/checkbox.js +13 -0
- package/dist/react/components/chip.d.ts +149 -0
- package/dist/react/components/chip.js +29 -0
- package/dist/react/components/code-block.d.ts +50 -0
- package/dist/react/components/code-block.js +77 -0
- package/dist/react/components/code-editor.d.ts +122 -0
- package/dist/react/components/code-editor.js +695 -0
- package/dist/react/components/column-manager.d.ts +28 -0
- package/dist/react/components/column-manager.js +85 -0
- package/dist/react/components/combobox.d.ts +32 -0
- package/dist/react/components/combobox.js +37 -0
- package/dist/react/components/data-grid.d.ts +108 -0
- package/dist/react/components/data-grid.js +159 -0
- package/dist/react/components/data-table.d.ts +2 -0
- package/dist/react/components/data-table.js +6 -0
- package/dist/react/components/date.d.ts +23 -0
- package/dist/react/components/date.js +11 -0
- package/dist/react/components/details.d.ts +13 -0
- package/dist/react/components/details.js +20 -0
- package/dist/react/components/dialog.d.ts +74 -0
- package/dist/react/components/dialog.js +31 -0
- package/dist/react/components/diff-view.d.ts +73 -0
- package/dist/react/components/diff-view.js +68 -0
- package/dist/react/components/documents.d.ts +70 -0
- package/dist/react/components/documents.js +10 -0
- package/dist/react/components/drawer.d.ts +45 -0
- package/dist/react/components/drawer.js +35 -0
- package/dist/react/components/editable-grid-cells.d.ts +32 -0
- package/dist/react/components/editable-grid-cells.js +116 -0
- package/dist/react/components/eyebrow-kicker-lede-pull-quote.d.ts +39 -0
- package/dist/react/components/eyebrow-kicker-lede-pull-quote.js +12 -0
- package/dist/react/components/field.d.ts +32 -0
- package/dist/react/components/field.js +27 -0
- package/dist/react/components/file-tree.d.ts +75 -0
- package/dist/react/components/file-tree.js +247 -0
- package/dist/react/components/file.d.ts +43 -0
- package/dist/react/components/file.js +73 -0
- package/dist/react/components/files-table.d.ts +174 -0
- package/dist/react/components/files-table.js +237 -0
- package/dist/react/components/filter-builder.d.ts +37 -0
- package/dist/react/components/filter-builder.js +109 -0
- package/dist/react/components/form-error-summary.d.ts +16 -0
- package/dist/react/components/form-error-summary.js +49 -0
- package/dist/react/components/icon-button.d.ts +8 -0
- package/dist/react/components/icon-button.js +14 -0
- package/dist/react/components/icon.d.ts +7 -0
- package/dist/react/components/icon.js +15 -0
- package/dist/react/components/image.d.ts +72 -0
- package/dist/react/components/image.js +24 -0
- package/dist/react/components/inline-edit.d.ts +70 -0
- package/dist/react/components/inline-edit.js +149 -0
- package/dist/react/components/input.d.ts +29 -0
- package/dist/react/components/input.js +20 -0
- package/dist/react/components/kanban-board.d.ts +140 -0
- package/dist/react/components/kanban-board.js +374 -0
- package/dist/react/components/layout.d.ts +51 -0
- package/dist/react/components/layout.js +28 -0
- package/dist/react/components/list.d.ts +28 -0
- package/dist/react/components/list.js +6 -0
- package/dist/react/components/masthead-and-verdict.d.ts +60 -0
- package/dist/react/components/masthead-and-verdict.js +8 -0
- package/dist/react/components/menu.d.ts +26 -0
- package/dist/react/components/menu.js +31 -0
- package/dist/react/components/multi-select-picker.d.ts +49 -0
- package/dist/react/components/multi-select-picker.js +20 -0
- package/dist/react/components/note.d.ts +33 -0
- package/dist/react/components/note.js +8 -0
- package/dist/react/components/number-field.d.ts +16 -0
- package/dist/react/components/number-field.js +17 -0
- package/dist/react/components/pagination.d.ts +45 -0
- package/dist/react/components/pagination.js +87 -0
- package/dist/react/components/persistent-action-banner.d.ts +71 -0
- package/dist/react/components/persistent-action-banner.js +39 -0
- package/dist/react/components/popconfirm.d.ts +42 -0
- package/dist/react/components/popconfirm.js +59 -0
- package/dist/react/components/popover.d.ts +16 -0
- package/dist/react/components/popover.js +21 -0
- package/dist/react/components/progress-and-gauge.d.ts +44 -0
- package/dist/react/components/progress-and-gauge.js +19 -0
- package/dist/react/components/radio.d.ts +7 -0
- package/dist/react/components/radio.js +13 -0
- package/dist/react/components/rich-text-toolbar.d.ts +26 -0
- package/dist/react/components/rich-text-toolbar.js +64 -0
- package/dist/react/components/rows-and-card.d.ts +88 -0
- package/dist/react/components/rows-and-card.js +10 -0
- package/dist/react/components/save-status-indicator.d.ts +11 -0
- package/dist/react/components/save-status-indicator.js +33 -0
- package/dist/react/components/segmented-control.d.ts +21 -0
- package/dist/react/components/segmented-control.js +15 -0
- package/dist/react/components/select.d.ts +29 -0
- package/dist/react/components/select.js +29 -0
- package/dist/react/components/selectable-cards.d.ts +30 -0
- package/dist/react/components/selectable-cards.js +29 -0
- package/dist/react/components/settings-rows.d.ts +51 -0
- package/dist/react/components/settings-rows.js +8 -0
- package/dist/react/components/sidebar-nav.d.ts +77 -0
- package/dist/react/components/sidebar-nav.js +41 -0
- package/dist/react/components/skeleton-and-empty.d.ts +51 -0
- package/dist/react/components/skeleton-and-empty.js +14 -0
- package/dist/react/components/slider.d.ts +19 -0
- package/dist/react/components/slider.js +17 -0
- package/dist/react/components/small-charts.d.ts +60 -0
- package/dist/react/components/small-charts.js +76 -0
- package/dist/react/components/sortable.d.ts +30 -0
- package/dist/react/components/sortable.js +85 -0
- package/dist/react/components/split-button.d.ts +38 -0
- package/dist/react/components/split-button.js +43 -0
- package/dist/react/components/split-panes.d.ts +35 -0
- package/dist/react/components/split-panes.js +102 -0
- package/dist/react/components/stat-tiles.d.ts +54 -0
- package/dist/react/components/stat-tiles.js +8 -0
- package/dist/react/components/steps.d.ts +11 -0
- package/dist/react/components/steps.js +13 -0
- package/dist/react/components/switch.d.ts +6 -0
- package/dist/react/components/switch.js +13 -0
- package/dist/react/components/table.d.ts +61 -0
- package/dist/react/components/table.js +6 -0
- package/dist/react/components/tabs.d.ts +7 -0
- package/dist/react/components/tabs.js +13 -0
- package/dist/react/components/tags.d.ts +33 -0
- package/dist/react/components/tags.js +83 -0
- package/dist/react/components/textarea.d.ts +10 -0
- package/dist/react/components/textarea.js +6 -0
- package/dist/react/components/toast.d.ts +35 -0
- package/dist/react/components/toast.js +90 -0
- package/dist/react/components/tooltip-and-key.d.ts +20 -0
- package/dist/react/components/tooltip-and-key.js +20 -0
- package/dist/react/components/tree-view.d.ts +34 -0
- package/dist/react/components/tree-view.js +118 -0
- package/dist/react/components/upload-dropzone.d.ts +92 -0
- package/dist/react/components/upload-dropzone.js +116 -0
- package/dist/react/components/wizard-shell.d.ts +78 -0
- package/dist/react/components/wizard-shell.js +176 -0
- package/dist/react/fonts.css.d.ts +1 -0
- package/dist/react/index.d.ts +76 -0
- package/dist/react/index.js +77 -0
- package/dist/react/integrations/quickcrop.d.ts +58 -0
- package/dist/react/integrations/quickcrop.js +137 -0
- package/dist/react/integrations/richclay.d.ts +43 -0
- package/dist/react/integrations/richclay.js +129 -0
- package/dist/react/internal/classes.d.ts +3 -0
- package/dist/react/internal/classes.js +10 -0
- package/dist/react/internal/close-mark.d.ts +1 -0
- package/dist/react/internal/close-mark.js +10 -0
- package/dist/react/internal/controllable-state.d.ts +9 -0
- package/dist/react/internal/controllable-state.js +22 -0
- package/dist/react/internal/drop-effect.d.ts +28 -0
- package/dist/react/internal/drop-effect.js +8 -0
- package/dist/react/internal/form-reset.d.ts +2 -0
- package/dist/react/internal/form-reset.js +22 -0
- package/dist/react/internal/format.d.ts +1 -0
- package/dist/react/internal/format.js +14 -0
- package/dist/react/internal/link.d.ts +2 -0
- package/dist/react/internal/link.js +8 -0
- package/dist/react/internal/part.d.ts +20 -0
- package/dist/react/internal/part.js +47 -0
- package/dist/react/internal/pointer-session.d.ts +8 -0
- package/dist/react/internal/pointer-session.js +60 -0
- package/dist/react/internal/refs.d.ts +2 -0
- package/dist/react/internal/refs.js +22 -0
- package/dist/react/internal/rich-text.d.ts +28 -0
- package/dist/react/internal/rich-text.js +4 -0
- package/dist/react/internal/table-context.d.ts +39 -0
- package/dist/react/internal/table-context.js +12 -0
- package/dist/react/internal/use-object-url.d.ts +1 -0
- package/dist/react/internal/use-object-url.js +15 -0
- package/dist/react/layout.css +274 -0
- package/dist/react/layout.css.d.ts +1 -0
- package/dist/react/models/filter.d.ts +31 -0
- package/dist/react/models/filter.js +79 -0
- package/dist/react/models/kanban.d.ts +51 -0
- package/dist/react/models/kanban.js +35 -0
- package/dist/react/models/reorder.d.ts +9 -0
- package/dist/react/models/reorder.js +23 -0
- package/dist/react/models/table.d.ts +85 -0
- package/dist/react/models/table.js +144 -0
- package/dist/react/models/tree.d.ts +16 -0
- package/dist/react/models/tree.js +26 -0
- package/dist/react/provider.d.ts +18 -0
- package/dist/react/provider.js +31 -0
- package/dist/react/recipes/context-hypercms.d.ts +17 -0
- package/dist/react/recipes/context-hypercms.js +71 -0
- package/dist/react/recipes/context-quickcrop.d.ts +8 -0
- package/dist/react/recipes/context-quickcrop.js +49 -0
- package/dist/react/theme.css +8004 -0
- package/dist/react/theme.css.d.ts +1 -0
- package/examples/README.md +34 -0
- package/examples/components/activity-feed.html +28 -0
- package/examples/components/app-shell.html +12 -0
- package/examples/components/app-toolbar.html +38 -0
- package/examples/components/avatar-group.html +27 -0
- package/examples/components/breadcrumbs.html +26 -0
- package/examples/components/bulk-bar.html +22 -0
- package/examples/components/code-block.html +12 -0
- package/examples/components/code-editor.html +25 -0
- package/examples/components/column-manager.html +9 -0
- package/examples/components/combobox.html +13 -0
- package/examples/components/context-hypercms.css +41 -0
- package/examples/components/context-hypercms.html +40 -0
- package/examples/components/context-hypercms.js +62 -0
- package/examples/components/context-quickcrop.html +137 -0
- package/examples/components/diff-view.html +9 -0
- package/examples/components/drawer.html +11 -0
- package/examples/components/editable-grid-cells.html +9 -0
- package/examples/components/file-browser.html +53 -0
- package/examples/components/file-tree.html +34 -0
- package/examples/components/files-table.html +80 -0
- package/examples/components/filter-builder.html +11 -0
- package/examples/components/form-error-summary.html +11 -0
- package/examples/components/index.html +51 -0
- package/examples/components/inline-edit.html +42 -0
- package/examples/components/kanban-board.html +42 -0
- package/examples/components/manifest.json +3279 -0
- package/examples/components/modal.html +11 -0
- package/examples/components/multi-select-picker.html +13 -0
- package/examples/components/pagination.html +32 -0
- package/examples/components/persistent-action-banner.html +23 -0
- package/examples/components/popconfirm.html +13 -0
- package/examples/components/popover-menu.html +13 -0
- package/examples/components/reference/baseline/DECISIONS.md +85 -0
- package/examples/components/reference/baseline/README.md +58 -0
- package/examples/components/reference/baseline/bevel-fonts.css +16 -0
- package/examples/components/reference/baseline/bevel.css +1339 -0
- package/examples/components/reference/baseline/bevel.js +496 -0
- package/examples/components/reference/baseline/fonts/LICENSE-ibm-plex-mono.txt +93 -0
- package/examples/components/reference/baseline/fonts/LICENSE-ibm-plex-sans.txt +93 -0
- package/examples/components/reference/baseline/fonts/LICENSE-newsreader.txt +93 -0
- package/examples/components/reference/baseline/fonts/ibm-plex-mono-latin-400-normal.woff2 +0 -0
- package/examples/components/reference/baseline/fonts/ibm-plex-mono-latin-500-normal.woff2 +0 -0
- package/examples/components/reference/baseline/fonts/ibm-plex-mono-latin-600-normal.woff2 +0 -0
- package/examples/components/reference/baseline/fonts/ibm-plex-sans-latin-400-italic.woff2 +0 -0
- package/examples/components/reference/baseline/fonts/ibm-plex-sans-latin-400-normal.woff2 +0 -0
- package/examples/components/reference/baseline/fonts/ibm-plex-sans-latin-500-normal.woff2 +0 -0
- package/examples/components/reference/baseline/fonts/ibm-plex-sans-latin-600-normal.woff2 +0 -0
- package/examples/components/reference/baseline/fonts/newsreader-latin-opsz-italic.woff2 +0 -0
- package/examples/components/reference/baseline/fonts/newsreader-latin-opsz-normal.woff2 +0 -0
- package/examples/components/reference/fable/IMPROVEMENTS.md +106 -0
- package/examples/components/reference/fable/PARENT-REPAIRS.md +17 -0
- package/examples/components/reference/fable/__pycache__/build_repairs.cpython-311.pyc +0 -0
- package/examples/components/reference/fable/__pycache__/kanban.cpython-311.pyc +0 -0
- package/examples/components/reference/fable/as-authored/IMPROVEMENTS-completed.md +106 -0
- package/examples/components/reference/fable/as-authored/base-astra.css +17 -0
- package/examples/components/reference/fable/as-authored/base-parent.css +416 -0
- package/examples/components/reference/fable/as-authored/build.py +858 -0
- package/examples/components/reference/fable/as-authored/fable.css +823 -0
- package/examples/components/reference/fable/as-authored/kanban-completed.css +235 -0
- package/examples/components/reference/fable/as-authored/kanban-completed.html +53 -0
- package/examples/components/reference/fable/as-authored/kanban-completed.py +212 -0
- package/examples/components/reference/fable/as-authored/kanban.py +207 -0
- package/examples/components/reference/fable/base-astra.css +17 -0
- package/examples/components/reference/fable/base-parent.css +416 -0
- package/examples/components/reference/fable/build.py +858 -0
- package/examples/components/reference/fable/build_repairs.py +25 -0
- package/examples/components/reference/fable/components/activity-feed.html +3 -0
- package/examples/components/reference/fable/components/app-toolbar.html +3 -0
- package/examples/components/reference/fable/components/avatar-group.html +4 -0
- package/examples/components/reference/fable/components/breadcrumbs.html +3 -0
- package/examples/components/reference/fable/components/code-block.html +9 -0
- package/examples/components/reference/fable/components/column-manager.html +3 -0
- package/examples/components/reference/fable/components/combobox.html +6 -0
- package/examples/components/reference/fable/components/context-hypercms.html +3 -0
- package/examples/components/reference/fable/components/context-quickcrop.html +4 -0
- package/examples/components/reference/fable/components/diff-view.html +13 -0
- package/examples/components/reference/fable/components/drawer.html +3 -0
- package/examples/components/reference/fable/components/editable-grid-cells.html +3 -0
- package/examples/components/reference/fable/components/filter-builder.html +3 -0
- package/examples/components/reference/fable/components/form-error-summary.html +4 -0
- package/examples/components/reference/fable/components/inline-edit.html +3 -0
- package/examples/components/reference/fable/components/kanban-board.html +53 -0
- package/examples/components/reference/fable/components/modal.html +3 -0
- package/examples/components/reference/fable/components/multi-select-picker.html +5 -0
- package/examples/components/reference/fable/components/pagination.html +3 -0
- package/examples/components/reference/fable/components/persistent-action-banner.html +4 -0
- package/examples/components/reference/fable/components/popconfirm.html +5 -0
- package/examples/components/reference/fable/components/popover-menu.html +3 -0
- package/examples/components/reference/fable/components/rich-text-toolbar.html +3 -0
- package/examples/components/reference/fable/components/save-status-indicator.html +2 -0
- package/examples/components/reference/fable/components/selectable-cards.html +3 -0
- package/examples/components/reference/fable/components/settings-rows.html +3 -0
- package/examples/components/reference/fable/components/sidebar-nav.html +4 -0
- package/examples/components/reference/fable/components/small-charts.html +5 -0
- package/examples/components/reference/fable/components/split-button.html +4 -0
- package/examples/components/reference/fable/components/split-panes.html +8 -0
- package/examples/components/reference/fable/components/stat-tiles.html +3 -0
- package/examples/components/reference/fable/components/toast-stack.html +5 -0
- package/examples/components/reference/fable/components/tree-view.html +4 -0
- package/examples/components/reference/fable/components/upload-dropzone.html +6 -0
- package/examples/components/reference/fable/components/wizard-shell.html +3 -0
- package/examples/components/reference/fable/coverage.json +414 -0
- package/examples/components/reference/fable/fable.css +823 -0
- package/examples/components/reference/fable/index.html +5 -0
- package/examples/components/reference/fable/kanban.css +237 -0
- package/examples/components/reference/fable/kanban.py +212 -0
- package/examples/components/reference/fable/parent-repairs.css +9 -0
- package/examples/components/reference/fixtures/data.json +102 -0
- package/examples/components/reference/fixtures/host.js +47 -0
- package/examples/components/reference/fixtures/static-host.js +39 -0
- package/examples/components/reference/fixtures/workspace.jpg +0 -0
- package/examples/components/reference/parent/CHANGES.md +179 -0
- package/examples/components/reference/parent/__pycache__/kanban.cpython-311.pyc +0 -0
- package/examples/components/reference/parent/base-astra.css +17 -0
- package/examples/components/reference/parent/base-parent.css +416 -0
- package/examples/components/reference/parent/build.py +148 -0
- package/examples/components/reference/parent/components/activity-feed.html +2 -0
- package/examples/components/reference/parent/components/app-toolbar.html +2 -0
- package/examples/components/reference/parent/components/avatar-group.html +4 -0
- package/examples/components/reference/parent/components/breadcrumbs.html +2 -0
- package/examples/components/reference/parent/components/code-block.html +8 -0
- package/examples/components/reference/parent/components/column-manager.html +2 -0
- package/examples/components/reference/parent/components/combobox.html +6 -0
- package/examples/components/reference/parent/components/context-hypercms.html +2 -0
- package/examples/components/reference/parent/components/context-quickcrop.html +4 -0
- package/examples/components/reference/parent/components/diff-view.html +4 -0
- package/examples/components/reference/parent/components/drawer.html +2 -0
- package/examples/components/reference/parent/components/editable-grid-cells.html +2 -0
- package/examples/components/reference/parent/components/filter-builder.html +2 -0
- package/examples/components/reference/parent/components/form-error-summary.html +2 -0
- package/examples/components/reference/parent/components/inline-edit.html +2 -0
- package/examples/components/reference/parent/components/kanban-board.html +84 -0
- package/examples/components/reference/parent/components/modal.html +2 -0
- package/examples/components/reference/parent/components/multi-select-picker.html +5 -0
- package/examples/components/reference/parent/components/pagination.html +2 -0
- package/examples/components/reference/parent/components/persistent-action-banner.html +4 -0
- package/examples/components/reference/parent/components/popconfirm.html +5 -0
- package/examples/components/reference/parent/components/popover-menu.html +2 -0
- package/examples/components/reference/parent/components/rich-text-toolbar.html +2 -0
- package/examples/components/reference/parent/components/save-status-indicator.html +2 -0
- package/examples/components/reference/parent/components/selectable-cards.html +2 -0
- package/examples/components/reference/parent/components/settings-rows.html +2 -0
- package/examples/components/reference/parent/components/sidebar-nav.html +4 -0
- package/examples/components/reference/parent/components/small-charts.html +2 -0
- package/examples/components/reference/parent/components/split-button.html +5 -0
- package/examples/components/reference/parent/components/split-panes.html +8 -0
- package/examples/components/reference/parent/components/stat-tiles.html +2 -0
- package/examples/components/reference/parent/components/toast-stack.html +5 -0
- package/examples/components/reference/parent/components/tree-view.html +4 -0
- package/examples/components/reference/parent/components/upload-dropzone.html +6 -0
- package/examples/components/reference/parent/components/wizard-shell.html +2 -0
- package/examples/components/reference/parent/coverage.json +414 -0
- package/examples/components/reference/parent/index.html +1 -0
- package/examples/components/reference/parent/kanban.css +114 -0
- package/examples/components/reference/parent/kanban.py +55 -0
- package/examples/components/reference/parent/refinement.css +53 -0
- package/examples/components/reference/selected/build.py +70 -0
- package/examples/components/reference/selected/components/activity-feed.html +3 -0
- package/examples/components/reference/selected/components/app-toolbar.html +3 -0
- package/examples/components/reference/selected/components/avatar-group.html +4 -0
- package/examples/components/reference/selected/components/breadcrumbs.html +3 -0
- package/examples/components/reference/selected/components/code-block.html +9 -0
- package/examples/components/reference/selected/components/column-manager.html +3 -0
- package/examples/components/reference/selected/components/combobox.html +6 -0
- package/examples/components/reference/selected/components/context-hypercms.html +3 -0
- package/examples/components/reference/selected/components/context-quickcrop.html +4 -0
- package/examples/components/reference/selected/components/diff-view.html +13 -0
- package/examples/components/reference/selected/components/drawer.html +3 -0
- package/examples/components/reference/selected/components/editable-grid-cells.html +3 -0
- package/examples/components/reference/selected/components/filter-builder.html +3 -0
- package/examples/components/reference/selected/components/form-error-summary.html +4 -0
- package/examples/components/reference/selected/components/inline-edit.html +3 -0
- package/examples/components/reference/selected/components/kanban-board.html +53 -0
- package/examples/components/reference/selected/components/modal.html +2 -0
- package/examples/components/reference/selected/components/multi-select-picker.html +5 -0
- package/examples/components/reference/selected/components/pagination.html +3 -0
- package/examples/components/reference/selected/components/persistent-action-banner.html +4 -0
- package/examples/components/reference/selected/components/popconfirm.html +5 -0
- package/examples/components/reference/selected/components/popover-menu.html +3 -0
- package/examples/components/reference/selected/components/rich-text-toolbar.html +3 -0
- package/examples/components/reference/selected/components/save-status-indicator.html +2 -0
- package/examples/components/reference/selected/components/selectable-cards.html +3 -0
- package/examples/components/reference/selected/components/settings-rows.html +3 -0
- package/examples/components/reference/selected/components/sidebar-nav.html +4 -0
- package/examples/components/reference/selected/components/small-charts.html +5 -0
- package/examples/components/reference/selected/components/split-button.html +4 -0
- package/examples/components/reference/selected/components/split-panes.html +8 -0
- package/examples/components/reference/selected/components/stat-tiles.html +3 -0
- package/examples/components/reference/selected/components/toast-stack.html +5 -0
- package/examples/components/reference/selected/components/tree-view.html +4 -0
- package/examples/components/reference/selected/components/upload-dropzone.html +6 -0
- package/examples/components/reference/selected/components/wizard-shell.html +3 -0
- package/examples/components/reference/selected/corrections.css +11 -0
- package/examples/components/reference/selected/coverage.json +413 -0
- package/examples/components/reference/selected/gallery-build.mjs +49 -0
- package/examples/components/reference/selected/gallery-spec.json +12 -0
- package/examples/components/reference/selected/index.html +1 -0
- package/examples/components/reference/selected/kanban-comparison.json +6 -0
- package/examples/components/reference/selected/manifest.json +476 -0
- package/examples/components/reference/sha256.json +142 -0
- package/examples/components/reference/sources/diagonal-close.svg +1 -0
- package/examples/components/reference/sources/hyperclay/public-assets/css/hyperclay-app-source.css +614 -0
- package/examples/components/reference/sources/hyperclay/public-assets/js/app.js +94 -0
- package/examples/components/reference/sources/hyperclayjs/src/ui/theModal.js +897 -0
- package/examples/components/reference/sources/hypercms/scripts/build-theme.js +203 -0
- package/examples/components/reference/sources/hypercms/src/anchor.js +24 -0
- package/examples/components/reference/sources/hypercms/src/apply-loop.js +167 -0
- package/examples/components/reference/sources/hypercms/src/diagnostics.js +44 -0
- package/examples/components/reference/sources/hypercms/src/enhance.js +173 -0
- package/examples/components/reference/sources/hypercms/src/events.js +955 -0
- package/examples/components/reference/sources/hypercms/src/form-builder.js +518 -0
- package/examples/components/reference/sources/hypercms/src/form-rules.js +208 -0
- package/examples/components/reference/sources/hypercms/src/hooks.js +100 -0
- package/examples/components/reference/sources/hypercms/src/hypercms-bundle.js +10 -0
- package/examples/components/reference/sources/hypercms/src/hypercms.js +347 -0
- package/examples/components/reference/sources/hypercms/src/morph.js +10 -0
- package/examples/components/reference/sources/hypercms/src/path.js +61 -0
- package/examples/components/reference/sources/hypercms/src/place.js +131 -0
- package/examples/components/reference/sources/hypercms/src/platform.js +131 -0
- package/examples/components/reference/sources/hypercms/src/refresh.js +87 -0
- package/examples/components/reference/sources/hypercms/src/richclay-bridge.js +140 -0
- package/examples/components/reference/sources/hypercms/src/row-identity.js +111 -0
- package/examples/components/reference/sources/hypercms/src/scaffold.js +10 -0
- package/examples/components/reference/sources/hypercms/src/session.js +303 -0
- package/examples/components/reference/sources/hypercms/src/shell.js +248 -0
- package/examples/components/reference/sources/hypercms/src/styles.css +298 -0
- package/examples/components/reference/sources/hypercms/src/targets.js +144 -0
- package/examples/components/reference/sources/hypercms/src/templates.js +656 -0
- package/examples/components/reference/sources/hypercms/src/theme/pixel-quiet.overrides.css +761 -0
- package/examples/components/reference/sources/hypercms/src/theme.generated.css +1772 -0
- package/examples/components/reference/sources/hypercms/src/toggle.js +666 -0
- package/examples/components/reference/sources/hypercms/src/unresolved.js +211 -0
- package/examples/components/reference/sources/hypercms/src/vendor/mirk.vendor.js +212 -0
- package/examples/components/reference/sources/hypercms/src/views/inline-layer.js +421 -0
- package/examples/components/reference/sources/hypercms/src/views/inline.js +1072 -0
- package/examples/components/reference/sources/hypercms/src/views/sidebar.js +97 -0
- package/examples/components/reference/sources/modal-reference.html +301 -0
- package/examples/components/reference/sources/quickcrop/quickcrop.css +124 -0
- package/examples/components/reference/sources/quickcrop/quickcrop.js +400 -0
- package/examples/components/reference/sources/richclay/richclay.css +416 -0
- package/examples/components/reference/sources/richclay/richclay.js +2962 -0
- package/examples/components/reference/sources/richclay/src/a11y.js +67 -0
- package/examples/components/reference/sources/richclay/src/browser-global.js +7 -0
- package/examples/components/reference/sources/richclay/src/buttons.js +254 -0
- package/examples/components/reference/sources/richclay/src/hyperclay.js +470 -0
- package/examples/components/reference/sources/richclay/src/normalize.js +380 -0
- package/examples/components/reference/sources/richclay/src/richclay.js +1356 -0
- package/examples/components/reference/sources/richclay/src/sanitize.js +189 -0
- package/examples/components/reference/sources/richclay/src/styles.js +23 -0
- package/examples/components/reference/sources/richclay/src/toolbar-float.js +175 -0
- package/examples/components/reference/sources/richclay/src/toolbar.js +394 -0
- package/examples/components/reference/sources/richclay/src/vendor-bundle.js +15 -0
- package/examples/components/reference/sources/richclay/vendor/DOMPURIFY-LICENSE +202 -0
- package/examples/components/reference/sources/richclay/vendor/DOMPURIFY-LICENSE-MPL +373 -0
- package/examples/components/reference/sources/richclay/vendor/SQUIRE-LICENSE +21 -0
- package/examples/components/reference/sources/richclay/vendor/purify.es.mjs +2249 -0
- package/examples/components/reference/sources/richclay/vendor/purify.min.js +3 -0
- package/examples/components/reference/sources/richclay/vendor/squire.js +22 -0
- package/examples/components/reference/sources/richclay/vendor/squire.mjs +22 -0
- package/examples/components/reference/sources/richclay/vendor/squire.provenance.json +19 -0
- package/examples/components/rich-text-toolbar.html +43 -0
- package/examples/components/save-status-indicator.html +11 -0
- package/examples/components/selectable-cards.html +9 -0
- package/examples/components/settings-rows.html +10 -0
- package/examples/components/sidebar-nav.html +9 -0
- package/examples/components/small-charts.html +21 -0
- package/examples/components/split-button.html +13 -0
- package/examples/components/split-panes-editor.html +6 -0
- package/examples/components/split-panes.html +9 -0
- package/examples/components/stat-tiles.html +23 -0
- package/examples/components/toast-stack.html +21 -0
- package/examples/components/tree-view.html +9 -0
- package/examples/components/upload-dropzone.html +88 -0
- package/examples/components/wizard-shell.html +50 -0
- package/examples/datastar/index.html +38 -0
- package/examples/datastar/server.mjs +31 -0
- package/examples/fixtures/field-guide.pdf +14 -0
- package/examples/fixtures/workspace.jpg +0 -0
- package/examples/setup-peers.mjs +35 -0
- package/fonts/LICENSE-ibm-plex-mono.txt +93 -0
- package/fonts/LICENSE-ibm-plex-sans.txt +93 -0
- package/fonts/LICENSE-newsreader.txt +93 -0
- package/fonts/ibm-plex-mono-latin-400-normal.woff2 +0 -0
- package/fonts/ibm-plex-mono-latin-500-normal.woff2 +0 -0
- package/fonts/ibm-plex-mono-latin-600-normal.woff2 +0 -0
- package/fonts/ibm-plex-sans-latin-400-italic.woff2 +0 -0
- package/fonts/ibm-plex-sans-latin-400-normal.woff2 +0 -0
- package/fonts/ibm-plex-sans-latin-500-normal.woff2 +0 -0
- package/fonts/ibm-plex-sans-latin-600-normal.woff2 +0 -0
- package/fonts/newsreader-latin-opsz-italic.woff2 +0 -0
- package/fonts/newsreader-latin-opsz-normal.woff2 +0 -0
- package/icons/LICENSE +21 -0
- package/icons/house.json +71 -0
- package/icons/icons.d.ts +17 -0
- package/icons/icons.js +648 -0
- package/icons/icons.svg +126 -0
- package/icons/marks/build-tray.source.mjs +45 -0
- package/icons/marks/hyperclay-local.svg +11 -0
- package/icons/phosphor.json +53 -0
- package/icons/round.json +8 -0
- package/integrations/datastar.js +202 -0
- package/integrations/quickcrop.css +26 -0
- package/integrations/quickcrop.js +56 -0
- package/integrations/richclay.css +100 -0
- package/integrations/richclay.js +131 -0
- package/package.json +630 -0
- package/react/README.md +244 -0
- package/src/README.md +83 -0
- package/vendor/datastar/datastar-1.0.3.js +10 -0
- package/vendor/datastar/provenance.json +6 -0
- package/vendor/floating-ui/LICENSE-core +20 -0
- package/vendor/floating-ui/LICENSE-dom +20 -0
- package/vendor/floating-ui/floating-ui.core.umd.min.js +1 -0
- package/vendor/floating-ui/floating-ui.dom.umd.min.js +1 -0
- package/vendor/floating-ui/provenance.json +17 -0
- package/vendor/richclay/LICENSE +16 -0
- package/vendor/richclay/THIRD-PARTY-NOTICES.md +45 -0
- package/vendor/richclay/provenance.json +17 -0
- package/vendor/richclay/richclay.css +404 -0
- package/vendor/richclay/richclay.js +2940 -0
- package/vendor/richclay/vendor/DOMPURIFY-LICENSE +202 -0
- package/vendor/richclay/vendor/DOMPURIFY-LICENSE-MPL +373 -0
- package/vendor/richclay/vendor/SQUIRE-LICENSE +21 -0
- package/vendor/richclay/vendor/purify.min.js +3 -0
- package/vendor/richclay/vendor/squire.js +22 -0
- package/vendor/richclay/vendor/squire.provenance.json +30 -0
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"""Fable Kanban board. An independent composition for the Northstar Studio /
|
|
2
|
+
Field notes project: broadsheet masthead, view tabs, filter chrome, an
|
|
3
|
+
aggregate tape, four open lanes on the ground (no lane containers), dense
|
|
4
|
+
sans cards, a blocking dependency drawn on both ends, and a task panel that
|
|
5
|
+
pushes the board into a visibly scrollable strip. Static markup only."""
|
|
6
|
+
|
|
7
|
+
PEOPLE = {'MC': ('Mira Chen', 'Designer'), 'AR': ('Alex Rivera', 'Developer'),
|
|
8
|
+
'SP': ('Sam Patel', 'Editor'), 'JP': ('Jules Park', 'Owner')}
|
|
9
|
+
|
|
10
|
+
ICONS = {
|
|
11
|
+
'plus': 'M12 5v14M5 12h14',
|
|
12
|
+
'more': 'M5 12h1m5 0h1m5 0h1',
|
|
13
|
+
'search': 'M20 20l-4.5-4.5M17 10a7 7 0 1 1-14 0 7 7 0 0 1 14 0',
|
|
14
|
+
'filter': 'M3 5h18l-7 8v6l-4 2v-8Z',
|
|
15
|
+
'chevron': 'm6 9 6 6 6-6',
|
|
16
|
+
'check': 'm5 12 4 4L19 6',
|
|
17
|
+
'clock': 'M12 7v5l3 2M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0',
|
|
18
|
+
'comment': 'M4 4h16v12H9l-5 4V4Z',
|
|
19
|
+
'clip': 'm9 16 7-7a3 3 0 0 0-4-4l-7 7a5 5 0 0 0 7 7l8-8',
|
|
20
|
+
'flag': 'M5 21V4h13l-3 4 3 4H5',
|
|
21
|
+
'board': 'M3 4h5v16H3ZM10 4h5v11h-5ZM17 4h4v7h-4Z',
|
|
22
|
+
'list': 'M8 6h13M8 12h13M8 18h13M3 6h1M3 12h1M3 18h1',
|
|
23
|
+
'calendar': 'M4 5h16v16H4ZM4 10h16M8 2v6m8-6v6',
|
|
24
|
+
'timeline': 'M3 6h8M9 12h10M5 18h9',
|
|
25
|
+
'lock': 'M6 11h12v10H6ZM8 11V7a4 4 0 0 1 8 0v4',
|
|
26
|
+
'link': 'm10 14 4-4M9 15l-2 2a3 3 0 0 1-4-4l4-4a3 3 0 0 1 4 0m2 0 2-2a3 3 0 0 1 4 4l-4 4a3 3 0 0 1-4 0',
|
|
27
|
+
'close': 'm6 6 12 12M18 6 6 18',
|
|
28
|
+
'doc': 'M5 3h9l5 5v13H5ZM14 3v6h5',
|
|
29
|
+
'image': 'M3 5h18v14H3ZM3 15l5-5 4 4 3-3 6 6M16 9h1',
|
|
30
|
+
'share': 'M12 3v12m-4-8 4-4 4 4M5 14v6h14v-6',
|
|
31
|
+
'sort': 'M4 6h16M7 12h10M10 18h4',
|
|
32
|
+
'group': 'M3 4h7v7H3ZM14 4h7v7h-7ZM3 13h7v7H3ZM14 13h7v7h-7Z',
|
|
33
|
+
'arrow': 'M4 12h16m-6-6 6 6-6 6',
|
|
34
|
+
'blocked': 'M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18ZM5.6 5.6l12.8 12.8',
|
|
35
|
+
'expand': 'M4 4h6M4 4v6M20 20h-6m6 0v-6M4 20l6-6M20 4l-6 6',
|
|
36
|
+
'template': 'M4 4h16v5H4ZM4 12h7v8H4ZM14 12h6v8h-6Z',
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
from build_repairs import ICONS as REPAIR_ICONS
|
|
41
|
+
ICONS.update(REPAIR_ICONS)
|
|
42
|
+
|
|
43
|
+
def icon(name, size=16):
|
|
44
|
+
return (f'<svg width="{size}" height="{size}" viewBox="0 0 24 24" fill="none" stroke="currentColor" '
|
|
45
|
+
f'stroke-width="1.6" stroke-linecap="square" stroke-linejoin="miter" aria-hidden="true">'
|
|
46
|
+
f'<path d="{ICONS[name]}"/></svg>')
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def avatar(who, size=''):
|
|
50
|
+
name = PEOPLE[who][0]
|
|
51
|
+
return f'<span class="f-avatar {size}" data-who="{who}" aria-label="{name}" title="{name}">{who}</span>'
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def button(label, name=None, kind='', attrs=''):
|
|
55
|
+
cls = ('bevel-button ' + kind).strip()
|
|
56
|
+
inner = (icon(name, 15) if name else '') + f'<span class="bevel-button__label">{label}</span>'
|
|
57
|
+
return f'<button type="button" class="{cls}" {attrs}>{inner}</button>'
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
TASKS = {
|
|
61
|
+
'backlog': [
|
|
62
|
+
dict(id='FN-109', title='Archive the 2025 field notes', labels=['editorial'], priority='normal', due='Sep 19', people=['SP'], comments=0, files=0),
|
|
63
|
+
dict(id='FN-110', title='Print-ready export for the field guide', labels=['engineering'], priority='normal', due='Sep 24', people=['AR'], check=(0, 3), comments=1, files=0),
|
|
64
|
+
dict(id='FN-111', title='Photograph the studio for the cover', labels=['design'], priority='normal', due='Sep 26', people=['MC'], comments=0, files=1),
|
|
65
|
+
],
|
|
66
|
+
'next': [
|
|
67
|
+
dict(id='FN-101', title='Turn research into a field guide', labels=['editorial'], priority='high', due='Sep 10', people=['SP'], check=(2, 5), comments=3, files=2,
|
|
68
|
+
desc='A useful home for what we learned in the interviews.'),
|
|
69
|
+
dict(id='FN-102', title='Shape the cover story', labels=['design'], priority='normal', due='Sep 11', people=['MC', 'SP'], comments=2, files=1, cover=True),
|
|
70
|
+
dict(id='FN-103', title='Invite the next four collaborators', labels=['studio'], priority='normal', due='Sep 12', people=['JP'], check=(0, 4), comments=0, files=0),
|
|
71
|
+
],
|
|
72
|
+
'progress': [
|
|
73
|
+
dict(id='FN-104', title='Make room for good work', labels=['design', 'launch'], priority='urgent', due='Today', due_kind='today', people=['MC', 'AR'], check=(3, 4), comments=8, files=3,
|
|
74
|
+
desc='Finish the new project experience. Keep the first step calm and easy to return to.', blocked_by='FN-105'),
|
|
75
|
+
dict(id='FN-105', title='Polish the document export', labels=['engineering'], priority='high', due='Sep 07', due_kind='overdue', people=['AR'], check=(1, 3), comments=4, files=0, blocks='FN-104'),
|
|
76
|
+
dict(id='FN-106', title='Give every empty state a voice', labels=['editorial'], priority='normal', due='Sep 09', people=['SP'], check=(2, 3), comments=1, files=0),
|
|
77
|
+
],
|
|
78
|
+
'done': [
|
|
79
|
+
dict(id='FN-107', title='A calmer workspace navigation', labels=['design'], priority='normal', due='Sep 08', due_kind='done', people=['MC'], check=(4, 4), comments=5, files=2),
|
|
80
|
+
dict(id='FN-108', title='Write the first welcome', labels=['editorial'], priority='normal', due='Sep 07', due_kind='done', people=['SP', 'JP'], check=(3, 3), comments=2, files=0),
|
|
81
|
+
],
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
LANES = [
|
|
85
|
+
('backlog', 'Backlog', '', 'Ideas that are not scheduled yet.', 'Nothing waiting'),
|
|
86
|
+
('next', 'Up next', '', 'Scheduled for this week.', 'Nothing scheduled'),
|
|
87
|
+
('progress', 'In progress', 'WIP 3 / 3', 'Being worked on right now.', 'Nothing in progress'),
|
|
88
|
+
('done', 'Done', 'This week', 'Finished and reviewed.', 'Nothing finished yet'),
|
|
89
|
+
]
|
|
90
|
+
|
|
91
|
+
LABEL_NAMES = {'design': 'Design', 'editorial': 'Editorial', 'engineering': 'Engineering', 'studio': 'Studio', 'launch': 'Launch'}
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def label(key):
|
|
95
|
+
return f'<span class="kb-label" data-label="{key}">{LABEL_NAMES[key]}</span>'
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
def priority(p):
|
|
99
|
+
text = {'urgent': 'Urgent', 'high': 'High', 'normal': 'Normal'}[p]
|
|
100
|
+
return f'<span class="kb-priority" data-priority="{p}">{icon("flag", 11)}{text}</span>'
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
def card(t, selected=False):
|
|
104
|
+
classes = ['kb-card']
|
|
105
|
+
if selected: classes.append('is-selected')
|
|
106
|
+
if t.get('due_kind') == 'done': classes.append('is-done')
|
|
107
|
+
if t.get('blocked_by'): classes.append('is-blocked')
|
|
108
|
+
parts = [f'<article class="{" ".join(classes)}" data-task="{t["id"]}" {"aria-current=true" if selected else ""}>']
|
|
109
|
+
if t.get('cover'):
|
|
110
|
+
parts.append('<figure class="kb-cover"><img src="../../fixtures/workspace.jpg" alt="The studio desk, a reference for the cover"><figcaption>Cover reference</figcaption></figure>')
|
|
111
|
+
parts.append(f'<div class="kb-card-top"><span class="kb-id">{t["id"]}</span>{priority(t["priority"])}</div>')
|
|
112
|
+
parts.append(f'<h3>{t["title"]}</h3>')
|
|
113
|
+
if t.get('desc'):
|
|
114
|
+
parts.append(f'<p class="kb-desc">{t["desc"]}</p>')
|
|
115
|
+
parts.append('<div class="kb-labels">' + ''.join(label(l) for l in t['labels']) + '</div>')
|
|
116
|
+
if t.get('blocked_by'):
|
|
117
|
+
parts.append(f'<div class="kb-dep is-blocked">{icon("lock", 12)}<span>Blocked by <b>{t["blocked_by"]}</b> · Font licensing</span></div>')
|
|
118
|
+
if t.get('blocks'):
|
|
119
|
+
parts.append(f'<div class="kb-dep">{icon("link", 12)}<span>Blocks <b>{t["blocks"]}</b> · Make room for good work</span></div>')
|
|
120
|
+
if t.get('check'):
|
|
121
|
+
done, total = t['check']
|
|
122
|
+
pct = round(done / total * 100)
|
|
123
|
+
parts.append(f'<div class="kb-check" aria-label="Checklist {done} of {total}"><i class="kb-check-bar"><b style="width:{pct}%"></b></i><span class="kb-check-count">{done}/{total}</span></div>')
|
|
124
|
+
kind = t.get('due_kind', '')
|
|
125
|
+
due_icon = 'check' if kind == 'done' else 'calendar'
|
|
126
|
+
meta = ''
|
|
127
|
+
if t['comments']: meta += f'<span>{icon("comment", 12)}{t["comments"]}</span>'
|
|
128
|
+
if t['files']: meta += f'<span>{icon("clip", 12)}{t["files"]}</span>'
|
|
129
|
+
parts.append(f'<footer class="kb-card-foot"><span class="kb-due" data-due="{kind}">{icon(due_icon, 12)}{t["due"]}</span><span class="kb-meta">{meta}</span><span class="kb-people">{"".join(avatar(p, "small") for p in t["people"])}</span></footer>')
|
|
130
|
+
parts.append('</article>')
|
|
131
|
+
return ''.join(parts)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def lane(key, title, wip, blurb, empty_title, tasks, state):
|
|
135
|
+
empty = state == 'empty'
|
|
136
|
+
count = 0 if empty else len(tasks)
|
|
137
|
+
head = (f'<header class="kb-lane-head"><span class="kb-lane-mark" data-lane="{key}"></span><h2>{title}</h2>'
|
|
138
|
+
f'<span class="kb-count">{count}</span>'
|
|
139
|
+
+ (f'<span class="kb-wip" data-full="{"true" if key == "progress" and not empty else "false"}">{wip}</span>' if wip and not empty else '')
|
|
140
|
+
+ f'<button type="button" class="kb-icon" aria-label="Add a task to {title}">{icon("plus", 15)}</button></header>')
|
|
141
|
+
if empty:
|
|
142
|
+
cta = ''
|
|
143
|
+
if key == 'backlog':
|
|
144
|
+
cta = f'<div class="kb-empty-actions">{button("Add the first task", "plus", "bevel-button--small")}{button("Start from a template", "template", "bevel-button--small bevel-button--quiet")}</div>'
|
|
145
|
+
body = f'<div class="kb-lane-empty"><strong>{empty_title}</strong><p>{blurb}</p>{cta}</div>'
|
|
146
|
+
else:
|
|
147
|
+
body = ''.join(card(t, selected=(state == 'selected' and t['id'] == 'FN-104')) for t in tasks)
|
|
148
|
+
body += f'<button type="button" class="kb-add">{icon("plus", 13)}Add task</button>'
|
|
149
|
+
return f'<section class="kb-lane" data-lane="{key}" aria-label="{title}">{head}<div class="kb-lane-body">{body}</div></section>'
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def checklist_item(text, done):
|
|
153
|
+
return (f'<label class="bevel-checkbox bevel-checkbox--small kb-check-item"><input type="checkbox" class="bevel-sr-only" {"checked" if done else ""}>'
|
|
154
|
+
f'<span class="bevel-checkbox__box" aria-hidden="true"></span><span class="bevel-checkbox__label">{text}</span></label>')
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def panel():
|
|
158
|
+
return f'''<aside class="kb-panel" aria-label="Task FN-104">
|
|
159
|
+
<header class="kb-panel-head"><span class="kb-id">FN-104</span><span class="kb-status" data-lane="progress">In progress {icon("chevron", 12)}</span><span class="kb-spacer"></span><button type="button" class="kb-icon" aria-label="Task options">{icon("more", 16)}</button><button type="button" class="kb-icon" aria-label="Close task">{icon("close", 16)}</button></header>
|
|
160
|
+
<h2>Make room for good work</h2>
|
|
161
|
+
<p class="kb-panel-lede">Finish the new project experience. Keep the first step calm, direct and easy to return to.</p>
|
|
162
|
+
<dl class="kb-props">
|
|
163
|
+
<dt>Assignees</dt><dd><span class="kb-people">{avatar("MC", "small")}{avatar("AR", "small")}</span>Mira Chen, Alex Rivera</dd>
|
|
164
|
+
<dt>Priority</dt><dd>{priority("urgent")}</dd>
|
|
165
|
+
<dt>Due</dt><dd><span class="kb-due" data-due="today">{icon("calendar", 12)}Today, Sep 08</span></dd>
|
|
166
|
+
<dt>Labels</dt><dd class="kb-labels">{label("design")}{label("launch")}</dd>
|
|
167
|
+
<dt>Estimate</dt><dd class="f-mono">3 days · 2 spent</dd>
|
|
168
|
+
</dl>
|
|
169
|
+
<section class="kb-panel-section"><h4>Checklist <b class="kb-check-count">3/4</b></h4><i class="kb-check-bar"><b style="width:75%"></b></i>
|
|
170
|
+
{checklist_item("Set the project details", True)}{checklist_item("Check both colour modes", True)}{checklist_item("Review the compact layout", True)}{checklist_item("Get Jules’ final review", False)}
|
|
171
|
+
</section>
|
|
172
|
+
<section class="kb-panel-section"><h4>Blocked by <b class="kb-check-count">1</b></h4>
|
|
173
|
+
<div class="kb-dep-row">{icon("lock", 14)}<div><b>FN-105</b> Polish the document export<small>In progress · Alex Rivera · <span class="kb-due" data-due="overdue">due Sep 07</span></small></div>{avatar("AR", "small")}</div>
|
|
174
|
+
</section>
|
|
175
|
+
<section class="kb-panel-section"><h4>Attachments <b class="kb-check-count">3</b></h4>
|
|
176
|
+
<div class="kb-files"><a class="kb-file" href="#workspace"><img src="../../fixtures/workspace.jpg" alt=""><span>workspace.jpg<small>184 KB</small></span></a><a class="kb-file" href="#brief">{icon("doc", 18)}<span>project-brief.pdf<small>420 KB</small></span></a><a class="kb-file" href="#copy">{icon("doc", 18)}<span>welcome-copy.md<small>3 KB</small></span></a></div>
|
|
177
|
+
</section>
|
|
178
|
+
<section class="kb-panel-section"><h4>Activity <b class="kb-check-count">8</b></h4>
|
|
179
|
+
<div class="kb-comment">{avatar("AR", "small")}<div><b>Alex Rivera <small>18 min ago</small></b><p>The new flow reads clearly. Ready for one last look at the copy.</p></div></div>
|
|
180
|
+
<div class="kb-comment">{avatar("SP", "small")}<div><b>Sam Patel <small>2 h ago</small></b><p>Tightened the welcome line. It is on the card now.</p></div></div>
|
|
181
|
+
<div class="kb-event"><span class="kb-event-dot"></span>Mira moved this from <b>Up next</b> to <b>In progress</b><small>Yesterday</small></div>
|
|
182
|
+
<div class="kb-composer"><span>Leave a comment…</span><kbd>⌘ ↵</kbd></div>
|
|
183
|
+
</section>
|
|
184
|
+
<footer class="kb-panel-foot"><span class="f-mono">Created Sep 02 by Jules Park</span>{button("Open task", "expand", "bevel-button--small")}</footer>
|
|
185
|
+
</aside>'''
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def kanban(state):
|
|
189
|
+
empty = state == 'empty'
|
|
190
|
+
total = 0 if empty else sum(len(v) for v in TASKS.values())
|
|
191
|
+
done = 0 if empty else len(TASKS['done'])
|
|
192
|
+
progress = 0 if empty else len(TASKS['progress'])
|
|
193
|
+
blocked = 0 if empty else 1
|
|
194
|
+
pct = 0 if empty else round(done / total * 100)
|
|
195
|
+
lanes = ''.join(lane(k, t, w, b, e, TASKS[k], state) for k, t, w, b, e in LANES)
|
|
196
|
+
tape = (f'<dl class="kb-tape"><div><dt>Open</dt><dd>{total - done}</dd></div><div><dt>In progress</dt><dd>{progress}<small>of 3</small></dd></div>'
|
|
197
|
+
f'<div><dt>Blocked</dt><dd data-tone="{"ox" if blocked else ""}">{blocked}</dd></div><div><dt>Done this week</dt><dd>{done}</dd></div>'
|
|
198
|
+
f'<div class="kb-tape-meter"><dt>Progress</dt><dd><i class="kb-check-bar"><b style="width:{pct}%"></b></i>{pct}%</dd></div></dl>')
|
|
199
|
+
filters = ('' if empty else f'<button type="button" class="kb-chip" aria-pressed="true">{icon("calendar", 13)}Due: this week{icon("close", 11)}</button>') + \
|
|
200
|
+
f'<button type="button" class="kb-chip">Assignee: anyone{icon("chevron", 12)}</button><button type="button" class="kb-chip">Label: all{icon("chevron", 12)}</button>'
|
|
201
|
+
hint = (f'<div class="kb-scroll-rail" aria-hidden="true"><b style="width:80%"></b></div>'
|
|
202
|
+
f'<p class="kb-scroll-hint">{icon("arrow", 12)}Four lanes. Scroll the board sideways for <b>Done</b>.</p>') if state == 'selected' else ''
|
|
203
|
+
empty_note = ('<div class="kb-empty-note"><strong>This board is empty.</strong> New tasks land in Backlog. Move them across the lanes as the work moves.</div>' if empty else '')
|
|
204
|
+
return f'''<main class="kb" data-state="{state}">
|
|
205
|
+
<header class="kb-mast"><div class="kb-mast-title"><div class="kb-kicker">Northstar Studio<i>/</i>Project 004<i>/</i>Board</div><h1>Field notes</h1><p>Everything the studio is making for the field guide, in the order it will ship.</p></div>
|
|
206
|
+
<div class="kb-mast-side"><div class="kb-team"><span class="kb-people">{"".join(avatar(p) for p in PEOPLE)}</span><small>4 people</small></div>{button("Share", "share")}{button("New task", "plus", "bevel-button--primary")}</div></header>
|
|
207
|
+
<nav class="kb-views" aria-label="Views"><a href="#board" aria-current="page">{icon("board", 15)}Board<b>{total}</b></a><a href="#list">{icon("list", 15)}List</a><a href="#timeline">{icon("timeline", 15)}Timeline</a><a href="#calendar">{icon("calendar", 15)}Calendar</a><span class="kb-views-note">{icon("lock", 12)}Private · updated 10:42</span></nav>
|
|
208
|
+
<div class="kb-tools"><label class="kb-search">{icon("search", 15)}<input type="search" placeholder="Search tasks" aria-label="Search tasks"><kbd>⌘ K</kbd></label>{filters}<span class="kb-spacer"></span><button type="button" class="kb-chip kb-chip-quiet">{icon("group", 13)}Group: status</button><button type="button" class="kb-chip kb-chip-quiet">{icon("sort", 13)}Sort: priority</button></div>
|
|
209
|
+
{tape}{empty_note}
|
|
210
|
+
<div class="kb-work {"has-panel" if state == "selected" else ""}"><div class="kb-board-wrap"><div class="kb-board" tabindex="0" aria-label="Board lanes">{lanes}</div>{hint}</div>{panel() if state == "selected" else ""}</div>
|
|
211
|
+
<footer class="kb-foot"><span>{icon("board", 13)}Grouped by status · sorted by priority</span><span>{total} tasks · {done} done · 4 people</span></footer>
|
|
212
|
+
</main>'''
|
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
"""Fable Kanban board. An independent composition for the Northstar Studio /
|
|
2
|
+
Field notes project: broadsheet masthead, view tabs, filter chrome, an
|
|
3
|
+
aggregate tape, four open lanes on the ground (no lane containers), dense
|
|
4
|
+
sans cards, a blocking dependency drawn on both ends, and a task panel that
|
|
5
|
+
pushes the board into a visibly scrollable strip. Static markup only."""
|
|
6
|
+
|
|
7
|
+
PEOPLE = {'MC': ('Mira Chen', 'Designer'), 'AR': ('Alex Rivera', 'Developer'),
|
|
8
|
+
'SP': ('Sam Patel', 'Editor'), 'JP': ('Jules Park', 'Owner')}
|
|
9
|
+
|
|
10
|
+
ICONS = {
|
|
11
|
+
'plus': 'M12 5v14M5 12h14',
|
|
12
|
+
'more': 'M5 12h1m5 0h1m5 0h1',
|
|
13
|
+
'search': 'M20 20l-4.5-4.5M17 10a7 7 0 1 1-14 0 7 7 0 0 1 14 0',
|
|
14
|
+
'filter': 'M3 5h18l-7 8v6l-4 2v-8Z',
|
|
15
|
+
'chevron': 'm6 9 6 6 6-6',
|
|
16
|
+
'check': 'm5 12 4 4L19 6',
|
|
17
|
+
'clock': 'M12 7v5l3 2M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0',
|
|
18
|
+
'comment': 'M4 4h16v12H9l-5 4V4Z',
|
|
19
|
+
'clip': 'm9 16 7-7a3 3 0 0 0-4-4l-7 7a5 5 0 0 0 7 7l8-8',
|
|
20
|
+
'flag': 'M5 21V4h13l-3 4 3 4H5',
|
|
21
|
+
'board': 'M3 4h5v16H3ZM10 4h5v11h-5ZM17 4h4v7h-4Z',
|
|
22
|
+
'list': 'M8 6h13M8 12h13M8 18h13M3 6h1M3 12h1M3 18h1',
|
|
23
|
+
'calendar': 'M4 5h16v16H4ZM4 10h16M8 2v6m8-6v6',
|
|
24
|
+
'timeline': 'M3 6h8M9 12h10M5 18h9',
|
|
25
|
+
'lock': 'M6 11h12v10H6ZM8 11V7a4 4 0 0 1 8 0v4',
|
|
26
|
+
'link': 'm10 14 4-4M9 15l-2 2a3 3 0 0 1-4-4l4-4a3 3 0 0 1 4 0m2 0 2-2a3 3 0 0 1 4 4l-4 4a3 3 0 0 1-4 0',
|
|
27
|
+
'close': 'm6 6 12 12M18 6 6 18',
|
|
28
|
+
'doc': 'M5 3h9l5 5v13H5ZM14 3v6h5',
|
|
29
|
+
'image': 'M3 5h18v14H3ZM3 15l5-5 4 4 3-3 6 6M16 9h1',
|
|
30
|
+
'share': 'M12 3v12m-4-8 4-4 4 4M5 14v6h14v-6',
|
|
31
|
+
'sort': 'M4 6h16M7 12h10M10 18h4',
|
|
32
|
+
'group': 'M3 4h7v7H3ZM14 4h7v7h-7ZM3 13h7v7H3ZM14 13h7v7h-7Z',
|
|
33
|
+
'arrow': 'M4 12h16m-6-6 6 6-6 6',
|
|
34
|
+
'blocked': 'M12 21a9 9 0 1 0 0-18 9 9 0 0 0 0 18ZM5.6 5.6l12.8 12.8',
|
|
35
|
+
'expand': 'M4 4h6M4 4v6M20 20h-6m6 0v-6M4 20l6-6M20 4l-6 6',
|
|
36
|
+
'template': 'M4 4h16v5H4ZM4 12h7v8H4ZM14 12h6v8h-6Z',
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def icon(name, size=16):
|
|
41
|
+
return (f'<svg width="{size}" height="{size}" viewBox="0 0 24 24" fill="none" stroke="currentColor" '
|
|
42
|
+
f'stroke-width="1.6" stroke-linecap="square" stroke-linejoin="miter" aria-hidden="true">'
|
|
43
|
+
f'<path d="{ICONS[name]}"/></svg>')
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def avatar(who, size=''):
|
|
47
|
+
name = PEOPLE[who][0]
|
|
48
|
+
return f'<span class="f-avatar {size}" data-who="{who}" aria-label="{name}" title="{name}">{who}</span>'
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def button(label, name=None, kind='', attrs=''):
|
|
52
|
+
cls = ('bevel-button ' + kind).strip()
|
|
53
|
+
inner = (icon(name, 15) if name else '') + f'<span class="bevel-button__label">{label}</span>'
|
|
54
|
+
return f'<button type="button" class="{cls}" {attrs}>{inner}</button>'
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
TASKS = {
|
|
58
|
+
'backlog': [
|
|
59
|
+
dict(id='FN-109', title='Archive the 2025 field notes', labels=['editorial'], priority='normal', due='Sep 19', people=['SP'], comments=0, files=0),
|
|
60
|
+
dict(id='FN-110', title='Print-ready export for the field guide', labels=['engineering'], priority='normal', due='Sep 24', people=['AR'], check=(0, 3), comments=1, files=0),
|
|
61
|
+
dict(id='FN-111', title='Photograph the studio for the cover', labels=['design'], priority='normal', due='Sep 26', people=['MC'], comments=0, files=1),
|
|
62
|
+
],
|
|
63
|
+
'next': [
|
|
64
|
+
dict(id='FN-101', title='Turn research into a field guide', labels=['editorial'], priority='high', due='Sep 10', people=['SP'], check=(2, 5), comments=3, files=2,
|
|
65
|
+
desc='A useful home for what we learned in the interviews.'),
|
|
66
|
+
dict(id='FN-102', title='Shape the cover story', labels=['design'], priority='normal', due='Sep 11', people=['MC', 'SP'], comments=2, files=1, cover=True),
|
|
67
|
+
dict(id='FN-103', title='Invite the next four collaborators', labels=['studio'], priority='normal', due='Sep 12', people=['JP'], check=(0, 4), comments=0, files=0),
|
|
68
|
+
],
|
|
69
|
+
'progress': [
|
|
70
|
+
dict(id='FN-104', title='Make room for good work', labels=['design', 'launch'], priority='urgent', due='Today', due_kind='today', people=['MC', 'AR'], check=(3, 4), comments=8, files=3,
|
|
71
|
+
desc='Finish the new project experience. Keep the first step calm and easy to return to.', blocked_by='FN-105'),
|
|
72
|
+
dict(id='FN-105', title='Polish the document export', labels=['engineering'], priority='high', due='Sep 07', due_kind='overdue', people=['AR'], check=(1, 3), comments=4, files=0, blocks='FN-104'),
|
|
73
|
+
dict(id='FN-106', title='Give every empty state a voice', labels=['editorial'], priority='normal', due='Sep 09', people=['SP'], check=(2, 3), comments=1, files=0),
|
|
74
|
+
],
|
|
75
|
+
'done': [
|
|
76
|
+
dict(id='FN-107', title='A calmer workspace navigation', labels=['design'], priority='normal', due='Sep 08', due_kind='done', people=['MC'], check=(4, 4), comments=5, files=2),
|
|
77
|
+
dict(id='FN-108', title='Write the first welcome', labels=['editorial'], priority='normal', due='Sep 07', due_kind='done', people=['SP', 'JP'], check=(3, 3), comments=2, files=0),
|
|
78
|
+
],
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
LANES = [
|
|
82
|
+
('backlog', 'Backlog', '', 'Ideas that are not scheduled yet.', 'Nothing waiting'),
|
|
83
|
+
('next', 'Up next', '', 'Scheduled for this week.', 'Nothing scheduled'),
|
|
84
|
+
('progress', 'In progress', 'WIP 3 / 3', 'Being worked on right now.', 'Nothing in progress'),
|
|
85
|
+
('done', 'Done', 'This week', 'Finished and reviewed.', 'Nothing finished yet'),
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
LABEL_NAMES = {'design': 'Design', 'editorial': 'Editorial', 'engineering': 'Engineering', 'studio': 'Studio', 'launch': 'Launch'}
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def label(key):
|
|
92
|
+
return f'<span class="kb-label" data-label="{key}">{LABEL_NAMES[key]}</span>'
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
def priority(p):
|
|
96
|
+
text = {'urgent': 'Urgent', 'high': 'High', 'normal': 'Normal'}[p]
|
|
97
|
+
return f'<span class="kb-priority" data-priority="{p}">{icon("flag", 11)}{text}</span>'
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def card(t, selected=False):
|
|
101
|
+
classes = ['kb-card']
|
|
102
|
+
if selected: classes.append('is-selected')
|
|
103
|
+
if t.get('due_kind') == 'done': classes.append('is-done')
|
|
104
|
+
if t.get('blocked_by'): classes.append('is-blocked')
|
|
105
|
+
parts = [f'<article class="{" ".join(classes)}" data-task="{t["id"]}" {"aria-current=true" if selected else ""}>']
|
|
106
|
+
if t.get('cover'):
|
|
107
|
+
parts.append('<figure class="kb-cover"><img src="../../fixtures/workspace.jpg" alt="The studio desk, a reference for the cover"><figcaption>Cover reference</figcaption></figure>')
|
|
108
|
+
parts.append(f'<div class="kb-card-top"><span class="kb-id">{t["id"]}</span>{priority(t["priority"])}</div>')
|
|
109
|
+
parts.append(f'<h3>{t["title"]}</h3>')
|
|
110
|
+
if t.get('desc'):
|
|
111
|
+
parts.append(f'<p class="kb-desc">{t["desc"]}</p>')
|
|
112
|
+
parts.append('<div class="kb-labels">' + ''.join(label(l) for l in t['labels']) + '</div>')
|
|
113
|
+
if t.get('blocked_by'):
|
|
114
|
+
parts.append(f'<div class="kb-dep is-blocked">{icon("lock", 12)}<span>Blocked by <b>{t["blocked_by"]}</b> · Font licensing</span></div>')
|
|
115
|
+
if t.get('blocks'):
|
|
116
|
+
parts.append(f'<div class="kb-dep">{icon("link", 12)}<span>Blocks <b>{t["blocks"]}</b> · Make room for good work</span></div>')
|
|
117
|
+
if t.get('check'):
|
|
118
|
+
done, total = t['check']
|
|
119
|
+
pct = round(done / total * 100)
|
|
120
|
+
parts.append(f'<div class="kb-check" aria-label="Checklist {done} of {total}"><i class="kb-check-bar"><b style="width:{pct}%"></b></i><span class="kb-check-count">{done}/{total}</span></div>')
|
|
121
|
+
kind = t.get('due_kind', '')
|
|
122
|
+
due_icon = 'check' if kind == 'done' else 'calendar'
|
|
123
|
+
meta = ''
|
|
124
|
+
if t['comments']: meta += f'<span>{icon("comment", 12)}{t["comments"]}</span>'
|
|
125
|
+
if t['files']: meta += f'<span>{icon("clip", 12)}{t["files"]}</span>'
|
|
126
|
+
parts.append(f'<footer class="kb-card-foot"><span class="kb-due" data-due="{kind}">{icon(due_icon, 12)}{t["due"]}</span><span class="kb-meta">{meta}</span><span class="kb-people">{"".join(avatar(p, "small") for p in t["people"])}</span></footer>')
|
|
127
|
+
parts.append('</article>')
|
|
128
|
+
return ''.join(parts)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def lane(key, title, wip, blurb, empty_title, tasks, state):
|
|
132
|
+
empty = state == 'empty'
|
|
133
|
+
count = 0 if empty else len(tasks)
|
|
134
|
+
head = (f'<header class="kb-lane-head"><span class="kb-lane-mark" data-lane="{key}"></span><h2>{title}</h2>'
|
|
135
|
+
f'<span class="kb-count">{count}</span>'
|
|
136
|
+
+ (f'<span class="kb-wip" data-full="{"true" if key == "progress" and not empty else "false"}">{wip}</span>' if wip and not empty else '')
|
|
137
|
+
+ f'<button type="button" class="kb-icon" aria-label="Add a task to {title}">{icon("plus", 15)}</button></header>')
|
|
138
|
+
if empty:
|
|
139
|
+
cta = ''
|
|
140
|
+
if key == 'backlog':
|
|
141
|
+
cta = f'<div class="kb-empty-actions">{button("Add the first task", "plus", "bevel-button--small")}{button("Start from a template", "template", "bevel-button--small bevel-button--quiet")}</div>'
|
|
142
|
+
body = f'<div class="kb-lane-empty"><strong>{empty_title}</strong><p>{blurb}</p>{cta}</div>'
|
|
143
|
+
else:
|
|
144
|
+
body = ''.join(card(t, selected=(state == 'selected' and t['id'] == 'FN-104')) for t in tasks)
|
|
145
|
+
body += f'<button type="button" class="kb-add">{icon("plus", 13)}Add task</button>'
|
|
146
|
+
return f'<section class="kb-lane" data-lane="{key}" aria-label="{title}">{head}<div class="kb-lane-body">{body}</div></section>'
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def checklist_item(text, done):
|
|
150
|
+
return (f'<label class="bevel-checkbox bevel-checkbox--small kb-check-item"><input type="checkbox" class="bevel-sr-only" {"checked" if done else ""}>'
|
|
151
|
+
f'<span class="bevel-checkbox__box" aria-hidden="true"></span><span class="bevel-checkbox__label">{text}</span></label>')
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def panel():
|
|
155
|
+
return f'''<aside class="kb-panel" aria-label="Task FN-104">
|
|
156
|
+
<header class="kb-panel-head"><span class="kb-id">FN-104</span><span class="kb-status" data-lane="progress">In progress {icon("chevron", 12)}</span><span class="kb-spacer"></span><button type="button" class="kb-icon" aria-label="Task options">{icon("more", 16)}</button><button type="button" class="kb-icon" aria-label="Close task">{icon("close", 16)}</button></header>
|
|
157
|
+
<h2>Make room for good work</h2>
|
|
158
|
+
<p class="kb-panel-lede">Finish the new project experience. Keep the first step calm, direct and easy to return to.</p>
|
|
159
|
+
<dl class="kb-props">
|
|
160
|
+
<dt>Assignees</dt><dd><span class="kb-people">{avatar("MC", "small")}{avatar("AR", "small")}</span>Mira Chen, Alex Rivera</dd>
|
|
161
|
+
<dt>Priority</dt><dd>{priority("urgent")}</dd>
|
|
162
|
+
<dt>Due</dt><dd><span class="kb-due" data-due="today">{icon("calendar", 12)}Today, Sep 08</span></dd>
|
|
163
|
+
<dt>Labels</dt><dd class="kb-labels">{label("design")}{label("launch")}</dd>
|
|
164
|
+
<dt>Estimate</dt><dd class="f-mono">3 days · 2 spent</dd>
|
|
165
|
+
</dl>
|
|
166
|
+
<section class="kb-panel-section"><h4>Checklist <b class="kb-check-count">3/4</b></h4><i class="kb-check-bar"><b style="width:75%"></b></i>
|
|
167
|
+
{checklist_item("Set the project details", True)}{checklist_item("Check both colour modes", True)}{checklist_item("Review the compact layout", True)}{checklist_item("Get Jules’ final review", False)}
|
|
168
|
+
</section>
|
|
169
|
+
<section class="kb-panel-section"><h4>Blocked by <b class="kb-check-count">1</b></h4>
|
|
170
|
+
<div class="kb-dep-row">{icon("lock", 14)}<div><b>FN-105</b> Polish the document export<small>In progress · Alex Rivera · <span class="kb-due" data-due="overdue">due Sep 07</span></small></div>{avatar("AR", "small")}</div>
|
|
171
|
+
</section>
|
|
172
|
+
<section class="kb-panel-section"><h4>Attachments <b class="kb-check-count">3</b></h4>
|
|
173
|
+
<div class="kb-files"><a class="kb-file" href="#workspace"><img src="../../fixtures/workspace.jpg" alt=""><span>workspace.jpg<small>184 KB</small></span></a><a class="kb-file" href="#brief">{icon("doc", 18)}<span>project-brief.pdf<small>420 KB</small></span></a><a class="kb-file" href="#copy">{icon("doc", 18)}<span>welcome-copy.md<small>3 KB</small></span></a></div>
|
|
174
|
+
</section>
|
|
175
|
+
<section class="kb-panel-section"><h4>Activity <b class="kb-check-count">8</b></h4>
|
|
176
|
+
<div class="kb-comment">{avatar("AR", "small")}<div><b>Alex Rivera <small>18 min ago</small></b><p>The new flow reads clearly. Ready for one last look at the copy.</p></div></div>
|
|
177
|
+
<div class="kb-comment">{avatar("SP", "small")}<div><b>Sam Patel <small>2 h ago</small></b><p>Tightened the welcome line. It is on the card now.</p></div></div>
|
|
178
|
+
<div class="kb-event"><span class="kb-event-dot"></span>Mira moved this from <b>Up next</b> to <b>In progress</b><small>Yesterday</small></div>
|
|
179
|
+
<div class="kb-composer"><span>Leave a comment…</span><kbd>⌘ ↵</kbd></div>
|
|
180
|
+
</section>
|
|
181
|
+
<footer class="kb-panel-foot"><span class="f-mono">Created Sep 02 by Jules Park</span>{button("Open task", "expand", "bevel-button--small")}</footer>
|
|
182
|
+
</aside>'''
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def kanban(state):
|
|
186
|
+
empty = state == 'empty'
|
|
187
|
+
total = 0 if empty else sum(len(v) for v in TASKS.values())
|
|
188
|
+
done = 0 if empty else len(TASKS['done'])
|
|
189
|
+
progress = 0 if empty else len(TASKS['progress'])
|
|
190
|
+
blocked = 0 if empty else 1
|
|
191
|
+
pct = 0 if empty else round(done / total * 100)
|
|
192
|
+
lanes = ''.join(lane(k, t, w, b, e, TASKS[k], state) for k, t, w, b, e in LANES)
|
|
193
|
+
tape = (f'<dl class="kb-tape"><div><dt>Open</dt><dd>{total - done}</dd></div><div><dt>In progress</dt><dd>{progress}<small>of 3</small></dd></div>'
|
|
194
|
+
f'<div><dt>Blocked</dt><dd data-tone="{"ox" if blocked else ""}">{blocked}</dd></div><div><dt>Done this week</dt><dd>{done}</dd></div>'
|
|
195
|
+
f'<div class="kb-tape-meter"><dt>Progress</dt><dd><i class="kb-check-bar"><b style="width:{pct}%"></b></i>{pct}%</dd></div></dl>')
|
|
196
|
+
filters = ('' if empty else f'<button type="button" class="kb-chip" aria-pressed="true">{icon("calendar", 13)}Due: this week{icon("close", 11)}</button>') + \
|
|
197
|
+
f'<button type="button" class="kb-chip">Assignee: anyone{icon("chevron", 12)}</button><button type="button" class="kb-chip">Label: all{icon("chevron", 12)}</button>'
|
|
198
|
+
empty_note = ('<div class="kb-empty-note"><strong>This board is empty.</strong> New tasks land in Backlog. Move them across the lanes as the work moves.</div>' if empty else '')
|
|
199
|
+
return f'''<main class="kb" data-state="{state}">
|
|
200
|
+
<header class="kb-mast"><div class="kb-mast-title"><div class="kb-kicker">Northstar Studio<i>/</i>Project 004<i>/</i>Board</div><h1>Field notes</h1><p>Everything the studio is making for the field guide, in the order it will ship.</p></div>
|
|
201
|
+
<div class="kb-mast-side"><div class="kb-team"><span class="kb-people">{"".join(avatar(p) for p in PEOPLE)}</span><small>4 people</small></div>{button("Share", "share")}{button("New task", "plus", "bevel-button--primary")}</div></header>
|
|
202
|
+
<nav class="kb-views" aria-label="Views"><a href="#board" aria-current="page">{icon("board", 15)}Board<b>{total}</b></a><a href="#list">{icon("list", 15)}List</a><a href="#timeline">{icon("timeline", 15)}Timeline</a><a href="#calendar">{icon("calendar", 15)}Calendar</a><span class="kb-views-note">{icon("lock", 12)}Private · updated 10:42</span></nav>
|
|
203
|
+
<div class="kb-tools"><label class="kb-search">{icon("search", 15)}<input type="search" placeholder="Search tasks" aria-label="Search tasks"><kbd>⌘ K</kbd></label>{filters}<span class="kb-spacer"></span><button type="button" class="kb-chip kb-chip-quiet">{icon("group", 13)}Group: status</button><button type="button" class="kb-chip kb-chip-quiet">{icon("sort", 13)}Sort: priority</button></div>
|
|
204
|
+
{tape}{empty_note}
|
|
205
|
+
<div class="kb-work {"has-panel" if state == "selected" else ""}"><div class="kb-board" tabindex="0" aria-label="Board lanes">{lanes}</div>{panel() if state == "selected" else ""}</div>
|
|
206
|
+
<footer class="kb-foot"><span>{icon("board", 13)}Grouped by status · sorted by priority</span><span>{total} tasks · {done} done · 4 people</span></footer>
|
|
207
|
+
</main>'''
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
[hidden]{display:none!important}*{box-sizing:border-box}body{font-size:15px;line-height:1.5}button{cursor:pointer}button:disabled{cursor:not-allowed}h1,h2,h3,p{margin:0}h1,h2,h3{font-family:var(--bevel-font-serif);font-weight:400;line-height:1.1}h1{font-size:38px;letter-spacing:-.025em}h2{font-size:30px}h3{font-size:23px}a{color:var(--bevel-brass);text-underline-offset:3px}small,.muted{color:var(--bevel-muted)}small{font-size:12px}.mono,.eyebrow,kbd,time{font-family:var(--bevel-font-mono)}.eyebrow{font-size:10px;letter-spacing:.13em;text-transform:uppercase;color:var(--bevel-muted);margin-bottom:12px}.specimen{padding:34px 38px;min-height:580px;position:relative}.specimen>header{margin-bottom:30px}.specimen>header p{color:var(--bevel-muted);margin-top:10px;max-width:490px}.row{display:flex;align-items:center;gap:12px}.between{justify-content:space-between}.wrap{flex-wrap:wrap}.stack{display:grid;gap:16px}.spacer{flex:1}.rule{border-top:1px solid var(--bevel-line);padding-top:18px;margin-top:20px}.panel{border:1px solid var(--bevel-line-2);background:var(--bevel-surface)}.pad{padding:24px}.well{background:var(--bevel-sunk);padding:18px}.note{font-size:12px;color:var(--bevel-muted);margin-top:20px}.actions{display:flex;justify-content:flex-end;gap:10px;align-items:center;flex-wrap:wrap;margin-top:24px}.bevel-button{font-size:14px;padding:6px 13px}.bevel-input,.bevel-select__field{font-size:15px}.field{display:grid;gap:7px;font-size:13px;font-weight:500}.field small{font-weight:400}.cols{display:grid;grid-template-columns:1fr 1fr;gap:18px}.tag{display:inline-flex;align-items:center;gap:7px;border:1px solid var(--bevel-line-2);padding:3px 8px;font-size:12px;background:var(--bevel-sunk)}.tag button{padding:0;border:0;background:none;color:var(--bevel-muted);font-size:17px}.badge{display:inline-flex;align-items:center;gap:6px;font-size:11px;padding:3px 7px;background:var(--bevel-brass-soft);color:var(--bevel-brass)}.good{color:var(--bevel-teal)}.bad{color:var(--bevel-ox)}.badge.good{background:var(--bevel-teal-soft)}.badge.bad{background:var(--bevel-ox-soft)}.notice{padding:14px 17px;background:var(--bevel-brass-soft);border-left:3px solid var(--bevel-brass);font-size:13px}.notice.error{background:var(--bevel-ox-soft);border-color:var(--bevel-ox);color:var(--bevel-ox)}.notice.success{background:var(--bevel-teal-soft);border-color:var(--bevel-teal);color:var(--bevel-teal)}.invalid{border-color:var(--bevel-ox)!important}.avatar{width:35px;height:35px;display:inline-grid;place-items:center;background:var(--bevel-brass-soft);color:var(--bevel-brass);font-family:var(--bevel-font-mono);font-size:11px;flex-shrink:0;border:1px solid var(--bevel-line-2)}.avatar.alt{background:var(--bevel-teal-soft);color:var(--bevel-teal)}.person{display:flex;align-items:center;gap:12px}.person strong{display:block;font-weight:500}.person small{display:block}.listrow{padding:13px 0;border-bottom:1px solid var(--bevel-line);display:flex;align-items:center;gap:12px}.listrow:last-child{border-bottom:0}.overlay-scene{background:var(--bevel-sunk);display:grid;place-items:center;min-height:580px;padding:35px 28px}.micromodal__container{position:relative;border:2px solid light-dark(#fff,#ECEAF2);outline:1px solid var(--bevel-line-2);background:var(--bevel-surface);max-width:490px;width:100%;box-shadow:var(--bevel-shadow)}.micromodal__inner{padding:38px 40px 30px}.micromodal__heading{font-size:34px;margin-bottom:12px}.micromodal__content>p{color:var(--bevel-muted);margin-bottom:22px}.micromodal__close{position:absolute;right:-2px;top:-2px;width:32px;height:32px;background:var(--bevel-ink);border:2px solid light-dark(#fff,#ECEAF2);color:var(--bevel-ground);padding:7px}.micromodal__close svg{width:14px;height:14px;display:block}.micromodal__buttons{border-top:1px solid var(--bevel-line);padding-top:22px;margin-top:26px;display:flex;gap:9px;justify-content:flex-end;flex-wrap:wrap}.scroll-copy{max-height:210px;overflow:auto;padding-right:14px}.scroll-copy p{margin:12px 0;color:var(--bevel-muted)}.menu{width:280px;padding:7px;background:var(--bevel-surface);border:1px solid var(--bevel-line-2);box-shadow:var(--bevel-shadow)}.menu button{display:flex;width:100%;align-items:center;gap:12px;border:0;background:none;padding:9px 12px;text-align:left;font-size:14px;color:var(--bevel-ink)}.menu button:hover{background:var(--bevel-sunk)}.menu button:disabled{color:var(--bevel-faint)}.menu button.danger{color:var(--bevel-ox)}.menu kbd{margin-left:auto;font-size:10px;color:var(--bevel-muted)}.menu hr{border:0;border-top:1px solid var(--bevel-line);margin:5px}.menu-title{padding:8px 12px;font:10px var(--bevel-font-mono);color:var(--bevel-muted);letter-spacing:.08em}.anchor-stage{position:relative;min-height:360px;padding:24px;background:var(--bevel-sunk)}.anchor-stage .menu{margin-top:7px}.drawer-scene{padding:0;display:grid;grid-template-columns:1fr minmax(320px,440px);background:var(--bevel-sunk)}.drawer-underlay{padding:35px 22px;color:var(--bevel-muted)}.drawer-panel{height:580px;border-left:1px solid var(--bevel-line-2);background:var(--bevel-surface);display:flex;flex-direction:column}.drawer-panel header{padding:30px 28px 22px;border-bottom:1px solid var(--bevel-line)}.drawer-panel main{padding:24px 28px;overflow:auto;flex:1}.drawer-panel footer{padding:18px 28px;border-top:1px solid var(--bevel-line)}.detail-grid{display:grid;grid-template-columns:90px 1fr;gap:17px;font-size:13px}.detail-grid dt{color:var(--bevel-muted)}.detail-grid dd{margin:0}.popconfirm{position:relative;width:330px;max-width:100%;margin-top:12px;padding:22px;background:var(--bevel-surface);border:1px solid var(--bevel-line-2)}.popconfirm:before{content:'';position:absolute;top:-6px;left:30px;width:10px;height:10px;transform:rotate(45deg);background:var(--bevel-surface);border-top:1px solid var(--bevel-line-2);border-left:1px solid var(--bevel-line-2)}.picker{max-width:460px;margin:auto}.picker-options{border:1px solid var(--bevel-line-2);border-top:0;background:var(--bevel-surface);padding:6px}.option{display:flex;align-items:center;gap:12px;padding:10px 12px;background:none;border:0;text-align:left;width:100%;color:var(--bevel-ink)}.option:hover,.option.selected{background:var(--bevel-sunk)}.option .tick{margin-left:auto;color:var(--bevel-brass)}.choice{display:flex;gap:15px;padding:22px;border:1px solid var(--bevel-line-2);cursor:pointer;background:var(--bevel-surface)}.choice:has(:checked){border-color:var(--bevel-brass);background:var(--bevel-brass-soft)}.choice:has(:disabled){opacity:.5;cursor:not-allowed}.choice strong{display:block;font-size:16px}.choice p{font-size:13px;color:var(--bevel-muted);margin:7px 0}.choice input{margin-top:4px}.dropzone{display:grid;place-items:center;text-align:center;padding:44px 25px;border:1px dashed var(--bevel-faint);background:var(--bevel-surface)}.drop-icon{font:40px var(--bevel-font-serif);margin-bottom:12px}.dropzone p{color:var(--bevel-muted);font-size:13px;margin:10px 0 20px}.image-thumb{width:70px;height:56px;object-fit:cover}.progress{height:4px;background:var(--bevel-line);margin-top:11px}.progress span{display:block;height:100%;background:var(--bevel-brass)}.qc-stage{position:relative;line-height:0;overflow:hidden;background:#11131e}.qc-stage>img{width:100%;height:280px;object-fit:cover;display:block}.qc-dim{position:absolute;inset:0;background:rgba(0,0,0,.48);clip-path:polygon(0 0,100% 0,100% 100%,0 100%,0 0,15% 20%,15% 80%,85% 80%,85% 20%,15% 20%)}.qc-box{position:absolute;left:15%;top:20%;width:70%;height:60%;outline:1px solid white}.qc-box:before,.qc-box:after{content:'';position:absolute;inset:33.333% 0;border-top:1px solid #ffffff80;border-bottom:1px solid #ffffff80}.qc-box:after{inset:0 33.333%;border:0;border-left:1px solid #ffffff80;border-right:1px solid #ffffff80}.qc-handle{position:absolute;width:9px;height:9px;background:white}.qc-nw{left:-4px;top:-4px}.qc-ne{right:-4px;top:-4px}.qc-sw{left:-4px;bottom:-4px}.qc-se{right:-4px;bottom:-4px}.qc-bar{display:flex;gap:10px;justify-content:flex-end;margin-top:18px}.setting{display:grid;grid-template-columns:1fr 180px;gap:25px;padding:23px 0;border-bottom:1px solid var(--bevel-line);align-items:center}.setting p{font-size:13px;color:var(--bevel-muted);margin-top:5px}.settings-disabled{opacity:.6}.inline-title{padding:22px 0;border-top:1px solid var(--bevel-line);border-bottom:1px solid var(--bevel-line);margin-top:26px}.sidebar-layout{display:grid;grid-template-columns:225px 1fr;min-height:580px}.sidebar{background:var(--bevel-surface);border-right:1px solid var(--bevel-line-2);padding:25px 16px;display:flex;flex-direction:column;gap:25px}.navitem{display:flex;gap:12px;align-items:center;padding:9px 10px;background:none;border:0;color:var(--bevel-muted);width:100%;text-align:left}.navitem.active{background:var(--bevel-brass-soft);color:var(--bevel-ink);border-left:2px solid var(--bevel-brass)}.navitem .count{margin-left:auto;font:11px var(--bevel-font-mono)}.sidebar-content{padding:38px 26px}.sidebar-compact{grid-template-columns:66px 1fr}.sidebar-compact .sidebar{padding:25px 8px}.sidebar-compact .navitem{justify-content:center;padding:10px 6px}.toolbar{padding:12px;border:1px solid var(--bevel-line-2);display:flex;align-items:center;gap:10px;flex-wrap:wrap;background:var(--bevel-surface)}.toolbar .bevel-input{width:170px}.toolbar-sep{height:26px;border-left:1px solid var(--bevel-line-2)}.breadcrumb{display:flex;align-items:center;gap:12px;flex-wrap:wrap;font-size:13px;padding:14px 0;border-bottom:1px solid var(--bevel-line)}.breadcrumb span{color:var(--bevel-faint)}.breadcrumb strong{font-weight:500}.pagination{display:flex;align-items:center;gap:6px;flex-wrap:wrap}.pagination .bevel-button{min-width:35px;padding:5px 9px}.pagination .current{background:var(--bevel-face-in);border-color:var(--bevel-edge-in) var(--bevel-edge-in-hi) var(--bevel-edge-in-hi) var(--bevel-edge-in)}table{border-collapse:collapse;width:100%;font-size:13px}th{text-align:left;font-weight:500;color:var(--bevel-muted);font-size:11px;text-transform:uppercase;letter-spacing:.055em;padding:13px 12px;background:var(--bevel-sunk)}td{padding:15px 12px;border-bottom:1px solid var(--bevel-line)}td.numeric{text-align:right;font-family:var(--bevel-font-mono);white-space:nowrap}.table-scroll{overflow:auto}.tree{font-size:14px}.tree details{margin-left:20px}.tree>details{margin-left:0}.tree summary{padding:10px;cursor:pointer}.tree button{display:block;margin-left:27px;border:0;padding:9px 12px;width:calc(100% - 27px);text-align:left;background:none;color:var(--bevel-ink)}.tree button.selected{background:var(--bevel-brass-soft);border-left:2px solid var(--bevel-brass)}.wizard{display:grid;grid-template-columns:170px 1fr;gap:30px}.wizard-steps{border-right:1px solid var(--bevel-line);padding-right:20px}.wizard-step{padding:0 0 28px;color:var(--bevel-muted);font-size:13px}.wizard-step b{display:block;font-family:var(--bevel-font-mono);margin-bottom:8px;color:var(--bevel-brass)}.wizard-step.current{color:var(--bevel-ink);font-weight:600}.toast-space{background:var(--bevel-sunk);padding:25px;display:grid;gap:12px;max-width:560px;margin:auto}.toast{display:flex;align-items:flex-start;gap:13px;background:var(--bevel-surface);border:1px solid var(--bevel-line-2);border-left:3px solid var(--bevel-teal);padding:16px}.toast.error{border-left-color:var(--bevel-ox)}.toast.action{border-left-color:var(--bevel-brass)}.toast p{font-size:13px;color:var(--bevel-muted);margin-top:3px}.toast .close{border:0;background:none;color:var(--bevel-muted);font-size:18px}.save-dot{display:inline-block;width:7px;height:7px;background:currentColor;margin-right:7px}.code-shell{border:1px solid var(--bevel-line-2);background:var(--bevel-surface)}.code-head{display:flex;gap:12px;align-items:center;padding:12px 16px;border-bottom:1px solid var(--bevel-line);font:12px var(--bevel-font-mono);flex-wrap:wrap}.code-lines{margin:0;padding:20px 20px 20px 48px;overflow:auto;font:12px/2 var(--bevel-font-mono);color:var(--bevel-ink-2);white-space:pre}.code-lines li{padding-left:12px}.code-lines li::marker{color:var(--bevel-faint)}.code-lines.wrap-code{white-space:pre-wrap;overflow-wrap:anywhere}.syntax{color:var(--bevel-teal)}.diff-line{font:12px/2 var(--bevel-font-mono);padding:3px 15px;overflow-wrap:anywhere}.diff-line.add{background:var(--bevel-teal-soft);color:var(--bevel-teal)}.diff-line.remove{background:var(--bevel-ox-soft);color:var(--bevel-ox)}.diff-line mark{color:inherit;background:color-mix(in srgb,currentColor 15%,transparent)}.diff-split{display:grid;grid-template-columns:1fr 1fr}.diff-split>div+div{border-left:1px solid var(--bevel-line)}.timeline{margin-left:16px;border-left:1px solid var(--bevel-line-2);padding-left:27px}.event{position:relative;padding-bottom:24px}.event .avatar{position:absolute;left:-45px;top:0;width:33px;height:33px;border:4px solid var(--bevel-ground)}.event p{font-size:14px}.event time{font-size:10px;color:var(--bevel-muted);display:block;margin-top:5px}.stat-grid{display:grid;grid-template-columns:repeat(3,1fr);border-top:1px solid var(--bevel-line-2);border-bottom:1px solid var(--bevel-line-2)}.stat{padding:26px 20px}.stat+.stat{border-left:1px solid var(--bevel-line)}.stat-value{font:34px var(--bevel-font-mono);letter-spacing:-.06em;margin:14px 0}.stat small{font:11px var(--bevel-font-mono)}.sparkline{height:42px;width:100%;margin-top:24px;color:var(--bevel-brass)}.chart{width:100%;height:auto;color:var(--bevel-brass);overflow:visible}.chart text{fill:var(--bevel-muted);font:11px var(--bevel-font-mono)}.chart .grid{stroke:var(--bevel-line)}.chart .data{fill:var(--bevel-brass)}.chart .line{fill:none;stroke:var(--bevel-brass);stroke-width:3}.avatar-pile{display:flex;padding-left:7px}.avatar-pile .avatar{margin-left:-7px;width:44px;height:44px;border:3px solid var(--bevel-surface)}.avatar img{width:100%;height:100%;object-fit:cover}.filters{display:grid;gap:12px}.filter-row{display:grid;grid-template-columns:40px 1fr 1fr 1.1fr 30px;gap:8px;align-items:center}.filter-row .bevel-select__field{font-size:13px;padding:7px}.filter-row>span{font:10px var(--bevel-font-mono);color:var(--bevel-muted)}.icon-button{border:0;background:none;font-size:17px;color:var(--bevel-muted);padding:4px}.column-item{display:flex;align-items:center;gap:12px;padding:12px;border-bottom:1px solid var(--bevel-line)}.column-item label{flex:1}.split-work{display:grid;grid-template-columns:230px 8px 1fr;min-height:360px;border:1px solid var(--bevel-line-2)}.split-list{padding:10px;background:var(--bevel-sunk)}.split-list button{border:0;background:none;width:100%;padding:16px 12px;text-align:left;color:var(--bevel-ink);border-bottom:1px solid var(--bevel-line)}.split-list button.selected{background:var(--bevel-surface);border-left:2px solid var(--bevel-brass)}.divider{background:var(--bevel-line);display:grid;place-items:center;color:var(--bevel-faint);font-size:11px}.split-detail{padding:28px;min-width:0}.richclay-toolbar{display:flex;align-items:center;gap:3px;flex-wrap:wrap;padding:8px;background:var(--bevel-sunk);border:1px solid var(--bevel-line-2);position:relative}.richclay-button{min-width:31px;min-height:32px;background:var(--bevel-face);border:2px solid;border-color:var(--bevel-edge-hi) var(--bevel-edge-lo) var(--bevel-edge-lo) var(--bevel-edge-hi);padding:3px 7px;color:var(--bevel-ink);font-size:14px}.richclay-button[aria-pressed=true]{background:var(--bevel-face-in);border-color:var(--bevel-edge-in) var(--bevel-edge-in-hi) var(--bevel-edge-in-hi) var(--bevel-edge-in)}.richclay-separator{height:22px;border-left:1px solid var(--bevel-line-2);margin:0 6px}.richclay-menu-wrap{position:relative}.richclay-menu{position:absolute;z-index:3;top:40px;left:0;width:200px;background:var(--bevel-surface);border:1px solid var(--bevel-line-2);padding:7px}.richclay-menu-item{display:block;background:none;border:0;width:100%;padding:9px;text-align:left;color:var(--bevel-ink)}.richclay-menu-item:hover{background:var(--bevel-sunk)}.richclay-editor{padding:30px;background:var(--bevel-surface);border:1px solid var(--bevel-line-2);border-top:0;min-height:240px}.richclay-editor p{margin:15px 0;color:var(--bevel-ink-2);line-height:1.75}.richclay-editor blockquote{border-left:2px solid var(--bevel-brass);margin:22px 0;padding-left:20px;font-family:var(--bevel-font-serif);font-size:22px}.richclay-link-dialog{border:1px solid var(--bevel-line-2);padding:18px;background:var(--bevel-surface);max-width:410px;margin-top:14px}.kanban{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:15px}.kanban-column{background:var(--bevel-sunk);padding:12px;min-height:320px}.kanban-column>header{display:flex;justify-content:space-between;font-size:12px;font-weight:500;padding:3px 0 14px}.kanban-card{padding:16px 13px;background:var(--bevel-surface);border:1px solid var(--bevel-line-2);margin-bottom:10px;font-size:14px}.kanban-card.selected{border:2px solid var(--bevel-brass);padding:15px 12px}.kanban-card .tag{font-size:10px;padding:2px 5px;margin-bottom:12px}.kanban-card footer{margin-top:20px;display:flex;align-items:center;justify-content:space-between}.kanban-card .avatar{width:25px;height:25px;font-size:9px}.empty-column{border:1px dashed var(--bevel-line-2);padding:25px 10px;text-align:center;color:var(--bevel-muted);font-size:12px}.hcms-context{display:grid;grid-template-columns:1fr 355px;padding:0;min-height:720px}.hcms-preview{padding:38px 25px;background:var(--bevel-sunk)}.hcms-preview img{width:100%;height:130px;object-fit:cover;margin:22px 0}.hcms-shell{background:var(--bevel-surface);border-left:1px solid var(--bevel-line-2);height:720px;overflow:auto}.hcms-shell-body{padding:24px}.hcms-shell-header{display:flex;align-items:flex-start;justify-content:space-between;margin-bottom:24px}.hcms-shell-title{font-size:30px}.hcms-shell-eyebrow{font:10px var(--bevel-font-mono);color:var(--bevel-muted);margin-bottom:10px}.hcms-form{display:grid;gap:18px}.hcms-field{display:grid;gap:7px;font-size:12px}.hcms-field textarea{font-size:13px;min-height:38px;padding:8px;resize:vertical}.hcms-object{padding-top:18px;border-top:1px solid var(--bevel-line)}.hcms-object-title,.hcms-array-title{font:13px var(--bevel-font-sans);font-weight:600;margin-bottom:12px}.hcms-object-fields{padding-left:14px;border-left:1px solid var(--bevel-line-2);display:grid;gap:12px}.hcms-array-items{display:grid;gap:8px}.hcms-card{border:1px solid var(--bevel-line-2);padding:12px;display:flex;gap:10px;background:var(--bevel-sunk)}.hcms-card-body{flex:1;min-width:0}.hcms-card-fields{display:grid;gap:10px}.hcms-card-controls{text-align:right}.hcms-error{color:var(--bevel-ox);font-size:12px}.hcms-upload img{width:90px;height:64px;object-fit:cover}.hcms-shell-footer{margin-top:20px;padding-top:20px;border-top:1px solid var(--bevel-line)}.index-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(230px,1fr));gap:1px;background:var(--bevel-line);border:1px solid var(--bevel-line)}.index-grid a{padding:22px;background:var(--bevel-surface);text-decoration:none;color:var(--bevel-ink)}.index-grid a:hover{background:var(--bevel-brass-soft)}.index-grid strong{display:block;font-family:var(--bevel-font-serif);font-size:23px;margin:6px 0}.local-result:empty{display:none}.local-result{font-size:12px;color:var(--bevel-teal);padding-top:12px}
|
|
2
|
+
@media(max-width:520px){.specimen{padding:26px 20px;min-height:580px}h1{font-size:32px}.cols{grid-template-columns:1fr}.overlay-scene{padding:25px 18px}.micromodal__inner{padding:34px 25px 25px}.micromodal__heading{font-size:29px}.drawer-scene{padding:0;grid-template-columns:1fr}.drawer-underlay{display:none}.drawer-panel{border-left:0}.setting{grid-template-columns:1fr;gap:12px;padding:18px 0}.setting>label,.setting>button,.setting>select{justify-self:start}.sidebar-layout{grid-template-columns:170px 1fr}.sidebar-content{padding:28px 18px}.sidebar-compact{grid-template-columns:62px 1fr}.sidebar-content h1{font-size:27px}.wizard{grid-template-columns:1fr;gap:15px}.wizard-steps{display:flex;border:0;border-bottom:1px solid var(--bevel-line);gap:20px}.wizard-step{padding-bottom:16px;font-size:11px}.wizard-step b{margin-bottom:4px}.stat-grid{grid-template-columns:1fr}.stat{padding:18px 0}.stat+.stat{border-left:0;border-top:1px solid var(--bevel-line)}.stat-value{margin:6px 0;font-size:30px}.stat .sparkline{display:none}.stat{display:grid;grid-template-columns:1fr 1fr;align-items:center}.stat>small{grid-column:2}.filter-row{grid-template-columns:28px 1fr 1fr 25px;gap:5px}.filter-row>input{grid-column:2/4}.filter-row>button{grid-column:4;grid-row:1/3}.filter-row .bevel-select__field{font-size:11px;padding-left:5px;padding-right:20px}.split-work{grid-template-columns:120px 5px 1fr}.split-detail{padding:20px 15px}.split-detail h2{font-size:25px}.split-list{padding:5px}.split-list button{padding:14px 8px;font-size:12px}.richclay-editor{padding:22px}.kanban{overflow-x:auto;grid-template-columns:repeat(3,185px);padding-bottom:12px}.hcms-context{padding:0;grid-template-columns:1fr}.hcms-preview{display:none}.hcms-shell{border:0;width:100%;height:720px}.diff-split{grid-template-columns:1fr}.diff-split>div+div{border:0;border-top:1px solid var(--bevel-line)}.qc-stage>img{height:230px}.pad{padding:20px}.anchor-stage{padding:20px}.menu{max-width:100%}.toast-space{padding:15px}.toolbar .bevel-input{width:100%}}
|
|
3
|
+
body[data-component="tree-view"] .tree summary{padding:7px 10px}body[data-component="tree-view"] .tree button{padding:7px 12px}body[data-component="tree-view"] .specimen>header{margin-bottom:22px}
|
|
4
|
+
body[data-component="toast-stack"] .specimen>header{margin-bottom:22px}body[data-component="toast-stack"] .toast-space{padding:16px;gap:9px}body[data-component="toast-stack"] .toast{padding:12px}body[data-component="toast-stack"] .toast .bevel-button{padding:2px 8px;margin-top:4px}body[data-component="toast-stack"] .actions{margin-top:18px}
|
|
5
|
+
body[data-component="column-manager"] .panel .pad{padding:16px 20px}body[data-component="column-manager"] .panel h2{font-size:26px}body[data-component="column-manager"] .panel .note{margin-top:8px}body[data-component="column-manager"] .column-item{padding:8px 12px}body[data-component="column-manager"] .column-item .bevel-button{padding:2px 7px;font-size:12px}
|
|
6
|
+
body[data-component="filter-builder"] .specimen{padding-top:28px;padding-bottom:26px}body[data-component="filter-builder"] .specimen>header{margin-bottom:20px}body[data-component="filter-builder"] .panel.pad{padding:18px}body[data-component="filter-builder"] td{padding:10px 12px}body[data-component="filter-builder"] .actions{margin-top:16px}
|
|
7
|
+
body[data-component="upload-dropzone"] [data-ref-state="crop"] .qc-stage>img{height:235px}
|
|
8
|
+
body[data-component="rich-text-toolbar"] .richclay-link-dialog{position:absolute;z-index:4;top:247px;right:56px;width:365px;box-shadow:var(--bevel-shadow)}body[data-component="rich-text-toolbar"] [data-ref-state="link"] .richclay-editor{min-height:290px}body[data-component="rich-text-toolbar"] [data-ref-state="floating"] .richclay-editor{padding:23px}body[data-component="rich-text-toolbar"] .richclay-editor p{font-size:14px;line-height:1.65}
|
|
9
|
+
@media(max-width:520px){body[data-component="rich-text-toolbar"] .richclay-link-dialog{top:265px;right:30px;width:calc(100% - 60px)}body[data-component="rich-text-toolbar"] .richclay-editor{padding:20px}body[data-component="rich-text-toolbar"] .richclay-editor blockquote{font-size:19px;margin:16px 0}body[data-component="rich-text-toolbar"] [data-ref-state="floating"] .specimen>header{margin-bottom:18px}body[data-component="wizard-shell"] .specimen>header{margin-bottom:20px}body[data-component="wizard-shell"] .wizard-step small{display:none!important}body[data-component="wizard-shell"] .wizard .actions{margin-top:18px}body[data-component="pagination"] td{padding:10px 8px}body[data-component="selectable-cards"] .choice{padding:17px}body[data-component="selectable-cards"] .specimen>header{margin-bottom:20px}}
|
|
10
|
+
.hcms-shell-body{padding:22px}.hcms-shell-header{margin-bottom:18px}.hcms-form{gap:13px}.hcms-field{gap:5px}.hcms-field textarea{min-height:32px;padding:5px 8px;font-size:12px;line-height:1.6}.hcms-object{padding-top:13px}.hcms-object-fields{gap:10px}.hcms-card{position:relative;padding:11px}.hcms-card-controls{position:absolute;top:3px;right:4px}.hcms-card-controls .bevel-button{font-size:10px;padding:0 5px}.hcms-upload img{height:51px;width:78px}.hcms-shell-footer{margin-top:15px;padding-top:15px}.hcms-shell-error{margin-bottom:12px}
|
|
11
|
+
.choice{width:100%;position:relative}.option.bevel-checkbox{width:100%;align-items:center}.column-item .bevel-checkbox{align-items:center}.setting .bevel-toggle{justify-self:end}@media(max-width:520px){.setting .bevel-toggle{justify-self:start}}
|
|
12
|
+
.choice{padding:18px 22px}.choice:has(:disabled){opacity:.75}
|
|
13
|
+
|
|
14
|
+
.qc-stage[data-crop-ratio="16/9"]{container-type:inline-size;--crop-width:min(70cqw,350px);--crop-height:calc(var(--crop-width) * 9 / 16);--crop-left:calc((100cqw - var(--crop-width)) / 2);--crop-top:calc((100% - var(--crop-height)) / 2)}
|
|
15
|
+
.qc-stage[data-crop-ratio="16/9"] .qc-box{left:var(--crop-left);top:var(--crop-top);width:var(--crop-width);height:var(--crop-height);aspect-ratio:16/9}
|
|
16
|
+
.qc-stage[data-crop-ratio="16/9"] .qc-dim{clip-path:polygon(0 0,100% 0,100% 100%,0 100%,0 0,var(--crop-left) var(--crop-top),var(--crop-left) calc(var(--crop-top) + var(--crop-height)),calc(var(--crop-left) + var(--crop-width)) calc(var(--crop-top) + var(--crop-height)),calc(var(--crop-left) + var(--crop-width)) var(--crop-top),var(--crop-left) var(--crop-top))}
|
|
17
|
+
.option strong{display:block;font-weight:500}.option small{display:block}
|