dsh-plugin-core 0.35.3 → 0.35.6
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/dist/design/tokens-css.generated.d.ts +1 -1
- package/dist/design/tokens-css.generated.d.ts.map +1 -1
- package/dist/design/tokens-css.generated.js +1 -1
- package/dist/design/tokens-css.generated.js.map +1 -1
- package/dist/ui/actions/Button.d.ts +4 -0
- package/dist/ui/actions/Button.d.ts.map +1 -1
- package/dist/ui/actions/Button.js +7 -5
- package/dist/ui/actions/Button.js.map +1 -1
- package/dist/ui/actions/button-css.generated.d.ts +1 -1
- package/dist/ui/actions/button-css.generated.d.ts.map +1 -1
- package/dist/ui/actions/button-css.generated.js +1 -1
- package/dist/ui/actions/button-css.generated.js.map +1 -1
- package/dist/ui/display/Card.d.ts +11 -0
- package/dist/ui/display/Card.d.ts.map +1 -1
- package/dist/ui/display/Card.js +10 -1
- package/dist/ui/display/Card.js.map +1 -1
- package/dist/ui/display/ListRow.d.ts +40 -0
- package/dist/ui/display/ListRow.d.ts.map +1 -0
- package/dist/ui/display/ListRow.js +71 -0
- package/dist/ui/display/ListRow.js.map +1 -0
- package/dist/ui/display/card-css.generated.d.ts +1 -1
- package/dist/ui/display/card-css.generated.d.ts.map +1 -1
- package/dist/ui/display/card-css.generated.js +1 -1
- package/dist/ui/display/card-css.generated.js.map +1 -1
- package/dist/ui/display/list-row-css.d.ts +2 -0
- package/dist/ui/display/list-row-css.d.ts.map +1 -0
- package/dist/ui/display/list-row-css.generated.d.ts +2 -0
- package/dist/ui/display/list-row-css.generated.d.ts.map +1 -0
- package/dist/ui/display/list-row-css.generated.js +4 -0
- package/dist/ui/display/list-row-css.generated.js.map +1 -0
- package/dist/ui/display/list-row-css.js +7 -0
- package/dist/ui/display/list-row-css.js.map +1 -0
- package/dist/ui/index.d.ts +1 -0
- package/dist/ui/index.d.ts.map +1 -1
- package/dist/ui/index.js +2 -0
- package/dist/ui/index.js.map +1 -1
- package/dist/ui/inputs/Segmented.js +1 -1
- package/dist/ui/inputs/Segmented.js.map +1 -1
- package/dist/ui/inputs/segmented-css.generated.d.ts +1 -1
- package/dist/ui/inputs/segmented-css.generated.d.ts.map +1 -1
- package/dist/ui/inputs/segmented-css.generated.js +1 -1
- package/dist/ui/inputs/segmented-css.generated.js.map +1 -1
- package/docs/design/structure.md +3 -3
- package/docs/design/style.md +96 -0
- package/docs/help/ui.doc.ts +79 -3
- package/docs/help/ui.md +74 -3
- package/package.json +1 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const SEGMENTED_CSS = "\n/* \u2500\u2500 \u5206\u6BB5\u63A7\u4EF6 P2 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n \u7ED3\u6784\u7167\u5144\u5F1F\u9879\u76EE dsh-task-dispatch-table \u7684 Segmented \u76AE\u80A4\uFF08item \u65E0\u8FB9\u6846\u3001hover \u53EA\u63D0\u4EAE\u6587\u5B57\uFF09\uFF0C\n \u524D\u7F00 / \u53D8\u91CF\u540D\u6362\u6210\u672C\u4ED3\u53E3\u5F84\u3002\u7528\u6237\u989D\u5916\u8981\u7684\u4E24\u5904\uFF08\u5144\u5F1F\u6CA1\u6709\uFF09\uFF1Aweekday \u65B9\u5757\u95F4\u9694\uFF08\u73B0\u4E3A 2px\uFF09\uFF1B\u6BB5\u5185\u4E2D\u6027\u8BA1\u6570 __count\u3002\n \u26A0\uFE0F 2026-10-19 \u4E24\u6B21\u8BEF\u5224\u5747\u5DF2\u6F84\u6E05\uFF1A\u2460 \u300C\u5BBF\u4E3B\u53EA\u8BA4\u5355\u884C CSS\u300D\u2014\u2014\u5047\uFF0C\u591A\u884C\u4E00\u76F4\u6B63\u5E38\uFF1B\n \u2461 \u300C\u5BBF\u4E3B\u5403\u6389 token \u5757\u4E4B\u540E\u7B2C\u4E00\u6761\u89C4\u5219\u300D\u2014\u2014\u4E5F\u5047\uFF0C\u771F\u56E0\u662F tokens \u6A21\u677F\u5B57\u7B26\u4E32\u7ED3\u5C3E\u591A\u4E86\u4E00\u4E2A\u53CD\u659C\u6760\uFF0C\n \u6CE8\u5165\u6587\u672C\u91CC\u7559\u4E0B\u5B57\u9762\u53CD\u5F15\u53F7\uFF0C\u628A\u7D27\u968F\u5176\u540E\u7684\u90A3\u6761\u89C4\u5219\u7684\u9009\u62E9\u5668\u6C61\u67D3\u6389\u4E86\uFF08\u89C1 dsh-host.md \u00A79\uFF09\u3002\n \u6837\u5F0F\u7167\u5E38\u591A\u884C\u4E66\u5199\uFF0C\u4E0D\u5FC5\u538B\u884C\uFF1B\u4E5F\u4E0D\u9700\u8981\u4EFB\u4F55\u300C\u727A\u7272\u89C4\u5219\u300D\u3002 */\n/* \u5916\u89C2\u53EA\u6709\u4E00\u5957\uFF082026-10-26\uFF09\uFF1A\u539F variant \u7684 default / inset \u4E24\u6863\u5728 CSS \u91CC\u53EA\u5DEE 1px \u5185\u8DDD\uFF0C\n \u4E14 default \u6BD4\u6587\u6863\u627F\u8BFA\u77EE 2px\uFF0C\u5374\u8BA9\u4E0B\u6E38\u4EE5\u4E3A\u300C\u6709\u5F97\u9009\u300D\u800C\u53CD\u590D\u5BF9\u56FE \u21D2 \u6574\u8F74\u5220\u9664\u3002\n padding 3px \u662F\u5C3A\u5BF8\u5951\u7EA6\u7684\u4E00\u90E8\u5206\uFF1Aitem \u9AD8\u5EA6 = \u63A7\u5236\u9AD8 \u2212 6px\uFF0C\u52A0\u8D77\u6765\u6B63\u597D 24 / 28 / 32\u3002 */\n/* \u9009\u4E2D\u7247\u914D\u8272\u6536\u5728\u4E24\u6761\u5C40\u90E8\u53D8\u91CF\u91CC\uFF08--seg-thumb \u5E95 / --seg-on \u5B57\uFF09\uFF1A\u9ED8\u8BA4\u8D70\u4E3B\u9898\u4EAE\u7247\uFF0C\n tone \u6863\u4E0E\u81EA\u5B9A\u4E49 {bg, fg} \u90FD\u53EA\u6539\u8FD9\u4E24\u6761\uFF08\u540E\u8005\u7531\u7EC4\u4EF6\u5185\u8054\u5199\u6839\u8282\u70B9\uFF0C\u5185\u8054\u6052\u80DC\uFF09\u3002 */\n.dshpc-seg{display:inline-flex;align-items:center;gap:2px;padding:3px;border-radius:var(--dshpc-radius-md);--seg-thumb:var(--dshpc-surface-raised);--seg-on:var(--dshpc-fg);background:var(--dshpc-seg-track);}\n.dshpc-seg__item{appearance:none;display:inline-flex;align-items:center;gap:4px;box-sizing:border-box;height:calc(var(--dshpc-control-h-sm) - 6px);padding:0 12px;border:0;border-radius:var(--dshpc-radius-sm);background:transparent;color:var(--dshpc-fg-2);font-family:inherit;font-size:var(--dshpc-font-xs);font-weight:500;white-space:nowrap;cursor:pointer;flex:none;transition:color var(--dshpc-dur-fast) var(--dshpc-ease),background-color var(--dshpc-dur-fast) var(--dshpc-ease),box-shadow var(--dshpc-dur-fast) var(--dshpc-ease);}\n.dshpc-seg--md .dshpc-seg__item{height:calc(var(--dshpc-control-h-md) - 6px);}\n.dshpc-seg--lg .dshpc-seg__item{height:calc(var(--dshpc-control-h-lg) - 6px);}\n/* \u6BB5\u5185\u56FE\u6807\uFF08\u524D\u7F6E\uFF09\uFF1A\u4E0E Button \u540C\u53E3\u5F84 \u2014\u2014 inline-flex \u5403\u6389\u884C\u9AD8\u57FA\u7EBF\uFF0Csvg \u6309\u5757\u7EA7\u3002 */\n.dshpc-seg__icon{display:inline-flex;align-items:center;justify-content:center;flex:none;line-height:0;}\n.dshpc-seg__icon svg{display:block;margin:0;}\n/* \u53EA\u6709\u56FE\u6807\uFF08\u65E0\u6587\u5B57 / \u8BA1\u6570 / \u89D2\u6807\uFF09\uFF1A\u6BB5\u5FC5\u987B\u662F\u6B63\u65B9\u5F62 \u21D2 \u5BBD = \u6BB5\u9AD8\u3001\u5DE6\u53F3\u5185\u8DDD\u5F52\u96F6\u3001\u5185\u5BB9\u5C45\u4E2D\uFF1B\n \u5426\u5219\u57FA\u7840\u89C4\u5219\u7684 0 12px \u4F1A\u628A\u5B83\u62C9\u6210\u957F\u65B9\u5F62\u3002\u653E\u5728\u4E09\u6863\u4E4B\u540E\uFF1A\u540C\u540D\u7279\u5F02\u6027\u4E0B\u540E\u5199\u8005\u80DC\u3002 */\n.dshpc-seg__item--icon-only{width:calc(var(--dshpc-control-h-sm) - 6px);padding:0;justify-content:center;}\n.dshpc-seg--md .dshpc-seg__item--icon-only{width:calc(var(--dshpc-control-h-md) - 6px);}\n.dshpc-seg--lg .dshpc-seg__item--icon-only{width:calc(var(--dshpc-control-h-lg) - 6px);}\n.dshpc-seg__item:hover:not([aria-pressed='true']):not(:disabled){color:var(--dshpc-fg);}\n.dshpc-seg__item[aria-pressed='true']{background:var(--seg-thumb);box-shadow:var(--dshpc-shadow-raised);color:var(--seg-on);font-weight:600;}\n.dshpc-seg__item:focus-visible{outline:2px solid var(--dshpc-focus);outline-offset:-2px;}\n.dshpc-seg__item:disabled{cursor:default;opacity:.4;}\n/* \u6BB5\u5185\u89D2\u6807\uFF08\u5982\u300C\u5F02\u5E38\u300D\u7684\u6570\u91CF\uFF09\uFF1A\u8BED\u4E49\u8272\u5B9E\u9762 + \u53CD\u767D\u5B57\uFF0C0 \u7531\u7EC4\u4EF6\u4FA7\u4E0D\u6E32\u67D3\u3002\u5FC5\u987B\u662F\u6B63\u5706\uFF08\u7528\u6237 2026-10-03\uFF09\u3002 */\n.dshpc-seg__badge{display:inline-flex;align-items:center;justify-content:center;flex:none;width:16px;height:16px;padding:0;overflow:hidden;border-radius:50%;background:var(--dshpc-danger);color:var(--dshpc-on-signal);font-size:10px;line-height:16px;font-weight:500;font-variant-numeric:tabular-nums;}\n/* \u6BB5\u5185\u4E2D\u6027\u8BA1\u6570\uFF08\u5982\u7B5B\u9009\u6761\u300C\u5168\u90E8 11\u300D\uFF09\uFF1A\u7EAF\u6587\u5B57\u3001\u65E0\u5E95\u65E0\u8FB9\uFF08\u5BF9\u9F50 task-ledger .dtl-seg__num \u62CD\u677F\u53E3\u5F84\uFF09\uFF1B0 \u7531\u7EC4\u4EF6\u4FA7\u4E0D\u6E32\u67D3\u3002 */\n.dshpc-seg__count{display:inline;flex:none;margin-left:3px;padding:0;border:0;border-radius:0;background:none;color:var(--dshpc-fg-3);font-size:10px;line-height:1;font-weight:400;font-variant-numeric:tabular-nums;}\n/* \u9009\u4E2D\u6BB5\uFF08\u5F69\u8272\u5B9E\u9762\uFF09\u91CC\u7684\u8BA1\u6570\uFF1A\u5FC5\u987B\u8DDF\u7740 --seg-on \u8D70\u518D\u538B\u6697\u4E00\u6863\uFF0872% \u767D \u2248 \u300C\u6BD4\u6B63\u6587\u7A0D\u7070\u300D\uFF09\u3002\n \u4E0D\u8BB8\u7528 --dshpc-fg-3\uFF1A\u5B83\u8DDF\u4E3B\u9898\u8D70\uFF0C\u6697\u8272\u4E0B\u662F\u6DF1\u7070 \u21D2 \u84DD\u5E95\u4E0A\u51E0\u4E4E\u770B\u4E0D\u89C1\uFF082026-10-29 \u7528\u6237\u622A\u56FE\u300CMy todos 4\u300D\uFF09\u3002 */\n.dshpc-seg__item[aria-pressed='true'] .dshpc-seg__count{color:color-mix(in srgb,var(--seg-on) 72%,transparent);}\n/* block\uFF1A\u6491\u6EE1\u7236\u5BBD\uFF08\u8868\u5355\u884C\u7528\uFF09\uFF0C\u5404\u6BB5\u7B49\u5206 */\n.dshpc-seg--block{display:flex;width:100%;}\n.dshpc-seg--block .dshpc-seg__item{flex:1 1 auto;justify-content:center;}\n/* weekday\uFF1A\u661F\u671F\u591A\u9009\u65B9\u5757\u3002\u57FA\u7840\u63D2\u4EF6\u7684\u7279\u6B8A\u5316\u5B9A\u5236\uFF08\u7528\u6237 2026-10-01\uFF1A\u539F WeekdayPicker \u5373\u300C\u84DD\u5E95 + \u8FD1\u4F3C\u65B9\u5F62\u300D\uFF09\uFF1A\n \u6BCF\u683C\u6B63\u65B9\u5F62\uFF08\u5BBD = \u6BB5\u9AD8\uFF09\u3001\u9009\u4E2D\u54C1\u724C\u84DD\u53CD\u767D\u5B57\u3001**\u65E0\u5916\u63CF\u8FB9**\uFF082026-10-18 \u91CD\u7533\uFF09\u3001\n \u65B9\u5757\u4E4B\u95F4\u95F4\u8DDD gap:2px\uFF082026-10-20 \u7528\u6237\u5B9A\u7A3F\uFF1A\u65B9\u5757\u6539\u5C0F\u540E 6px \u663E\u5F97\u592A\u5BBD\u300210-18 \u66FE\u4ECE 2px \u653E\u5BBD\u5230 6px\uFF0C\n \u4E24\u6B21\u90FD\u662F\u7528\u6237\u62CD\u677F \u2014\u2014 \u522B\u81EA\u4F5C\u4E3B\u5F20\u6539\u56DE\u53BB\uFF09\u3002 */\n.dshpc-seg--weekday{--seg-track:var(--dshpc-seg-track);gap:2px;border:0;padding:3px;background:var(--seg-track);}\n.dshpc-seg--weekday .dshpc-seg__item{width:calc(var(--dshpc-control-h-lg) - 8px);padding:0;justify-content:center;}\n/* \u84DD\u5E95\u53CD\u767D\uFF1A\u5B57\u8272\u5FC5\u987B\u662F\u5E38\u91CF\u767D\uFF08--dshpc-on-signal\uFF09\u30022026-10-29 \u7528\u6237\u5B9E\u6D4B\uFF1A\u6697\u8272\u4E3B\u9898\u4E0B\u8FD9\u91CC\u66FE\u7528\n --dshpc-fg-inverse\uFF0C\u800C\u5B83\u8DDF\u968F\u5BBF\u4E3B label-primary-foreground\uFF0C\u6697\u8272\u4E0B\u662F\u8FD1\u9ED1 \u21D2 \u84DD\u5E95\u9ED1\u5B57\u770B\u4E0D\u6E05\u3002 */\n.dshpc-seg--weekday{--seg-thumb:var(--dshpc-business);--seg-on:var(--dshpc-on-signal);}\n\n/* \u2500\u2500 tone\uFF082026-10-29 \u7528\u6237\uFF09\uFF1A\u9009\u4E2D\u7247\u4F20\u5185\u7F6E\u57FA\u7840\u8272\u540D\uFF0C\u5E95 / \u5B57\u7531\u6838\u5FC3\u7ED9\uFF0C\u6DF1\u6D45\u4E24\u4E3B\u9898\u5404\u81EA\u6210\u7ACB\u3002\n \u653E\u5728 weekday \u4E4B\u540E\uFF1A\u540C\u540D\u53D8\u91CF\u540E\u5199\u8005\u80DC\uFF0Ctone \u4E0E className=\"dshpc-seg--weekday\" \u540C\u7ED9\u65F6\u4EE5 tone \u4E3A\u51C6\u3002\n \u9EC4\u5E95\u6309 Chip / Button \u540C\u6E90\u53E3\u5F84\u7528 on-warning\uFF08\u4E2D\u9AD8\u660E\u5EA6\uFF0C\u767D\u5B57\u770B\u4E0D\u6E05\uFF09\u3002 */\n.dshpc-seg--tone-business{--seg-thumb:var(--dshpc-business);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-success{--seg-thumb:var(--dshpc-success);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-warning{--seg-thumb:var(--dshpc-warning);--seg-on:var(--dshpc-on-warning);}\n.dshpc-seg--tone-danger{--seg-thumb:var(--dshpc-danger);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-purple{--seg-thumb:var(--dshpc-purple);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-pink{--seg-thumb:var(--dshpc-pink);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-cyan{--seg-thumb:var(--dshpc-cyan);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-teal{--seg-thumb:var(--dshpc-teal);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-orange{--seg-thumb:var(--dshpc-orange);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-indigo{--seg-thumb:var(--dshpc-indigo);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-rose{--seg-thumb:var(--dshpc-rose);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-slate{--seg-thumb:var(--dshpc-slate);--seg-on:var(--dshpc-on-signal);}\n\n/* \u2500\u2500 \u5355\u9009\u6ED1\u52A8\u5757\uFF082026-10-26 \u7528\u6237\uFF1A\u70B9\u9009\u540E\u9009\u4E2D\u5E95\u5E94\u300C\u6ED1\u8FC7\u53BB\u300D\uFF0C\u4E0D\u662F\u65E7\u6BB5\u6D88\u5931\u3001\u65B0\u6BB5\u76F4\u63A5\u4EAE\uFF09\u3002\n \u7ED3\u6784 = \u4E00\u5757\u7EDD\u5BF9\u5B9A\u4F4D\u7684\u5171\u7528\u5E95 + \u5404\u6BB5\u900F\u660E\uFF1B\u4F4D\u7F6E/\u5C3A\u5BF8\u7531\u7EC4\u4EF6\u91CF\u51FA\u540E\u5185\u8054\uFF0C\u8FD9\u91CC\u53EA\u7BA1\u5916\u89C2\u4E0E\u8FC7\u6E21\u3002\n --slide \u53EA\u5728\u5355\u9009\u6302\u4E0A\uFF1A\u591A\u9009\uFF08\u5982\u661F\u671F\uFF09\u6BCF\u6BB5\u5404\u81EA\u7740\u8272\uFF0C\u6CA1\u6709\u552F\u4E00\u6ED1\u5757\u53EF\u6ED1\uFF0C\u4FDD\u6301\u539F\u6837\u3002 */\n.dshpc-seg--slide{position:relative;}\n.dshpc-seg--slide .dshpc-seg__item{position:relative;z-index:1;}\n.dshpc-seg--slide .dshpc-seg__item[aria-pressed='true']{background:transparent;box-shadow:none;}\n.dshpc-seg__thumb{position:absolute;z-index:0;border-radius:var(--dshpc-radius-sm);background:var(--seg-thumb);box-shadow:var(--dshpc-shadow-raised);pointer-events:none;transition:left var(--dshpc-dur) var(--dshpc-ease),top var(--dshpc-dur) var(--dshpc-ease),width var(--dshpc-dur) var(--dshpc-ease),height var(--dshpc-dur) var(--dshpc-ease);}\n\n/* \u2500\u2500 bordered \u5916\u6846\uFF082026-10-20 \u7528\u6237\u8981\u7684\u7B2C\u4E8C\u79CD\u6A21\u5F0F\uFF09\uFF1A**\u53EA\u5728\u6700\u5916\u9762\u5957\u4E00\u5708 1px \u63CF\u8FB9**\uFF0C\n \u91CC\u9762\u4E00\u6982\u4E0D\u52A8 \u2014\u2014 \u9009\u4E2D\u7247\u7684\u586B\u5145\u8272 / \u9634\u5F71 / \u6587\u5B57\u8272\u5168\u90E8\u4FDD\u6301\u539F\u6837\uFF08weekday \u7684\u84DD\u9762\u7167\u65E7\uFF09\uFF0C\n \u8FD9\u91CC\u4E0D\u5199\u4EFB\u4F55\u9488\u5BF9 __item \u7684\u89C4\u5219\u3002\n \u603B\u9AD8\u5FC5\u987B\u4E0E\u65E0\u6846\u7248\u9010\u50CF\u7D20\u4E00\u81F4\uFF1Aborder 1px\u00D72 \u7531 padding \u5404\u8BA9 1px \u62B5\u6D88\uFF083 \u2192 2\uFF09\uFF1B\n weekday \u81EA\u5DF1\u58F0\u660E\u7684 3px \u5728\u6587\u4EF6\u66F4\u540E\u9762\uFF0C\u9760\u53CC\u7C7B\u9009\u62E9\u5668\u538B\u56DE 2px\u3002 */\n.dshpc-seg--bordered{border:1px solid var(--dshpc-border);padding:2px;}\n.dshpc-seg--bordered.dshpc-seg--weekday{padding:2px;}\n\n@media (prefers-reduced-motion: reduce){.dshpc-seg__item{transition:none;}.dshpc-seg__thumb{transition:none;}}\n";
|
|
1
|
+
export declare const SEGMENTED_CSS = "\n/* \u2500\u2500 \u5206\u6BB5\u63A7\u4EF6 P2 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n \u7ED3\u6784\u7167\u5144\u5F1F\u9879\u76EE dsh-task-dispatch-table \u7684 Segmented \u76AE\u80A4\uFF08item \u65E0\u8FB9\u6846\u3001hover \u53EA\u63D0\u4EAE\u6587\u5B57\uFF09\uFF0C\n \u524D\u7F00 / \u53D8\u91CF\u540D\u6362\u6210\u672C\u4ED3\u53E3\u5F84\u3002\u7528\u6237\u989D\u5916\u8981\u7684\u4E24\u5904\uFF08\u5144\u5F1F\u6CA1\u6709\uFF09\uFF1Aweekday \u65B9\u5757\u95F4\u9694\uFF08\u73B0\u4E3A 2px\uFF09\uFF1B\u6BB5\u5185\u4E2D\u6027\u8BA1\u6570 __count\u3002\n \u26A0\uFE0F 2026-10-19 \u4E24\u6B21\u8BEF\u5224\u5747\u5DF2\u6F84\u6E05\uFF1A\u2460 \u300C\u5BBF\u4E3B\u53EA\u8BA4\u5355\u884C CSS\u300D\u2014\u2014\u5047\uFF0C\u591A\u884C\u4E00\u76F4\u6B63\u5E38\uFF1B\n \u2461 \u300C\u5BBF\u4E3B\u5403\u6389 token \u5757\u4E4B\u540E\u7B2C\u4E00\u6761\u89C4\u5219\u300D\u2014\u2014\u4E5F\u5047\uFF0C\u771F\u56E0\u662F tokens \u6A21\u677F\u5B57\u7B26\u4E32\u7ED3\u5C3E\u591A\u4E86\u4E00\u4E2A\u53CD\u659C\u6760\uFF0C\n \u6CE8\u5165\u6587\u672C\u91CC\u7559\u4E0B\u5B57\u9762\u53CD\u5F15\u53F7\uFF0C\u628A\u7D27\u968F\u5176\u540E\u7684\u90A3\u6761\u89C4\u5219\u7684\u9009\u62E9\u5668\u6C61\u67D3\u6389\u4E86\uFF08\u89C1 dsh-host.md \u00A79\uFF09\u3002\n \u6837\u5F0F\u7167\u5E38\u591A\u884C\u4E66\u5199\uFF0C\u4E0D\u5FC5\u538B\u884C\uFF1B\u4E5F\u4E0D\u9700\u8981\u4EFB\u4F55\u300C\u727A\u7272\u89C4\u5219\u300D\u3002 */\n/* \u5916\u89C2\u53EA\u6709\u4E00\u5957\uFF082026-10-26\uFF09\uFF1A\u539F variant \u7684 default / inset \u4E24\u6863\u5728 CSS \u91CC\u53EA\u5DEE 1px \u5185\u8DDD\uFF0C\n \u4E14 default \u6BD4\u6587\u6863\u627F\u8BFA\u77EE 2px\uFF0C\u5374\u8BA9\u4E0B\u6E38\u4EE5\u4E3A\u300C\u6709\u5F97\u9009\u300D\u800C\u53CD\u590D\u5BF9\u56FE \u21D2 \u6574\u8F74\u5220\u9664\u3002\n padding 3px \u662F\u5C3A\u5BF8\u5951\u7EA6\u7684\u4E00\u90E8\u5206\uFF1Aitem \u9AD8\u5EA6 = \u63A7\u5236\u9AD8 \u2212 6px\uFF0C\u52A0\u8D77\u6765\u6B63\u597D 24 / 28 / 32\u3002 */\n/* \u9009\u4E2D\u7247\u914D\u8272\u6536\u5728\u4E24\u6761\u5C40\u90E8\u53D8\u91CF\u91CC\uFF08--seg-thumb \u5E95 / --seg-on \u5B57\uFF09\uFF1A\u9ED8\u8BA4\u8D70\u4E3B\u9898\u4EAE\u7247\uFF0C\n tone \u6863\u4E0E\u81EA\u5B9A\u4E49 {bg, fg} \u90FD\u53EA\u6539\u8FD9\u4E24\u6761\uFF08\u540E\u8005\u7531\u7EC4\u4EF6\u5185\u8054\u5199\u6839\u8282\u70B9\uFF0C\u5185\u8054\u6052\u80DC\uFF09\u3002 */\n.dshpc-seg{display:inline-flex;align-items:center;gap:2px;padding:3px;border-radius:var(--dshpc-radius-md);--seg-thumb:var(--dshpc-surface-raised);--seg-on:var(--dshpc-fg);background:var(--dshpc-seg-track);}\n.dshpc-seg__item{appearance:none;display:inline-flex;align-items:center;gap:4px;box-sizing:border-box;height:calc(var(--dshpc-control-h-sm) - 6px);padding:0 12px;border:0;border-radius:var(--dshpc-radius-sm);background:transparent;color:var(--dshpc-fg-2);font-family:inherit;font-size:var(--dshpc-font-xs);font-weight:500;white-space:nowrap;cursor:pointer;flex:none;transition:color var(--dshpc-dur-fast) var(--dshpc-ease),background-color var(--dshpc-dur-fast) var(--dshpc-ease),box-shadow var(--dshpc-dur-fast) var(--dshpc-ease);}\n.dshpc-seg--md .dshpc-seg__item{height:calc(var(--dshpc-control-h-md) - 6px);}\n.dshpc-seg--lg .dshpc-seg__item{height:calc(var(--dshpc-control-h-lg) - 6px);}\n/* \u6BB5\u5185\u56FE\u6807\uFF08\u524D\u7F6E\uFF09\uFF1A\u4E0E Button \u540C\u53E3\u5F84 \u2014\u2014 inline-flex \u5403\u6389\u884C\u9AD8\u57FA\u7EBF\uFF0Csvg \u6309\u5757\u7EA7\u3002 */\n.dshpc-seg__icon{display:inline-flex;align-items:center;justify-content:center;flex:none;line-height:0;}\n.dshpc-seg__icon svg{display:block;margin:0;}\n/* \u53EA\u6709\u56FE\u6807\uFF08\u65E0\u6587\u5B57 / \u8BA1\u6570 / \u89D2\u6807\uFF09\uFF1A\u6BB5\u5FC5\u987B\u662F\u6B63\u65B9\u5F62 \u21D2 \u5BBD = \u6BB5\u9AD8\u3001\u5DE6\u53F3\u5185\u8DDD\u5F52\u96F6\u3001\u5185\u5BB9\u5C45\u4E2D\uFF1B\n \u5426\u5219\u57FA\u7840\u89C4\u5219\u7684 0 12px \u4F1A\u628A\u5B83\u62C9\u6210\u957F\u65B9\u5F62\u3002\u653E\u5728\u4E09\u6863\u4E4B\u540E\uFF1A\u540C\u540D\u7279\u5F02\u6027\u4E0B\u540E\u5199\u8005\u80DC\u3002 */\n.dshpc-seg__item--icon-only{width:calc(var(--dshpc-control-h-sm) - 6px);padding:0;justify-content:center;}\n.dshpc-seg--md .dshpc-seg__item--icon-only{width:calc(var(--dshpc-control-h-md) - 6px);}\n.dshpc-seg--lg .dshpc-seg__item--icon-only{width:calc(var(--dshpc-control-h-lg) - 6px);}\n/* \u591A\u9009\uFF082026-11-07 \u7528\u6237\uFF09\uFF1A\u6BCF\u6BB5\u6700\u5C0F\u5BBD = \u8BE5\u6863\u6BB5\u9AD8 \u21D2 \u6700\u7A84\u4E5F\u662F\u6B63\u65B9\u5F62\uFF0C\u7EDD\u4E0D\u4F1A\u51FA\u73B0\u6BD4\u9AD8\u8FD8\u7A84\u7684\u7AD6\u6761\uFF1B\n \u6587\u6848\u66F4\u957F\u65F6\u7531\u5185\u5BB9\u81EA\u7136\u6491\u5BBD\u6210\u6A2A\u5411\u957F\u65B9\u5F62\u3002\u4E09\u6863\u5404\u8DDF\u81EA\u5DF1\u7684\u63A7\u5236\u9AD8\uFF0C\u4E0D\u5199\u6B7B px\u3002\n weekday / icon-only \u90A3\u79CD\u56FA\u5B9A width \u82E5\u5C0F\u4E8E\u6BB5\u9AD8\uFF0C\u540C\u6837\u88AB min-width \u9876\u5230\u6B63\u65B9\u5F62\u3002 */\n.dshpc-seg--multiple .dshpc-seg__item{min-width:calc(var(--dshpc-control-h-sm) - 6px);}\n.dshpc-seg--multiple.dshpc-seg--md .dshpc-seg__item{min-width:calc(var(--dshpc-control-h-md) - 6px);}\n.dshpc-seg--multiple.dshpc-seg--lg .dshpc-seg__item{min-width:calc(var(--dshpc-control-h-lg) - 6px);}\n.dshpc-seg__item:hover:not([aria-pressed='true']):not(:disabled){color:var(--dshpc-fg);}\n.dshpc-seg__item[aria-pressed='true']{background:var(--seg-thumb);box-shadow:var(--dshpc-shadow-raised);color:var(--seg-on);font-weight:600;}\n.dshpc-seg__item:focus-visible{outline:2px solid var(--dshpc-focus);outline-offset:-2px;}\n.dshpc-seg__item:disabled{cursor:default;opacity:.4;}\n/* \u6BB5\u5185\u89D2\u6807\uFF08\u5982\u300C\u5F02\u5E38\u300D\u7684\u6570\u91CF\uFF09\uFF1A\u8BED\u4E49\u8272\u5B9E\u9762 + \u53CD\u767D\u5B57\uFF0C0 \u7531\u7EC4\u4EF6\u4FA7\u4E0D\u6E32\u67D3\u3002\u5FC5\u987B\u662F\u6B63\u5706\uFF08\u7528\u6237 2026-10-03\uFF09\u3002 */\n.dshpc-seg__badge{display:inline-flex;align-items:center;justify-content:center;flex:none;width:16px;height:16px;padding:0;overflow:hidden;border-radius:50%;background:var(--dshpc-danger);color:var(--dshpc-on-signal);font-size:10px;line-height:16px;font-weight:500;font-variant-numeric:tabular-nums;}\n/* \u6BB5\u5185\u4E2D\u6027\u8BA1\u6570\uFF08\u5982\u7B5B\u9009\u6761\u300C\u5168\u90E8 11\u300D\uFF09\uFF1A\u7EAF\u6587\u5B57\u3001\u65E0\u5E95\u65E0\u8FB9\uFF08\u5BF9\u9F50 task-ledger .dtl-seg__num \u62CD\u677F\u53E3\u5F84\uFF09\uFF1B0 \u7531\u7EC4\u4EF6\u4FA7\u4E0D\u6E32\u67D3\u3002 */\n.dshpc-seg__count{display:inline;flex:none;margin-left:3px;padding:0;border:0;border-radius:0;background:none;color:var(--dshpc-fg-3);font-size:10px;line-height:1;font-weight:400;font-variant-numeric:tabular-nums;}\n/* \u9009\u4E2D\u6BB5\uFF08\u5F69\u8272\u5B9E\u9762\uFF09\u91CC\u7684\u8BA1\u6570\uFF1A\u5FC5\u987B\u8DDF\u7740 --seg-on \u8D70\u518D\u538B\u6697\u4E00\u6863\uFF0872% \u767D \u2248 \u300C\u6BD4\u6B63\u6587\u7A0D\u7070\u300D\uFF09\u3002\n \u4E0D\u8BB8\u7528 --dshpc-fg-3\uFF1A\u5B83\u8DDF\u4E3B\u9898\u8D70\uFF0C\u6697\u8272\u4E0B\u662F\u6DF1\u7070 \u21D2 \u84DD\u5E95\u4E0A\u51E0\u4E4E\u770B\u4E0D\u89C1\uFF082026-10-29 \u7528\u6237\u622A\u56FE\u300CMy todos 4\u300D\uFF09\u3002 */\n.dshpc-seg__item[aria-pressed='true'] .dshpc-seg__count{color:color-mix(in srgb,var(--seg-on) 72%,transparent);}\n/* block\uFF1A\u6491\u6EE1\u7236\u5BBD\uFF08\u8868\u5355\u884C\u7528\uFF09\uFF0C\u5404\u6BB5\u7B49\u5206 */\n.dshpc-seg--block{display:flex;width:100%;}\n.dshpc-seg--block .dshpc-seg__item{flex:1 1 auto;justify-content:center;}\n/* weekday\uFF1A\u661F\u671F\u591A\u9009\u65B9\u5757\u3002\u57FA\u7840\u63D2\u4EF6\u7684\u7279\u6B8A\u5316\u5B9A\u5236\uFF08\u7528\u6237 2026-10-01\uFF1A\u539F WeekdayPicker \u5373\u300C\u84DD\u5E95 + \u8FD1\u4F3C\u65B9\u5F62\u300D\uFF09\uFF1A\n \u6BCF\u683C\u6B63\u65B9\u5F62\uFF08\u5BBD = \u6BB5\u9AD8\uFF09\u3001\u9009\u4E2D\u54C1\u724C\u84DD\u53CD\u767D\u5B57\u3001**\u65E0\u5916\u63CF\u8FB9**\uFF082026-10-18 \u91CD\u7533\uFF09\u3001\n \u65B9\u5757\u4E4B\u95F4\u95F4\u8DDD gap:2px\uFF082026-10-20 \u7528\u6237\u5B9A\u7A3F\uFF1A\u65B9\u5757\u6539\u5C0F\u540E 6px \u663E\u5F97\u592A\u5BBD\u300210-18 \u66FE\u4ECE 2px \u653E\u5BBD\u5230 6px\uFF0C\n \u4E24\u6B21\u90FD\u662F\u7528\u6237\u62CD\u677F \u2014\u2014 \u522B\u81EA\u4F5C\u4E3B\u5F20\u6539\u56DE\u53BB\uFF09\u3002 */\n.dshpc-seg--weekday{--seg-track:var(--dshpc-seg-track);gap:2px;border:0;padding:3px;background:var(--seg-track);}\n.dshpc-seg--weekday .dshpc-seg__item{width:calc(var(--dshpc-control-h-lg) - 8px);padding:0;justify-content:center;}\n/* \u84DD\u5E95\u53CD\u767D\uFF1A\u5B57\u8272\u5FC5\u987B\u662F\u5E38\u91CF\u767D\uFF08--dshpc-on-signal\uFF09\u30022026-10-29 \u7528\u6237\u5B9E\u6D4B\uFF1A\u6697\u8272\u4E3B\u9898\u4E0B\u8FD9\u91CC\u66FE\u7528\n --dshpc-fg-inverse\uFF0C\u800C\u5B83\u8DDF\u968F\u5BBF\u4E3B label-primary-foreground\uFF0C\u6697\u8272\u4E0B\u662F\u8FD1\u9ED1 \u21D2 \u84DD\u5E95\u9ED1\u5B57\u770B\u4E0D\u6E05\u3002 */\n.dshpc-seg--weekday{--seg-thumb:var(--dshpc-business);--seg-on:var(--dshpc-on-signal);}\n\n/* \u2500\u2500 tone\uFF082026-10-29 \u7528\u6237\uFF09\uFF1A\u9009\u4E2D\u7247\u4F20\u5185\u7F6E\u57FA\u7840\u8272\u540D\uFF0C\u5E95 / \u5B57\u7531\u6838\u5FC3\u7ED9\uFF0C\u6DF1\u6D45\u4E24\u4E3B\u9898\u5404\u81EA\u6210\u7ACB\u3002\n \u653E\u5728 weekday \u4E4B\u540E\uFF1A\u540C\u540D\u53D8\u91CF\u540E\u5199\u8005\u80DC\uFF0Ctone \u4E0E className=\"dshpc-seg--weekday\" \u540C\u7ED9\u65F6\u4EE5 tone \u4E3A\u51C6\u3002\n \u9EC4\u5E95\u6309 Chip / Button \u540C\u6E90\u53E3\u5F84\u7528 on-warning\uFF08\u4E2D\u9AD8\u660E\u5EA6\uFF0C\u767D\u5B57\u770B\u4E0D\u6E05\uFF09\u3002 */\n.dshpc-seg--tone-business{--seg-thumb:var(--dshpc-business);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-success{--seg-thumb:var(--dshpc-success);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-warning{--seg-thumb:var(--dshpc-warning);--seg-on:var(--dshpc-on-warning);}\n.dshpc-seg--tone-danger{--seg-thumb:var(--dshpc-danger);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-purple{--seg-thumb:var(--dshpc-purple);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-pink{--seg-thumb:var(--dshpc-pink);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-cyan{--seg-thumb:var(--dshpc-cyan);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-teal{--seg-thumb:var(--dshpc-teal);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-orange{--seg-thumb:var(--dshpc-orange);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-indigo{--seg-thumb:var(--dshpc-indigo);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-rose{--seg-thumb:var(--dshpc-rose);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-slate{--seg-thumb:var(--dshpc-slate);--seg-on:var(--dshpc-on-signal);}\n\n/* \u2500\u2500 \u5355\u9009\u6ED1\u52A8\u5757\uFF082026-10-26 \u7528\u6237\uFF1A\u70B9\u9009\u540E\u9009\u4E2D\u5E95\u5E94\u300C\u6ED1\u8FC7\u53BB\u300D\uFF0C\u4E0D\u662F\u65E7\u6BB5\u6D88\u5931\u3001\u65B0\u6BB5\u76F4\u63A5\u4EAE\uFF09\u3002\n \u7ED3\u6784 = \u4E00\u5757\u7EDD\u5BF9\u5B9A\u4F4D\u7684\u5171\u7528\u5E95 + \u5404\u6BB5\u900F\u660E\uFF1B\u4F4D\u7F6E/\u5C3A\u5BF8\u7531\u7EC4\u4EF6\u91CF\u51FA\u540E\u5185\u8054\uFF0C\u8FD9\u91CC\u53EA\u7BA1\u5916\u89C2\u4E0E\u8FC7\u6E21\u3002\n --slide \u53EA\u5728\u5355\u9009\u6302\u4E0A\uFF1A\u591A\u9009\uFF08\u5982\u661F\u671F\uFF09\u6BCF\u6BB5\u5404\u81EA\u7740\u8272\uFF0C\u6CA1\u6709\u552F\u4E00\u6ED1\u5757\u53EF\u6ED1\uFF0C\u4FDD\u6301\u539F\u6837\u3002 */\n.dshpc-seg--slide{position:relative;}\n.dshpc-seg--slide .dshpc-seg__item{position:relative;z-index:1;}\n.dshpc-seg--slide .dshpc-seg__item[aria-pressed='true']{background:transparent;box-shadow:none;}\n.dshpc-seg__thumb{position:absolute;z-index:0;border-radius:var(--dshpc-radius-sm);background:var(--seg-thumb);box-shadow:var(--dshpc-shadow-raised);pointer-events:none;transition:left var(--dshpc-dur) var(--dshpc-ease),top var(--dshpc-dur) var(--dshpc-ease),width var(--dshpc-dur) var(--dshpc-ease),height var(--dshpc-dur) var(--dshpc-ease);}\n\n/* \u2500\u2500 bordered \u5916\u6846\uFF082026-10-20 \u7528\u6237\u8981\u7684\u7B2C\u4E8C\u79CD\u6A21\u5F0F\uFF09\uFF1A**\u53EA\u5728\u6700\u5916\u9762\u5957\u4E00\u5708 1px \u63CF\u8FB9**\uFF0C\n \u91CC\u9762\u4E00\u6982\u4E0D\u52A8 \u2014\u2014 \u9009\u4E2D\u7247\u7684\u586B\u5145\u8272 / \u9634\u5F71 / \u6587\u5B57\u8272\u5168\u90E8\u4FDD\u6301\u539F\u6837\uFF08weekday \u7684\u84DD\u9762\u7167\u65E7\uFF09\uFF0C\n \u8FD9\u91CC\u4E0D\u5199\u4EFB\u4F55\u9488\u5BF9 __item \u7684\u89C4\u5219\u3002\n \u603B\u9AD8\u5FC5\u987B\u4E0E\u65E0\u6846\u7248\u9010\u50CF\u7D20\u4E00\u81F4\uFF1Aborder 1px\u00D72 \u7531 padding \u5404\u8BA9 1px \u62B5\u6D88\uFF083 \u2192 2\uFF09\uFF1B\n weekday \u81EA\u5DF1\u58F0\u660E\u7684 3px \u5728\u6587\u4EF6\u66F4\u540E\u9762\uFF0C\u9760\u53CC\u7C7B\u9009\u62E9\u5668\u538B\u56DE 2px\u3002 */\n.dshpc-seg--bordered{border:1px solid var(--dshpc-border);padding:2px;}\n.dshpc-seg--bordered.dshpc-seg--weekday{padding:2px;}\n\n@media (prefers-reduced-motion: reduce){.dshpc-seg__item{transition:none;}.dshpc-seg__thumb{transition:none;}}\n";
|
|
2
2
|
//# sourceMappingURL=segmented-css.generated.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"segmented-css.generated.d.ts","sourceRoot":"","sources":["../../../src/ui/inputs/segmented-css.generated.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,aAAa,
|
|
1
|
+
{"version":3,"file":"segmented-css.generated.d.ts","sourceRoot":"","sources":["../../../src/ui/inputs/segmented-css.generated.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,aAAa,glaAAsoO,CAAA"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// ⚠️ 生成物,勿手改。真源 = src/ui/inputs/segmented.css
|
|
2
2
|
// 由 scripts/gen-css.mjs 生成(`pnpm run gen:css`):改样式请改那个 .css 文件后重新生成。
|
|
3
|
-
export const SEGMENTED_CSS = "\n/* ── 分段控件 P2 ─────────────────────────────────────────────────────\n 结构照兄弟项目 dsh-task-dispatch-table 的 Segmented 皮肤(item 无边框、hover 只提亮文字),\n 前缀 / 变量名换成本仓口径。用户额外要的两处(兄弟没有):weekday 方块间隔(现为 2px);段内中性计数 __count。\n ⚠️ 2026-10-19 两次误判均已澄清:① 「宿主只认单行 CSS」——假,多行一直正常;\n ② 「宿主吃掉 token 块之后第一条规则」——也假,真因是 tokens 模板字符串结尾多了一个反斜杠,\n 注入文本里留下字面反引号,把紧随其后的那条规则的选择器污染掉了(见 dsh-host.md §9)。\n 样式照常多行书写,不必压行;也不需要任何「牺牲规则」。 */\n/* 外观只有一套(2026-10-26):原 variant 的 default / inset 两档在 CSS 里只差 1px 内距,\n 且 default 比文档承诺矮 2px,却让下游以为「有得选」而反复对图 ⇒ 整轴删除。\n padding 3px 是尺寸契约的一部分:item 高度 = 控制高 − 6px,加起来正好 24 / 28 / 32。 */\n/* 选中片配色收在两条局部变量里(--seg-thumb 底 / --seg-on 字):默认走主题亮片,\n tone 档与自定义 {bg, fg} 都只改这两条(后者由组件内联写根节点,内联恒胜)。 */\n.dshpc-seg{display:inline-flex;align-items:center;gap:2px;padding:3px;border-radius:var(--dshpc-radius-md);--seg-thumb:var(--dshpc-surface-raised);--seg-on:var(--dshpc-fg);background:var(--dshpc-seg-track);}\n.dshpc-seg__item{appearance:none;display:inline-flex;align-items:center;gap:4px;box-sizing:border-box;height:calc(var(--dshpc-control-h-sm) - 6px);padding:0 12px;border:0;border-radius:var(--dshpc-radius-sm);background:transparent;color:var(--dshpc-fg-2);font-family:inherit;font-size:var(--dshpc-font-xs);font-weight:500;white-space:nowrap;cursor:pointer;flex:none;transition:color var(--dshpc-dur-fast) var(--dshpc-ease),background-color var(--dshpc-dur-fast) var(--dshpc-ease),box-shadow var(--dshpc-dur-fast) var(--dshpc-ease);}\n.dshpc-seg--md .dshpc-seg__item{height:calc(var(--dshpc-control-h-md) - 6px);}\n.dshpc-seg--lg .dshpc-seg__item{height:calc(var(--dshpc-control-h-lg) - 6px);}\n/* 段内图标(前置):与 Button 同口径 —— inline-flex 吃掉行高基线,svg 按块级。 */\n.dshpc-seg__icon{display:inline-flex;align-items:center;justify-content:center;flex:none;line-height:0;}\n.dshpc-seg__icon svg{display:block;margin:0;}\n/* 只有图标(无文字 / 计数 / 角标):段必须是正方形 ⇒ 宽 = 段高、左右内距归零、内容居中;\n 否则基础规则的 0 12px 会把它拉成长方形。放在三档之后:同名特异性下后写者胜。 */\n.dshpc-seg__item--icon-only{width:calc(var(--dshpc-control-h-sm) - 6px);padding:0;justify-content:center;}\n.dshpc-seg--md .dshpc-seg__item--icon-only{width:calc(var(--dshpc-control-h-md) - 6px);}\n.dshpc-seg--lg .dshpc-seg__item--icon-only{width:calc(var(--dshpc-control-h-lg) - 6px);}\n.dshpc-seg__item:hover:not([aria-pressed='true']):not(:disabled){color:var(--dshpc-fg);}\n.dshpc-seg__item[aria-pressed='true']{background:var(--seg-thumb);box-shadow:var(--dshpc-shadow-raised);color:var(--seg-on);font-weight:600;}\n.dshpc-seg__item:focus-visible{outline:2px solid var(--dshpc-focus);outline-offset:-2px;}\n.dshpc-seg__item:disabled{cursor:default;opacity:.4;}\n/* 段内角标(如「异常」的数量):语义色实面 + 反白字,0 由组件侧不渲染。必须是正圆(用户 2026-10-03)。 */\n.dshpc-seg__badge{display:inline-flex;align-items:center;justify-content:center;flex:none;width:16px;height:16px;padding:0;overflow:hidden;border-radius:50%;background:var(--dshpc-danger);color:var(--dshpc-on-signal);font-size:10px;line-height:16px;font-weight:500;font-variant-numeric:tabular-nums;}\n/* 段内中性计数(如筛选条「全部 11」):纯文字、无底无边(对齐 task-ledger .dtl-seg__num 拍板口径);0 由组件侧不渲染。 */\n.dshpc-seg__count{display:inline;flex:none;margin-left:3px;padding:0;border:0;border-radius:0;background:none;color:var(--dshpc-fg-3);font-size:10px;line-height:1;font-weight:400;font-variant-numeric:tabular-nums;}\n/* 选中段(彩色实面)里的计数:必须跟着 --seg-on 走再压暗一档(72% 白 ≈ 「比正文稍灰」)。\n 不许用 --dshpc-fg-3:它跟主题走,暗色下是深灰 ⇒ 蓝底上几乎看不见(2026-10-29 用户截图「My todos 4」)。 */\n.dshpc-seg__item[aria-pressed='true'] .dshpc-seg__count{color:color-mix(in srgb,var(--seg-on) 72%,transparent);}\n/* block:撑满父宽(表单行用),各段等分 */\n.dshpc-seg--block{display:flex;width:100%;}\n.dshpc-seg--block .dshpc-seg__item{flex:1 1 auto;justify-content:center;}\n/* weekday:星期多选方块。基础插件的特殊化定制(用户 2026-10-01:原 WeekdayPicker 即「蓝底 + 近似方形」):\n 每格正方形(宽 = 段高)、选中品牌蓝反白字、**无外描边**(2026-10-18 重申)、\n 方块之间间距 gap:2px(2026-10-20 用户定稿:方块改小后 6px 显得太宽。10-18 曾从 2px 放宽到 6px,\n 两次都是用户拍板 —— 别自作主张改回去)。 */\n.dshpc-seg--weekday{--seg-track:var(--dshpc-seg-track);gap:2px;border:0;padding:3px;background:var(--seg-track);}\n.dshpc-seg--weekday .dshpc-seg__item{width:calc(var(--dshpc-control-h-lg) - 8px);padding:0;justify-content:center;}\n/* 蓝底反白:字色必须是常量白(--dshpc-on-signal)。2026-10-29 用户实测:暗色主题下这里曾用\n --dshpc-fg-inverse,而它跟随宿主 label-primary-foreground,暗色下是近黑 ⇒ 蓝底黑字看不清。 */\n.dshpc-seg--weekday{--seg-thumb:var(--dshpc-business);--seg-on:var(--dshpc-on-signal);}\n\n/* ── tone(2026-10-29 用户):选中片传内置基础色名,底 / 字由核心给,深浅两主题各自成立。\n 放在 weekday 之后:同名变量后写者胜,tone 与 className=\"dshpc-seg--weekday\" 同给时以 tone 为准。\n 黄底按 Chip / Button 同源口径用 on-warning(中高明度,白字看不清)。 */\n.dshpc-seg--tone-business{--seg-thumb:var(--dshpc-business);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-success{--seg-thumb:var(--dshpc-success);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-warning{--seg-thumb:var(--dshpc-warning);--seg-on:var(--dshpc-on-warning);}\n.dshpc-seg--tone-danger{--seg-thumb:var(--dshpc-danger);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-purple{--seg-thumb:var(--dshpc-purple);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-pink{--seg-thumb:var(--dshpc-pink);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-cyan{--seg-thumb:var(--dshpc-cyan);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-teal{--seg-thumb:var(--dshpc-teal);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-orange{--seg-thumb:var(--dshpc-orange);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-indigo{--seg-thumb:var(--dshpc-indigo);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-rose{--seg-thumb:var(--dshpc-rose);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-slate{--seg-thumb:var(--dshpc-slate);--seg-on:var(--dshpc-on-signal);}\n\n/* ── 单选滑动块(2026-10-26 用户:点选后选中底应「滑过去」,不是旧段消失、新段直接亮)。\n 结构 = 一块绝对定位的共用底 + 各段透明;位置/尺寸由组件量出后内联,这里只管外观与过渡。\n --slide 只在单选挂上:多选(如星期)每段各自着色,没有唯一滑块可滑,保持原样。 */\n.dshpc-seg--slide{position:relative;}\n.dshpc-seg--slide .dshpc-seg__item{position:relative;z-index:1;}\n.dshpc-seg--slide .dshpc-seg__item[aria-pressed='true']{background:transparent;box-shadow:none;}\n.dshpc-seg__thumb{position:absolute;z-index:0;border-radius:var(--dshpc-radius-sm);background:var(--seg-thumb);box-shadow:var(--dshpc-shadow-raised);pointer-events:none;transition:left var(--dshpc-dur) var(--dshpc-ease),top var(--dshpc-dur) var(--dshpc-ease),width var(--dshpc-dur) var(--dshpc-ease),height var(--dshpc-dur) var(--dshpc-ease);}\n\n/* ── bordered 外框(2026-10-20 用户要的第二种模式):**只在最外面套一圈 1px 描边**,\n 里面一概不动 —— 选中片的填充色 / 阴影 / 文字色全部保持原样(weekday 的蓝面照旧),\n 这里不写任何针对 __item 的规则。\n 总高必须与无框版逐像素一致:border 1px×2 由 padding 各让 1px 抵消(3 → 2);\n weekday 自己声明的 3px 在文件更后面,靠双类选择器压回 2px。 */\n.dshpc-seg--bordered{border:1px solid var(--dshpc-border);padding:2px;}\n.dshpc-seg--bordered.dshpc-seg--weekday{padding:2px;}\n\n@media (prefers-reduced-motion: reduce){.dshpc-seg__item{transition:none;}.dshpc-seg__thumb{transition:none;}}\n";
|
|
3
|
+
export const SEGMENTED_CSS = "\n/* ── 分段控件 P2 ─────────────────────────────────────────────────────\n 结构照兄弟项目 dsh-task-dispatch-table 的 Segmented 皮肤(item 无边框、hover 只提亮文字),\n 前缀 / 变量名换成本仓口径。用户额外要的两处(兄弟没有):weekday 方块间隔(现为 2px);段内中性计数 __count。\n ⚠️ 2026-10-19 两次误判均已澄清:① 「宿主只认单行 CSS」——假,多行一直正常;\n ② 「宿主吃掉 token 块之后第一条规则」——也假,真因是 tokens 模板字符串结尾多了一个反斜杠,\n 注入文本里留下字面反引号,把紧随其后的那条规则的选择器污染掉了(见 dsh-host.md §9)。\n 样式照常多行书写,不必压行;也不需要任何「牺牲规则」。 */\n/* 外观只有一套(2026-10-26):原 variant 的 default / inset 两档在 CSS 里只差 1px 内距,\n 且 default 比文档承诺矮 2px,却让下游以为「有得选」而反复对图 ⇒ 整轴删除。\n padding 3px 是尺寸契约的一部分:item 高度 = 控制高 − 6px,加起来正好 24 / 28 / 32。 */\n/* 选中片配色收在两条局部变量里(--seg-thumb 底 / --seg-on 字):默认走主题亮片,\n tone 档与自定义 {bg, fg} 都只改这两条(后者由组件内联写根节点,内联恒胜)。 */\n.dshpc-seg{display:inline-flex;align-items:center;gap:2px;padding:3px;border-radius:var(--dshpc-radius-md);--seg-thumb:var(--dshpc-surface-raised);--seg-on:var(--dshpc-fg);background:var(--dshpc-seg-track);}\n.dshpc-seg__item{appearance:none;display:inline-flex;align-items:center;gap:4px;box-sizing:border-box;height:calc(var(--dshpc-control-h-sm) - 6px);padding:0 12px;border:0;border-radius:var(--dshpc-radius-sm);background:transparent;color:var(--dshpc-fg-2);font-family:inherit;font-size:var(--dshpc-font-xs);font-weight:500;white-space:nowrap;cursor:pointer;flex:none;transition:color var(--dshpc-dur-fast) var(--dshpc-ease),background-color var(--dshpc-dur-fast) var(--dshpc-ease),box-shadow var(--dshpc-dur-fast) var(--dshpc-ease);}\n.dshpc-seg--md .dshpc-seg__item{height:calc(var(--dshpc-control-h-md) - 6px);}\n.dshpc-seg--lg .dshpc-seg__item{height:calc(var(--dshpc-control-h-lg) - 6px);}\n/* 段内图标(前置):与 Button 同口径 —— inline-flex 吃掉行高基线,svg 按块级。 */\n.dshpc-seg__icon{display:inline-flex;align-items:center;justify-content:center;flex:none;line-height:0;}\n.dshpc-seg__icon svg{display:block;margin:0;}\n/* 只有图标(无文字 / 计数 / 角标):段必须是正方形 ⇒ 宽 = 段高、左右内距归零、内容居中;\n 否则基础规则的 0 12px 会把它拉成长方形。放在三档之后:同名特异性下后写者胜。 */\n.dshpc-seg__item--icon-only{width:calc(var(--dshpc-control-h-sm) - 6px);padding:0;justify-content:center;}\n.dshpc-seg--md .dshpc-seg__item--icon-only{width:calc(var(--dshpc-control-h-md) - 6px);}\n.dshpc-seg--lg .dshpc-seg__item--icon-only{width:calc(var(--dshpc-control-h-lg) - 6px);}\n/* 多选(2026-11-07 用户):每段最小宽 = 该档段高 ⇒ 最窄也是正方形,绝不会出现比高还窄的竖条;\n 文案更长时由内容自然撑宽成横向长方形。三档各跟自己的控制高,不写死 px。\n weekday / icon-only 那种固定 width 若小于段高,同样被 min-width 顶到正方形。 */\n.dshpc-seg--multiple .dshpc-seg__item{min-width:calc(var(--dshpc-control-h-sm) - 6px);}\n.dshpc-seg--multiple.dshpc-seg--md .dshpc-seg__item{min-width:calc(var(--dshpc-control-h-md) - 6px);}\n.dshpc-seg--multiple.dshpc-seg--lg .dshpc-seg__item{min-width:calc(var(--dshpc-control-h-lg) - 6px);}\n.dshpc-seg__item:hover:not([aria-pressed='true']):not(:disabled){color:var(--dshpc-fg);}\n.dshpc-seg__item[aria-pressed='true']{background:var(--seg-thumb);box-shadow:var(--dshpc-shadow-raised);color:var(--seg-on);font-weight:600;}\n.dshpc-seg__item:focus-visible{outline:2px solid var(--dshpc-focus);outline-offset:-2px;}\n.dshpc-seg__item:disabled{cursor:default;opacity:.4;}\n/* 段内角标(如「异常」的数量):语义色实面 + 反白字,0 由组件侧不渲染。必须是正圆(用户 2026-10-03)。 */\n.dshpc-seg__badge{display:inline-flex;align-items:center;justify-content:center;flex:none;width:16px;height:16px;padding:0;overflow:hidden;border-radius:50%;background:var(--dshpc-danger);color:var(--dshpc-on-signal);font-size:10px;line-height:16px;font-weight:500;font-variant-numeric:tabular-nums;}\n/* 段内中性计数(如筛选条「全部 11」):纯文字、无底无边(对齐 task-ledger .dtl-seg__num 拍板口径);0 由组件侧不渲染。 */\n.dshpc-seg__count{display:inline;flex:none;margin-left:3px;padding:0;border:0;border-radius:0;background:none;color:var(--dshpc-fg-3);font-size:10px;line-height:1;font-weight:400;font-variant-numeric:tabular-nums;}\n/* 选中段(彩色实面)里的计数:必须跟着 --seg-on 走再压暗一档(72% 白 ≈ 「比正文稍灰」)。\n 不许用 --dshpc-fg-3:它跟主题走,暗色下是深灰 ⇒ 蓝底上几乎看不见(2026-10-29 用户截图「My todos 4」)。 */\n.dshpc-seg__item[aria-pressed='true'] .dshpc-seg__count{color:color-mix(in srgb,var(--seg-on) 72%,transparent);}\n/* block:撑满父宽(表单行用),各段等分 */\n.dshpc-seg--block{display:flex;width:100%;}\n.dshpc-seg--block .dshpc-seg__item{flex:1 1 auto;justify-content:center;}\n/* weekday:星期多选方块。基础插件的特殊化定制(用户 2026-10-01:原 WeekdayPicker 即「蓝底 + 近似方形」):\n 每格正方形(宽 = 段高)、选中品牌蓝反白字、**无外描边**(2026-10-18 重申)、\n 方块之间间距 gap:2px(2026-10-20 用户定稿:方块改小后 6px 显得太宽。10-18 曾从 2px 放宽到 6px,\n 两次都是用户拍板 —— 别自作主张改回去)。 */\n.dshpc-seg--weekday{--seg-track:var(--dshpc-seg-track);gap:2px;border:0;padding:3px;background:var(--seg-track);}\n.dshpc-seg--weekday .dshpc-seg__item{width:calc(var(--dshpc-control-h-lg) - 8px);padding:0;justify-content:center;}\n/* 蓝底反白:字色必须是常量白(--dshpc-on-signal)。2026-10-29 用户实测:暗色主题下这里曾用\n --dshpc-fg-inverse,而它跟随宿主 label-primary-foreground,暗色下是近黑 ⇒ 蓝底黑字看不清。 */\n.dshpc-seg--weekday{--seg-thumb:var(--dshpc-business);--seg-on:var(--dshpc-on-signal);}\n\n/* ── tone(2026-10-29 用户):选中片传内置基础色名,底 / 字由核心给,深浅两主题各自成立。\n 放在 weekday 之后:同名变量后写者胜,tone 与 className=\"dshpc-seg--weekday\" 同给时以 tone 为准。\n 黄底按 Chip / Button 同源口径用 on-warning(中高明度,白字看不清)。 */\n.dshpc-seg--tone-business{--seg-thumb:var(--dshpc-business);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-success{--seg-thumb:var(--dshpc-success);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-warning{--seg-thumb:var(--dshpc-warning);--seg-on:var(--dshpc-on-warning);}\n.dshpc-seg--tone-danger{--seg-thumb:var(--dshpc-danger);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-purple{--seg-thumb:var(--dshpc-purple);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-pink{--seg-thumb:var(--dshpc-pink);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-cyan{--seg-thumb:var(--dshpc-cyan);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-teal{--seg-thumb:var(--dshpc-teal);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-orange{--seg-thumb:var(--dshpc-orange);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-indigo{--seg-thumb:var(--dshpc-indigo);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-rose{--seg-thumb:var(--dshpc-rose);--seg-on:var(--dshpc-on-signal);}\n.dshpc-seg--tone-slate{--seg-thumb:var(--dshpc-slate);--seg-on:var(--dshpc-on-signal);}\n\n/* ── 单选滑动块(2026-10-26 用户:点选后选中底应「滑过去」,不是旧段消失、新段直接亮)。\n 结构 = 一块绝对定位的共用底 + 各段透明;位置/尺寸由组件量出后内联,这里只管外观与过渡。\n --slide 只在单选挂上:多选(如星期)每段各自着色,没有唯一滑块可滑,保持原样。 */\n.dshpc-seg--slide{position:relative;}\n.dshpc-seg--slide .dshpc-seg__item{position:relative;z-index:1;}\n.dshpc-seg--slide .dshpc-seg__item[aria-pressed='true']{background:transparent;box-shadow:none;}\n.dshpc-seg__thumb{position:absolute;z-index:0;border-radius:var(--dshpc-radius-sm);background:var(--seg-thumb);box-shadow:var(--dshpc-shadow-raised);pointer-events:none;transition:left var(--dshpc-dur) var(--dshpc-ease),top var(--dshpc-dur) var(--dshpc-ease),width var(--dshpc-dur) var(--dshpc-ease),height var(--dshpc-dur) var(--dshpc-ease);}\n\n/* ── bordered 外框(2026-10-20 用户要的第二种模式):**只在最外面套一圈 1px 描边**,\n 里面一概不动 —— 选中片的填充色 / 阴影 / 文字色全部保持原样(weekday 的蓝面照旧),\n 这里不写任何针对 __item 的规则。\n 总高必须与无框版逐像素一致:border 1px×2 由 padding 各让 1px 抵消(3 → 2);\n weekday 自己声明的 3px 在文件更后面,靠双类选择器压回 2px。 */\n.dshpc-seg--bordered{border:1px solid var(--dshpc-border);padding:2px;}\n.dshpc-seg--bordered.dshpc-seg--weekday{padding:2px;}\n\n@media (prefers-reduced-motion: reduce){.dshpc-seg__item{transition:none;}.dshpc-seg__thumb{transition:none;}}\n";
|
|
4
4
|
//# sourceMappingURL=segmented-css.generated.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"segmented-css.generated.js","sourceRoot":"","sources":["../../../src/ui/inputs/segmented-css.generated.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,qEAAqE;AACrE,MAAM,CAAC,MAAM,aAAa,GAAG,
|
|
1
|
+
{"version":3,"file":"segmented-css.generated.js","sourceRoot":"","sources":["../../../src/ui/inputs/segmented-css.generated.ts"],"names":[],"mappings":"AAAA,8CAA8C;AAC9C,qEAAqE;AACrE,MAAM,CAAC,MAAM,aAAa,GAAG,moOAAmoO,CAAA"}
|
package/docs/design/structure.md
CHANGED
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
|---|---|---|
|
|
33
33
|
| **动作** `actions` | 点它触发一次操作,本身不产生值 | Button、IconButton |
|
|
34
34
|
| **录入** `inputs` | 产生或修改一个值 | Input、NumberInput、PrefixedInput、Textarea、Checkbox、Segmented、Picker、DateTimePicker、WorkspacePicker、ModelPicker、InputGroup |
|
|
35
|
-
| **展示** `display` | 只呈现内容,不改变状态 | Card、StripCard、Surface、Chip、Table、CodeViewer、MarqueeText、FlipText、LiveText、SectionHead、FieldHint |
|
|
35
|
+
| **展示** `display` | 只呈现内容,不改变状态 | Card、StripCard、Surface、Chip、Table、ListRow、CodeViewer、MarqueeText、FlipText、LiveText、SectionHead、FieldHint |
|
|
36
36
|
| **反馈** `feedback` | 表达「正在进行 / 刚完成 / 出错了」 | Modal、SideSheet、AlertModal、ConfirmModal、alertModal、confirmModal、Toast、host-toast、Loader、LoaderBar、Loading |
|
|
37
37
|
| **布局** `layout` | 只决定内部元素怎么摆、怎么拼 | SplitGroup、PanelDock、QuickToolbar、resizer |
|
|
38
38
|
| **导航** `navigation` | 在多个视图 / 页之间移动 | Pagination |
|
|
@@ -63,7 +63,7 @@ src/
|
|
|
63
63
|
│ │ Segmented · Picker(+ picker-logic / picker-icons)
|
|
64
64
|
│ │ DateTimePicker(+ datetime-logic)· InputGroup
|
|
65
65
|
│ │ WorkspacePicker · ModelPicker
|
|
66
|
-
│ ├── display/ Card · StripCard · Surface · Chip · Table(+ table-logic / table-shared)
|
|
66
|
+
│ ├── display/ Card · StripCard · Surface · Chip · Table · ListRow(+ table-logic / table-shared)
|
|
67
67
|
│ │ CodeViewer(+ code-viewer-lang / -theme)· MarqueeText · FlipText
|
|
68
68
|
│ │ LiveText · SectionHead · FieldHint
|
|
69
69
|
│ ├── feedback/ Modal · SideSheet · AlertModal · ConfirmModal(+ modal-host)
|
|
@@ -132,7 +132,7 @@ utils(谁都不依赖,谁都可以用)
|
|
|
132
132
|
├─ 录入 inputs Input · NumberInput · PrefixedInput · Textarea · Checkbox
|
|
133
133
|
│ Segmented · Picker · DateTimePicker · WorkspacePicker
|
|
134
134
|
│ ModelPicker · InputGroup
|
|
135
|
-
├─ 展示 display Card · StripCard · Surface · Chip · Table · CodeViewer
|
|
135
|
+
├─ 展示 display Card · StripCard · Surface · Chip · Table · ListRow · CodeViewer
|
|
136
136
|
│ MarqueeText · FlipText · LiveText · SectionHead · FieldHint
|
|
137
137
|
├─ 反馈 feedback Modal · SideSheet · AlertModal · ConfirmModal
|
|
138
138
|
│ Toast · Loader · LoaderBar · Loading
|
package/docs/design/style.md
CHANGED
|
@@ -113,6 +113,14 @@ the dark theme.
|
|
|
113
113
|
|
|
114
114
|
尺寸类 props 承诺的数值必须有自检盯着(`test/css-contract.test.mjs`:`Segmented` 三档总高 = 24 / 28 / 32)。
|
|
115
115
|
|
|
116
|
+
**多选段不许比高还窄**(2026-11-07):`Segmented` 挂 `multiple` 时每段的 `min-width` = 该档段高
|
|
117
|
+
(`calc(var(--dshpc-control-h-*) - 6px)`)—— 最窄正方形、文案更长则横向长方形,绝不出现竖着一小溜。
|
|
118
|
+
固定 `width` 的 `weekday` / `--icon-only` 也由这条下限兜住;下限只作用多选,单选外观一个字节不变。
|
|
119
|
+
由 `test/css-contract.test.mjs` 盯着。
|
|
120
|
+
|
|
121
|
+
EN: In `multiple` mode every `Segmented` item has `min-width` equal to its own segment height: square at the
|
|
122
|
+
narrowest, landscape when labels are longer, never taller than wide. Single-select rendering is unchanged.
|
|
123
|
+
|
|
116
124
|
EN: Never ship a visually equivalent appearance tier. `Segmented`'s `variant` was removed on 2026-10-26: the two
|
|
117
125
|
tiers differed by 1px of padding, and `default` rendered 2px shorter than `size` promised — downstream read it as
|
|
118
126
|
"there is a choice", compared against the demo, and chased tokens/bundling instead. Any numeric size promise gets
|
|
@@ -274,3 +282,91 @@ checks all three, including inline `overflowY/X` in the demo.
|
|
|
274
282
|
|
|
275
283
|
EN: No second `document.createElement('style')` — always go through the kit. No second style tag id — one kit
|
|
276
284
|
per plugin. Rules inside a domain consume `var(--dshpc-*)` only; never hard-code colors, sizes or fonts.
|
|
285
|
+
|
|
286
|
+
## 控件默认字号
|
|
287
|
+
|
|
288
|
+
> EN: Default type scale for controls
|
|
289
|
+
|
|
290
|
+
`Surface` 是纯容器,只给外框,`font:inherit` 刻意不接管内容排版;**但承载文字的控件必须在自己的域内给默认字号**
|
|
291
|
+
(`font-size:var(--dshpc-font-md)` + `line-height:var(--dshpc-line-md)`,与 `Table` / `Input md` 同档)。
|
|
292
|
+
不许把这件事推给每个消费者重复补一遍 —— 2026-11-07 用户拍板:`ListRow` 曾漏设,会话列表标题继承到宿主默认
|
|
293
|
+
16px,消费者被迫自己写 `fontSize` 压回去。调用方仍可用内联 style 覆盖这一档。
|
|
294
|
+
|
|
295
|
+
EN: `Surface` is a pure frame and deliberately inherits typography, but any control that renders text must set its
|
|
296
|
+
own default `font-size` / `line-height` from tokens (same tier as `Table` / `Input md`). Do not make every consumer
|
|
297
|
+
repeat it; callers can still override that tier inline.
|
|
298
|
+
|
|
299
|
+
## 行控件的两槽居中
|
|
300
|
+
|
|
301
|
+
> EN: Symmetric alignment for row slots
|
|
302
|
+
|
|
303
|
+
`ListRow` 的 `__main` 与 `__actions` 必须**同时**是 `display:flex;align-items:center`。
|
|
304
|
+
只给右侧操作槽居中、主内容槽留成普通块级流,调用方按常规写法把主内容包成 `inline-flex`
|
|
305
|
+
的 `span` 就会按基线排,基线下方多出 descender 空隙 ⇒ 左侧偏上、左右不齐
|
|
306
|
+
(2026-11-08 兄弟项目「附加文件」行真机反馈;用户拍板按正规方式修核心,不接受调用方逐个补)。
|
|
307
|
+
`__main` 的子项统一 `min-width:0`,`MarqueeText` 这类可截断内容在 flex 里才不会被自身内容撑破。
|
|
308
|
+
主内容内部横排结构仍归调用方 —— 核心只负责两槽的垂直对齐,不接管内容排版。
|
|
309
|
+
|
|
310
|
+
EN: Both slots of `ListRow` — `__main` and `__actions` — must be `display:flex;align-items:center`.
|
|
311
|
+
Centering only the actions slot leaves the main content in normal block flow, so a caller's `inline-flex`
|
|
312
|
+
wrapper is laid out on the baseline and gains a descender gap underneath: the left side rides high while
|
|
313
|
+
the right stays centered (reported from a consuming plugin on 2026-11-08; fixed in the core, not patched
|
|
314
|
+
per consumer). `__main > *` gets `min-width:0` so truncating content such as `MarqueeText` can still shrink
|
|
315
|
+
inside a flex container. The internal horizontal layout of main content remains the caller's job.
|
|
316
|
+
|
|
317
|
+
## 卡片 hover 作用域与底色轴
|
|
318
|
+
|
|
319
|
+
> EN: Card hover scope and fill switch
|
|
320
|
+
|
|
321
|
+
`Card` / `StripCard` 的悬停统一吃 `--dshpc-card-hover`(亮 `rgba(37,99,235,.07)` / 暗
|
|
322
|
+
`rgba(96,165,250,.13)`),由 `hoverable` 开启、**默认关**;底色由 `filled` 控制、**默认有底**。
|
|
323
|
+
底色只改 `--surface-bg` 一个变量,不许写 `background` / `background-image` 属性去覆盖根节点底色 ——
|
|
324
|
+
`StripCard` 的浅底也必须走这个变量,否则覆盖顺序会打架(兄弟项目曾用渐变叠加绕过,2026-11-07 收编)。
|
|
325
|
+
|
|
326
|
+
EN: Hover on `Card` / `StripCard` uses `--dshpc-card-hover` only; it is opt-in via `hoverable`
|
|
327
|
+
(default off). The fill is controlled by `filled` (default on) and only rewrites `--surface-bg`; never
|
|
328
|
+
override the root background with `background` / `background-image` properties.
|
|
329
|
+
|
|
330
|
+
开启 `hoverable` 时**同时**给 `cursor:pointer` —— 既然声明可交互,手势不能只换背景不变;
|
|
331
|
+
没开这根轴的卡片保持默认光标(2026-11-07 用户反馈)。
|
|
332
|
+
|
|
333
|
+
EN: Enabling `hoverable` also sets `cursor:pointer`. Cards without the axis keep the default cursor.
|
|
334
|
+
|
|
335
|
+
### 展开态:hover 只作用「上面那一块」
|
|
336
|
+
|
|
337
|
+
2026-11-07 用户否决「只中间变色」:外圈 `padding` 圈也要一起变,否则头部像被挖掉一圈;
|
|
338
|
+
也否决「给展开区铺一层常态底色去盖住根节点」—— 底色 token 是半透明的,叠两层会更暗,
|
|
339
|
+
真机上就是一块深色补丁。
|
|
340
|
+
|
|
341
|
+
**正解是结构分区,不是遮盖**:根节点 `padding:0`、只铺一层常态底、用 `overflow:hidden` 统一裁圆角;
|
|
342
|
+
`__body` 是「上面那一整块」,独立承担四边内距,是 head 作用域下唯一的 hover 目标;`__panel` 是它的
|
|
343
|
+
兄弟节点,不铺任何背景、不参与 hover,自己承担左右 / 底部内距。**展开态不改 `__body` 内距**:
|
|
344
|
+
上下两圈留白始终对称,色条上下才不会一长一短;两块之间的间隔就是 `__body` 的 `padding-bottom`,
|
|
345
|
+
属于头部区、跟着一起变色,`__panel` 的 `margin-top` 归 0、从分隔线开始,中间不留不变色的带子。
|
|
346
|
+
`__body` 不许写 `border-radius` 裸值(圆角契约只认 Surface 一处),圆角由根节点裁切保证。
|
|
347
|
+
|
|
348
|
+
`StripCard` 的 4px 色条相对根节点绝对定位(`top:0` / `bottom:0`),展开后仍通高贯穿整卡、
|
|
349
|
+
包括展开区;它不属于 hover 分区,颜色也不随 hover 变(2026-11-08 拍板)。
|
|
350
|
+
|
|
351
|
+
`hoverScope` 决定展开区是否跟着变,**默认 `'head'`**:
|
|
352
|
+
|
|
353
|
+
| 作用域 | 变色范围 | 鼠标落在展开区 | 展开区手势 |
|
|
354
|
+
|---|---|---|---|
|
|
355
|
+
| `'head'`(默认) | `__body` 整块边到边变色(含内距圈、圆角) | `__body:hover` 不成立 ⇒ 整卡完全不触发 | `cursor:auto` |
|
|
356
|
+
| `'card'`(消费端显式选) | 根节点改 `--surface-bg`,整卡含展开区一起变色 | 照常触发 | `cursor:pointer` |
|
|
357
|
+
|
|
358
|
+
内距走 `--card-pad-t/r/b/l` 四根变量(strip / 四方位各自覆盖);消费端 `style.padding` 由
|
|
359
|
+
`Card.ts` 转成 `--card-pad-all` 交给 `__body`,根节点永远零内距。
|
|
360
|
+
|
|
361
|
+
**契约**:消费端必须把展开内容放进 `panel`(`children` 属于头部区),核心才有分区信号;
|
|
362
|
+
`__panel` 是 `__body` 的兄弟节点,由 `test/card.test.mjs` 盯着。
|
|
363
|
+
|
|
364
|
+
EN: The root keeps `padding:0` and paints one resting fill. `__body` is the header block — it owns all four
|
|
365
|
+
paddings, inherits the root radius, and is the only hover target under `hoverScope: 'head'`. `__panel` is its
|
|
366
|
+
sibling: no background at all, never hovered, with its own horizontal / bottom padding. Expanding never
|
|
367
|
+
rewrites the header padding: top and bottom stay symmetric, and the gap between the blocks is the header's
|
|
368
|
+
own `padding-bottom`, so it changes color together with the header. `__panel` starts at the divider with
|
|
369
|
+
`margin-top:0`. The StripCard rail is absolutely positioned against the root (`top:0` / `bottom:0`), so it
|
|
370
|
+
stays full-height across the expanded area too. `:has()` and "paint a resting-fill snapshot over the
|
|
371
|
+
expanded area" are forbidden — semi-transparent tokens stacked twice render darker. Callers must put
|
|
372
|
+
expandable content in `panel`; `children` belongs to the header block.
|
package/docs/help/ui.doc.ts
CHANGED
|
@@ -28,6 +28,7 @@ const cardExample = `import { Card, Chip, StripCard } from 'dsh-plugin-core/ui'
|
|
|
28
28
|
h(Card, {
|
|
29
29
|
accent: 'warning',
|
|
30
30
|
bar: { side: 'left', inset: 12, gap: 12 }, // 色条可放 left / right / top / bottom
|
|
31
|
+
hoverable: true, // 头部区整块悬停变色(默认关)
|
|
31
32
|
action: h(Button, { size: 'sm', variant: 'ghost' }, '跳过'),
|
|
32
33
|
},
|
|
33
34
|
h('div', null, '标题'),
|
|
@@ -36,8 +37,11 @@ h(Card, {
|
|
|
36
37
|
|
|
37
38
|
h(StripCard, {
|
|
38
39
|
accent: 'success',
|
|
40
|
+
hoverable: true, filled: false, // 底色关掉 = 透明(默认有底)
|
|
41
|
+
// hoverScope 默认 'head':只有上面头部区变色,展开区完全不受影响
|
|
42
|
+
// 要连展开区一起变色才显式写 hoverScope: 'card'
|
|
39
43
|
expanded: open, onToggle: () => setOpen(!open),
|
|
40
|
-
panel: h('div', null, '展开详情'),
|
|
44
|
+
panel: h('div', null, '展开详情'), // 展开内容放 panel,别塞进 children
|
|
41
45
|
}, h('div', null, '标题 + 元信息'))`
|
|
42
46
|
|
|
43
47
|
const surfaceExample = `import { Surface, Card } from 'dsh-plugin-core/ui'
|
|
@@ -51,6 +55,25 @@ h(Surface, { border: 'faint', padding: 'lg' }, h(Card, null, '框里再放卡'))
|
|
|
51
55
|
// 虚线占位框也走它,不要自己写 1px dashed:
|
|
52
56
|
h(Surface, { tone: 'sunken', border: 'dashed', padding: 'lg' }, '还没做的东西')`
|
|
53
57
|
|
|
58
|
+
const listRowExample = `import { ListRow, Button, Chip } from 'dsh-plugin-core/ui'
|
|
59
|
+
|
|
60
|
+
// 一行一条:常态带底,点整行打开 / 选中,右侧小操作不连带触发整行
|
|
61
|
+
h(ListRow, {
|
|
62
|
+
onClick: () => openFile(entry),
|
|
63
|
+
selected: entry.path === currentPath,
|
|
64
|
+
actions: h(Button, {
|
|
65
|
+
size: 'sm', variant: 'ghost', onClick: () => removeEntry(entry),
|
|
66
|
+
}, '移除'),
|
|
67
|
+
},
|
|
68
|
+
h('div', { style: { display: 'flex', alignItems: 'center', gap: 8 } },
|
|
69
|
+
h(Chip, null, 'TS'),
|
|
70
|
+
h('span', null, entry.name),
|
|
71
|
+
),
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
// 带边 / 关掉 hover / 纯展示(不可点)
|
|
75
|
+
h(ListRow, { bordered: true, hoverable: false }, '只读的一行')`
|
|
76
|
+
|
|
54
77
|
const panelDockExample = `const dock = createPanelDock({ maxPanels: 3 }) // 一次,挂在插件级
|
|
55
78
|
|
|
56
79
|
// 页面里:结构就在这儿写,不塞进任何调用参数
|
|
@@ -284,7 +307,7 @@ const doc: DocTopic = {
|
|
|
284
307
|
exports: [
|
|
285
308
|
'Button', 'IconButton', 'Segmented', 'SplitGroup', 'Input', 'PrefixedInput', 'NumberInput', 'Textarea',
|
|
286
309
|
'Checkbox', 'fieldMetricsOf', 'Picker', 'WorkspacePicker', 'ModelPicker', 'DateTimePicker', 'Surface', 'Card', 'StripCard',
|
|
287
|
-
'Chip', 'Table', 'Pagination', 'Modal', 'SideSheet', 'FieldHint', 'setTooltipRenderer', 'showToast', 'notify', 'showHostToast',
|
|
310
|
+
'Chip', 'Table', 'ListRow', 'Pagination', 'Modal', 'SideSheet', 'FieldHint', 'setTooltipRenderer', 'showToast', 'notify', 'showHostToast',
|
|
288
311
|
'Loader', 'LoaderBar', 'Loading', 'RunningBlocks', 'SectionHead', 'MarqueeText', 'FlipText', 'LiveText',
|
|
289
312
|
'QuickToolbar', 'startResizeLayoutWidth', 'PanelDock', 'createPanelDock', 'DockPanel',
|
|
290
313
|
'ensureControls', 'setStyleKit',
|
|
@@ -321,6 +344,10 @@ const doc: DocTopic = {
|
|
|
321
344
|
zh: 'IconButton:variant: plain|outline|danger(默认 plain,**无底色**)、size(默认 lg)、icon(必填)、label(必填,无障碍名兼 title)、color(图标色)、background(底色,不传即无底色)。',
|
|
322
345
|
en: 'IconButton: variant plain|outline|danger (default plain, **no background**), size (default lg), icon (required), label (required, doubles as a11y name and title), color (icon colour), background (fill; omitted = no fill).',
|
|
323
346
|
},
|
|
347
|
+
{
|
|
348
|
+
zh: '`dense` 是两者共用的紧凑图标档:`size` / 高度一律不变,图标放大一档、内距收紧(Button 的 `--btn-pad` 从 10/12/14 收到 6,图标容器从 0.875em 到 1.25em;IconButton 把图标 `<svg>` 的 `width/height` 从 1em 提到 1.25em,正方形宽高不变、四周留白变小)。两者 dense 下图标都是 sm 15px / md·lg 16.25px。IconButton 的按钮显式 `padding:0`、图标 `flex:none`:svg 是 flex item,不禁止收缩会被内距压成窄条,此时改 `width` 或加 `!important` 都无效。给描边细、缩到 sm 看不清的图标用(如文件类型 / 语言图标);默认 false,原有按钮外观不变。',
|
|
349
|
+
en: '`dense` is a shared compact-icon tier for both: `size` and height stay put while the icon grows one step and padding tightens (Button: `--btn-pad` 10/12/14 → 6, icon container 0.875em → 1.25em; IconButton: the icon `<svg>` goes from `width/height:1em` to `1.25em`, same square box, less breathing room). Both give sm 15px / md·lg 16.25px icons. An IconButton sets `padding:0` on itself and `flex:none` on the icon: the svg is a flex item, and without disabling shrinking the padding squeezes it into a narrow strip — changing `width` or adding `!important` cannot fix that. Use it for thin-stroke icons that vanish at `sm` (file-type / language glyphs). Defaults to false, so existing buttons are unchanged.',
|
|
350
|
+
},
|
|
324
351
|
{
|
|
325
352
|
zh: '两者的 loading 语义一致:`onClick` 返回 Promise 就转圈(纯图标钮把图标位换成小圈,`aria-label` 不变、补 `aria-busy`),`onBusyChange` 把「在跑」报出去;受控 `loading` 与它取或 —— 别处刷新也能点亮同一颗按钮。转圈期间按钮自己的图标位(`icon` / `iconRight`)全部让位,只留转圈 + 文字。',
|
|
326
353
|
en: 'Both share one loading semantics: a Promise-returning `onClick` spins (an icon button swaps its icon for the spinner, keeps `aria-label` and adds `aria-busy`), `onBusyChange` reports "running", and the controlled `loading` prop is OR-ed in — an external refresh lights the same button too. While spinning, the button’s own icon slots (`icon` / `iconRight`) all step aside: spinner plus label only.',
|
|
@@ -333,6 +360,10 @@ const doc: DocTopic = {
|
|
|
333
360
|
zh: 'Segmented:`items`(必填)支持单选 / 多选,`size`(默认 lg;三档总高 24 / 28 / 32)、`bordered`(1px 外框,总高不变)、`multiple`(多选)。外观只有一套:灰底轨道 + 白色选中片,选中片的描边环与阴影由宿主 elevation token 提供(离线兜底值没有那圈环)。选中片配色只经 `tone`:传内置色名(与 Chip 同名的 business / success / warning / danger / purple / pink / cyan / teal / orange / indigo / rose / slate)时底与字由核心定、深浅两主题各自成立;传 `{ bg, fg }` 时两个主题都用调用方这一对颜色(对比度由调用方负责)。段内 `icon` 是前置图标槽(官方图标组件 / 数组 / 自绘节点均可),`label` 也可传节点;顺序固定为 icon → label → count。只有图标(无文字 / 计数 / 角标)时该段自动变正方形(宽 = 段高),读屏名用 `ariaLabel`,缺省退回 `tooltip`。段内 `count`(弱化灰字,选中段内自动跟着选中片字色提亮)/ `badge`(红角标)接受 `number | string`:数字 ≤0 不显示,字符串原样显示(如 `1K` / `99+`)。',
|
|
334
361
|
en: 'Segmented: `items` (required) supports single or multiple selection; `size` (default lg; totals 24 / 28 / 32), `bordered` (1px outer frame, same total height), `multiple` (multi-select). One look only: grey track + white selected pill; its stroke ring and shadow come from the host elevation token (the offline fallback has no ring). The selected pill’s colors go through `tone` only: a built-in color name (business / success / warning / danger / purple / pink / cyan / teal / orange / indigo / rose / slate, same names as Chip) lets the core pick background and text per theme; `{ bg, fg }` uses that pair verbatim in both themes (contrast is the caller’s call). An item’s leading `icon` takes any node (official icon component, array, or custom); `label` also accepts a node; order is always icon → label → count. With only an icon (no label / count / badge) the segment squares itself (width = segment height), and the accessible name comes from `ariaLabel`, falling back to `tooltip`. An item’s `count` (muted text; auto-lightened to follow the selected pill’s text color while selected) and `badge` (red pill) take `number | string`: numbers ≤0 render nothing, strings render as given (e.g. `\'1K\'` / `\'99+\'`).',
|
|
335
362
|
},
|
|
363
|
+
{
|
|
364
|
+
zh: '多选(`multiple`)时每段的最小宽度等于该档段高:最窄也是正方形,文案更长则自然撑成横向长方形,不会出现宽比高还小的竖条;`weekday` 与只有图标的固定方块也由这条下限兜住。',
|
|
365
|
+
en: 'In `multiple` mode every segment has a minimum width equal to its own segment height: the narrowest case is a square, longer labels grow it into a landscape rectangle, and no segment is ever taller than it is wide. Fixed-width squares (`weekday`, icon-only) are clamped by this floor too.',
|
|
366
|
+
},
|
|
336
367
|
],
|
|
337
368
|
api: [
|
|
338
369
|
{
|
|
@@ -340,6 +371,7 @@ const doc: DocTopic = {
|
|
|
340
371
|
rows: [
|
|
341
372
|
{ name: 'variant', type: "上表 18 档(primary/secondary/danger/success/warning/info/outline/danger-outline/ghost/link + 扩展 purple/pink/cyan/teal/orange/indigo/rose/slate)", def: "'outline'", desc: { zh: '外观档', en: 'Appearance tier' } },
|
|
342
373
|
{ name: 'size', type: "'sm' | 'md' | 'lg'", def: "'lg'", desc: { zh: '高度档(24 / 28 / 32,有边无边同高)', en: 'Height tier (24 / 28 / 32, same height with or without border)' } },
|
|
374
|
+
{ name: 'dense', type: 'boolean', def: 'false', desc: { zh: '紧凑图标档:高度不变,图标放大、内距收紧(Button / IconButton 同名同义)', en: 'Compact-icon tier: same height, larger icon and tighter padding (same prop on Button and IconButton)' } },
|
|
343
375
|
{ name: 'icon', type: 'ReactNode', def: '—', desc: { zh: '前置图标(官方图标组件 / 字符串均可)', en: 'Leading icon (official icon component or string)' } },
|
|
344
376
|
{ name: 'iconRight', type: 'ReactNode', def: '—', desc: { zh: '后置图标(展开箭头、外链)', en: 'Trailing icon (expand arrow, external link)' } },
|
|
345
377
|
{ name: 'color', type: 'string', def: '—', desc: { zh: '自定义主色:实心档作底色,线框 / 无底档作主色', en: 'Custom main color: background for solid tiers, main color for outline/bare' } },
|
|
@@ -606,6 +638,14 @@ const doc: DocTopic = {
|
|
|
606
638
|
zh: '头部整体垂直居中,`action` 里裸放一个元素即居中。颜色全走 token,明暗跟随宿主。',
|
|
607
639
|
en: 'The header centers vertically as a whole; drop a bare element into `action` and it centers. Colors come from tokens, so light/dark follows the host.',
|
|
608
640
|
},
|
|
641
|
+
{
|
|
642
|
+
zh: '`hoverable` 开启后悬停变色、同时把光标改成 `pointer`,统一吃 `--dshpc-card-hover`(亮 7% 蓝 / 暗 13% 蓝),默认关;`filled` 切底色,默认有底(Card = surface-1,StripCard = accent 浅底),`false` 时底透明但边框仍在。两根轴都只改 `--surface-bg`,插件不用再自己写 `:hover` 规则。',
|
|
643
|
+
en: '`hoverable` (default off) changes the fill on hover and switches the cursor to `pointer`, using `--dshpc-card-hover` (7% blue light / 13% blue dark). `filled` (default on) controls the background — Card uses surface-1, StripCard the accent tint; `false` makes it transparent but keeps the border. Both axes only rewrite `--surface-bg`, so plugins no longer need their own `:hover` rules.',
|
|
644
|
+
},
|
|
645
|
+
{
|
|
646
|
+
zh: '展开的卡片用 `hoverScope` 选作用域,默认 `\'head\'`:根节点零内距并统一裁圆角,`__body` 作为「上面那一整块」独立承担内距、边到边变色;展开态不改内距,上下两圈留白对称,两块之间的间隔也属于头部区、跟着一起变色;`__panel` 是它的兄弟节点,不铺背景、不参与 hover,鼠标在展开区里操作时整卡都不触发。StripCard 的通高色条相对根节点定位,展开后仍贯穿整卡(包括展开区)。想要整卡含展开区一起变色,才显式传 `\'card\'`。**展开内容必须放进 `panel`**(`children` 属于头部区),核心才有分区信号。',
|
|
647
|
+
en: 'For expandable cards, `hoverScope` selects the scope. The default `\'head\'` gives the root zero padding and clips the radius, while `__body` — the header block owning all padding — changes color edge to edge; expanding keeps its top and bottom padding symmetric, so the gap between the two blocks changes color too. `__panel` is a sibling with no background and never hovered, so operating inside the expanded area triggers nothing. The StripCard rail is positioned against the root and stays full-height across the expanded area. Pass `\'card\'` explicitly to include it. **Expandable content must go into `panel`**; `children` belongs to the header block.',
|
|
648
|
+
},
|
|
609
649
|
],
|
|
610
650
|
api: [
|
|
611
651
|
{
|
|
@@ -617,13 +657,49 @@ const doc: DocTopic = {
|
|
|
617
657
|
{ name: 'onToggle', type: '() => void', def: '—', desc: { zh: '传了才显示右侧折叠箭头;展开状态由调用方管', en: 'Only shows the right collapse arrow if provided; caller owns the expanded state' } },
|
|
618
658
|
{ name: 'action', type: 'ReactNode', def: '—', desc: { zh: '右上角操作区', en: 'Top-right action area' } },
|
|
619
659
|
{ name: 'children', type: 'ReactNode', def: '—', desc: { zh: '主内容,排版随你', en: 'Main content, layout is yours' } },
|
|
620
|
-
{ name: 'panel', type: 'ReactNode', def: '—', desc: { zh: '
|
|
660
|
+
{ name: 'panel', type: 'ReactNode', def: '—', desc: { zh: '展开后才显示的额外内容;必须放这里,核心才能把展开区与头部区分开', en: 'Extra content shown only when expanded; must live here so the core can separate it from the header' } },
|
|
661
|
+
{ name: 'hoverable', type: 'boolean', def: "'false'", desc: { zh: '悬停变色 + 光标变 pointer,统一 --dshpc-card-hover;默认关', en: 'Hover color plus a pointer cursor, using --dshpc-card-hover; default off' } },
|
|
662
|
+
{ name: 'hoverScope', type: "'head' | 'card'", def: "'head'", desc: { zh: "'head'(默认)只让上面头部区整块边到边变色、展开区不受影响;'card' 整卡含展开区一起变色。仅 hoverable 为 true 时生效", en: "'head' (default) changes only the header block and leaves the expanded area untouched; 'card' includes it. Applies only when hoverable is true" } },
|
|
663
|
+
{ name: 'filled', type: 'boolean', def: "'true'", desc: { zh: '是否带底色;false 时底透明、边框仍在。默认有底(Card = surface-1 / StripCard = accent 浅底)', en: 'Background fill; false makes it transparent while keeping the border. Default on (Card = surface-1 / StripCard = accent tint)' } },
|
|
621
664
|
{ name: 'className / style', type: '—', def: '—', desc: { zh: '追加类 / 样式', en: 'Append class / style' } },
|
|
622
665
|
],
|
|
623
666
|
},
|
|
624
667
|
],
|
|
625
668
|
code: [{ id: 'ui-card-example', lang: 'tsx', src: cardExample }],
|
|
626
669
|
},
|
|
670
|
+
{
|
|
671
|
+
id: 'list-row',
|
|
672
|
+
heading: { zh: 'ListRow(一行一条)', en: 'ListRow (one item per line)' },
|
|
673
|
+
prose: [
|
|
674
|
+
{
|
|
675
|
+
zh: '一行代表一个可选 / 可点的对象(文件、任务、候选项):常态就带底色,鼠标移上去按 Button 灰色档加深一档;选中换成 slate 的极浅蓝灰单色背景,不描边、不画竖条。左主内容、右侧一组小操作,点右侧不连带触发整行。两个槽都自带垂直居中,主内容包成 `inline-flex` 也不会按基线偏上;内部怎么横排仍由调用方定。底 / 边 / 圆角复用 Surface,颜色全走 token,插件不写第二套皮肤。',
|
|
676
|
+
en: 'One line per selectable / clickable object (file, task, candidate): a visible background at rest that darkens one step on hover using the same grey tokens as Button; selected rows swap to a single pale slate-blue-grey background — no border, no rail. Main content on the left, a group of small actions on the right that never trigger the row. Both slots are vertically centered by the core, so even an `inline-flex` main-content wrapper does not ride high on the baseline; its internal horizontal layout is still yours. Background / border / radius come from Surface and colors from tokens, so plugins write no second skin.',
|
|
677
|
+
},
|
|
678
|
+
{
|
|
679
|
+
zh: '默认中号(min-height 28,与 Button md 同档),不设 size 轴;四边内距 8px 等距;默认字号 13px / 行高 20px 由核心给(`--dshpc-font-md` / `--dshpc-line-md`,与 Table 同档),调用方不必自己设、可用内联 style 覆盖。`bordered` 切带边 / 不带边,无边档仍是 1px 透明占位,两档同高。`selected` 只改外观,状态由调用方管。',
|
|
680
|
+
en: 'One medium tier by default (min-height 28, same as Button md); no size axis; equal 8px padding on all four sides. The core sets a default 13px / 20px type scale (`--dshpc-font-md` / `--dshpc-line-md`, same as Table) — callers need not set it and can override it inline. `bordered` switches the edge on/off — the borderless tier keeps a transparent 1px placeholder so heights stay equal. `selected` only changes appearance; the caller owns the state.',
|
|
681
|
+
},
|
|
682
|
+
{
|
|
683
|
+
zh: '`hoverable` 默认跟随「整行可点」(可点行开、纯展示行关,与 Table 的 hover 口径一致),可显式开关;hover 取 `--dshpc-listrow-hover-bg`,只比常态深一点点(亮 9% 黑 / 暗 10% 白),不会把整行内容和文字对比度一起改掉;选中取 `--dshpc-listrow-selected-bg`(由 `--dshpc-slate` 派生,亮色 14% / 暗色 26% 两档,暗色不发黑)。整行不是 `<button>`:调用方要往里放 Button / IconButton,嵌 button 是非法 HTML;键盘走 Enter / Space,右侧操作槽挡住冒泡。',
|
|
684
|
+
en: '`hoverable` follows row clickability by default (on for clickable rows, off for static ones, matching Table), and can be forced on/off. Hover uses `--dshpc-listrow-hover-bg`, only a touch deeper than the resting row (9% black light / 10% white dark), so it does not repaint the whole row or shift text contrast; selected uses `--dshpc-listrow-selected-bg` (derived from `--dshpc-slate`, 14% light / 26% dark, so the dark theme never goes black). The row is not a `<button>`: callers put Buttons inside it and nested buttons are invalid HTML. Keyboard uses Enter / Space; the actions slot stops propagation.',
|
|
685
|
+
},
|
|
686
|
+
],
|
|
687
|
+
api: [
|
|
688
|
+
{
|
|
689
|
+
id: 'ui-list-row',
|
|
690
|
+
rows: [
|
|
691
|
+
{ name: 'children', type: 'ReactNode', def: '—', desc: { zh: '主内容:槽自带垂直居中,图标 / 名字 / 标签 / 左右分区自己排', en: 'Main content: the slot centers vertically on its own; icons, labels, tags and left/right layout are yours' } },
|
|
692
|
+
{ name: 'actions', type: 'ReactNode', def: '—', desc: { zh: '右侧操作槽;核心挡住事件冒泡,不连带整行', en: 'Right-side actions; the core stops propagation so the row is not triggered' } },
|
|
693
|
+
{ name: 'onClick', type: '() => void', def: '—', desc: { zh: '给了才让整行可点(role=button / tabIndex / Enter·Space)', en: 'Only makes the row clickable when provided (role=button / tabIndex / Enter·Space)' } },
|
|
694
|
+
{ name: 'selected', type: 'boolean', def: "'false'", desc: { zh: '选中态:slate 极浅蓝灰单色背景(明暗各一档),不描边 / 不画竖条,压在 hover 之上', en: 'Selected: a single pale slate-blue-grey background (separate light / dark tiers), no border or rail, above hover' } },
|
|
695
|
+
{ name: 'bordered', type: 'boolean', def: "'false'", desc: { zh: '带边 / 不带边,两档同高', en: 'Bordered / borderless; both tiers share the same height' } },
|
|
696
|
+
{ name: 'hoverable', type: 'boolean', def: '自动', desc: { zh: 'hover 灰态加深开关;默认跟随整行可点', en: 'Grey-state hover switch; defaults to row clickability' } },
|
|
697
|
+
{ name: 'className / style', type: '—', def: '—', desc: { zh: '追加类 / 样式,只允许补布局', en: 'Append class / style, layout patches only' } },
|
|
698
|
+
],
|
|
699
|
+
},
|
|
700
|
+
],
|
|
701
|
+
code: [{ id: 'ui-listrow-example', lang: 'tsx', src: listRowExample }],
|
|
702
|
+
},
|
|
627
703
|
{
|
|
628
704
|
id: 'chip',
|
|
629
705
|
heading: { zh: 'Chip', en: 'Chip' },
|
package/docs/help/ui.md
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
> EN: ui — base controls
|
|
6
6
|
|
|
7
|
-
导出:Button、IconButton、Segmented、SplitGroup、Input、PrefixedInput、NumberInput、Textarea、Checkbox、fieldMetricsOf、Picker、WorkspacePicker、ModelPicker、DateTimePicker、Surface、Card、StripCard、Chip、Table、Pagination、Modal、SideSheet、FieldHint、setTooltipRenderer、showToast、notify、showHostToast、Loader、LoaderBar、Loading、RunningBlocks、SectionHead、MarqueeText、FlipText、LiveText、QuickToolbar、startResizeLayoutWidth、PanelDock、createPanelDock、DockPanel、ensureControls、setStyleKit
|
|
7
|
+
导出:Button、IconButton、Segmented、SplitGroup、Input、PrefixedInput、NumberInput、Textarea、Checkbox、fieldMetricsOf、Picker、WorkspacePicker、ModelPicker、DateTimePicker、Surface、Card、StripCard、Chip、Table、ListRow、Pagination、Modal、SideSheet、FieldHint、setTooltipRenderer、showToast、notify、showHostToast、Loader、LoaderBar、Loading、RunningBlocks、SectionHead、MarqueeText、FlipText、LiveText、QuickToolbar、startResizeLayoutWidth、PanelDock、createPanelDock、DockPanel、ensureControls、setStyleKit
|
|
8
8
|
|
|
9
9
|
## 概览
|
|
10
10
|
|
|
@@ -43,6 +43,10 @@ IconButton:variant: plain|outline|danger(默认 plain,**无底色**)、s
|
|
|
43
43
|
|
|
44
44
|
> EN: IconButton: variant plain|outline|danger (default plain, **no background**), size (default lg), icon (required), label (required, doubles as a11y name and title), color (icon colour), background (fill; omitted = no fill).
|
|
45
45
|
|
|
46
|
+
`dense` 是两者共用的紧凑图标档:`size` / 高度一律不变,图标放大一档、内距收紧(Button 的 `--btn-pad` 从 10/12/14 收到 6,图标容器从 0.875em 到 1.25em;IconButton 把图标 `<svg>` 的 `width/height` 从 1em 提到 1.25em,正方形宽高不变、四周留白变小)。两者 dense 下图标都是 sm 15px / md·lg 16.25px。IconButton 的按钮显式 `padding:0`、图标 `flex:none`:svg 是 flex item,不禁止收缩会被内距压成窄条,此时改 `width` 或加 `!important` 都无效。给描边细、缩到 sm 看不清的图标用(如文件类型 / 语言图标);默认 false,原有按钮外观不变。
|
|
47
|
+
|
|
48
|
+
> EN: `dense` is a shared compact-icon tier for both: `size` and height stay put while the icon grows one step and padding tightens (Button: `--btn-pad` 10/12/14 → 6, icon container 0.875em → 1.25em; IconButton: the icon `<svg>` goes from `width/height:1em` to `1.25em`, same square box, less breathing room). Both give sm 15px / md·lg 16.25px icons. An IconButton sets `padding:0` on itself and `flex:none` on the icon: the svg is a flex item, and without disabling shrinking the padding squeezes it into a narrow strip — changing `width` or adding `!important` cannot fix that. Use it for thin-stroke icons that vanish at `sm` (file-type / language glyphs). Defaults to false, so existing buttons are unchanged.
|
|
49
|
+
|
|
46
50
|
两者的 loading 语义一致:`onClick` 返回 Promise 就转圈(纯图标钮把图标位换成小圈,`aria-label` 不变、补 `aria-busy`),`onBusyChange` 把「在跑」报出去;受控 `loading` 与它取或 —— 别处刷新也能点亮同一颗按钮。转圈期间按钮自己的图标位(`icon` / `iconRight`)全部让位,只留转圈 + 文字。
|
|
47
51
|
|
|
48
52
|
> EN: Both share one loading semantics: a Promise-returning `onClick` spins (an icon button swaps its icon for the spinner, keeps `aria-label` and adds `aria-busy`), `onBusyChange` reports "running", and the controlled `loading` prop is OR-ed in — an external refresh lights the same button too. While spinning, the button’s own icon slots (`icon` / `iconRight`) all step aside: spinner plus label only.
|
|
@@ -55,10 +59,15 @@ Segmented:`items`(必填)支持单选 / 多选,`size`(默认 lg;三
|
|
|
55
59
|
|
|
56
60
|
> EN: Segmented: `items` (required) supports single or multiple selection; `size` (default lg; totals 24 / 28 / 32), `bordered` (1px outer frame, same total height), `multiple` (multi-select). One look only: grey track + white selected pill; its stroke ring and shadow come from the host elevation token (the offline fallback has no ring). The selected pill’s colors go through `tone` only: a built-in color name (business / success / warning / danger / purple / pink / cyan / teal / orange / indigo / rose / slate, same names as Chip) lets the core pick background and text per theme; `{ bg, fg }` uses that pair verbatim in both themes (contrast is the caller’s call). An item’s leading `icon` takes any node (official icon component, array, or custom); `label` also accepts a node; order is always icon → label → count. With only an icon (no label / count / badge) the segment squares itself (width = segment height), and the accessible name comes from `ariaLabel`, falling back to `tooltip`. An item’s `count` (muted text; auto-lightened to follow the selected pill’s text color while selected) and `badge` (red pill) take `number | string`: numbers ≤0 render nothing, strings render as given (e.g. `'1K'` / `'99+'`).
|
|
57
61
|
|
|
62
|
+
多选(`multiple`)时每段的最小宽度等于该档段高:最窄也是正方形,文案更长则自然撑成横向长方形,不会出现宽比高还小的竖条;`weekday` 与只有图标的固定方块也由这条下限兜住。
|
|
63
|
+
|
|
64
|
+
> EN: In `multiple` mode every segment has a minimum width equal to its own segment height: the narrowest case is a square, longer labels grow it into a landscape rectangle, and no segment is ever taller than it is wide. Fixed-width squares (`weekday`, icon-only) are clamped by this floor too.
|
|
65
|
+
|
|
58
66
|
| 参数 | 类型 | 默认 | 说明(zh) | 说明(en) |
|
|
59
67
|
|---|---|---|---|---|
|
|
60
68
|
| `variant` | `上表 18 档(primary/secondary/danger/success/warning/info/outline/danger-outline/ghost/link + 扩展 purple/pink/cyan/teal/orange/indigo/rose/slate)` | 'outline' | 外观档 | Appearance tier |
|
|
61
69
|
| `size` | `'sm' \| 'md' \| 'lg'` | 'lg' | 高度档(24 / 28 / 32,有边无边同高) | Height tier (24 / 28 / 32, same height with or without border) |
|
|
70
|
+
| `dense` | `boolean` | false | 紧凑图标档:高度不变,图标放大、内距收紧(Button / IconButton 同名同义) | Compact-icon tier: same height, larger icon and tighter padding (same prop on Button and IconButton) |
|
|
62
71
|
| `icon` | `ReactNode` | — | 前置图标(官方图标组件 / 字符串均可) | Leading icon (official icon component or string) |
|
|
63
72
|
| `iconRight` | `ReactNode` | — | 后置图标(展开箭头、外链) | Trailing icon (expand arrow, external link) |
|
|
64
73
|
| `color` | `string` | — | 自定义主色:实心档作底色,线框 / 无底档作主色 | Custom main color: background for solid tiers, main color for outline/bare |
|
|
@@ -360,6 +369,14 @@ h(Surface, { tone: 'sunken', border: 'dashed', padding: 'lg' }, '还没做的东
|
|
|
360
369
|
|
|
361
370
|
> EN: The header centers vertically as a whole; drop a bare element into `action` and it centers. Colors come from tokens, so light/dark follows the host.
|
|
362
371
|
|
|
372
|
+
`hoverable` 开启后悬停变色、同时把光标改成 `pointer`,统一吃 `--dshpc-card-hover`(亮 7% 蓝 / 暗 13% 蓝),默认关;`filled` 切底色,默认有底(Card = surface-1,StripCard = accent 浅底),`false` 时底透明但边框仍在。两根轴都只改 `--surface-bg`,插件不用再自己写 `:hover` 规则。
|
|
373
|
+
|
|
374
|
+
> EN: `hoverable` (default off) changes the fill on hover and switches the cursor to `pointer`, using `--dshpc-card-hover` (7% blue light / 13% blue dark). `filled` (default on) controls the background — Card uses surface-1, StripCard the accent tint; `false` makes it transparent but keeps the border. Both axes only rewrite `--surface-bg`, so plugins no longer need their own `:hover` rules.
|
|
375
|
+
|
|
376
|
+
展开的卡片用 `hoverScope` 选作用域,默认 `'head'`:根节点零内距并统一裁圆角,`__body` 作为「上面那一整块」独立承担内距、边到边变色;展开态不改内距,上下两圈留白对称,两块之间的间隔也属于头部区、跟着一起变色;`__panel` 是它的兄弟节点,不铺背景、不参与 hover,鼠标在展开区里操作时整卡都不触发。StripCard 的通高色条相对根节点定位,展开后仍贯穿整卡(包括展开区)。想要整卡含展开区一起变色,才显式传 `'card'`。**展开内容必须放进 `panel`**(`children` 属于头部区),核心才有分区信号。
|
|
377
|
+
|
|
378
|
+
> EN: For expandable cards, `hoverScope` selects the scope. The default `'head'` gives the root zero padding and clips the radius, while `__body` — the header block owning all padding — changes color edge to edge; expanding keeps its top and bottom padding symmetric, so the gap between the two blocks changes color too. `__panel` is a sibling with no background and never hovered, so operating inside the expanded area triggers nothing. The StripCard rail is positioned against the root and stays full-height across the expanded area. Pass `'card'` explicitly to include it. **Expandable content must go into `panel`**; `children` belongs to the header block.
|
|
379
|
+
|
|
363
380
|
| 参数 | 类型 | 默认 | 说明(zh) | 说明(en) |
|
|
364
381
|
|---|---|---|---|---|
|
|
365
382
|
| `accent` | `13 档 or 任意 CSS 色值(business/success/warning/danger/neutral + 扩展 purple/pink/cyan/teal/orange/indigo/rose/slate)` | 'business' | 档位映射到 design 的 token;也可传 '#f59e0b' 这类自定义值 | Tiers map to design tokens; also accepts custom values like '#f59e0b' |
|
|
@@ -368,7 +385,10 @@ h(Surface, { tone: 'sunken', border: 'dashed', padding: 'lg' }, '还没做的东
|
|
|
368
385
|
| `onToggle` | `() => void` | — | 传了才显示右侧折叠箭头;展开状态由调用方管 | Only shows the right collapse arrow if provided; caller owns the expanded state |
|
|
369
386
|
| `action` | `ReactNode` | — | 右上角操作区 | Top-right action area |
|
|
370
387
|
| `children` | `ReactNode` | — | 主内容,排版随你 | Main content, layout is yours |
|
|
371
|
-
| `panel` | `ReactNode` | — |
|
|
388
|
+
| `panel` | `ReactNode` | — | 展开后才显示的额外内容;必须放这里,核心才能把展开区与头部区分开 | Extra content shown only when expanded; must live here so the core can separate it from the header |
|
|
389
|
+
| `hoverable` | `boolean` | 'false' | 悬停变色 + 光标变 pointer,统一 --dshpc-card-hover;默认关 | Hover color plus a pointer cursor, using --dshpc-card-hover; default off |
|
|
390
|
+
| `hoverScope` | `'head' \| 'card'` | 'head' | 'head'(默认)只让上面头部区整块边到边变色、展开区不受影响;'card' 整卡含展开区一起变色。仅 hoverable 为 true 时生效 | 'head' (default) changes only the header block and leaves the expanded area untouched; 'card' includes it. Applies only when hoverable is true |
|
|
391
|
+
| `filled` | `boolean` | 'true' | 是否带底色;false 时底透明、边框仍在。默认有底(Card = surface-1 / StripCard = accent 浅底) | Background fill; false makes it transparent while keeping the border. Default on (Card = surface-1 / StripCard = accent tint) |
|
|
372
392
|
| `className / style` | `—` | — | 追加类 / 样式 | Append class / style |
|
|
373
393
|
|
|
374
394
|
```tsx id="ui-card-example"
|
|
@@ -377,6 +397,7 @@ import { Card, Chip, StripCard } from 'dsh-plugin-core/ui'
|
|
|
377
397
|
h(Card, {
|
|
378
398
|
accent: 'warning',
|
|
379
399
|
bar: { side: 'left', inset: 12, gap: 12 }, // 色条可放 left / right / top / bottom
|
|
400
|
+
hoverable: true, // 头部区整块悬停变色(默认关)
|
|
380
401
|
action: h(Button, { size: 'sm', variant: 'ghost' }, '跳过'),
|
|
381
402
|
},
|
|
382
403
|
h('div', null, '标题'),
|
|
@@ -385,11 +406,61 @@ h(Card, {
|
|
|
385
406
|
|
|
386
407
|
h(StripCard, {
|
|
387
408
|
accent: 'success',
|
|
409
|
+
hoverable: true, filled: false, // 底色关掉 = 透明(默认有底)
|
|
410
|
+
// hoverScope 默认 'head':只有上面头部区变色,展开区完全不受影响
|
|
411
|
+
// 要连展开区一起变色才显式写 hoverScope: 'card'
|
|
388
412
|
expanded: open, onToggle: () => setOpen(!open),
|
|
389
|
-
panel: h('div', null, '展开详情'),
|
|
413
|
+
panel: h('div', null, '展开详情'), // 展开内容放 panel,别塞进 children
|
|
390
414
|
}, h('div', null, '标题 + 元信息'))
|
|
391
415
|
```
|
|
392
416
|
|
|
417
|
+
## ListRow(一行一条)
|
|
418
|
+
|
|
419
|
+
> EN: ListRow (one item per line)
|
|
420
|
+
|
|
421
|
+
一行代表一个可选 / 可点的对象(文件、任务、候选项):常态就带底色,鼠标移上去按 Button 灰色档加深一档;选中换成 slate 的极浅蓝灰单色背景,不描边、不画竖条。左主内容、右侧一组小操作,点右侧不连带触发整行。两个槽都自带垂直居中,主内容包成 `inline-flex` 也不会按基线偏上;内部怎么横排仍由调用方定。底 / 边 / 圆角复用 Surface,颜色全走 token,插件不写第二套皮肤。
|
|
422
|
+
|
|
423
|
+
> EN: One line per selectable / clickable object (file, task, candidate): a visible background at rest that darkens one step on hover using the same grey tokens as Button; selected rows swap to a single pale slate-blue-grey background — no border, no rail. Main content on the left, a group of small actions on the right that never trigger the row. Both slots are vertically centered by the core, so even an `inline-flex` main-content wrapper does not ride high on the baseline; its internal horizontal layout is still yours. Background / border / radius come from Surface and colors from tokens, so plugins write no second skin.
|
|
424
|
+
|
|
425
|
+
默认中号(min-height 28,与 Button md 同档),不设 size 轴;四边内距 8px 等距;默认字号 13px / 行高 20px 由核心给(`--dshpc-font-md` / `--dshpc-line-md`,与 Table 同档),调用方不必自己设、可用内联 style 覆盖。`bordered` 切带边 / 不带边,无边档仍是 1px 透明占位,两档同高。`selected` 只改外观,状态由调用方管。
|
|
426
|
+
|
|
427
|
+
> EN: One medium tier by default (min-height 28, same as Button md); no size axis; equal 8px padding on all four sides. The core sets a default 13px / 20px type scale (`--dshpc-font-md` / `--dshpc-line-md`, same as Table) — callers need not set it and can override it inline. `bordered` switches the edge on/off — the borderless tier keeps a transparent 1px placeholder so heights stay equal. `selected` only changes appearance; the caller owns the state.
|
|
428
|
+
|
|
429
|
+
`hoverable` 默认跟随「整行可点」(可点行开、纯展示行关,与 Table 的 hover 口径一致),可显式开关;hover 取 `--dshpc-listrow-hover-bg`,只比常态深一点点(亮 9% 黑 / 暗 10% 白),不会把整行内容和文字对比度一起改掉;选中取 `--dshpc-listrow-selected-bg`(由 `--dshpc-slate` 派生,亮色 14% / 暗色 26% 两档,暗色不发黑)。整行不是 `<button>`:调用方要往里放 Button / IconButton,嵌 button 是非法 HTML;键盘走 Enter / Space,右侧操作槽挡住冒泡。
|
|
430
|
+
|
|
431
|
+
> EN: `hoverable` follows row clickability by default (on for clickable rows, off for static ones, matching Table), and can be forced on/off. Hover uses `--dshpc-listrow-hover-bg`, only a touch deeper than the resting row (9% black light / 10% white dark), so it does not repaint the whole row or shift text contrast; selected uses `--dshpc-listrow-selected-bg` (derived from `--dshpc-slate`, 14% light / 26% dark, so the dark theme never goes black). The row is not a `<button>`: callers put Buttons inside it and nested buttons are invalid HTML. Keyboard uses Enter / Space; the actions slot stops propagation.
|
|
432
|
+
|
|
433
|
+
| 参数 | 类型 | 默认 | 说明(zh) | 说明(en) |
|
|
434
|
+
|---|---|---|---|---|
|
|
435
|
+
| `children` | `ReactNode` | — | 主内容:槽自带垂直居中,图标 / 名字 / 标签 / 左右分区自己排 | Main content: the slot centers vertically on its own; icons, labels, tags and left/right layout are yours |
|
|
436
|
+
| `actions` | `ReactNode` | — | 右侧操作槽;核心挡住事件冒泡,不连带整行 | Right-side actions; the core stops propagation so the row is not triggered |
|
|
437
|
+
| `onClick` | `() => void` | — | 给了才让整行可点(role=button / tabIndex / Enter·Space) | Only makes the row clickable when provided (role=button / tabIndex / Enter·Space) |
|
|
438
|
+
| `selected` | `boolean` | 'false' | 选中态:slate 极浅蓝灰单色背景(明暗各一档),不描边 / 不画竖条,压在 hover 之上 | Selected: a single pale slate-blue-grey background (separate light / dark tiers), no border or rail, above hover |
|
|
439
|
+
| `bordered` | `boolean` | 'false' | 带边 / 不带边,两档同高 | Bordered / borderless; both tiers share the same height |
|
|
440
|
+
| `hoverable` | `boolean` | 自动 | hover 灰态加深开关;默认跟随整行可点 | Grey-state hover switch; defaults to row clickability |
|
|
441
|
+
| `className / style` | `—` | — | 追加类 / 样式,只允许补布局 | Append class / style, layout patches only |
|
|
442
|
+
|
|
443
|
+
```tsx id="ui-listrow-example"
|
|
444
|
+
import { ListRow, Button, Chip } from 'dsh-plugin-core/ui'
|
|
445
|
+
|
|
446
|
+
// 一行一条:常态带底,点整行打开 / 选中,右侧小操作不连带触发整行
|
|
447
|
+
h(ListRow, {
|
|
448
|
+
onClick: () => openFile(entry),
|
|
449
|
+
selected: entry.path === currentPath,
|
|
450
|
+
actions: h(Button, {
|
|
451
|
+
size: 'sm', variant: 'ghost', onClick: () => removeEntry(entry),
|
|
452
|
+
}, '移除'),
|
|
453
|
+
},
|
|
454
|
+
h('div', { style: { display: 'flex', alignItems: 'center', gap: 8 } },
|
|
455
|
+
h(Chip, null, 'TS'),
|
|
456
|
+
h('span', null, entry.name),
|
|
457
|
+
),
|
|
458
|
+
)
|
|
459
|
+
|
|
460
|
+
// 带边 / 关掉 hover / 纯展示(不可点)
|
|
461
|
+
h(ListRow, { bordered: true, hoverable: false }, '只读的一行')
|
|
462
|
+
```
|
|
463
|
+
|
|
393
464
|
## Chip
|
|
394
465
|
|
|
395
466
|
> EN: Chip
|
package/package.json
CHANGED