跳转到内容

PromptInput 提示输入框 alpha

会话界面的输入框:值、输入法、能否提交,以及发送与停止共用的按钮。

用法

Enter 提交、Shift+Enter 换行;输入法组合中的 Enter 一律放行,该按键是在确认候选词

组件结构

加粗的是必需部件。

data-scope="prompt-input"root · control · input · submit-trigger

示例

与消息流组成一个对话

发送键原位变为停止;提交后粘底跟随到最新一条,生成期间仍可继续编辑下一句

助手
问点什么试试。

竖排布局与兜底字形

写一层输入行,root 即切换为竖排:输入行在上、动作行在下;按钮留空时皮肤按身份绘制箭头或停止方块

0 字

三档提交按键

enter 档回车即发送、mod-enter 档只有 Ctrl/Cmd+Enter 发送、none 档两种按法都换行,提交只剩发送按钮

(还没发过)

禁用与空值

disabled 覆盖整框并使用原生 disabled;输入为空或只有空白时发送按钮转灰,但位置保留不收起

框内的附加节点

root 中除三件部件外还可放置自己的按钮与计数;值的读写归宿主,原生属性照常直接落到输入框上

15 / 40
(还没发过)

随内容增高

输入框的高度跟随内容,rows 决定起始行数;不手动拖拽,也不写死高度

聚焦与选中

输入部件就是一个原生 textarea,取得它的节点即可聚焦、全选、失焦;发送后把焦点送回,继续输入下一条

(还没发过)

发送失败的错误态

判定是否出错由宿主决定:属性直接落到真实元素上,整框换色依靠覆盖公开变量,原因由活区播报

(还没发过)

颜色

tone 切换聚焦描边与发送按钮使用哪族颜色,输入与提交链路不受影响

设计指引

何时使用

  • AI 对话、聊天或任何输入一段话后提交的界面。
  • 生成期间需要一键停止。

何时不用

  • 只是表单中的多行文本域时,使用文本字段表单字段
  • 需要 @提及或斜杠命令时,整体使用提及作为输入器,见下方的组合。

特性

  • 发送与停止原位共用一个节点:正在按它的用户不会按空。生成期间按钮始终可用,此时它的语义是停止。
  • submitKey 一个 prop 表达三档:enter 档 Enter 提交、Shift+Enter 换行、Mod+Enter 也提交;mod-enter 档 Enter 换行,只有 Mod+Enter 提交;none 档两种按法都换行,不保留任何键盘提交出口,只剩发送按钮与程序化的 submit()
  • 输入法组合期间的 Enter 一律放行,该按键用于确认候选词。
  • 同一个输入框上叠加了其他处理器且它已处理该按键时,组件让位。
  • 自动长高是两行 CSS,不进入状态机;引擎不支持时退化为 rows 决定的固定行数。
  • 两种排布同一份皮肤:直接把输入框与按钮放进 root 是单行;套一层输入行后 root 变为竖排,输入行上下两侧可以再放附件条与动作行。
  • 默认形态是 outline:不填底、--xh-border-control 描边、无影,不画顶光与背景模糊;输入段透明,底由外框承担。发送按钮与 Button 缺省同为品牌实心,生成中降为中性淡底的停止身份。
  • 发送按钮留空时皮肤绘制兜底字形:发送身份为上箭头,停止身份为圆角方块;放入自定义图标或文案即覆盖。

组合

  • 附件使用文件上传:它已覆盖 accept、大小校验、拖拽投放与逐条删除;有附件而正文为空时把 allowEmptySubmit 置真。附件条放在输入行上方,动作行放在下方,两者都是 root 的直接子节点,与输入行并列。
  • 粘贴上传由作者在输入框上自行挂 onPaste,处理器会与组件的处理器链式组合。
  • 模型选择器使用选择器组合框,工具开关使用切换按钮组,它们连同自己的容器一起放进输入行下方。
  • 消息流组合即是最小对话界面。

最佳实践

  • 受控用法下提交后由宿主清空;clearOnSubmit 关闭时组件不改动值。
  • 生成期间把 loading 置真而不是禁用整个输入框,用户仍需要编辑下一句。
  • 需要胶囊形状时不必更换形态轴:在任意祖先上写 --xh-prompt-input-radius: var(--xh-shape-pill),按钮另有 --xh-prompt-input-submit-radius。形态轴只决定底与描边的画法。

反模式

  • 另起一个停止按钮放在旁边:两个按钮的位置会互相挤压,按下的瞬间位置也会变化。
  • disabled 表达正在生成:会连输入一起挡住,也关闭了停止的出口。

API 参考

产物

