@kerfjs/ui 5.0.0-beta.111 → 5.0.0-beta.113

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.
Files changed (93) hide show
  1. package/README.md +2 -0
  2. package/ai/component-catalog.json +152 -6
  3. package/ai/component-composition.json +111 -1
  4. package/ai/components/README.md +2 -0
  5. package/ai/components/backdrop-image.md +1 -0
  6. package/ai/components/content-item.md +1 -0
  7. package/ai/components/editor-frame.md +80 -0
  8. package/ai/components/summary-row.md +5 -2
  9. package/ai/components/value-preview.md +75 -0
  10. package/ai/public-api-signatures-v1.md +124 -14
  11. package/ai/skill.md +13 -0
  12. package/ai/webawesome-jsx-signatures-v1.md +1 -1
  13. package/dist/backdrop-image.d.ts +3 -0
  14. package/dist/backdrop-image.js +1 -1
  15. package/dist/browser/editor-frame.js +3 -0
  16. package/dist/browser/value-preview.js +3 -0
  17. package/dist/catalog.js +4 -3
  18. package/dist/catalog.js.map +1 -1
  19. package/dist/{chunk-JCCN3U6X.js → chunk-2J7XKAZX.js} +3 -2
  20. package/dist/chunk-2J7XKAZX.js.map +1 -0
  21. package/dist/{chunk-WD6KABEU.js → chunk-3KFMLOTH.js} +3 -2
  22. package/dist/chunk-3KFMLOTH.js.map +1 -0
  23. package/dist/{chunk-ATGAJVZ6.js → chunk-3OP66VXU.js} +64 -4
  24. package/dist/chunk-3OP66VXU.js.map +1 -0
  25. package/dist/{chunk-ZNROKDSZ.js → chunk-3V4OCDTL.js} +2 -8
  26. package/dist/chunk-3V4OCDTL.js.map +1 -0
  27. package/dist/{chunk-3GLYIIFR.js → chunk-3WWX2O4G.js} +3 -2
  28. package/dist/chunk-3WWX2O4G.js.map +1 -0
  29. package/dist/{chunk-SOBRGH7T.js → chunk-5CLMV5YU.js} +5 -2
  30. package/dist/chunk-5CLMV5YU.js.map +1 -0
  31. package/dist/chunk-F653O57X.js +41 -0
  32. package/dist/chunk-F653O57X.js.map +1 -0
  33. package/dist/{chunk-4UB5Z3ZZ.js → chunk-K67XBCHG.js} +8 -4
  34. package/dist/chunk-K67XBCHG.js.map +1 -0
  35. package/dist/chunk-OK7FUK7U.js +9 -0
  36. package/dist/chunk-OK7FUK7U.js.map +1 -0
  37. package/dist/{chunk-VGECEXM6.js → chunk-S3DCRI2M.js} +21 -4
  38. package/dist/chunk-S3DCRI2M.js.map +1 -0
  39. package/dist/chunk-V6N3YLTM.js +56 -0
  40. package/dist/chunk-V6N3YLTM.js.map +1 -0
  41. package/dist/content-item.d.ts +2 -0
  42. package/dist/content-item.js +1 -1
  43. package/dist/editor-frame.d.ts +41 -0
  44. package/dist/editor-frame.js +3 -0
  45. package/dist/editor-frame.js.map +1 -0
  46. package/dist/index.d.ts +2 -0
  47. package/dist/index.js +24 -21
  48. package/dist/list-action-row.js +2 -1
  49. package/dist/list-detail-dialog.js +2 -2
  50. package/dist/list-item.js +2 -1
  51. package/dist/styles/backdrop-image.css +6 -0
  52. package/dist/styles/components/actions/popup-menu/popup-menu.css +1 -1
  53. package/dist/styles/components/collections/summary-row/summary-row.css +7 -3
  54. package/dist/styles/components/data-display/value-preview/value-preview.css +18 -0
  55. package/dist/styles/components/surfaces/backdrop-image/backdrop-image.css +6 -0
  56. package/dist/styles/components/surfaces/editor-frame/editor-frame.css +121 -0
  57. package/dist/styles/components/surfaces/surface-scaffold/surface-scaffold.css +16 -0
  58. package/dist/styles/editor-frame.css +121 -0
  59. package/dist/styles/foundation.css +5 -0
  60. package/dist/styles/popup-menu.css +1 -1
  61. package/dist/styles/styles.css +2 -0
  62. package/dist/styles/summary-row.css +7 -3
  63. package/dist/styles/surface-scaffold.css +16 -0
  64. package/dist/styles/value-preview.css +18 -0
  65. package/dist/summary-row.d.ts +20 -11
  66. package/dist/summary-row.js +2 -1
  67. package/dist/surface-scaffold-register.js +1 -1
  68. package/dist/surface-scaffold.d.ts +26 -2
  69. package/dist/surface-scaffold.js +2 -2
  70. package/dist/value-preview.d.ts +21 -0
  71. package/dist/value-preview.js +3 -0
  72. package/dist/value-preview.js.map +1 -0
  73. package/dist/wire-catalog.js +1 -1
  74. package/dist/wire-content-items.js +34 -8
  75. package/dist/wire-content-items.js.map +1 -1
  76. package/dist/workbench-dialog.js +2 -2
  77. package/docs/component-contract.md +28 -5
  78. package/docs/component-selection.md +15 -0
  79. package/docs/editor-frame.md +47 -0
  80. package/docs/investigations/content-item-media-scroll-performance.md +46 -0
  81. package/docs/layout.md +10 -1
  82. package/docs/surface-scaffold.md +46 -0
  83. package/docs/value-preview.md +16 -0
  84. package/llms.txt +7 -1
  85. package/package.json +13 -1
  86. package/dist/chunk-3GLYIIFR.js.map +0 -1
  87. package/dist/chunk-4UB5Z3ZZ.js.map +0 -1
  88. package/dist/chunk-ATGAJVZ6.js.map +0 -1
  89. package/dist/chunk-JCCN3U6X.js.map +0 -1
  90. package/dist/chunk-SOBRGH7T.js.map +0 -1
  91. package/dist/chunk-VGECEXM6.js.map +0 -1
  92. package/dist/chunk-WD6KABEU.js.map +0 -1
  93. package/dist/chunk-ZNROKDSZ.js.map +0 -1
