Barista: 研究:Combobox / Select as webcomponents

创建于 2020-07-28  ·  11评论  ·  资料来源: dynatrace-oss/barista

功能要求

概括

我们需要研究如何将选择/组合框的 API 想象成 Web 组件世界中的样子。

功能描述

选择框或组合框可能是同一个组件,但也许我们想将它们分开。 这还没有定论。

将不同的组件库/设计系统方法与组合框/选择组件进行比较,并提出可行的 API 建议。

一些潜在资源:

请记住,选项的虚拟化将是必须的。 这是我们应该在 Web 组件层上处理的事情,还是我们的消费者在潜在的框架层上处理的事情。
使用虚拟滚动选项在 Angular 设置中使用上述 Web 组件之一进行测试和研究。
尝试在 Web 组件中使用 React 和虚拟化。

如果我们决定自己处理这个问题 - 构建一个模板机制,为创建的选项设置上下文是我们需要做的事情。

有关如何实现此类目标的一些资源可能是microsoft-graph-toolkit

这个问题的结果应该是我们的选择和优缺点的概述,以便我们就如何继续前进做出明智的决定。

Basic select mock

feature has-pr next

最有用的评论

要求

  • 虚拟滚动:实际上应该只呈现部分选项以避免性能问题
  • 自定义模板:用户必须能够提供用于呈现选项的模板
  • 过滤:用户必须能够输入输入来过滤项目列表; 过滤应该使用用户提供的过滤功能进行
  • 滚动指示器:是否有更多选项必须始终显而易见 --> 只要有更多选项,最初最后一个可见选项的一半(或最大 x 像素)应该是可见的,以清楚地表明容器是可滚动的.

后续步骤要求

  • 加载状态:只要没有可用的项目,就应该在叠加层中显示加载微调器ToDo加载微调器应该显示在哪里?
  • 多选:用户应该能够选择多个选项
  • 选项组:应该可以对选项进行分组

无障碍

聚焦时,组合框应在点击EnterArrowUpArrowDown键或用户开始在输入字段中输入过滤器时打开。

打开时,用户应该能够使用ArrowUp / ArrowDown键从现有选项中进行选择。 输入过滤器的焦点应保留在输入字段中,选项不应为选项卡式。 应使用aria-selected属性指示选项的选择状态。

应使用Enter键提交选择。

TabEscape键应该会关闭覆盖层,并且不应更改所选项目。

键入过滤器然后跳出输入字段时,应重置过滤器并显示先前选择的项目。

自定义模板语法

用户必须提供模板部件的开始和结束字符串。 这应该可以在全局或每个组件级别上实现(尚未决定)。

默认为{{}}

API 提案

_WIP_

ComboBox 应该分为主要的FluidComboBox组件、 FluidComboBoxOptionsList组件和FluidComboBoxOption组件。

流体组合框

包含一个FluidComboBoxOptionsList ,它又包含FluidComboBoxOption s。
处理覆盖和覆盖定位的打开和关闭。
接受一个模板作为接受基HTMLElement的子元素。

提供模板时,必须设置用于模板绑定的开始和结束字符串。

输入

| 姓名 | 计划用于 | 类型 | 默认 | 说明 |
| -------------- | ----------- | -------- | ------- | -------------------------------------------------- ------------------------------ |
| 选项| MVP | 数组 | [] | 在FluidComboBoxOptionsList显示的选项数组 |
| 过滤器Fn | MVP | (option: T) => boolean | null | 用于过滤选项的函数 |
| renderOptionFn | MVP | (option: T) => string | null | 用于自动完成面板中的渲染选项的函数 |
| 占位符| MVP | 字符串 | '' | 未选择任何选项时在输入字段中显示的占位符 |
| 禁用 | MVP | 布尔值 | 假| Boolean 判断组合框是否被禁用 |
| 加载 | MVP | 布尔值 | 假| 布尔判断是否显示加载指示器|
| 选择 | MVP | 任何 | 空| 要预选的项目 |
| 多选 | v2 | 布尔值 | 假| 布尔判断是否可以同时选择多个选项|

输出

| 姓名 | 计划用于 | 类型 | 说明 |
| ---------------- | ----------- | --------------------------------- | -------------------------------------------------- ---- |
| 改变 | MVP | FluidComboBoxChangeEvent | 值更改时触发的事件 |
| 过滤器变化| MVP | FluidComboBoxFilterChangeEvent | 当用户输入过滤值时触发的事件 |
| 选择-改变| MVP | FluidComboBoxSelectionChangeEvent | 所选选项更改时触发的事件 |

流体加载旋转器