自定义元素<xh-prompt-input>
Vue 组件XhPromptInputControl XhPromptInputInput XhPromptInputRoot XhPromptInputSubmitTrigger
组合式函数usePromptInput
状态机promptInputMachine
皮肤@xihan-ui/styles/prompt-input.css

Props

属性类型必填说明
valuestring
defaultValuestring
disabledboolean
loadingboolean正在生成:按钮换为停止身份,所有提交路径被拦截。 使用一个布尔而不是四档运行态字符串:组件只需要二值判断, 本轮进行到哪一步是宿主的事,透传为 data 属性属于作者的容器。
submitKeyPromptInputSubmitKey按哪一档提交,默认 enter。
allowEmptySubmitboolean允许空值提交,默认 false;有附件时由作者置真。这是唯一为附件保留的钩子。
clearOnSubmitboolean提交后清空,默认 true。
variantControlVariant形态:outline / subtle / ghost,决定底色与描边的绘制方式。默认 outline。
toneTone
sizeSize
translationsPartial<PromptInputTranslations>
onValueChange(details: PromptInputValueChangeDetails) => void
onSubmit(details: PromptInputSubmitDetails) => void
onStop() => void

事件

自定义元素将载荷放在 detail;Vue 使用同名 emit。

事件载荷说明
value-changePromptInputValueChangeDetails值变化;detail 为 { value: string }
submitPromptInputSubmitDetails提交;detail 为 { value: string },清空发生在派发之后。 与原生表单提交同名,故不冒泡,请直接在 &lt;xh-prompt-input&gt; 元素上监听
stop``生成期间按下停止;无 detail

插槽

仅列出带载荷的插槽。

Vue 组件插槽载荷说明
XhPromptInputRootdefaultPromptInputRootSlotProps

状态

公开状态写入 data-state

部件取值
input'empty' | 'editing' | 'disabled'

以下名称仅用于内部状态机。

状态empty · editing · disabled

事件VALUE.SET · COMPOSITION.START · COMPOSITION.END · KEY.SUBMIT · SUBMIT · STOP · CONTROLLED.DISABLE · CONTROLLED.ENABLE · CONTROLLED.VALUE.EMPTY · PRESS.START · PRESS.END · CONTROLLED.VALUE.FILLED

判据canSubmit · isLoading · isValueEmpty · isNextValueEmpty · canPress

connect API

getXxxProps() 返回对应部件的宿主属性。

成员类型说明
valuestring
isComposingboolean
canSubmitboolean是否可以提交。比状态机守卫多一条非禁用,供按钮置灰使用。
loadingboolean
disabledboolean
setValue(next: string) => void
submit() => void
stop() => void
getRootProps() => T['element']
getControlProps() => T['element']可选的输入行容器:渲染它后,输入框与按钮并排收在这一行中,root 改为纵向排列。
getInputProps() => T['textarea']
getSubmitTriggerProps() => T['button']

无障碍

键盘

规格出处:W3C APG

按键生效条件行为
Enter焦点在输入框、submitKey 为 enter、非组合态、可提交,且这一下还没被别的处理器处理过提交,并按 clearOnSubmit 决定清不清空
Shift+Enter焦点在输入框不归组件管:原样放行,浏览器插入换行
Control+Enter / Meta+Enter焦点在输入框、submitKey 为 enter 或 mod-enter、非组合态、可提交提交,并按 clearOnSubmit 决定清不清空
Enter / Control+Enter / Meta+Enter焦点在输入框、submitKey 为 none都不提交也不拦截:原样放行,浏览器插入换行;提交只剩按钮与程序化两条路
Enter输入法组合中不提交也不拦截:这一下是在确认候选词
Enter同一个输入框上叠了别的处理器且它已经处理过这一下让位,本组件什么都不做
Enter / Space焦点在发送按钮上按当前身份触发提交或停止(原生按钮激活)
Enter / Spaceheld on submit-trigger, not disabled(发送身份要可提交,停止身份恒可用)按住期间按钮投影 data-pressed,与指针 :active 同一副按压面;抬起或失焦撤下,身份随 loading 切换或提交后清空使按钮转禁用时一并撤下
Escape任何时候不接管:留给叠在输入框上的浮层与页面

ARIA

以下属性由 connect 生成。

部件属性
inputaria-labeltranslations?.input
submit-triggeraria-labeltranslations?.stop | translations?.send
  • 输入框的可访问名称只在提供 translations.input 时才发出:无条件发出会覆盖作者自己的 <label for>aria-label
  • 按钮的可访问名称随身份切换,读屏读到的与屏幕上看到的一致。
  • 焦点由整框的 :focus-within 环表达;高对比、减少透明度、强制色与打印时外壳保持实体描边面。

样式参考

皮肤