package/README.md CHANGED
@@ -273,6 +273,8 @@ interchangeable. `ListItem` and `ListActionRow` deliberately expose no raw
273
273
  | `LoadingSpinner` | `@kerfjs/ui/loading-spinner` | `@kerfjs/ui/loading-spinner.css` |
274
274
  | `Skeleton` | `@kerfjs/ui/skeleton` | `@kerfjs/ui/skeleton.css` |
275
275
  | `SunkenPanel` | `@kerfjs/ui/sunken-panel` | `@kerfjs/ui/sunken-panel.css` |
276
+ | `ValuePreview` | `@kerfjs/ui/value-preview` | `@kerfjs/ui/value-preview.css` |
277
+ | `EditorFrame` | `@kerfjs/ui/editor-frame` | `@kerfjs/ui/editor-frame.css` |
276
278
  | `BackdropImage` | `@kerfjs/ui/backdrop-image` | `@kerfjs/ui/backdrop-image.css` |
277
279
  | `Select` | `@kerfjs/ui/select` | `@kerfjs/ui/select.css` |
278
280
  | `SegmentedControl` | `@kerfjs/ui/segmented-control` | `@kerfjs/ui/segmented-control.css` |
@@ -1726,7 +1726,8 @@
1726
1726
  "progressive blur from a once-filtered copy or an app-supplied blurred asset, with an optional dim",
1727
1727
  "fade into a color that also paints below",
1728
1728
  "bottom or full scrim under overlay content",
1729
- "image running beneath clear or overlay chrome (underChrome)"
1729
+ "image running beneath clear or overlay chrome (underChrome)",
1730
+ "opt-in deferOffscreen hero paint deferral for dense image feeds without changing reserved height"
1730
1731
  ],
1731
1732
  "accessibility": [
1732
1733
  "alt describes a meaningful image; pass an empty alt for a decorative one. A tiled image with alt text is exposed as role=\"img\". Parallax and the progressive blur run only with prefers-reduced-motion: no-preference and scroll-driven animation support, and are off under data-kui-effects=\"static\" and on slow-update displays, leaving a static, sharp image; the blurred copy is decorative and aria-hidden. Reduced transparency or increased contrast replaces the fade with a hard edge on solid fadeTo and puts overlay content on a solid fadeTo band. Overlay text needs a scrim or fade color that keeps it at AA."
@@ -3049,6 +3050,147 @@
3049
3050
  "recipe": "docs/component-selection.md#ambiguous-choices"
3050
3051
  }