作为 FluidComboBox 的先决条件,我们需要先实现一个可重用的加载微调组件。
ToDo向 UX 询问新加载微调器的 L&F(或者是否可以重新使用旧设计)。

流体虚拟滚动器

作为 FluidComboBox 的先决条件,我们需要实现一个可复用的组件,实现虚拟滚动
为了能够使用带有大量项目的组合框。

也可以看看:
https://github.com/WICG/virtual-scroller/blob/master/README.md
https://www.sitepen.com/blog/next-generation-virtual-scrolling/
https://dev.to/adamklein/build-your-own-virtual-scroll-part-i-11ib
https://blog.logrocket.com/virtual-scrolling-core-principles-and-basic-implementation-in-react/

流体爆裂

作为FluidComboBox的先决条件,我们需要实现一个可复用的popover组件,可以放置
完美地位于组合框的输入元素下方。

这个库应该用于实现该组件:
https://popper.js.org/docs/v2/

所有11条评论

@heartdisease同步关于组合框的 API 想法。 他正在改进我们当前的 Angular 实验版本

我测试了microsoft-graph-toolkit TemplateHelper以生成具有给定上下文和插槽中提供的模板的组合框项。 这正如我们希望的那样工作,也适用于模板中的嵌套元素。
我将测试上传到这个 repo

因此,我们应该将项目列表和(可选)模板传递给组合框,并在实际渲染项目之前“仅”添加虚拟化以仅渲染 x 个项目,具体取决于滚动位置和高度覆盖容器。

目前, TemplateHelper.renderTemplate()方法接受一个 HTMLElement 作为根节点、一个模板和一个上下文(以及一个可选的附加上下文)。 它根据给定的模板创建所有节点并将它们附加到根节点。
最好改变这种行为,让该方法只接受一个模板和一个上下文,并返回编译后的模板,然后能够直接在组件的 lit-template 中输出返回的 HTML。
你怎么认为?

要求

  • 虚拟滚动:实际上应该只呈现部分选项以避免性能问题
  • 自定义模板:用户必须能够提供用于呈现选项的模板
  • 过滤:用户必须能够输入输入来过滤项目列表; 过滤应该使用用户提供的过滤功能进行
  • 滚动指示器:是否有更多选项必须始终显而易见 --> 只要有更多选项,最初最后一个可见选项的一半(或最大 x 像素)应该是可见的,以清楚地表明容器是可滚动的.

后续步骤要求

  • 加载状态:只要没有可用的项目,就应该在叠加层中显示加载微调器ToDo加载微调器应该显示在哪里?
  • 多选:用户应该能够选择多个选项
  • 选项组:应该可以对选项进行分组

无障碍

聚焦时,组合框应在点击EnterArrowUpArrowDown键或用户开始在输入字段中输入过滤器时打开。

打开时,用户应该能够使用ArrowUp / ArrowDown键从现有选项中进行选择。 输入过滤器的焦点应保留在输入字段中,选项不应为选项卡式。 应使用aria-selected属性指示选项的选择状态。

应使用Enter键提交选择。

TabEscape键应该会关闭覆盖层,并且不应更改所选项目。

键入过滤器然后跳出输入字段时,应重置过滤器并显示先前选择的项目。

自定义模板语法

用户必须提供模板部件的开始和结束字符串。 这应该可以在全局或每个组件级别上实现(尚未决定)。

默认为{{}}

API 提案

_WIP_

ComboBox 应该分为主要的FluidComboBox组件、 FluidComboBoxOptionsList组件和FluidComboBoxOption组件。

流体组合框

包含一个FluidComboBoxOptionsList ,它又包含FluidComboBoxOption s。
处理覆盖和覆盖定位的打开和关闭。
接受一个模板作为接受基HTMLElement的子元素。

提供模板时,必须设置用于模板绑定的开始和结束字符串。

输入

| 姓名 | 计划用于 | 类型 | 默认 | 说明 |
| -------------- | ----------- | -------- | ------- | -------------------------------------------------- ------------------------------ |
| 选项| MVP | 数组 | [] | 在FluidComboBoxOptionsList显示的选项数组 |
| 过滤器Fn | MVP | (option: T) => boolean | null | 用于过滤选项的函数 |
| renderOptionFn | MVP | (option: T) => string | null | 用于自动完成面板中的渲染选项的函数 |
| 占位符| MVP | 字符串 | '' | 未选择任何选项时在输入字段中显示的占位符 |
| 禁用 | MVP | 布尔值 | 假| Boolean 判断组合框是否被禁用 |
| 加载 | MVP | 布尔值 | 假| 布尔判断是否显示加载指示器|
| 选择 | MVP | 任何 | 空| 要预选的项目 |
| 多选 | v2 | 布尔值 | 假| 布尔判断是否可以同时选择多个选项|