@xihan-ui/styles/prompt-input.css 使用 [data-scope="prompt-input"][data-part="root"] 部件选择器,位于 xihan.components 层。覆盖样式使用 xihan.overrides

数据属性

connect 生成;条件不成立时不输出无值属性。

部件属性
rootdata-disabled''(条件成立时才出现)
rootdata-loading''(条件成立时才出现)
rootdata-sizeprops.size
rootdata-toneprops.tone
rootdata-variantprops.variant
rootdata-xh-field-chrome''
rootdata-xh-field-sizeprops.size
inputdata-state'empty' | 'editing' | 'disabled'
inputdata-xh-field-input''
submit-triggerdata-disabled''(条件成立时才出现)
submit-triggerdata-mode'stop' | 'send'
submit-triggerdata-pressed''(条件成立时才出现)
submit-triggerdata-xh-action-control''
submit-triggerdata-xh-action-display'always'
submit-triggerdata-xh-action-profile'text'
submit-triggerdata-xh-action-sizeprops.size
submit-triggerdata-xh-action-variant'subtle' | 'solid'

CSS 变量

本组件公开覆盖槽由独立皮肤的实际消费位生成;默认来源、作用部件和状态均与 CSS 同源。

变量部件CSS 属性状态默认来源说明
--xh-prompt-input-bgrootbackground-colorxh-field-chrome--xh-_field-variant-bg-restprompt-input 的 root 部件 background-color 覆盖槽。
--xh-prompt-input-bg-disabledrootbackground-colordisabled
xh-field-chrome
--xh-_field-variant-bg-disabledprompt-input 的 root 部件 background-color 覆盖槽。
--xh-prompt-input-bg-hoverrootbackground-colordisabled
hover
invalid
loading
not([data-disabled])
not([data-invalid])
not([data-loading])
not([data-readonly])
readonly
xh-field-chrome
--xh-_field-variant-bg-hoverprompt-input 的 root 部件 background-color 覆盖槽。
--xh-prompt-input-borderrootborderxh-field-chrome--xh-_field-variant-border-restprompt-input 的 root 部件 border 覆盖槽。
--xh-prompt-input-border-focusrootborder-colordisabled
focus-within
not([data-disabled])
xh-field-chrome
--xh-_field-variant-border-focusprompt-input 的 root 部件 border-color 覆盖槽。
--xh-prompt-input-border-hoverrootborder-colordisabled
hover
invalid
loading
not([data-disabled])
not([data-invalid])
not([data-loading])
not([data-readonly])
readonly
xh-field-chrome
--xh-_field-variant-border-hoverprompt-input 的 root 部件 border-color 覆盖槽。
--xh-prompt-input-gaprootgapxh-field-chrome--xh-_prompt-input-gapprompt-input 的 root 部件 gap 覆盖槽。
--xh-prompt-input-icon-sizeroot--xh-icon-sizedefault
size=lg
size=md
size=sm
xh-field-chrome
--xh-_field-size-glyph-size
--xh-glyph-size-lg
--xh-glyph-size-md
--xh-glyph-size-sm
prompt-input 的 root 部件 --xh-icon-size 覆盖槽。
--xh-prompt-input-input-autofill-bginputbox-shadow-webkit-autofill
autofill
xh-field-input
--xh-bg-canvasprompt-input 的 input 部件 box-shadow 覆盖槽。
--xh-prompt-input-input-autofill-fginput-webkit-text-fill-color-webkit-autofill
autofill
xh-field-input
--xh-fg-defaultprompt-input 的 input 部件 -webkit-text-fill-color 覆盖槽。
--xh-prompt-input-input-fginputcolorxh-field-input--xh-fg-defaultprompt-input 的 input 部件 color 覆盖槽。
--xh-prompt-input-input-font-sizeinputfont-size
padding-block
default
xh-field-input
--xh-_prompt-input-font-sizeprompt-input 的 input 部件 font-size、padding-block 覆盖槽。
--xh-prompt-input-input-radiusinputborder-radiusdefault--xh-shape-insetprompt-input 的 input 部件 border-radius 覆盖槽。
--xh-prompt-input-max-hinputmax-block-sizedefault--xh-leading-normalprompt-input 的 input 部件 max-block-size 覆盖槽。
--xh-prompt-input-proot--xh-prompt-input-computed-px
padding
padding-inline
default
xh-field-chrome
--xh-_prompt-input-pxprompt-input 的 root 部件 --xh-prompt-input-computed-px、padding、padding-inline 覆盖槽。
--xh-prompt-input-placeholder-fginputcolorplaceholder
xh-field-input
--xh-fg-subtleprompt-input 的 input 部件 color 覆盖槽。
--xh-prompt-input-radiusrootborder-radiusxh-field-chrome--xh-shape-surfaceprompt-input 的 root 部件 border-radius 覆盖槽。
--xh-prompt-input-row-gapcontrolgapdefault--xh-_prompt-input-gapprompt-input 的 control 部件 gap 覆盖槽。
--xh-prompt-input-send-bgsubmit-triggerbackground-colordefault--xh-_action-variant-bg-restprompt-input 的 submit-trigger 部件 background-color 覆盖槽。
--xh-prompt-input-send-bg-activesubmit-triggerbackground-colordisabled
is(:active, [data-pressed])
loading
not([data-disabled])
not([data-loading])
pressed
--xh-_action-variant-bg-pressedprompt-input 的 submit-trigger 部件 background-color 覆盖槽。
--xh-prompt-input-send-bg-hoversubmit-triggerbackground-colordisabled
hover
loading
not([data-disabled])
not([data-loading])
--xh-_action-variant-bg-hoverprompt-input 的 submit-trigger 部件 background-color 覆盖槽。
--xh-prompt-input-send-bg-offsubmit-triggerbackground-colordisabled--xh-bg-mutedprompt-input 的 submit-trigger 部件 background-color 覆盖槽。
--xh-prompt-input-send-fgsubmit-triggercolordefault
disabled
hover
is(:active, [data-pressed])
loading
not([data-disabled])
not([data-loading])
pressed
--xh-_action-variant-fg-hover
--xh-_action-variant-fg-pressed
--xh-_action-variant-fg-rest
prompt-input 的 submit-trigger 部件 color 覆盖槽。
--xh-prompt-input-shadowrootbox-shadowxh-field-chromenoneprompt-input 的 root 部件 box-shadow 覆盖槽。
--xh-prompt-input-stop-bgsubmit-triggerbackground-colormode=stop--xh-_action-variant-bg-restprompt-input 的 submit-trigger 部件 background-color 覆盖槽。
--xh-prompt-input-stop-bg-activesubmit-triggerbackground-colordisabled
is(:active, [data-pressed])
loading
mode=stop
not([data-disabled])
not([data-loading])
pressed
--xh-_action-variant-bg-pressedprompt-input 的 submit-trigger 部件 background-color 覆盖槽。
--xh-prompt-input-stop-bg-hoversubmit-triggerbackground-colordisabled
hover
loading
mode=stop
not([data-disabled])
not([data-loading])
--xh-_action-variant-bg-hoverprompt-input 的 submit-trigger 部件 background-color 覆盖槽。
--xh-prompt-input-stop-fgsubmit-triggercolordisabled
hover
is(:active, [data-pressed])
loading
mode=stop
not([data-disabled])
not([data-loading])
pressed
--xh-_action-variant-fg-hover
--xh-_action-variant-fg-pressed
--xh-_action-variant-fg-rest
prompt-input 的 submit-trigger 部件 color 覆盖槽。
--xh-prompt-input-stop-mark-radiussubmit-triggerborder-radiusempty
mode=stop
--xh-shape-insetprompt-input 的 submit-trigger 部件 border-radius 覆盖槽。
--xh-prompt-input-stop-mark-sizesubmit-triggerblock-size
inline-size
empty
mode=stop
--xh-icon-sizeprompt-input 的 submit-trigger 部件 block-size、inline-size 覆盖槽。
--xh-prompt-input-submit-font-sizesubmit-triggerfont-sizedefault--xh-text-label-sizeprompt-input 的 submit-trigger 部件 font-size 覆盖槽。
--xh-prompt-input-submit-font-weightsubmit-triggerfont-weightdefault--xh-text-label-weightprompt-input 的 submit-trigger 部件 font-weight 覆盖槽。
--xh-prompt-input-submit-pxsubmit-triggerpadding-inlinedefault--xh-_prompt-input-submit-pxprompt-input 的 submit-trigger 部件 padding-inline 覆盖槽。
--xh-prompt-input-submit-radiussubmit-triggerborder-radiusdefault--xh-shape-controlprompt-input 的 submit-trigger 部件 border-radius 覆盖槽。
--xh-prompt-input-submit-shadowsubmit-triggerbox-shadowdefault
disabled
hover
is(:active, [data-pressed])
loading
not([data-disabled])
not([data-loading])
pressed
--xh-_highlight-toneprompt-input 的 submit-trigger 部件 box-shadow 覆盖槽。

动效

border-radiustransition 过渡。时长与缓动读动效令牌,改令牌即改全局节奏。

系统开启减弱动效时由令牌层统一收敛,皮肤不另作判断。

RTL

皮肤用逻辑属性排布(inline-start 一族),dir="rtl" 下自动镜像。

Released under The MIT License