3051
3052
  },
3053
+ {
3054
+ "id": "editor-frame",
3055
+ "name": "EditorFrame",
3056
+ "category": "Structure",
3057
+ "kind": "component",
3058
+ "source": "kerf",
3059
+ "description": "A bounded editor surface with a fixed toolbar and one native source or preview scroll owner.",
3060
+ "uses": [
3061
+ "toolbar"
3062
+ ],
3063
+ "purpose": "Own a framed or embedded writing surface while the app owns its native textarea, draft, and rendered preview.",
3064
+ "publicExports": [
3065
+ "EditorFrame"
3066
+ ],
3067
+ "useWhen": [
3068
+ "A standalone Markdown or text editor needs a fixed toolbar above a bounded native textarea or preview.",
3069
+ "An embedded editor needs the same source/preview anatomy without a second frame."
3070
+ ],
3071
+ "avoidWhen": [
3072
+ "Do not use for an ordinary single form field; use TextField.",
3073
+ "Do not replace the app's draft, recovery, focus, or preview behavior."
3074
+ ],
3075
+ "alternatives": [
3076
+ {
3077
+ "id": "text-field",
3078
+ "relationship": "nearest",
3079
+ "when": "Use TextField for a conventional form value without editor toolbar and preview."
3080
+ }
3081
+ ],
3082
+ "appOwns": [
3083
+ "draft value",
3084
+ "editing actions",
3085
+ "preview rendering",
3086
+ "recovery and focus management"
3087
+ ],
3088
+ "variants": [
3089
+ "source and preview modes",
3090
+ "framed and embedded appearances",
3091
+ "padded and flush insets",
3092
+ "expanded overlay",
3093
+ "embedded autosize or restored source height"
3094
+ ],
3095
+ "accessibility": [
3096
+ "Give the editor frame a label when it is a distinct region; the app labels its native textarea and supplies toolbar controls."
3097
+ ],
3098
+ "geometry": {
3099
+ "margin": "none",
3100
+ "border": "self",
3101
+ "padding": "self"
3102
+ },
3103
+ "delivery": {
3104
+ "browserImport": "@kerfjs/ui/editor-frame",
3105
+ "manualCssImport": "@kerfjs/ui/editor-frame.css",
3106
+ "sideEffects": [
3107
+ "browser-condition-css"
3108
+ ]
3109
+ },
3110
+ "wiring": [],
3111
+ "publicClasses": [
3112
+ "kui-editor-frame",
3113
+ "kui-editor-frame__toolbar",
3114
+ "kui-editor-frame__surface"
3115
+ ],
3116
+ "publicTokens": [
3117
+ "--kui-color-neutral-border-normal",
3118
+ "--kui-color-neutral-on-normal",
3119
+ "--kui-color-surface",
3120
+ "--kui-radius-l",
3121
+ "--kui-shadow-l"
3122
+ ],
3123
+ "links": {
3124
+ "catalogRoute": "?component=editor-frame",
3125
+ "documentation": "docs/editor-frame.md",
3126
+ "recipe": "docs/editor-frame.md"
3127
+ }
3128
+ },
3129
+ {
3130
+ "id": "value-preview",
3131
+ "name": "ValuePreview",
3132
+ "category": "Structure",
3133
+ "kind": "component",
3134
+ "source": "kerf",
3135
+ "description": "A bounded, read-only multiline text value with keyboard scrolling.",
3136
+ "uses": [
3137
+ "sunken-panel"
3138
+ ],
3139
+ "purpose": "Display a literal long value with line breaks and long tokens inside a bounded scroll region.",
3140
+ "publicExports": [
3141
+ "ValuePreview"
3142
+ ],
3143
+ "useWhen": [
3144
+ "A read-only value may have multiple lines or long unbroken text and needs bounded scrolling, such as a conflict version."
3145
+ ],
3146
+ "avoidWhen": [
3147
+ "Do not use for editing; use a multiline TextField.",
3148
+ "Do not use for short label/value facts; use ValueTable."
3149
+ ],
3150
+ "alternatives": [
3151
+ {
3152
+ "id": "value-table",
3153
+ "relationship": "nearest",
3154
+ "when": "Use ValueTable for rows of short labelled facts."
3155
+ }
3156
+ ],
3157
+ "appOwns": [
3158
+ "value",
3159
+ "empty wording"
3160
+ ],
3161
+ "variants": [
3162
+ "typed minimum and maximum height"
3163
+ ],
3164
+ "accessibility": [
3165
+ "Give the focusable output a label so keyboard and screen-reader users can identify and scroll it."
3166
+ ],
3167
+ "geometry": {
3168
+ "margin": "none",
3169
+ "border": "none",
3170
+ "padding": "none"
3171
+ },
3172
+ "delivery": {
3173
+ "browserImport": "@kerfjs/ui/value-preview",
3174
+ "manualCssImport": "@kerfjs/ui/value-preview.css",
3175
+ "sideEffects": [
3176
+ "browser-condition-css"
3177
+ ]
3178
+ },
3179
+ "wiring": [],
3180
+ "publicClasses": [
3181
+ "kui-value-preview"
3182
+ ],
3183
+ "publicTokens": [
3184
+ "--kui-color-text",
3185
+ "--kui-font-xs",
3186
+ "--kui-focus-ring"
3187
+ ],
3188
+ "links": {
3189
+ "catalogRoute": "?component=value-preview",
3190
+ "documentation": "docs/value-preview.md",
3191
+ "recipe": "docs/value-preview.md"
3192
+ }
3193
+ },
3052
3194
  {
3053
3195
  "id": "value-table",
3054
3196
  "name": "ValueTable",
@@ -3224,14 +3366,15 @@
3224
3366
  "category": "Structure",
3225
3367
  "kind": "component",
3226
3368
  "source": "kerf",
3227
- "description": "A selectable, focusable summary of one item as a list row or a board card, with a state rail, a clamped title, trailing meta, and a metadata line.",
3369
+ "description": "A selectable option or static diagnostic group as a list row or board card, with a state rail, a clamped title, trailing meta, and a metadata line.",
3228
3370
  "uses": [],
3229
3371
  "purpose": "Present dense item summaries (tickets, tasks, messages) as selectable list rows or board cards with Kerf-owned selection, hover, focus, rail, clamping, list-edge rounding, and narrow compaction, without app row CSS.",
3230
3372
  "publicExports": [
3231
3373
  "SummaryRow"
3232
3374
  ],
3233
3375
  "useWhen": [
3234
- "A list or board shows many items as dense, selectable summaries with an identifier, a title, a timestamp, and metadata."
3376
+ "A list or board shows many items as dense, selectable summaries with an identifier, a title, a timestamp, and metadata.",
3377
+ "An unreadable item needs the same summary chrome with a nested recovery action but must be a labeled non-option group."
3235
3378
  ],
3236
3379
  "avoidWhen": [
3237
3380
  "Do not use for navigation rows with a single label; use ListItem.",
@@ -3263,10 +3406,12 @@
3263
3406
  "state rail",
3264
3407
  "list edge start, end, or only",
3265
3408
  "title line budget",
3266
- "deferred rendering"
3409
+ "deferred rendering",
3410
+ "static labeled group with a nested action (semanticRole=group)",
3411
+ "native draggable option root for list rows and board cards"
3267
3412
  ],
3268
3413
  "accessibility": [
3269
- "Each SummaryRow is role=option with tabindex=0 and aria-selected; place rows in a labeled role=listbox and move focus with the arrow keys in the app. The rail is decorative; carry its meaning in text."
3414
+ "By default SummaryRow is role=option with tabindex=0 and aria-selected; place options in a labeled role=listbox and move focus with the arrow keys in the app. semanticRole=group requires ariaLabel and omits the root Tab stop and aria-selected, so a nested native action owns focus and activation. The rail is decorative; carry its meaning in text."
3270
3415
  ],
3271
3416
  "geometry": {
3272
3417
  "margin": "none",
@@ -4967,7 +5112,8 @@
4967
5112
  "chat bubble at the start or end of the row (bubble), fit to its content up to 80%",
4968
5113
  "named focus-target region",
4969
5114
  "multi-select rich grid row",
4970
- "gridRow: a non-selectable row (role=\"row\" with a gridcell) between selectable rows of a multi-select List or Grid"
5115
+ "gridRow: a non-selectable row (role=\"row\" with a gridcell) between selectable rows of a multi-select List or Grid",
5116
+ "image-led feed media with opt-in deferOffscreen hero paint deferral"
4971
5117
  ],
4972
5118
  "accessibility": [
4973
5119
  "An ordinary item adds no role or name; pass ariaLabel only when the item is a distinct named region (it then renders role=\"region\").",
@@ -2709,6 +2709,116 @@
2709
2709
  "composition": "generated-permissive-default"
2710
2710
  }
2711
2711
  },