输出

| 姓名 | 计划用于 | 类型 | 说明 |
| ---------------- | ----------- | --------------------------------- | -------------------------------------------------- ---- |
| 改变 | MVP | FluidComboBoxChangeEvent | 值更改时触发的事件 |
| 过滤器变化| MVP | FluidComboBoxFilterChangeEvent | 当用户输入过滤值时触发的事件 |
| 选择-改变| MVP | FluidComboBoxSelectionChangeEvent | 所选选项更改时触发的事件 |

流体加载旋转器

作为 FluidComboBox 的先决条件,我们需要先实现一个可重用的加载微调组件。
ToDo向 UX 询问新加载微调器的 L&F(或者是否可以重新使用旧设计)。

流体虚拟滚动器

作为 FluidComboBox 的先决条件,我们需要实现一个可复用的组件,实现虚拟滚动
为了能够使用带有大量项目的组合框。

也可以看看:
https://github.com/WICG/virtual-scroller/blob/master/README.md
https://www.sitepen.com/blog/next-generation-virtual-scrolling/
https://dev.to/adamklein/build-your-own-virtual-scroll-part-i-11ib
https://blog.logrocket.com/virtual-scrolling-core-principles-and-basic-implementation-in-react/

流体爆裂

作为FluidComboBox的先决条件,我们需要实现一个可复用的popover组件,可以放置
完美地位于组合框的输入元素下方。

这个库应该用于实现该组件:
https://popper.js.org/docs/v2/

关于模板,我有一些担忧,因为开发人员只有文本替换不是很灵活和广泛。 考虑通过函数或简单条件进行文本转换,例如 if 那是不可能的,但我认为是必需的。

我的方法是编写返回一个 HTML 字符串的函数,该字符串可以放入 DocumentFragment 中,然后可以附加。

使用写入函数,您将获得转换或条件的完全灵活性。
为了提供一个简单的出口,我们可以利用类似于 JSX htm 的东西,它可以呈现为字符串,因此不需要编译。 它还具有我们所说的约 700 字节的非常小的占用空间。

然后可以以某种方式使用它,例如:

<script type="text/template">
html`
  <span>${text}</span>
   {count > 0
     <span>occurrences ${count}</span>
   }
   </div>
`;
</script>

import { render } from "preact-render-to-string";

const template = document.createElement('template');
template.innerHTML = render(option); // option is the script that can be passed via slot or input

const fragment = temp.content;

或者,我们可以使用标记模板https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals#Tagged_templates。

这可能是更小的解决方案。

我做了一些测试,不幸的是,Angular 从模板中删除了所有脚本标签。 关于在模板中声明脚本,我只需 2 美分。

也许让我们采用函数优先的方法,以便组合框有一个输入,您可以在其中提供有关如何呈现模板的函数。

是否可以在 LitElements 上提供一个函数作为属性? 因为那样我会将渲染传递给消费者,他在此功能中拥有 javascript 的所有灵活性。 该函数已声明参数(模板的输入)并且必须返回一个字符串。

默认实现可以这样完成:

_defaultTemplate<T>(display: string, value: T): string {
   return `<option>${display}</option>`
}

正如#1513 中所讨论的,我们需要正确处理弹出窗口。

我不确定这是否是讨论组合框组件一部分的输入的正确地方 - 但由于输入在焦点上增长,我认为扩展输入组件的框以占据最大状态的空间是有意义的拥有。

目前,一旦聚焦,输入的宽度就会增加 16 像素。 所以我建议让标签 + 输入移动 8 的填充。这意味着如果多个控件(输入、选择、...)处于垂直表单布局中,则任何控件的所有标签都需要对齐。 也许一个表单控件是有意义的,它负责统一标签 + 输入的间距。

我想修改提案,添加一个新的输入来呈现当前选择选项的显示字符串:

输入

| 姓名 | 计划用于 | 类型 | 默认 | 说明 |
| -------------- | ----------- | -------- | ------- | -------------------------------------------------- ------------------------------ |
| 显示名称Fn | MVP | (option: T) => string | (option) => `${option}` | 返回给定选项的显示字符串(不允许 HTML)的函数。 |

这也将为这个问题提供一个简单的解决方案:#1527

我认为很重要的一些小事:当前的 DtCombobox 使用选项的value作为默认的“选定选项”显示文本。 我认为使用选项的textContent更有意义。
1) textContent总是一个 UI 友好的值( value只是有时一个 UI 友好的值)
2)使用textContent是标准select的做法

我们将关闭这个问题,因为 Web 组件不是我们希望在未来创建组件的方式,这与团队中优先级的转变有关。

此页面是否有帮助?
0 / 5 - 0 等级