2712
+ {
2713
+ "key": "@kerfjs/ui:editor-frame",
2714
+ "package": "@kerfjs/ui",
2715
+ "id": "editor-frame",
2716
+ "name": "EditorFrame",
2717
+ "kind": "component",
2718
+ "source": "kerf",
2719
+ "parents": { "mode": "any", "entries": [] },
2720
+ "contexts": ["application-ui"],
2721
+ "zones": [],
2722
+ "children": { "mode": "any", "concepts": [], "requiredConcepts": [] },
2723
+ "state": [
2724
+ { "id": "draft value", "owner": "application", "required": false },
2725
+ { "id": "editing actions", "owner": "application", "required": false },
2726
+ {
2727
+ "id": "preview rendering",
2728
+ "owner": "application",
2729
+ "required": false
2730
+ },
2731
+ {
2732
+ "id": "recovery and focus management",
2733
+ "owner": "application",
2734
+ "required": false
2735
+ }
2736
+ ],
2737
+ "wiring": {
2738
+ "required": false,
2739
+ "helpers": [],
2740
+ "obligations": [],
2741
+ "stateAttributes": []
2742
+ },
2743
+ "responsive": { "owner": "not-applicable", "behaviors": [] },
2744
+ "layout": {
2745
+ "roles": ["structure"],
2746
+ "geometry": { "margin": "none", "border": "self", "padding": "self" }
2747
+ },
2748
+ "accessibility": {
2749
+ "obligations": [
2750
+ "Give the editor frame a label when it is a distinct region; the app labels its native textarea and supplies toolbar controls."
2751
+ ]
2752
+ },
2753
+ "cssValueProps": [],
2754
+ "boundaries": {
2755
+ "rootClass": "kui-editor-frame",
2756
+ "publicClasses": [
2757
+ "kui-editor-frame",
2758
+ "kui-editor-frame__toolbar",
2759
+ "kui-editor-frame__surface"
2760
+ ],
2761
+ "publicTokens": [
2762
+ "--kui-color-neutral-border-normal",
2763
+ "--kui-color-neutral-on-normal",
2764
+ "--kui-color-surface",
2765
+ "--kui-radius-l",
2766
+ "--kui-shadow-l"
2767
+ ]
2768
+ },
2769
+ "diagnostics": [],
2770
+ "provenance": {
2771
+ "selection": "ai/component-catalog.json",
2772
+ "composition": "generated-permissive-default"
2773
+ }
2774
+ },
2775
+ {
2776
+ "key": "@kerfjs/ui:value-preview",
2777
+ "package": "@kerfjs/ui",
2778
+ "id": "value-preview",
2779
+ "name": "ValuePreview",
2780
+ "kind": "component",
2781
+ "source": "kerf",
2782
+ "parents": { "mode": "any", "entries": [] },
2783
+ "contexts": ["application-ui"],
2784
+ "zones": [],
2785
+ "children": { "mode": "any", "concepts": [], "requiredConcepts": [] },
2786
+ "state": [
2787
+ { "id": "value", "owner": "application", "required": false },
2788
+ { "id": "empty wording", "owner": "application", "required": false }
2789
+ ],
2790
+ "wiring": {
2791
+ "required": false,
2792
+ "helpers": [],
2793
+ "obligations": [],
2794
+ "stateAttributes": []
2795
+ },
2796
+ "responsive": { "owner": "not-applicable", "behaviors": [] },
2797
+ "layout": {
2798
+ "roles": ["structure"],
2799
+ "geometry": { "margin": "none", "border": "none", "padding": "none" }
2800
+ },
2801
+ "accessibility": {
2802
+ "obligations": [
2803
+ "Give the focusable output a label so keyboard and screen-reader users can identify and scroll it."
2804
+ ]
2805
+ },
2806
+ "cssValueProps": [],
2807
+ "boundaries": {
2808
+ "rootClass": "kui-value-preview",
2809
+ "publicClasses": ["kui-value-preview"],
2810
+ "publicTokens": [
2811
+ "--kui-color-text",
2812
+ "--kui-font-xs",
2813
+ "--kui-focus-ring"
2814
+ ]
2815
+ },
2816
+ "diagnostics": [],
2817
+ "provenance": {
2818
+ "selection": "ai/component-catalog.json",
2819
+ "composition": "generated-permissive-default"
2820
+ }
2821
+ },
2712
2822
  {
2713
2823
  "key": "@kerfjs/ui:value-table",
2714
2824
  "package": "@kerfjs/ui",
@@ -2894,7 +3004,7 @@
2894
3004
  },
2895
3005
  "accessibility": {
2896
3006
  "obligations": [
2897
- "Each SummaryRow is role=option with tabindex=0 and aria-selected; place rows in a labeled role=listbox and move focus with the arrow keys in the app. The rail is decorative; carry its meaning in text."
3007
+ "By default SummaryRow is role=option with tabindex=0 and aria-selected; place options in a labeled role=listbox and move focus with the arrow keys in the app. semanticRole=group requires ariaLabel and omits the root Tab stop and aria-selected, so a nested native action owns focus and activation. The rail is decorative; carry its meaning in text."
2898
3008
  ]
2899
3009
  },
2900
3010
  "cssValueProps": [],
@@ -35,6 +35,8 @@ Exact prop and callback types live in [`public-api-signatures-v1.md`](../public-
35
35
  - [ToolbarText](./toolbar-text.md) — Extra-large through extra-small toolbar identity text.
36
36
  - [Text](./text.md) — Render paragraph semantics by default, h1 through h6 when selected, or geometry-free inline secondary text as a span while independently configuring quiet or danger tone, compact through extra-large size, or monospace font.
37
37
  - [Headers](./headers.md) — Page, dialog, and definition-list hierarchy.
38
+ - [EditorFrame](./editor-frame.md) — Own a framed or embedded writing surface while the app owns its native textarea, draft, and rendered preview.
39
+ - [ValuePreview](./value-preview.md) — Display a literal long value with line breaks and long tokens inside a bounded scroll region.
38
40
  - [ValueTable](./value-table.md) — Key/value rows with optional icons and aligned separators.
39
41
  - [FramedList](./framed-list.md) — Group settings-style rows of arbitrary content (copy, keycaps, controls) in one framed surface with between-row dividers and an optional highlighted row, without app list CSS.
40
42
  - [SummaryRow](./summary-row.md) — Present dense item summaries (tickets, tasks, messages) as selectable list rows or board cards with Kerf-owned selection, hover, focus, rail, clamping, list-edge rounding, and narrow compaction, without app row CSS.
@@ -43,6 +43,7 @@ Exact prop names and types: [`@kerfjs/ui/backdrop-image`](../public-api-signatur
43
43
  - fade into a color that also paints below
44
44
  - bottom or full scrim under overlay content
45
45
  - image running beneath clear or overlay chrome (underChrome)
46
+ - opt-in deferOffscreen hero paint deferral for dense image feeds without changing reserved height
46
47
 
47
48
  ## Composition
48
49
 
@@ -53,6 +53,7 @@ Exact prop names and types: [`@kerfjs/ui/content-item`](../public-api-signatures
53
53
  - named focus-target region
54
54
  - multi-select rich grid row
55
55
  - gridRow: a non-selectable row (role="row" with a gridcell) between selectable rows of a multi-select List or Grid
56
+ - image-led feed media with opt-in deferOffscreen hero paint deferral
56
57
 
57
58
  ## Composition
58
59
 
@@ -0,0 +1,80 @@
1
+ # EditorFrame
2
+
3
+ <!-- Generated by scripts/sync-component-docs.mjs from ai/component-catalog.json and ai/component-composition.json. Do not edit; run `npm run catalog:sync`. -->
4
+
5
+ `@kerfjs/ui:editor-frame` · Kerf UI · component · Structure
6
+
7
+ A bounded editor surface with a fixed toolbar and one native source or preview scroll owner.
8
+
9
+ ## When to use
10
+
11
+ Own a framed or embedded writing surface while the app owns its native textarea, draft, and rendered preview.
12
+
13
+ - A standalone Markdown or text editor needs a fixed toolbar above a bounded native textarea or preview.
14
+ - An embedded editor needs the same source/preview anatomy without a second frame.
15
+
16
+ **Not when:**
17
+
18
+ - Do not use for an ordinary single form field; use TextField.
19
+ - Do not replace the app's draft, recovery, focus, or preview behavior.
20
+
21
+ **Alternatives:**
22
+
23
+ - [TextField](./text-field.md) (nearest) — Use TextField for a conventional form value without editor toolbar and preview.
24
+
25
+ ## Imports
26
+
27
+ - JavaScript: `@kerfjs/ui/editor-frame` — exports `EditorFrame`.
28
+ - CSS: the browser build of `@kerfjs/ui/editor-frame` pulls its CSS automatically; import `@kerfjs/ui/editor-frame.css` manually only without the `browser` export condition.
29
+ - Declared side effects: browser-condition-css.
30
+
31
+ ## Props
32
+
33
+ Exact prop names and types: [`@kerfjs/ui/editor-frame`](../public-api-signatures-v1.md#kerfjsuieditor-frame) in `public-api-signatures-v1.md`. Do not infer props from examples.
34
+
35
+ **Variants (configure, do not restyle):**
36
+
37
+ - source and preview modes
38
+ - framed and embedded appearances
39
+ - padded and flush insets
40
+ - expanded overlay
41
+ - embedded autosize or restored source height
42
+
43
+ ## Composition
44
+
45
+ - Parents: any.
46
+ - Contexts: `application-ui`.
47
+ - Children: unrestricted.
48
+ - Built from: [Toolbar](./toolbar.md).
49
+
50
+ ## State and wiring
51
+
52
+ **The app owns:** draft value; editing actions; preview rendering; recovery and focus management.
53
+
54
+ No wiring helper.
55
+
56
+ ## Geometry
57
+
58
+ Margin: none · border: self · padding: self (layout role: structure). `self` means the component already owns it — do not add wrapper padding, margin, or borders around it.
59
+
60
+ ## Accessibility
61
+
62
+ - Give the editor frame a label when it is a distinct region; the app labels its native textarea and supplies toolbar controls.
63
+
64
+ ## Styling boundary
65
+
66
+ The component owns its own styles. Configure it through its props and variants; do not override its internals.
67
+
68
+ Public class hooks (select for layout placement only, never to change the component's look): `kui-editor-frame`, `kui-editor-frame__toolbar`, `kui-editor-frame__surface`.
69
+
70
+ Never put `kui-editor-frame`, `kui-editor-frame__toolbar`, `kui-editor-frame__surface` on an element you write; render `EditorFrame` instead (`KUI-L103`).
71
+
72
+ Public tokens it reads: `--kui-color-neutral-border-normal`, `--kui-color-neutral-on-normal`, `--kui-color-surface`, `--kui-radius-l`, `--kui-shadow-l`. Set a token only where its public contract allows; prefer a prop.
73
+
74
+ Everything else is internal: `kerf-ui-analyze` reports private or unknown `.kui-*` selectors (`KUI-L001`, `KUI-L010`), unknown or private tokens (`KUI-L002`, `KUI-L012`), and any application rule that restyles the component, forced dimensions included (`KUI-L019`).
75
+
76
+ ## Related
77
+
78
+ - Components: [Toolbar](./toolbar.md), [TextField](./text-field.md).
79
+ - Docs: [`docs/editor-frame.md`](../../docs/editor-frame.md).
80
+ - UX catalog route: `?component=editor-frame`.
@@ -4,13 +4,14 @@
4
4
 
5
5
  `@kerfjs/ui:summary-row` · Kerf UI · component · Structure
6
6
 
7
- A selectable, focusable summary of one item as a list row or a board card, with a state rail, a clamped title, trailing meta, and a metadata line.
7
+ A selectable option or static diagnostic group as a list row or board card, with a state rail, a clamped title, trailing meta, and a metadata line.
8
8
 
9
9
  ## When to use
10
10
 
11
11
  Present dense item summaries (tickets, tasks, messages) as selectable list rows or board cards with Kerf-owned selection, hover, focus, rail, clamping, list-edge rounding, and narrow compaction, without app row CSS.
12
12
 
13
13
  - A list or board shows many items as dense, selectable summaries with an identifier, a title, a timestamp, and metadata.
14
+ - An unreadable item needs the same summary chrome with a nested recovery action but must be a labeled non-option group.
14
15
 
15
16
  **Not when:**
16
17
 
@@ -43,6 +44,8 @@ Exact prop names and types: [`@kerfjs/ui/summary-row`](../public-api-signatures-
43
44
  - list edge start, end, or only
44
45
  - title line budget
45
46
  - deferred rendering
47
+ - static labeled group with a nested action (semanticRole=group)
48
+ - native draggable option root for list rows and board cards
46
49
 
47
50
  ## Composition
48
51
 
@@ -64,7 +67,7 @@ Margin: none · border: self · padding: self (layout role: structure). `self` m
64
67
 
65
68
  ## Accessibility
66
69
 
67
- - Each SummaryRow is role=option with tabindex=0 and aria-selected; place rows in a labeled role=listbox and move focus with the arrow keys in the app. The rail is decorative; carry its meaning in text.
70
+ - By default SummaryRow is role=option with tabindex=0 and aria-selected; place options in a labeled role=listbox and move focus with the arrow keys in the app. semanticRole=group requires ariaLabel and omits the root Tab stop and aria-selected, so a nested native action owns focus and activation. The rail is decorative; carry its meaning in text.
68
71
 
69
72
  ## Styling boundary
70
73
 
@@ -0,0 +1,75 @@
1
+ # ValuePreview
2
+
3
+ <!-- Generated by scripts/sync-component-docs.mjs from ai/component-catalog.json and ai/component-composition.json. Do not edit; run `npm run catalog:sync`. -->
4
+
5
+ `@kerfjs/ui:value-preview` · Kerf UI · component · Structure
6
+
7
+ A bounded, read-only multiline text value with keyboard scrolling.
8
+
9
+ ## When to use
10
+
11
+ Display a literal long value with line breaks and long tokens inside a bounded scroll region.
12
+
13
+ - A read-only value may have multiple lines or long unbroken text and needs bounded scrolling, such as a conflict version.
14
+
15
+ **Not when:**
16
+
17
+ - Do not use for editing; use a multiline TextField.
18
+ - Do not use for short label/value facts; use ValueTable.
19
+
20
+ **Alternatives:**
21
+
22
+ - [ValueTable](./value-table.md) (nearest) — Use ValueTable for rows of short labelled facts.
23
+
24
+ ## Imports
25
+
26
+ - JavaScript: `@kerfjs/ui/value-preview` — exports `ValuePreview`.
27
+ - CSS: the browser build of `@kerfjs/ui/value-preview` pulls its CSS automatically; import `@kerfjs/ui/value-preview.css` manually only without the `browser` export condition.
28
+ - Declared side effects: browser-condition-css.
29
+
30
+ ## Props
31
+
32
+ Exact prop names and types: [`@kerfjs/ui/value-preview`](../public-api-signatures-v1.md#kerfjsuivalue-preview) in `public-api-signatures-v1.md`. Do not infer props from examples.
33
+
34
+ **Variants (configure, do not restyle):**
35
+
36
+ - typed minimum and maximum height
37
+
38
+ ## Composition
39
+
40
+ - Parents: any.
41
+ - Contexts: `application-ui`.
42
+ - Children: unrestricted.
43
+ - Built from: [SunkenPanel](./sunken-panel.md).
44
+
45
+ ## State and wiring
46
+
47
+ **The app owns:** value; empty wording.
48
+
49
+ No wiring helper.
50
+
51
+ ## Geometry
52
+
53
+ Margin: none · border: none · padding: none (layout role: structure). `self` means the component already owns it — do not add wrapper padding, margin, or borders around it.
54
+
55
+ ## Accessibility
56
+
57
+ - Give the focusable output a label so keyboard and screen-reader users can identify and scroll it.
58
+
59
+ ## Styling boundary
60
+
61
+ The component owns its own styles. Configure it through its props and variants; do not override its internals.
62
+
63
+ Public class hooks (select for layout placement only, never to change the component's look): `kui-value-preview`.
64
+
65
+ Never put `kui-value-preview` on an element you write; render `ValuePreview` instead (`KUI-L103`).
66
+
67
+ Public tokens it reads: `--kui-color-text`, `--kui-font-xs`, `--kui-focus-ring`. Set a token only where its public contract allows; prefer a prop.
68
+
69
+ Everything else is internal: `kerf-ui-analyze` reports private or unknown `.kui-*` selectors (`KUI-L001`, `KUI-L010`), unknown or private tokens (`KUI-L002`, `KUI-L012`), and any application rule that restyles the component, forced dimensions included (`KUI-L019`).
70
+
71
+ ## Related
72
+
73
+ - Components: [SunkenPanel](./sunken-panel.md), [ValueTable](./value-table.md).
74
+ - Docs: [`docs/value-preview.md`](../../docs/value-preview.md).
75
+ - UX catalog route: `?component=value-preview`.