From 848b33c18d8db4b5a7e305ad48993b8efc78ffbf Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Tue, 31 Jan 2023 12:55:00 -0600 Subject: [PATCH 01/45] Duplicate table-column-text spec --- .../table-column-specs/table-column-number.md | 183 ++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 packages/nimble-components/src/table/specs/table-column-specs/table-column-number.md diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-number.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-number.md new file mode 100644 index 0000000000..c525a98947 --- /dev/null +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-number.md @@ -0,0 +1,183 @@ +# TableColumnText + +## Overview + +The `nimble-table-column-text` is a component that defines how to render a cell for that column in a `nimble-table` as text. + +### Background + +[Table Column API](../table-columns-hld.md) + +[Table Spec](../README.md) + +[Visual Design Spec](https://xd.adobe.com/view/5b476816-dad1-4671-b20a-efe796631c72-0e14/specs/) + +### Non-goals + +- Defining an API that supports editable text. Once we need editable text we will determine if it makes sense to modify this component or introduce a new column type. +- Provide API to customize styling of the column content. Styles will be defined statically in the implementation via the abstract `cssStyles` property. + +### Features + +- Offers a `placeholder` attribute that allows a user to define what text to render when no value is provided by the `nimble-table` data. + +--- + +## Design + +Below is an example of how the `nimble-table-column-text` would be used within a `nimble-table`: + +```HTML + + First Name + Last Name + +``` + +### API + +_Component Name_ + +- `nimble-table-column-text` + +_*Props/Attrs*_ + +- `field-name`: string +- `placeholder`: string + +_Type Reference_ + +- [`TableColumn`](../table-columns-hld.md#tablecolumn) +- [`TableStringField`](https://github.com/ni/nimble/blob/main/packages/nimble-components/src/table/specs/table-data-api.md#implementation--design) (section showing example types) +- [`TableCellState`](../table-columns-hld.md#tablecellstate-interface) + +The `TableColumnText` will extend the `TableColumn` in a manner similar to the following: + +```TS +type TableColumnTextCellRecord = TableStringField<'value'>; +type TableColumnTextColumnConfig = { placeholder: string }; + +public class TableColumnText extends TableColumn { + ... + + @attr({ attribute: 'field-name'}) + public fieldName: string; + + @attr + public placeholder: string; // Column auxiliary configuration + + public cellRecordFieldNames = ['value'] as const; + + public getDataRecordFieldNames(): string[] { + return [fieldName]; + } + + ... +} +``` + +### Anatomy + +As this component has no template, there is no anatomy of concern. + +### Angular integration + +An Angular directive will be created for the component. The component will not have form association, so a `ControlValueAccessor` will not be created. + +### Blazor integration + +A Blazor wrapper will be created for the component. + +### Visual Appearance + +The visual appearance of the text content will match that of a frameless `nimble-text-field`. + +--- + +## Implementation + +For the `cellTemplate` implementation required for a `TableColumn<>` implementation we will provide something similar to the following: + +```TS +public class TableColumnText ... +{ + ... + + public readonly cellStyles = css` + .text-value { + // set necessary text-value styles + } + + .placeholder { + // set necessary placeholder styles + } + `; + + public readonly cellTemplate = html>` + + ${x => x.data.value? x.data.value : x.columnConfig.plaeholder} + + `; + + ... +} +``` + +Note that as we are using a `span` element for the visual we will not support many of the features native to the `nimble-text-field` component as they have little value. This includes: + +- No alternate appearance modes (always frameless) +- No support for disabled state +- No support for error states +- No password display support + +### Alternatives considered + +We are using `span` elements for the text rendering of the values instead of a `nimble-text-field` for performance's sake, as we avoid the presumably heavier cost of using a custom element. The other benefits that using a `nimble-text-field` offer, such as built-in styling and a placeholder implementation seem trivial to replicate, which seems worth it for a performance improvement. + +One notable difference in behavior is that the proposed implementation will not support a behavior present in the `nimble-text-field` where a user can begin dragging at an arbitrary location in the text, and go to the end of the text, even if it has been clipped by the column (and thus showing an `...`). Users will still be able to double-click such text and copy the entire contents. + +### States + +N/A + +### Accessibility + +Accessibility of the cells rendered using the `nimble-table-column-text` are handled via the [`nimble-table-cell`](https://github.com/ni/nimble/blob/f663c38741e731bef91aa58e8fb2d1cec653b679/packages/nimble-components/src/table/components/cell/template.ts#L6) which has a `role` of [`cell`](https://w3c.github.io/aria/#cell). + +### Globalization + +None + +### Security + +Ensure no script/HTML injection can occur. + +### Performance + +As discussed in the implementation section we are making a deliberate choice to not use the `nimble-text-field` to provide the best initialization performance possible. + +### Dependencies + +None. + +### Test Plan + +- Unit tests will be written to test the component. + - Test for cases where rendered value is HTML content (i.e. `""`) + - Test for case where rendered value is a non-standard charater (e.g. emoji, Asian character, etc...) +- Verify manually that the column content appears in the accessibility tree and can be read by a screen reader. +- Have a Chromatic test in place for this column + +### Tooling + +None. + +### Documentation + +This component will be documented via its usage in the storybook for the `nimble-table`. + +--- + +## Open Issues + +- Are there specific configurarable styling requirements we need for both the rendered data value and the placeholder (e.g. italics for placeholder) From b1ec4fc9a29a9b6ffb96f49c829b80be8fc1da22 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Tue, 31 Jan 2023 13:23:24 -0600 Subject: [PATCH 02/45] Link from main spec --- packages/nimble-components/src/table/specs/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/nimble-components/src/table/specs/README.md b/packages/nimble-components/src/table/specs/README.md index bc14e35585..bdb8aa3397 100644 --- a/packages/nimble-components/src/table/specs/README.md +++ b/packages/nimble-components/src/table/specs/README.md @@ -104,6 +104,7 @@ The various APIs/features of the `nimble-table` will be split up amongst several - What column gets used for sorting? - List the set of column providers that Nimble will provide and provide their respective APIs where unique (e.g., formatter for DateTime column) - [TableColumnText](table-column-specs/table-column-text-field.md) + - [TableColumnNumber](table-column-specs/table-column-number.md) - Headers - Define the anatomy of headers in the table DOM - Require specific component type (i.e. do we need to create a `nimble-table-header`) From 5631729c050e699dca57c6acb7898a6c1427536b Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Thu, 2 Feb 2023 10:14:18 -0600 Subject: [PATCH 03/45] Initial thoughts --- .../table-column-specs/table-column-number.md | 24 ++++++++++++------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-number.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-number.md index c525a98947..a9bd6bca16 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-number.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-number.md @@ -1,21 +1,29 @@ -# TableColumnText +# TableColumnNumber ## Overview -The `nimble-table-column-text` is a component that defines how to render a cell for that column in a `nimble-table` as text. +The `nimble-table-column-number` is a component that defines how to render a number in a cell for that column in a `nimble-table` as text. + +One key advantage of the number column beyond the existing `nimble-table-column-text` is that it will ensure data in the column is sorted numerically rather than alphabetically. TODO: true? ### Background +[Number column work item](https://github.com/ni/nimble/issues/1011) + [Table Column API](../table-columns-hld.md) [Table Spec](../README.md) +[Table Column Text Spec](./table-column-text-field.md) + [Visual Design Spec](https://xd.adobe.com/view/5b476816-dad1-4671-b20a-efe796631c72-0e14/specs/) ### Non-goals -- Defining an API that supports editable text. Once we need editable text we will determine if it makes sense to modify this component or introduce a new column type. -- Provide API to customize styling of the column content. Styles will be defined statically in the implementation via the abstract `cssStyles` property. +- Editable numbers. This is not supported by the text column yet either. +- Customizing the styling or alignment of the column content. This is not supported by the text column yet either. +- API to include units with the number (e.g. "10 miles"). While it would be easy to append a client-configurable unit string after the number (and we may decide to do so eventually), the existing use cases we've found would require custom logic for each unit that doesn't belong in a generic column type. For example, formatting 76 seconds of elapsed time as "1m 16s" or formatting 1024 bytes of file size as "1 KB". These could be provided by Nimble or by clients as their own dedicated column types. +- API to configure numeric formatting. While clients may eventually wish to choose to display values with, for example, a specific number of decimal digits or a customizable thousands separator, the concrete use cases we have initially can be handled with a default formatting behavior (described below). ### Features @@ -25,12 +33,12 @@ The `nimble-table-column-text` is a component that defines how to render a cell ## Design -Below is an example of how the `nimble-table-column-text` would be used within a `nimble-table`: +Below is an example of how the `nimble-table-column-number` would be used within a `nimble-table`: ```HTML - First Name - Last Name + Count + Tag Value ``` @@ -38,7 +46,7 @@ Below is an example of how the `nimble-table-column-text` would be used within a _Component Name_ -- `nimble-table-column-text` +- `nimble-table-column-number` _*Props/Attrs*_ From d422606de2d58aaca453aa8343f0275d9ce4fc32 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Mon, 13 Feb 2023 17:18:54 -0600 Subject: [PATCH 04/45] Rename and add alternatives --- .../table-column-formatted-text.md | 243 ++++++++++++++++++ .../table-column-specs/table-column-number.md | 191 -------------- 2 files changed, 243 insertions(+), 191 deletions(-) create mode 100644 packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md delete mode 100644 packages/nimble-components/src/table/specs/table-column-specs/table-column-number.md diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md new file mode 100644 index 0000000000..8838a664aa --- /dev/null +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -0,0 +1,243 @@ +# Formatted Text Columns + +## Overview + +Clients will wish to display non-string text data in table columns for use cases like the following: +1. integer data like counts, formatted to be displayed with no trailing decimals +2. floating point data formatted to display values in standard ways ("3.1415", "1.04E47", "Infinity", -0.03) +3. a mix of the above with formatting determined by the application +4. numeric values with a static unit string appended before or after (e.g. "$4.23" or "15%") +5. numeric values with custom unit logic. Examples: + - a file size column that could show the value 1000 as "1000 bytes" but the value 1024 as "1KB" + - an elapsed time column that could show 63 seconds as "00:01:03" or "1 minute and 3 seconds" +6. enum values formatted as localized strings (0 -> "Fail", 1 -> "Pass") +7. date/time values formatted in various ways ("October 27", "yesterday", "2023-12-28 08:27") + +In all of the above cases: + - data should be sortable and groupable by its actual numeric value, not the string representation + - text styling like font and alignment should be provided by Nimble + - columns should support i18n behaviors like decimal separators, date/time formats, and localized content + - there should be an option to show "placeholder" text if no value is specified + +We may not choose to support all of the above initially but we should design our solutions with these use cases in mind. + +### Background + +[Number column work item](https://github.com/ni/nimble/issues/1011) + +[Date/time column work item](https://github.com/ni/nimble/issues/1014) + +[Table Column API](../table-columns-hld.md) + +[Table Spec](../README.md) + +[Table Column Text Spec](./table-column-text-field.md) + +[Visual Design Spec](https://xd.adobe.com/view/5b476816-dad1-4671-b20a-efe796631c72-0e14/specs/) + +### Non-goals + +- Editable numbers. This is not supported by the text column yet either. +- Customizing the styling or alignment of the column content. This is not supported by the text column yet either. + + +--- + +## Design + +### Alternatives + +Below are different alternatives to solve these use cases. Some alternatives will work better for certain use cases and worse for others. We may choose to implement a few of these alternatives in order to provide a great experience for all use cases. + +At this stage, code examples are meant to be illustrative pseudo-code, not proposed APIs. + +#### Use `table-column-text` + +With the changes proposed in #1049 to allow a column to be sorted by a different data field than the one being used for display, many of the above use cases could be met with minor changes to the existing text column. Clients would write custom logic populate their data with a new string field that contains formatted values. Then they would configure the table to display that string field while sorting by the original numeric field. + +```html + + + Progress + ` + +``` + +```ts +const originalData = [{progress: 0.1}, {progress: 0.2}]; +const tableData = originalData.map(x => { + progress: x.progress; + formattedProgress: x ? `${100 * x.progress}%` : undefined; +}); +table.data = tableData; +``` + +**Pros:** + +- formatted data is specified up front, guaranteeing fast scroll performance +- powerful; clients can format data however they want, including via browser APIs which are i18n-friendly or on the server + +**Cons:** + +- increased memory usage and data update time from clients pre-populating data with field for each formatted column +- added complexity of writing procedural code even for simple formatting use cases +- reduced cross-app consistency if formatting code isn't shared + +**Implementation Cost:** + +- Exposing `operational-data-field-name` to be set by client code rather than column definition + + +#### Client specifies formatting function + +When configuring a column, clients could provide a callback function that converts data of any supported type into a formatted string. + +There isn't a good way to set a function as an attribute value on a column, so the function would be specified in JS code. One possible mechanism would be for clients to override an abstract base class and register a new column type: + +```html + + + Progress + ` + +``` + +```ts +class MyAppProgressColumn : NimbleFormattedTextColumnBase { + public override format(value: number) : string { + return `${100 * value}%`; + } + + public override shouldUsePlaceholder(value: number | undefined) : boolean { + return value === undefined; + } +} + +MyAppProgressColumn.registerColumn('my-app-progress-column'); +``` + +**Pros:** + +- small memory footprint and fast data update time because formatting function is called on-demand +- powerful; clients can format data however they want, including via browser APIs which are i18n-friendly + +**Cons:** + +- possible reduced scroll performance because formatting function is called on-demand +- requires JS code to do formatting which is less convenient in frameworks like Blazor + +**Implementation Cost:** + +- Expose mechanism for providing format function + +#### Nimble provides column implementation for common use cases + +For common use cases we could provide column types that expose simplified formatting APIs: + +```html + + + Progress + ` + Start date + +``` + +**Pros:** + +- easy for clients to use since configuration is declarative + +**Cons:** + +- requires Nimble team to design simple but powerful formatting and i18n APIs +- can't solve some use cases like app-specific formatting logic + +**Implementation Cost:** + +- API design and implementation for each new column type + +#### Client provides custom column implementation for each use case + +Nimble already has a mechanism for clients to provide custom columns by deriving from a base class, specifying the data fields / template / styling, and registering the column type with Nimble. We could ask clients to use this mechanism for text column types. + +**Pros:** + +- Zero implementation cost to Nimble team + +**Cons:** + +- Higher burden on clients to specify template, styling, etc in JS +- Potential for inconsistent styling + + +### API + +_Component Name_ + + +_*Props/Attrs*_ + + +_Type Reference_ + + +### Anatomy + + +### Angular integration + + +### Blazor integration + + +### Visual Appearance + + +--- + +## Implementation + + +### Alternatives considered + + +### States + + +### Accessibility + + +### Globalization + + +### Security + + +### Performance + + +### Dependencies + + +### Test Plan + + +### Tooling + + +### Documentation + + +--- + +## Open Issues + diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-number.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-number.md deleted file mode 100644 index a9bd6bca16..0000000000 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-number.md +++ /dev/null @@ -1,191 +0,0 @@ -# TableColumnNumber - -## Overview - -The `nimble-table-column-number` is a component that defines how to render a number in a cell for that column in a `nimble-table` as text. - -One key advantage of the number column beyond the existing `nimble-table-column-text` is that it will ensure data in the column is sorted numerically rather than alphabetically. TODO: true? - -### Background - -[Number column work item](https://github.com/ni/nimble/issues/1011) - -[Table Column API](../table-columns-hld.md) - -[Table Spec](../README.md) - -[Table Column Text Spec](./table-column-text-field.md) - -[Visual Design Spec](https://xd.adobe.com/view/5b476816-dad1-4671-b20a-efe796631c72-0e14/specs/) - -### Non-goals - -- Editable numbers. This is not supported by the text column yet either. -- Customizing the styling or alignment of the column content. This is not supported by the text column yet either. -- API to include units with the number (e.g. "10 miles"). While it would be easy to append a client-configurable unit string after the number (and we may decide to do so eventually), the existing use cases we've found would require custom logic for each unit that doesn't belong in a generic column type. For example, formatting 76 seconds of elapsed time as "1m 16s" or formatting 1024 bytes of file size as "1 KB". These could be provided by Nimble or by clients as their own dedicated column types. -- API to configure numeric formatting. While clients may eventually wish to choose to display values with, for example, a specific number of decimal digits or a customizable thousands separator, the concrete use cases we have initially can be handled with a default formatting behavior (described below). - -### Features - -- Offers a `placeholder` attribute that allows a user to define what text to render when no value is provided by the `nimble-table` data. - ---- - -## Design - -Below is an example of how the `nimble-table-column-number` would be used within a `nimble-table`: - -```HTML - - Count - Tag Value - -``` - -### API - -_Component Name_ - -- `nimble-table-column-number` - -_*Props/Attrs*_ - -- `field-name`: string -- `placeholder`: string - -_Type Reference_ - -- [`TableColumn`](../table-columns-hld.md#tablecolumn) -- [`TableStringField`](https://github.com/ni/nimble/blob/main/packages/nimble-components/src/table/specs/table-data-api.md#implementation--design) (section showing example types) -- [`TableCellState`](../table-columns-hld.md#tablecellstate-interface) - -The `TableColumnText` will extend the `TableColumn` in a manner similar to the following: - -```TS -type TableColumnTextCellRecord = TableStringField<'value'>; -type TableColumnTextColumnConfig = { placeholder: string }; - -public class TableColumnText extends TableColumn { - ... - - @attr({ attribute: 'field-name'}) - public fieldName: string; - - @attr - public placeholder: string; // Column auxiliary configuration - - public cellRecordFieldNames = ['value'] as const; - - public getDataRecordFieldNames(): string[] { - return [fieldName]; - } - - ... -} -``` - -### Anatomy - -As this component has no template, there is no anatomy of concern. - -### Angular integration - -An Angular directive will be created for the component. The component will not have form association, so a `ControlValueAccessor` will not be created. - -### Blazor integration - -A Blazor wrapper will be created for the component. - -### Visual Appearance - -The visual appearance of the text content will match that of a frameless `nimble-text-field`. - ---- - -## Implementation - -For the `cellTemplate` implementation required for a `TableColumn<>` implementation we will provide something similar to the following: - -```TS -public class TableColumnText ... -{ - ... - - public readonly cellStyles = css` - .text-value { - // set necessary text-value styles - } - - .placeholder { - // set necessary placeholder styles - } - `; - - public readonly cellTemplate = html>` - - ${x => x.data.value? x.data.value : x.columnConfig.plaeholder} - - `; - - ... -} -``` - -Note that as we are using a `span` element for the visual we will not support many of the features native to the `nimble-text-field` component as they have little value. This includes: - -- No alternate appearance modes (always frameless) -- No support for disabled state -- No support for error states -- No password display support - -### Alternatives considered - -We are using `span` elements for the text rendering of the values instead of a `nimble-text-field` for performance's sake, as we avoid the presumably heavier cost of using a custom element. The other benefits that using a `nimble-text-field` offer, such as built-in styling and a placeholder implementation seem trivial to replicate, which seems worth it for a performance improvement. - -One notable difference in behavior is that the proposed implementation will not support a behavior present in the `nimble-text-field` where a user can begin dragging at an arbitrary location in the text, and go to the end of the text, even if it has been clipped by the column (and thus showing an `...`). Users will still be able to double-click such text and copy the entire contents. - -### States - -N/A - -### Accessibility - -Accessibility of the cells rendered using the `nimble-table-column-text` are handled via the [`nimble-table-cell`](https://github.com/ni/nimble/blob/f663c38741e731bef91aa58e8fb2d1cec653b679/packages/nimble-components/src/table/components/cell/template.ts#L6) which has a `role` of [`cell`](https://w3c.github.io/aria/#cell). - -### Globalization - -None - -### Security - -Ensure no script/HTML injection can occur. - -### Performance - -As discussed in the implementation section we are making a deliberate choice to not use the `nimble-text-field` to provide the best initialization performance possible. - -### Dependencies - -None. - -### Test Plan - -- Unit tests will be written to test the component. - - Test for cases where rendered value is HTML content (i.e. `""`) - - Test for case where rendered value is a non-standard charater (e.g. emoji, Asian character, etc...) -- Verify manually that the column content appears in the accessibility tree and can be read by a screen reader. -- Have a Chromatic test in place for this column - -### Tooling - -None. - -### Documentation - -This component will be documented via its usage in the storybook for the `nimble-table`. - ---- - -## Open Issues - -- Are there specific configurarable styling requirements we need for both the rendered data value and the placeholder (e.g. italics for placeholder) From e26ec21ca4c223a6decfb01a7444f26723d93327 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Mon, 13 Feb 2023 17:21:58 -0600 Subject: [PATCH 05/45] update link --- packages/nimble-components/src/table/specs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nimble-components/src/table/specs/README.md b/packages/nimble-components/src/table/specs/README.md index bdb8aa3397..a1d13d5201 100644 --- a/packages/nimble-components/src/table/specs/README.md +++ b/packages/nimble-components/src/table/specs/README.md @@ -104,7 +104,7 @@ The various APIs/features of the `nimble-table` will be split up amongst several - What column gets used for sorting? - List the set of column providers that Nimble will provide and provide their respective APIs where unique (e.g., formatter for DateTime column) - [TableColumnText](table-column-specs/table-column-text-field.md) - - [TableColumnNumber](table-column-specs/table-column-number.md) + - [TableColumnNumber](table-column-specs/table-column-formatted-text.md) - Headers - Define the anatomy of headers in the table DOM - Require specific component type (i.e. do we need to create a `nimble-table-header`) From 4282adb5ee1db4f0adedeea2ca40a2d836537bff Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Mon, 13 Feb 2023 17:24:53 -0600 Subject: [PATCH 06/45] link to HLD --- .../specs/table-column-specs/table-column-formatted-text.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index 8838a664aa..97c63d4861 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -53,7 +53,7 @@ At this stage, code examples are meant to be illustrative pseudo-code, not propo #### Use `table-column-text` -With the changes proposed in #1049 to allow a column to be sorted by a different data field than the one being used for display, many of the above use cases could be met with minor changes to the existing text column. Clients would write custom logic populate their data with a new string field that contains formatted values. Then they would configure the table to display that string field while sorting by the original numeric field. +With the changes proposed in [HLD for programmatically sorting columns](https://github.com/ni/nimble/pull/1049) to allow a column to be sorted by a different data field than the one being used for display, many of the above use cases could be met with minor changes to the existing text column. Clients would write custom logic populate their data with a new string field that contains formatted values. Then they would configure the table to display that string field while sorting by the original numeric field. ```html From fe2d8883356dfd0c9488b881c6a027f01c3de93b Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Mon, 13 Feb 2023 17:28:28 -0600 Subject: [PATCH 07/45] formatting --- .../table-column-formatted-text.md | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index 97c63d4861..06aaaa2653 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -53,7 +53,7 @@ At this stage, code examples are meant to be illustrative pseudo-code, not propo #### Use `table-column-text` -With the changes proposed in [HLD for programmatically sorting columns](https://github.com/ni/nimble/pull/1049) to allow a column to be sorted by a different data field than the one being used for display, many of the above use cases could be met with minor changes to the existing text column. Clients would write custom logic populate their data with a new string field that contains formatted values. Then they would configure the table to display that string field while sorting by the original numeric field. +With the changes proposed in [HLD for programmatically sorting columns](https://github.com/ni/nimble/pull/1049) to allow a column to be sorted by a different data field than the one being used for display, many of the above use cases could be met with minor changes to the existing text column. Clients would write custom logic to populate their data with a new string field that contains formatted values. Then they would configure the table to display that string field while sorting by the original numeric field. ```html @@ -82,9 +82,9 @@ table.data = tableData; **Cons:** -- increased memory usage and data update time from clients pre-populating data with field for each formatted column -- added complexity of writing procedural code even for simple formatting use cases -- reduced cross-app consistency if formatting code isn't shared +- Increased memory usage and data update time from clients pre-populating data with field for each formatted column +- Added complexity of writing procedural code even for simple formatting use cases +- Potential cross-app inconsistency if formatting code isn't shared **Implementation Cost:** @@ -123,13 +123,14 @@ MyAppProgressColumn.registerColumn('my-app-progress-column'); **Pros:** -- small memory footprint and fast data update time because formatting function is called on-demand -- powerful; clients can format data however they want, including via browser APIs which are i18n-friendly +- Small memory footprint and fast data update time because formatting function is called on-demand +- Powerful; clients can format data however they want, including via browser APIs which are i18n-friendly **Cons:** -- possible reduced scroll performance because formatting function is called on-demand -- requires JS code to do formatting which is less convenient in frameworks like Blazor +- Possible reduced scroll performance because formatting function is called on-demand +- Requires JS code to do formatting which is less convenient in frameworks like Blazor +- Potential cross-app inconsistency if formatting code isn't shared **Implementation Cost:** @@ -154,12 +155,12 @@ For common use cases we could provide column types that expose simplified format **Pros:** -- easy for clients to use since configuration is declarative +- Easy for clients to use since configuration is declarative **Cons:** -- requires Nimble team to design simple but powerful formatting and i18n APIs -- can't solve some use cases like app-specific formatting logic +- Requires Nimble team to design simple but powerful formatting and i18n APIs +- Can't solve some use cases like app-specific formatting logic **Implementation Cost:** @@ -177,6 +178,7 @@ Nimble already has a mechanism for clients to provide custom columns by deriving - Higher burden on clients to specify template, styling, etc in JS - Potential for inconsistent styling +- Potential cross-app inconsistency if formatting code isn't shared ### API From ae254ee1a0b642221158e067f00bb2fe7dbe203a Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Mon, 13 Feb 2023 17:30:28 -0600 Subject: [PATCH 08/45] label alternatives --- .../table-column-specs/table-column-formatted-text.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index 06aaaa2653..92909e4350 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -51,7 +51,7 @@ Below are different alternatives to solve these use cases. Some alternatives wil At this stage, code examples are meant to be illustrative pseudo-code, not proposed APIs. -#### Use `table-column-text` +#### Alternative 1: Use `table-column-text` With the changes proposed in [HLD for programmatically sorting columns](https://github.com/ni/nimble/pull/1049) to allow a column to be sorted by a different data field than the one being used for display, many of the above use cases could be met with minor changes to the existing text column. Clients would write custom logic to populate their data with a new string field that contains formatted values. Then they would configure the table to display that string field while sorting by the original numeric field. @@ -91,7 +91,7 @@ table.data = tableData; - Exposing `operational-data-field-name` to be set by client code rather than column definition -#### Client specifies formatting function +#### Alternative 2: Client specifies formatting function When configuring a column, clients could provide a callback function that converts data of any supported type into a formatted string. @@ -136,7 +136,7 @@ MyAppProgressColumn.registerColumn('my-app-progress-column'); - Expose mechanism for providing format function -#### Nimble provides column implementation for common use cases +#### Alternative 3: Nimble provides column implementation for common use cases For common use cases we could provide column types that expose simplified formatting APIs: @@ -166,7 +166,7 @@ For common use cases we could provide column types that expose simplified format - API design and implementation for each new column type -#### Client provides custom column implementation for each use case +#### Alternative 4: Client provides custom column implementation for each use case Nimble already has a mechanism for clients to provide custom columns by deriving from a base class, specifying the data fields / template / styling, and registering the column type with Nimble. We could ask clients to use this mechanism for text column types. From 71c7cb5c527f5db3e6441f873107e5e1afe6d1be Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Mon, 13 Feb 2023 17:31:40 -0600 Subject: [PATCH 09/45] remove date time example --- .../specs/table-column-specs/table-column-formatted-text.md | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index 92909e4350..b7d97d3f3b 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -149,7 +149,6 @@ For common use cases we could provide column types that expose simplified format > Progress ` - Start date ``` From 7eb1ada02b06d0e0e4ee25012791915ea9aa6ca4 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Tue, 14 Feb 2023 08:29:38 -0600 Subject: [PATCH 10/45] updates --- .../table-column-formatted-text.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index b7d97d3f3b..318732002c 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -121,6 +121,12 @@ class MyAppProgressColumn : NimbleFormattedTextColumnBase { MyAppProgressColumn.registerColumn('my-app-progress-column'); ``` +Some of this is prototyped in the [number-column-prototype branch](https://github.com/ni/nimble/compare/main...number-column-prototype?expand=1). + +Other variants of this idea include: +1. setting the formatting function as a property on a column element. +2. setting an [`Intl.NumberFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) object as a property on a column element. + **Pros:** - Small memory footprint and fast data update time because formatting function is called on-demand @@ -180,6 +186,14 @@ Nimble already has a mechanism for clients to provide custom columns by deriving - Potential cross-app inconsistency if formatting code isn't shared +### Strawman Proposal + +For the sake of discussion my initial proposal is: +1. For columns that require app-specific formatting logic I'm leaning towards the formatting function approach because it seems more like the API that app developers would expect (perhaps I'm biased by previous implementations). I'd like to do performance profiling to see how it impacts scroll performance before committing to this direction. +2. I would also like to provide a few built-in column types to save clients from having to write JS code. These could offer limited configuration to start since we don't have clear requirements yet. Proposed columns include: + - `nimble-table-column-numeric` + - `nimble-table-column-date` + ### API _Component Name_ @@ -242,3 +256,4 @@ _Type Reference_ ## Open Issues +1. API to configure text justification. Our working decision is that numeric column text and headers should be right aligned. Any alternatives we choose that might display numeric data will need a way to configure this. We'll update the HLD with a recommendation once we reach consensus on which alternatives to pursue (you're welcome to comment with ideas now though). \ No newline at end of file From ff973af97662b6616f727552a128449de3577182 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Tue, 14 Feb 2023 10:11:45 -0600 Subject: [PATCH 11/45] formatting --- .../table-column-formatted-text.md | 92 ++++++++----------- 1 file changed, 38 insertions(+), 54 deletions(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index 318732002c..ad10e13b4f 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -3,21 +3,23 @@ ## Overview Clients will wish to display non-string text data in table columns for use cases like the following: + 1. integer data like counts, formatted to be displayed with no trailing decimals 2. floating point data formatted to display values in standard ways ("3.1415", "1.04E47", "Infinity", -0.03) 3. a mix of the above with formatting determined by the application 4. numeric values with a static unit string appended before or after (e.g. "$4.23" or "15%") 5. numeric values with custom unit logic. Examples: - - a file size column that could show the value 1000 as "1000 bytes" but the value 1024 as "1KB" - - an elapsed time column that could show 63 seconds as "00:01:03" or "1 minute and 3 seconds" + - a file size column that could show the value 1000 as "1000 bytes" but the value 1024 as "1KB" + - an elapsed time column that could show 63 seconds as "00:01:03" or "1 minute and 3 seconds" 6. enum values formatted as localized strings (0 -> "Fail", 1 -> "Pass") 7. date/time values formatted in various ways ("October 27", "yesterday", "2023-12-28 08:27") In all of the above cases: - - data should be sortable and groupable by its actual numeric value, not the string representation - - text styling like font and alignment should be provided by Nimble - - columns should support i18n behaviors like decimal separators, date/time formats, and localized content - - there should be an option to show "placeholder" text if no value is specified + +- data should be sortable and groupable by its actual numeric value, not the string representation +- text styling like font and alignment should be provided by Nimble +- columns should support i18n behaviors like decimal separators, date/time formats, and localized content +- there should be an option to show "placeholder" text if no value is specified We may not choose to support all of the above initially but we should design our solutions with these use cases in mind. @@ -40,7 +42,6 @@ We may not choose to support all of the above initially but we should design our - Editable numbers. This is not supported by the text column yet either. - Customizing the styling or alignment of the column content. This is not supported by the text column yet either. - --- ## Design @@ -67,7 +68,7 @@ With the changes proposed in [HLD for programmatically sorting columns](https:// ``` ```ts -const originalData = [{progress: 0.1}, {progress: 0.2}]; +const originalData = [{ progress: 0.1 }, { progress: 0.2 }]; const tableData = originalData.map(x => { progress: x.progress; formattedProgress: x ? `${100 * x.progress}%` : undefined; @@ -77,19 +78,18 @@ table.data = tableData; **Pros:** -- formatted data is specified up front, guaranteeing fast scroll performance -- powerful; clients can format data however they want, including via browser APIs which are i18n-friendly or on the server +- formatted data is specified up front, guaranteeing fast scroll performance +- powerful; clients can format data however they want, including via browser APIs which are i18n-friendly or on the server **Cons:** -- Increased memory usage and data update time from clients pre-populating data with field for each formatted column -- Added complexity of writing procedural code even for simple formatting use cases -- Potential cross-app inconsistency if formatting code isn't shared +- Increased memory usage and data update time from clients pre-populating data with field for each formatted column +- Added complexity of writing procedural code even for simple formatting use cases +- Potential cross-app inconsistency if formatting code isn't shared **Implementation Cost:** -- Exposing `operational-data-field-name` to be set by client code rather than column definition - +- Exposing `operational-data-field-name` to be set by client code rather than column definition #### Alternative 2: Client specifies formatting function @@ -123,24 +123,25 @@ MyAppProgressColumn.registerColumn('my-app-progress-column'); Some of this is prototyped in the [number-column-prototype branch](https://github.com/ni/nimble/compare/main...number-column-prototype?expand=1). -Other variants of this idea include: +Other variants of this idea include: + 1. setting the formatting function as a property on a column element. -2. setting an [`Intl.NumberFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) object as a property on a column element. +2. setting an [`Intl.NumberFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) object as a property on a column element. **Pros:** -- Small memory footprint and fast data update time because formatting function is called on-demand -- Powerful; clients can format data however they want, including via browser APIs which are i18n-friendly +- Small memory footprint and fast data update time because formatting function is called on-demand +- Powerful; clients can format data however they want, including via browser APIs which are i18n-friendly **Cons:** -- Possible reduced scroll performance because formatting function is called on-demand -- Requires JS code to do formatting which is less convenient in frameworks like Blazor -- Potential cross-app inconsistency if formatting code isn't shared +- Possible reduced scroll performance because formatting function is called on-demand +- Requires JS code to do formatting which is less convenient in frameworks like Blazor +- Potential cross-app inconsistency if formatting code isn't shared **Implementation Cost:** -- Expose mechanism for providing format function +- Expose mechanism for providing format function #### Alternative 3: Nimble provides column implementation for common use cases @@ -148,7 +149,7 @@ For common use cases we could provide column types that expose simplified format ```html - Date: Tue, 14 Feb 2023 10:26:12 -0600 Subject: [PATCH 12/45] cleanup --- .../table-column-formatted-text.md | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index ad10e13b4f..d501a7c8d6 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -4,13 +4,13 @@ Clients will wish to display non-string text data in table columns for use cases like the following: -1. integer data like counts, formatted to be displayed with no trailing decimals +1. integer data like counts, formatted to be displayed with no trailing decimals ("4", "100") 2. floating point data formatted to display values in standard ways ("3.1415", "1.04E47", "Infinity", -0.03) -3. a mix of the above with formatting determined by the application +3. a mix of the above with formatting determined by the application ("1.000", "-0.030", "1024.000") 4. numeric values with a static unit string appended before or after (e.g. "$4.23" or "15%") 5. numeric values with custom unit logic. Examples: - a file size column that could show the value 1000 as "1000 bytes" but the value 1024 as "1KB" - - an elapsed time column that could show 63 seconds as "00:01:03" or "1 minute and 3 seconds" + - an elapsed time column that could show 63 seconds as "00:01:03" or "1 minute, 3 seconds" 6. enum values formatted as localized strings (0 -> "Fail", 1 -> "Pass") 7. date/time values formatted in various ways ("October 27", "yesterday", "2023-12-28 08:27") @@ -48,7 +48,7 @@ We may not choose to support all of the above initially but we should design our ### Alternatives -Below are different alternatives to solve these use cases. Some alternatives will work better for certain use cases and worse for others. We may choose to implement a few of these alternatives in order to provide a great experience for all use cases. +Below are different alternatives to solve these use cases. Some alternatives will work better for certain use cases and worse for others. We may choose to implement a few of these alternatives in order to provide a great experience for all use cases. See below for an initial proposal. At this stage, code examples are meant to be illustrative pseudo-code, not proposed APIs. @@ -79,7 +79,7 @@ table.data = tableData; **Pros:** - formatted data is specified up front, guaranteeing fast scroll performance -- powerful; clients can format data however they want, including via browser APIs which are i18n-friendly or on the server +- powerful; clients can format data however they want, including via browser APIs which are i18n-friendly or via server-side logic **Cons:** @@ -162,6 +162,7 @@ For common use cases we could provide column types that expose simplified format **Pros:** - Easy for clients to use since configuration is declarative +- Consistent formatting across apps **Cons:** @@ -183,18 +184,16 @@ Nimble already has a mechanism for clients to provide custom columns by deriving **Cons:** - Higher burden on clients to specify template, styling, etc in JS -- Potential for inconsistent styling +- Potential for inconsistent text styling - Potential cross-app inconsistency if formatting code isn't shared ### Strawman Proposal For the sake of discussion my initial proposal is: -1. For columns that require app-specific formatting logic I'm leaning towards the formatting function approach because it seems more like the API that app developers would expect (perhaps I'm biased by previous implementations). I'd like to do performance profiling to see how it impacts scroll performance before committing to this direction. -2. I would also like to provide a few built-in column types to save clients from having to write JS code. These could offer limited configuration to start since we don't have clear requirements yet. Proposed columns include: +1. For columns that require app-specific formatting logic I'm leaning towards "Client specifies formatting function" over "Use `table-column-text`" because it seems more like the API that app developers would expect (perhaps I'm biased by previous implementations). I'd like to do performance profiling to see how it impacts scroll performance before committing to this direction. +2. I would also like to provide a small number of built-in column types to save clients from having to write JS code. These could offer limited or no configuration to start since we don't have clear requirements yet. Initially this might be just `nimble-table-column-numeric` with default `toString()` formatting and no unit support. Later we could add support for basic formatting and also add column types for date/time or enums, but i18n considerations might make it hard to expose a clean attribute API for these. -- `nimble-table-column-numeric` -- `nimble-table-column-date` ### API From 438b57097d983ef56918d9bb51e2e660dd122b89 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Tue, 14 Feb 2023 10:26:46 -0600 Subject: [PATCH 13/45] lint fix --- .../specs/table-column-specs/table-column-formatted-text.md | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index d501a7c8d6..ebd46575cd 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -194,7 +194,6 @@ For the sake of discussion my initial proposal is: 1. For columns that require app-specific formatting logic I'm leaning towards "Client specifies formatting function" over "Use `table-column-text`" because it seems more like the API that app developers would expect (perhaps I'm biased by previous implementations). I'd like to do performance profiling to see how it impacts scroll performance before committing to this direction. 2. I would also like to provide a small number of built-in column types to save clients from having to write JS code. These could offer limited or no configuration to start since we don't have clear requirements yet. Initially this might be just `nimble-table-column-numeric` with default `toString()` formatting and no unit support. Later we could add support for basic formatting and also add column types for date/time or enums, but i18n considerations might make it hard to expose a clean attribute API for these. - ### API _Component Name_ From d6e547425e73c5ed678109e95208defac1f0c99a Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Wed, 1 Mar 2023 09:52:22 -0600 Subject: [PATCH 14/45] data -> setData Co-authored-by: mollykreis <20542556+mollykreis@users.noreply.github.com> --- .../specs/table-column-specs/table-column-formatted-text.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index ebd46575cd..2f64b35a51 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -73,7 +73,7 @@ const tableData = originalData.map(x => { progress: x.progress; formattedProgress: x ? `${100 * x.progress}%` : undefined; }); -table.data = tableData; +table.setData(tableData); ``` **Pros:** From 889491a6061d3fbeffb0eff0075987efc22f74f7 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Wed, 1 Mar 2023 10:17:59 -0600 Subject: [PATCH 15/45] Formatting and address some review feedback --- .../table-column-formatted-text.md | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index 2f64b35a51..bf69f76a54 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -40,7 +40,7 @@ We may not choose to support all of the above initially but we should design our ### Non-goals - Editable numbers. This is not supported by the text column yet either. -- Customizing the styling or alignment of the column content. This is not supported by the text column yet either. +- Customizing the styling of the column content (other than possibly text alignment). This is not supported by the text column yet either. --- @@ -54,12 +54,12 @@ At this stage, code examples are meant to be illustrative pseudo-code, not propo #### Alternative 1: Use `table-column-text` -With the changes proposed in [HLD for programmatically sorting columns](https://github.com/ni/nimble/pull/1049) to allow a column to be sorted by a different data field than the one being used for display, many of the above use cases could be met with minor changes to the existing text column. Clients would write custom logic to populate their data with a new string field that contains formatted values. Then they would configure the table to display that string field while sorting by the original numeric field. +With the changes proposed in [HLD for programmatically sorting columns](../table-column-sort-hld.md) to allow a column to be sorted by a different data field than the one being used for display, many of the above use cases could be met with minor changes to the existing text column. Clients would write custom logic to populate their data with a new string field that contains formatted values. Then they would configure the table to display that string field while sorting by the original numeric field. ```html Progress @@ -84,12 +84,14 @@ table.setData(tableData); **Cons:** - Increased memory usage and data update time from clients pre-populating data with field for each formatted column -- Added complexity of writing procedural code even for simple formatting use cases -- Potential cross-app inconsistency if formatting code isn't shared +- Added complexity of writing procedural code even for simple numeric formatting use cases +- Potential cross-app inconsistency if numeric formatting code isn't shared (versus Alternative 3) +- Difficult to enforce styling differences between string and numeric columns (e.g. right vs left text alignment) **Implementation Cost:** -- Exposing `operational-data-field-name` to be set by client code rather than column definition +- Exposing `operand-data-record-name` to be set by client code rather than column definition +- Exposing an API for clients to indicate their data should be styled as numeric data (right aligned) #### Alternative 2: Client specifies formatting function @@ -132,12 +134,14 @@ Other variants of this idea include: - Small memory footprint and fast data update time because formatting function is called on-demand - Powerful; clients can format data however they want, including via browser APIs which are i18n-friendly +- Easy to enforce styling differences between string and numeric columns (e.g. right vs left text alignment) **Cons:** - Possible reduced scroll performance because formatting function is called on-demand +- Requires creating a custom element to do formatting which is non-trivial for clients (must consider naming, registration, sharing, etc) - Requires JS code to do formatting which is less convenient in frameworks like Blazor -- Potential cross-app inconsistency if formatting code isn't shared +- Some potential for cross-app inconsistency if numeric formatting code isn't shared (versus Alternative 3) **Implementation Cost:** @@ -162,7 +166,8 @@ For common use cases we could provide column types that expose simplified format **Pros:** - Easy for clients to use since configuration is declarative -- Consistent formatting across apps +- Consistent numeric formatting across apps +- Easy to enforce styling differences between string and numeric columns (e.g. right vs left text alignment) **Cons:** @@ -183,8 +188,8 @@ Nimble already has a mechanism for clients to provide custom columns by deriving **Cons:** -- Higher burden on clients to specify template, styling, etc in JS -- Potential for inconsistent text styling +- Higher burden on clients to specify template, styling, numeric formatting, etc in JS. This is especially burdensome in frameworks like Blazor. +- Difficult to enforce styling differences between string and numeric columns (e.g. right vs left text alignment) - Potential cross-app inconsistency if formatting code isn't shared ### Strawman Proposal @@ -238,4 +243,4 @@ _Type Reference_ ## Open Issues -1. API to configure text justification. Our working decision is that numeric column text and headers should be right aligned. Any alternatives we choose that might display numeric data will need a way to configure this. We'll update the HLD with a recommendation once we reach consensus on which alternatives to pursue (you're welcome to comment with ideas now though). +1. API to configure text alignment. Our working decision is that numeric column text should be right aligned while string column text should remain left aligned. Any alternatives we choose that might display numeric data will need a way to configure this. We'll update the HLD with a recommendation once we reach consensus on which alternatives to pursue (you're welcome to comment with ideas now though). From 9d7db1de7d30af672d6c522d900738432cf6735a Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Wed, 1 Mar 2023 10:59:42 -0600 Subject: [PATCH 16/45] Better rationale for app-specific formatting logic --- .../specs/table-column-specs/table-column-formatted-text.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index bf69f76a54..59e0782e12 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -185,6 +185,7 @@ Nimble already has a mechanism for clients to provide custom columns by deriving **Pros:** - Zero implementation cost to Nimble team +- Powerful; clients can format data however they want, including via browser APIs which are i18n-friendly **Cons:** @@ -196,7 +197,9 @@ Nimble already has a mechanism for clients to provide custom columns by deriving For the sake of discussion my initial proposal is: -1. For columns that require app-specific formatting logic I'm leaning towards "Client specifies formatting function" over "Use `table-column-text`" because it seems more like the API that app developers would expect (perhaps I'm biased by previous implementations). I'd like to do performance profiling to see how it impacts scroll performance before committing to this direction. +1. We need to offer an approach for columns that require app-specific formatting logic (to support use cases like custom unit logic and enums). + - I think the cons of "Client provides a custom column implementation for each use case" are too great so I reject that approach. + - I'm leaning towards "Client specifies formatting function" over "Use `table-column-text`" because it more clearly encodes that the column is numeric, giving better type safety and allowing for more consistent styling. I'd like to do performance profiling to see how it impacts scroll performance before committing to this direction. 2. I would also like to provide a small number of built-in column types to save clients from having to write JS code. These could offer limited or no configuration to start since we don't have clear requirements yet. Initially this might be just `nimble-table-column-numeric` with default `toString()` formatting and no unit support. Later we could add support for basic formatting and also add column types for date/time or enums, but i18n considerations might make it hard to expose a clean attribute API for these. ### API From d673866b4e3c7c1bb292ef77b9fac63b6c75dff8 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Wed, 1 Mar 2023 11:28:39 -0600 Subject: [PATCH 17/45] Options for formatting API --- .../table-column-formatted-text.md | 54 ++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index 59e0782e12..76de59b0fd 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -151,6 +151,8 @@ Other variants of this idea include: For common use cases we could provide column types that expose simplified formatting APIs: +##### Example A: Nimble-designed API for known use cases + ```html Progress - ` + + +``` + +##### Example B: Pass through Intl.NumberFormat API + +The [NumberFormat API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat) gives highly configurable formatting with great documentation. It would solve use cases 1-4 above provided they use [supported units](https://tc39.es/proposal-unified-intl-numberformat/section6/locales-currencies-tz_proposed_out.html#sec-issanctionedsimpleunitidentifier) (includes `%`, currency, temperature, time). It throws for unsupported units (including V and A) and doesn't really support unit conversion. (Aside: it [almost supports](https://stackoverflow.com/a/73974452) our file size column use case but browsers use metric conversions (1KB === 1000B) but we want binary conversions (1KB === 1024B)). + +```html + + + Progress + + + + Count + + +``` + +##### Example C: Provide preconfigured formatters for NumberFormat API + +To improve consistency and reduce client configuration, we could provide formatters for common use cases like integers and percent. + +```html + + + Progress + + + + Count + ``` From 336939b98c858bc8c73e38676e7482f61cb4afbe Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Wed, 1 Mar 2023 11:36:53 -0600 Subject: [PATCH 18/45] Enum example --- .../table-column-formatted-text.md | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index 76de59b0fd..fc7be9e1df 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -193,7 +193,7 @@ The [NumberFormat API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/R ``` -##### Example C: Provide preconfigured formatters for NumberFormat API +##### Example C: Provide pre-configured formatters for NumberFormat API To improve consistency and reduce client configuration, we could provide formatters for common use cases like integers and percent. @@ -215,6 +215,22 @@ To improve consistency and reduce client configuration, we could provide formatt ``` +##### Example D: Enum Column + +We may try to provide an easy way for clients to map enum values to localized strings. Here is a concept for an API which probably has issues. + +```html + + + Status + Pass + Fail + + +``` + **Pros:** - Easy for clients to use since configuration is declarative @@ -252,7 +268,7 @@ For the sake of discussion my initial proposal is: 1. We need to offer an approach for columns that require app-specific formatting logic (to support use cases like custom unit logic and enums). - I think the cons of "Client provides a custom column implementation for each use case" are too great so I reject that approach. - I'm leaning towards "Client specifies formatting function" over "Use `table-column-text`" because it more clearly encodes that the column is numeric, giving better type safety and allowing for more consistent styling. I'd like to do performance profiling to see how it impacts scroll performance before committing to this direction. -2. I would also like to provide a small number of built-in column types to save clients from having to write JS code. These could offer limited or no configuration to start since we don't have clear requirements yet. Initially this might be just `nimble-table-column-numeric` with default `toString()` formatting and no unit support. Later we could add support for basic formatting and also add column types for date/time or enums, but i18n considerations might make it hard to expose a clean attribute API for these. +2. I would also like to provide a small number of built-in column types to save clients from having to write JS code. These could offer limited or no configuration to start since we don't have clear requirements yet. Initially this might be just `nimble-table-column-numeric` with default `toString()` formatting and no unit support. Later we could add support for some of the examples described in Alternative 3. ### API From 9c56c8f04d5045594e8342fab631145c19bd0071 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Wed, 1 Mar 2023 15:23:42 -0600 Subject: [PATCH 19/45] More requirements --- .../specs/table-column-specs/table-column-formatted-text.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index fc7be9e1df..5679ff7797 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -13,6 +13,7 @@ Clients will wish to display non-string text data in table columns for use cases - an elapsed time column that could show 63 seconds as "00:01:03" or "1 minute, 3 seconds" 6. enum values formatted as localized strings (0 -> "Fail", 1 -> "Pass") 7. date/time values formatted in various ways ("October 27", "yesterday", "2023-12-28 08:27") +8. combinations of the above in a single column in cases where the source data isn't uniformly typed (e.g. SLE tag values) In all of the above cases: @@ -20,6 +21,7 @@ In all of the above cases: - text styling like font and alignment should be provided by Nimble - columns should support i18n behaviors like decimal separators, date/time formats, and localized content - there should be an option to show "placeholder" text if no value is specified +- there should be a way to show the full value of truncated text (likely via a title / tooltip on hover) We may not choose to support all of the above initially but we should design our solutions with these use cases in mind. @@ -167,7 +169,7 @@ For common use cases we could provide column types that expose simplified format ##### Example B: Pass through Intl.NumberFormat API -The [NumberFormat API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat) gives highly configurable formatting with great documentation. It would solve use cases 1-4 above provided they use [supported units](https://tc39.es/proposal-unified-intl-numberformat/section6/locales-currencies-tz_proposed_out.html#sec-issanctionedsimpleunitidentifier) (includes `%`, currency, temperature, time). It throws for unsupported units (including V and A) and doesn't really support unit conversion. (Aside: it [almost supports](https://stackoverflow.com/a/73974452) our file size column use case but browsers use metric conversions (1KB === 1000B) but we want binary conversions (1KB === 1024B)). +The [NumberFormat API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat) gives highly configurable formatting with great documentation. It would solve use cases 1-4 above provided they use [supported units](https://tc39.es/proposal-unified-intl-numberformat/section6/locales-currencies-tz_proposed_out.html#sec-issanctionedsimpleunitidentifier) (includes `%`, currency, temperature, time). Unfortunately it throws for unsupported units (like volts and amps) and doesn't really support unit conversion. (Aside: it [almost supports](https://stackoverflow.com/a/73974452) our file size column use case but browsers use metric conversions (1KB === 1000B) but we want binary conversions (1KB === 1024B)). ```html From 817ced318ca28a25309bf7bed9261c47ceb95a98 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Wed, 1 Mar 2023 15:28:33 -0600 Subject: [PATCH 20/45] Wording --- .../specs/table-column-specs/table-column-formatted-text.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index 5679ff7797..558a01311e 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -268,7 +268,7 @@ Nimble already has a mechanism for clients to provide custom columns by deriving For the sake of discussion my initial proposal is: 1. We need to offer an approach for columns that require app-specific formatting logic (to support use cases like custom unit logic and enums). - - I think the cons of "Client provides a custom column implementation for each use case" are too great so I reject that approach. + - I think the cons of "Client provides a custom column implementation for each use case" are too great so I think we should invest in a simpler approach. - I'm leaning towards "Client specifies formatting function" over "Use `table-column-text`" because it more clearly encodes that the column is numeric, giving better type safety and allowing for more consistent styling. I'd like to do performance profiling to see how it impacts scroll performance before committing to this direction. 2. I would also like to provide a small number of built-in column types to save clients from having to write JS code. These could offer limited or no configuration to start since we don't have clear requirements yet. Initially this might be just `nimble-table-column-numeric` with default `toString()` formatting and no unit support. Later we could add support for some of the examples described in Alternative 3. From f9e3fe66e4195817fd64ef933fcd7dd1b7038916 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Thu, 2 Mar 2023 15:05:32 -0600 Subject: [PATCH 21/45] Feedback from Meyer conversation --- .../table-column-formatted-text.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index 558a01311e..054bbd1b48 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -235,7 +235,7 @@ We may try to provide an easy way for clients to map enum values to localized st **Pros:** -- Easy for clients to use since configuration is declarative +- Easy for clients to use since configuration is declarative. This means Blazor apps could do configuration from .NET code and not need to write JS. - Consistent numeric formatting across apps - Easy to enforce styling differences between string and numeric columns (e.g. right vs left text alignment) @@ -267,10 +267,10 @@ Nimble already has a mechanism for clients to provide custom columns by deriving For the sake of discussion my initial proposal is: -1. We need to offer an approach for columns that require app-specific formatting logic (to support use cases like custom unit logic and enums). - - I think the cons of "Client provides a custom column implementation for each use case" are too great so I think we should invest in a simpler approach. - - I'm leaning towards "Client specifies formatting function" over "Use `table-column-text`" because it more clearly encodes that the column is numeric, giving better type safety and allowing for more consistent styling. I'd like to do performance profiling to see how it impacts scroll performance before committing to this direction. -2. I would also like to provide a small number of built-in column types to save clients from having to write JS code. These could offer limited or no configuration to start since we don't have clear requirements yet. Initially this might be just `nimble-table-column-numeric` with default `toString()` formatting and no unit support. Later we could add support for some of the examples described in Alternative 3. +1. We need to offer an approach for columns that require app-specific formatting logic to support above use cases like 5 (custom unit logic) and 8 (data of unknown type). + - I believe the cons of **Client provides a custom column implementation for each use case** are too great so we should invest in an approach that offers clients more consistency and simplicity. + - I'm leaning towards **Client specifies formatting function** over **Use `table-column-text`** because it more clearly encodes that the column is numeric, giving better type safety and allowing for more consistent styling. I'd like to do performance profiling to see how it impacts scroll performance before committing to this direction. +2. I would also like to pursue **Nimble provides column implementation for common use cases** to save clients from having to write JS code. Ideally we would provide column implementations that can handle the above use cases 1-4 (numeric formatting and static units) in a first pass with 6 and 7 (enum and date) coming later. ### API @@ -315,5 +315,6 @@ _Type Reference_ --- ## Open Issues - +mention headers, not just columns 1. API to configure text alignment. Our working decision is that numeric column text should be right aligned while string column text should remain left aligned. Any alternatives we choose that might display numeric data will need a way to configure this. We'll update the HLD with a recommendation once we reach consensus on which alternatives to pursue (you're welcome to comment with ideas now though). +2. The APIs in this document are examples, not yet proposals. Once we agree on high-level direction I will do more prototyping to propose concrete APIs. From 6f5a076e2c15b136b9a76dd55e224085e059e41a Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Thu, 2 Mar 2023 15:09:29 -0600 Subject: [PATCH 22/45] Formatting and clarification --- .../table-column-specs/table-column-formatted-text.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index 054bbd1b48..c676b37420 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -267,9 +267,9 @@ Nimble already has a mechanism for clients to provide custom columns by deriving For the sake of discussion my initial proposal is: -1. We need to offer an approach for columns that require app-specific formatting logic to support above use cases like 5 (custom unit logic) and 8 (data of unknown type). - - I believe the cons of **Client provides a custom column implementation for each use case** are too great so we should invest in an approach that offers clients more consistency and simplicity. - - I'm leaning towards **Client specifies formatting function** over **Use `table-column-text`** because it more clearly encodes that the column is numeric, giving better type safety and allowing for more consistent styling. I'd like to do performance profiling to see how it impacts scroll performance before committing to this direction. +1. We need to offer an approach for columns that require app-specific formatting logic to support above use cases like 5 (custom unit logic) and 8 (data of unknown type). + - I believe the cons of **Client provides a custom column implementation for each use case** are too great so we should invest in an approach that offers clients more consistency and simplicity. + - I'm leaning towards **Client specifies formatting function** over **Use `table-column-text`** because it more clearly encodes that the column is numeric, giving better type safety and allowing for more consistent styling. I'd like to do performance profiling to see how it impacts scroll performance before committing to this direction. 2. I would also like to pursue **Nimble provides column implementation for common use cases** to save clients from having to write JS code. Ideally we would provide column implementations that can handle the above use cases 1-4 (numeric formatting and static units) in a first pass with 6 and 7 (enum and date) coming later. ### API @@ -315,6 +315,5 @@ _Type Reference_ --- ## Open Issues -mention headers, not just columns -1. API to configure text alignment. Our working decision is that numeric column text should be right aligned while string column text should remain left aligned. Any alternatives we choose that might display numeric data will need a way to configure this. We'll update the HLD with a recommendation once we reach consensus on which alternatives to pursue (you're welcome to comment with ideas now though). +1. API to configure text alignment of column content and column headers (e.g. right align numeric columns but left align string columns). We'll update the HLD with a recommendation once we reach consensus on which alternatives to pursue (you're welcome to comment with ideas now though). 2. The APIs in this document are examples, not yet proposals. Once we agree on high-level direction I will do more prototyping to propose concrete APIs. From 5f4ca03781446f37010bdb2abfd1ef2617e7a0d5 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Thu, 2 Mar 2023 15:15:26 -0600 Subject: [PATCH 23/45] Clarify Blazor recommendation --- .../specs/table-column-specs/table-column-formatted-text.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index c676b37420..366a28583a 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -142,7 +142,7 @@ Other variants of this idea include: - Possible reduced scroll performance because formatting function is called on-demand - Requires creating a custom element to do formatting which is non-trivial for clients (must consider naming, registration, sharing, etc) -- Requires JS code to do formatting which is less convenient in frameworks like Blazor +- Requires JS code to do formatting which is inconvenient in frameworks like Blazor. I propose we **would not** encourage Blazor clients to write formatting code in .NET due to performance concerns. - Some potential for cross-app inconsistency if numeric formatting code isn't shared (versus Alternative 3) **Implementation Cost:** From 5586759efe8a44848023085651b13c06a9291295 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Thu, 2 Mar 2023 15:20:45 -0600 Subject: [PATCH 24/45] prettier-fix --- .../specs/table-column-specs/table-column-formatted-text.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index 366a28583a..21dce4ff52 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -315,5 +315,6 @@ _Type Reference_ --- ## Open Issues + 1. API to configure text alignment of column content and column headers (e.g. right align numeric columns but left align string columns). We'll update the HLD with a recommendation once we reach consensus on which alternatives to pursue (you're welcome to comment with ideas now though). 2. The APIs in this document are examples, not yet proposals. Once we agree on high-level direction I will do more prototyping to propose concrete APIs. From fe92ed0b1241a40b8854b5f0d2d518b43a036627 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Thu, 2 Mar 2023 17:33:06 -0600 Subject: [PATCH 25/45] Change files --- ...le-components-e7154892-b084-429e-8d98-417c2721f61b.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/@ni-nimble-components-e7154892-b084-429e-8d98-417c2721f61b.json diff --git a/change/@ni-nimble-components-e7154892-b084-429e-8d98-417c2721f61b.json b/change/@ni-nimble-components-e7154892-b084-429e-8d98-417c2721f61b.json new file mode 100644 index 0000000000..4f4ac28d3a --- /dev/null +++ b/change/@ni-nimble-components-e7154892-b084-429e-8d98-417c2721f61b.json @@ -0,0 +1,7 @@ +{ + "type": "none", + "comment": "Add design document for table columns containing formatted text", + "packageName": "@ni/nimble-components", + "email": "jattasNI@users.noreply.github.com", + "dependentChangeType": "none" +} From 84e96c4969677d86b534fec813d3e026746e50d2 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Wed, 8 Mar 2023 16:23:10 -0600 Subject: [PATCH 26/45] Boolean text use case and column type --- .../table-column-formatted-text.md | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index 21dce4ff52..bc7de0e49b 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -11,7 +11,7 @@ Clients will wish to display non-string text data in table columns for use cases 5. numeric values with custom unit logic. Examples: - a file size column that could show the value 1000 as "1000 bytes" but the value 1024 as "1KB" - an elapsed time column that could show 63 seconds as "00:01:03" or "1 minute, 3 seconds" -6. enum values formatted as localized strings (0 -> "Fail", 1 -> "Pass") +6. enum and boolean values formatted as localized strings (0 -> "Fail", 1 -> "Pass") 7. date/time values formatted in various ways ("October 27", "yesterday", "2023-12-28 08:27") 8. combinations of the above in a single column in cases where the source data isn't uniformly typed (e.g. SLE tag values) @@ -217,19 +217,35 @@ To improve consistency and reduce client configuration, we could provide formatt ``` -##### Example D: Enum Column +##### Example D: Boolean Text Column + +We may try to provide an easy way for clients to map boolean values to localized strings. + +```html + + + Test Result + + +``` + +##### Example E: Enum Text Column We may try to provide an easy way for clients to map enum values to localized strings. Here is a concept for an API which probably has issues. ```html - Status Pass Fail - + ``` @@ -270,7 +286,7 @@ For the sake of discussion my initial proposal is: 1. We need to offer an approach for columns that require app-specific formatting logic to support above use cases like 5 (custom unit logic) and 8 (data of unknown type). - I believe the cons of **Client provides a custom column implementation for each use case** are too great so we should invest in an approach that offers clients more consistency and simplicity. - I'm leaning towards **Client specifies formatting function** over **Use `table-column-text`** because it more clearly encodes that the column is numeric, giving better type safety and allowing for more consistent styling. I'd like to do performance profiling to see how it impacts scroll performance before committing to this direction. -2. I would also like to pursue **Nimble provides column implementation for common use cases** to save clients from having to write JS code. Ideally we would provide column implementations that can handle the above use cases 1-4 (numeric formatting and static units) in a first pass with 6 and 7 (enum and date) coming later. +2. I would also like to pursue **Nimble provides column implementation for common use cases** to save clients from having to write JS code. Ideally we would provide column implementations that can handle the above use cases 1-4 (numeric formatting and static units) in a first pass with 6 and 7 (enum/boolean and date) coming later. ### API From 250292d53aa7b39fce26483102613ffcc7935718 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Wed, 12 Apr 2023 09:33:50 -0500 Subject: [PATCH 27/45] Solidifying proposals --- .../src/table/specs/README.md | 2 +- .../table-column-formatted-text.md | 268 ++++++++---------- 2 files changed, 125 insertions(+), 145 deletions(-) diff --git a/packages/nimble-components/src/table/specs/README.md b/packages/nimble-components/src/table/specs/README.md index 554f9afaa8..2757d97153 100644 --- a/packages/nimble-components/src/table/specs/README.md +++ b/packages/nimble-components/src/table/specs/README.md @@ -105,7 +105,7 @@ The various APIs/features of the `nimble-table` will be split up amongst several - What column gets used for sorting? - List the set of column providers that Nimble will provide and provide their respective APIs where unique (e.g., formatter for DateTime column) - [TableColumnText](table-column-specs/table-column-text-field.md) - - [TableColumnNumber](table-column-specs/table-column-formatted-text.md) + - [Formatted Text Columns](table-column-specs/table-column-formatted-text.md) - Headers - Define the anatomy of headers in the table DOM - What is the component to use for interaction? Outline Button? Ghost button? diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index bc7de0e49b..76c48dfdaf 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -13,7 +13,6 @@ Clients will wish to display non-string text data in table columns for use cases - an elapsed time column that could show 63 seconds as "00:01:03" or "1 minute, 3 seconds" 6. enum and boolean values formatted as localized strings (0 -> "Fail", 1 -> "Pass") 7. date/time values formatted in various ways ("October 27", "yesterday", "2023-12-28 08:27") -8. combinations of the above in a single column in cases where the source data isn't uniformly typed (e.g. SLE tag values) In all of the above cases: @@ -31,6 +30,8 @@ We may not choose to support all of the above initially but we should design our [Date/time column work item](https://github.com/ni/nimble/issues/1014) +[Boolean text column work item](https://github.com/ni/nimble/issues/1103) + [Table Column API](../table-columns-hld.md) [Table Spec](../README.md) @@ -41,6 +42,7 @@ We may not choose to support all of the above initially but we should design our ### Non-goals +- Combinations of the use cases listed above in a single column. This will be needed in cases where the source data isn't uniformly typed (e.g. SLE tag values or notebook outputs). This HLD focuses on uniform data types; future HLDs will discuss ways to configure multiple types of columns to be conditionally displayed together. - Editable numbers. This is not supported by the text column yet either. - Customizing the styling of the column content (other than possibly text alignment). This is not supported by the text column yet either. @@ -48,63 +50,28 @@ We may not choose to support all of the above initially but we should design our ## Design -### Alternatives - -Below are different alternatives to solve these use cases. Some alternatives will work better for certain use cases and worse for others. We may choose to implement a few of these alternatives in order to provide a great experience for all use cases. See below for an initial proposal. - -At this stage, code examples are meant to be illustrative pseudo-code, not proposed APIs. - -#### Alternative 1: Use `table-column-text` - -With the changes proposed in [HLD for programmatically sorting columns](../table-column-sort-hld.md) to allow a column to be sorted by a different data field than the one being used for display, many of the above use cases could be met with minor changes to the existing text column. Clients would write custom logic to populate their data with a new string field that contains formatted values. Then they would configure the table to display that string field while sorting by the original numeric field. - -```html - - - Progress - ` - -``` - -```ts -const originalData = [{ progress: 0.1 }, { progress: 0.2 }]; -const tableData = originalData.map(x => { - progress: x.progress; - formattedProgress: x ? `${100 * x.progress}%` : undefined; -}); -table.setData(tableData); -``` - -**Pros:** - -- formatted data is specified up front, guaranteeing fast scroll performance -- powerful; clients can format data however they want, including via browser APIs which are i18n-friendly or via server-side logic - -**Cons:** +### Summary -- Increased memory usage and data update time from clients pre-populating data with field for each formatted column -- Added complexity of writing procedural code even for simple numeric formatting use cases -- Potential cross-app inconsistency if numeric formatting code isn't shared (versus Alternative 3) -- Difficult to enforce styling differences between string and numeric columns (e.g. right vs left text alignment) +Nimble will provide a base class that can be derived from to define columns that call a formatting function to render their data as text. Clients which require app-specific formatting logic to support above use cases like 5 (custom unit logic) will define custom columns in their application that derive from this base class. -**Implementation Cost:** +Nimble will also provide several columns that derive from this base class and provide higher level formatting APIs for specific data types. We plan to provide column implementations that can handle the above use cases 1-4 (numeric formatting and static units) in a first pass with 6 and 7 (enum/boolean and date) coming later. These will be easier to use than the above custom column approach: + - the columns will be configurable via HTML attributes, saving clients from writing JS code (a particular challenge in Blazor) + - they provide strict type validation of the data record + - clients don't need to manage the lifecycle of registering a new column custom element in their application -- Exposing `operand-data-record-name` to be set by client code rather than column definition -- Exposing an API for clients to indicate their data should be styled as numeric data (right aligned) +### Formatted text column base class -#### Alternative 2: Client specifies formatting function +*Originally called "Alternative 2: Client specifies formatting function"* When configuring a column, clients could provide a callback function that converts data of any supported type into a formatted string. -There isn't a good way to set a function as an attribute value on a column, so the function would be specified in JS code. One possible mechanism would be for clients to override an abstract base class and register a new column type: +There isn't a good way to set a function as an attribute value on a column, so the function would be specified in JS code via clients overriding an abstract base class and registering a new column type: ```html Progress ` @@ -127,99 +94,74 @@ MyAppProgressColumn.registerColumn('my-app-progress-column'); Some of this is prototyped in the [number-column-prototype branch](https://github.com/ni/nimble/compare/main...number-column-prototype?expand=1). -Other variants of this idea include: +### Nimble formatted text columns -1. setting the formatting function as a property on a column element. -2. setting an [`Intl.NumberFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) object as a property on a column element. - -**Pros:** - -- Small memory footprint and fast data update time because formatting function is called on-demand -- Powerful; clients can format data however they want, including via browser APIs which are i18n-friendly -- Easy to enforce styling differences between string and numeric columns (e.g. right vs left text alignment) - -**Cons:** - -- Possible reduced scroll performance because formatting function is called on-demand -- Requires creating a custom element to do formatting which is non-trivial for clients (must consider naming, registration, sharing, etc) -- Requires JS code to do formatting which is inconvenient in frameworks like Blazor. I propose we **would not** encourage Blazor clients to write formatting code in .NET due to performance concerns. -- Some potential for cross-app inconsistency if numeric formatting code isn't shared (versus Alternative 3) - -**Implementation Cost:** +*Originally called "Alternative 3: Nimble provides column implementation for common use cases"* -- Expose mechanism for providing format function +#### Numeric text column -#### Alternative 3: Nimble provides column implementation for common use cases +We will introduce `nimble-table-column-numeric` which formats a numeric field value and displays it as text. It will offer sufficient configuration to support use cases 1-4 above. -For common use cases we could provide column types that expose simplified formatting APIs: +Similar to `nimble-table-column-text`: +- it will offer attributes to control which field is displayed and placeholder text when that field isn't a number. +- it will sort and group by the field value, not the display value. +- it will allow sizing by fractional widths with a minimum pixel width. +- it will truncate using an ellipsis and show a tooltip on hover when the value is truncated -##### Example A: Nimble-designed API for known use cases +The primary formatting API will leverage the native browser [`Intl.NumberFormat` API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat) which gives highly configurable formatting with great documentation. It supports features like locale-specific formatting, decimal separators, thousands separators, digits of precision, and units. Since it doesn't support some unit strings required by clients, the column will also offer ways to set a fixed prefix or suffix on every number. -```html - - - Progress - - -``` +##### ``nimble-table-column-numeric` API -##### Example B: Pass through Intl.NumberFormat API +_*Props/Attrs*_ +- `field-name` - +- `placeholder` - The string value to use if the value of the field is `undefined`, `null`, `NaN`, or isn't of type `number`. Note that other "special" values like `Infinity` will be formatted and displayed. +- TODO: ALIGNMENT +- `prefix` - A string to append before the formatted value of each cell. It will not include any spacing. +- `suffix` - A string to append after the formatted value of each cell. It will not include any spacing. +- `number-format-locales` - Corresponds to the [`locales` parameter of `NumberFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#parameters). Note that initially we will not support an array of locales; if this is necessary we could consider parsing this field as a comma-separated list. +- `number-format-options-*` - attributes that correspond to the properties of the [`options` parameter of `NumberFormat`]. Each property name will be converted from `camelCase` to `dash-case`. For example, `number-format-options-compact-display="long"` or `number-format-options-currency-display="narrowSymbol"`. -The [NumberFormat API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat) gives highly configurable formatting with great documentation. It would solve use cases 1-4 above provided they use [supported units](https://tc39.es/proposal-unified-intl-numberformat/section6/locales-currencies-tz_proposed_out.html#sec-issanctionedsimpleunitidentifier) (includes `%`, currency, temperature, time). Unfortunately it throws for unsupported units (like volts and amps) and doesn't really support unit conversion. (Aside: it [almost supports](https://stackoverflow.com/a/73974452) our file size column use case but browsers use metric conversions (1KB === 1000B) but we want binary conversions (1KB === 1024B)). +For values being passed through to the `NumberFormat` API we will provide types similar to [the TypeScript types from the browser API](https://github.com/microsoft/TypeScript/blob/0f724c04308e20d93d397e82b11f82ad6f810c44/src/lib/es2020.intl.d.ts#L232). Default values if the attribute is not provided will match the `NumberFormat` API. ```html Progress Count - -``` - -##### Example C: Provide pre-configured formatters for NumberFormat API - -To improve consistency and reduce client configuration, we could provide formatters for common use cases like integers and percent. - -```html - - - Progress - - Count + Voltage ``` -##### Example D: Boolean Text Column -We may try to provide an easy way for clients to map boolean values to localized strings. + +#### Boolean Text Column + +We will eventually provide an column type that maps boolean values to localized strings. This is an example API but the details will be updated in this document before implementation. ```html @@ -227,6 +169,7 @@ We may try to provide an easy way for clients to map boolean values to localized field-name="testResult" true-message="Pass" false-message="Fail" + placeholder="N/A" > Test Result @@ -235,12 +178,13 @@ We may try to provide an easy way for clients to map boolean values to localized ##### Example E: Enum Text Column -We may try to provide an easy way for clients to map enum values to localized strings. Here is a concept for an API which probably has issues. +We will eventually provide an column type that maps enum values to localized strings. This is an example API but the details will be updated in this document before implementation. ```html Status Pass @@ -249,66 +193,102 @@ We may try to provide an easy way for clients to map enum values to localized st ``` -**Pros:** +### API -- Easy for clients to use since configuration is declarative. This means Blazor apps could do configuration from .NET code and not need to write JS. -- Consistent numeric formatting across apps -- Easy to enforce styling differences between string and numeric columns (e.g. right vs left text alignment) +_Component Name_ -**Cons:** +_*Props/Attrs*_ -- Requires Nimble team to design simple but powerful formatting and i18n APIs -- Can't solve some use cases like app-specific formatting logic +_Type Reference_ -**Implementation Cost:** +### Anatomy -- API design and implementation for each new column type +### Angular integration -#### Alternative 4: Client provides custom column implementation for each use case +### Blazor integration -Nimble already has a mechanism for clients to provide custom columns by deriving from a base class, specifying the data fields / template / styling, and registering the column type with Nimble. We could ask clients to use this mechanism for text column types. +I propose we **would not** encourage Blazor clients to write formatting code in .NET due to performance concerns. + +### Visual Appearance + +### +TODO Items I asked Mert to include on hyperlink spec + +--- + +## Implementation + +### Alternatives considered + +#### Other ways to provide a formatting function + +1. setting the formatting function as a property on a column element. +2. setting an [`Intl.NumberFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) object as a property on a column element. + +Both of these require JS code which finds a specific column element and configures it. This is difficult to achieve in Blazor. + +#### Use `table-column-text` + +*Originally called "Alternative 1"* + +With the changes proposed in [HLD for programmatically sorting columns](../table-column-sort-hld.md) to allow a column to be sorted by a different data field than the one being used for display, many of the above use cases could be met with minor changes to the existing text column. Clients would write custom logic to populate their data with a new string field that contains formatted values. Then they would configure the table to display that string field while sorting by the original numeric field. + +```html + + + Progress + ` + +``` + +```ts +const originalData = [{ progress: 0.1 }, { progress: 0.2 }]; +const tableData = originalData.map(x => { + progress: x.progress; + formattedProgress: x ? `${100 * x.progress}%` : undefined; +}); +table.setData(tableData); +``` **Pros:** -- Zero implementation cost to Nimble team -- Powerful; clients can format data however they want, including via browser APIs which are i18n-friendly +- formatted data is specified up front, guaranteeing fast scroll performance +- powerful; clients can format data however they want, including via browser APIs which are i18n-friendly or via server-side logic **Cons:** -- Higher burden on clients to specify template, styling, numeric formatting, etc in JS. This is especially burdensome in frameworks like Blazor. +- Increased memory usage and data update time from clients pre-populating data with field for each formatted column +- Added complexity of writing procedural code even for simple numeric formatting use cases +- Potential cross-app inconsistency if numeric formatting code isn't shared (versus Alternative 3) - Difficult to enforce styling differences between string and numeric columns (e.g. right vs left text alignment) -- Potential cross-app inconsistency if formatting code isn't shared -### Strawman Proposal - -For the sake of discussion my initial proposal is: - -1. We need to offer an approach for columns that require app-specific formatting logic to support above use cases like 5 (custom unit logic) and 8 (data of unknown type). - - I believe the cons of **Client provides a custom column implementation for each use case** are too great so we should invest in an approach that offers clients more consistency and simplicity. - - I'm leaning towards **Client specifies formatting function** over **Use `table-column-text`** because it more clearly encodes that the column is numeric, giving better type safety and allowing for more consistent styling. I'd like to do performance profiling to see how it impacts scroll performance before committing to this direction. -2. I would also like to pursue **Nimble provides column implementation for common use cases** to save clients from having to write JS code. Ideally we would provide column implementations that can handle the above use cases 1-4 (numeric formatting and static units) in a first pass with 6 and 7 (enum/boolean and date) coming later. +**Implementation Cost:** -### API +- Exposing `operand-data-record-name` to be set by client code rather than column definition +- Exposing an API for clients to indicate their data should be styled as numeric data (right aligned) -_Component Name_ -_*Props/Attrs*_ +#### Client provides custom column implementation for each use case -_Type Reference_ +*Originally called "Alternative 4"* -### Anatomy +Nimble already has a mechanism for clients to provide custom columns by deriving from a base class, specifying the data fields / template / styling, and registering the column type with Nimble. We could ask clients to use this mechanism for text column types. -### Angular integration +**Pros:** -### Blazor integration +- Zero implementation cost to Nimble team +- Powerful; clients can format data however they want, including via browser APIs which are i18n-friendly -### Visual Appearance +**Cons:** ---- +- Higher burden on clients to specify template, styling, numeric formatting, etc in JS. This is especially burdensome in frameworks like Blazor. +- Difficult to enforce styling differences between string and numeric columns (e.g. right vs left text alignment) +- Potential cross-app inconsistency if formatting code isn't shared -## Implementation -### Alternatives considered ### States From c4a44c8f54ceabaa03cb170c12d3840a059bf807 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Tue, 2 May 2023 10:41:17 -0500 Subject: [PATCH 28/45] HLD updates --- .../table-column-formatted-text.md | 110 ++++++++++++++---- 1 file changed, 88 insertions(+), 22 deletions(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index 76c48dfdaf..137b93e3c5 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -5,7 +5,7 @@ Clients will wish to display non-string text data in table columns for use cases like the following: 1. integer data like counts, formatted to be displayed with no trailing decimals ("4", "100") -2. floating point data formatted to display values in standard ways ("3.1415", "1.04E47", "Infinity", -0.03) +2. floating point data formatted to display values in standard ways ("3.1415", "1.04E47", "Infinity", "-0.03") 3. a mix of the above with formatting determined by the application ("1.000", "-0.030", "1024.000") 4. numeric values with a static unit string appended before or after (e.g. "$4.23" or "15%") 5. numeric values with custom unit logic. Examples: @@ -44,6 +44,7 @@ We may not choose to support all of the above initially but we should design our - Combinations of the use cases listed above in a single column. This will be needed in cases where the source data isn't uniformly typed (e.g. SLE tag values or notebook outputs). This HLD focuses on uniform data types; future HLDs will discuss ways to configure multiple types of columns to be conditionally displayed together. - Editable numbers. This is not supported by the text column yet either. +- Numeric formatting for `nimble-number-field`. While we may choose to expose similar APIs for its numeric formatting, the complexities of it being an editable input control make this out of scope for now. - Customizing the styling of the column content (other than possibly text alignment). This is not supported by the text column yet either. --- @@ -52,20 +53,31 @@ We may not choose to support all of the above initially but we should design our ### Summary -Nimble will provide a base class that can be derived from to define columns that call a formatting function to render their data as text. Clients which require app-specific formatting logic to support above use cases like 5 (custom unit logic) will define custom columns in their application that derive from this base class. +Nimble will provide base classes that can be derived from to define columns that call a formatting function to render their data as text. Clients which require app-specific formatting logic to support above use cases like 5 (custom unit logic) will define custom columns in their application that derive from these base classes. -Nimble will also provide several columns that derive from this base class and provide higher level formatting APIs for specific data types. We plan to provide column implementations that can handle the above use cases 1-4 (numeric formatting and static units) in a first pass with 6 and 7 (enum/boolean and date) coming later. These will be easier to use than the above custom column approach: +Nimble will also provide several columns that derive from these base classes and provide higher level formatting APIs for specific data types. We plan to provide column implementations that can handle the above use cases 1-4 (numeric formatting and static units) in a first pass with 6 and 7 (enum/boolean and date) coming later. These will be easier to use than the above custom column approach: - the columns will be configurable via HTML attributes, saving clients from writing JS code (a particular challenge in Blazor) - - they provide strict type validation of the data record + - they provide strict type validation of the data field - clients don't need to manage the lifecycle of registering a new column custom element in their application -### Formatted text column base class +### Formatted text column base classes *Originally called "Alternative 2: Client specifies formatting function"* -When configuring a column, clients could provide a callback function that converts data of any supported type into a formatted string. +Nimble will provide abstract base classes, templates, and styles which handle rendering a string as text. Just like `nimble-table-column-text` today, these columns will: +- offer attributes to control which field is displayed and placeholder text when that field isn't a number. +- sort and group by the field value, not the display value. +- allow sizing by fractional widths with a minimum pixel width. +- truncate using an ellipsis and show a tooltip on hover when the value is truncated -There isn't a good way to set a function as an attribute value on a column, so the function would be specified in JS code via clients overriding an abstract base class and registering a new column type: +The base classes provided will be: +- `TableColumnTextBase` - specifies the custom element logic to configure the column +- `TableColumnTextCellViewBase` - derives from `TableCellView` to specify the custom element logic that renders a cell +- `TableColumnTextGroupHeaderViewBase` - derives from `TableGroupHeaderView` to specify the custom element logic that renders a group row + +Both clients and Nimble itself will derive from these base classes to specify the type of data that the column supports and how to convert it to a string. They will register the derived classes as custom elements using the same FAST APIs that Nimble itself uses. + +*** Use column custom element in an application** ```html @@ -78,39 +90,93 @@ There isn't a good way to set a function as an attribute value on a column, so t ``` +***Define and register column custom element** + ```ts -class MyAppProgressColumn : NimbleFormattedTextColumnBase { - public override format(value: number) : string { - return `${100 * value}%`; +export class MyAppProgressColumn extends TableColumnTextBase { + public constructor() { + super({ + cellRecordFieldNames: ['value'], + cellViewTag: tableColumnNumericTextCellViewTag, + groupHeaderViewTag: tableColumnNumericTextGroupHeaderTag + }); + this.columnInternals.sortOperation = TableColumnSortOperation.basic; } +} - public override shouldUsePlaceholder(value: number | undefined) : boolean { - return value === undefined; +const myAppProgressColumn = MyAppProgressColumn.compose({ + baseName: 'table-column-progress', + template, + styles +}); + +DesignSystem.getOrCreate() + .withPrefix('my-app') + .register(myAppProgressColumn()); +export const myAppProgressColumnTag = DesignSystem.tagFor(MyAppProgressColumn); +``` + +***Specify formatting of cells and group headers in their custom elements** + +```ts +export class MyAppProgressColumnCellView extends TableColumnTextCellViewBase< +TableColumnNumericTextCellRecord, +TableColumnNumericTextColumnConfig +> { + public override get text(): string { + return `${100 * this.cellRecord.value}%`; + } + + public override get placeholder(): string { + return this.columnConfig.placeholder; + } + + public override get shouldUsePlaceholder(): boolean { + return typeof this.cellRecord.value !== 'number'; + } +} + +export class MyAppProgressColumnGroupHeaderView extends TableColumnTextGroupHeaderViewBase< +TableNumberFieldValue, +TableColumnNumericTextColumnConfig +> { + public override get text(): string { + return `${100 * this.groupHeaderValue}%`; + } + + public override get placeholder(): string { + return this.columnConfig.placeholder; + } + + public override get shouldUsePlaceholder(): boolean { + return typeof this.groupHeaderValue !== 'number'; } } -MyAppProgressColumn.registerColumn('my-app-progress-column'); +// Not shown: registering the above two custom elements ``` -Some of this is prototyped in the [number-column-prototype branch](https://github.com/ni/nimble/compare/main...number-column-prototype?expand=1). +This is prototyped in the [formatted-text-column branch](https://github.com/ni/nimble/compare/main...users/jattas/formatted-text-column?expand=1). + ### Nimble formatted text columns *Originally called "Alternative 3: Nimble provides column implementation for common use cases"* -#### Numeric text column +#### Text column + +`nimble-table-column-text` will continue to present the same API it does today, but will derive from the base classes described above. + +#### Number column + -We will introduce `nimble-table-column-numeric` which formats a numeric field value and displays it as text. It will offer sufficient configuration to support use cases 1-4 above. +Nimble could introduce `nimble-table-column-number` which formats a numeric field value and displays it as text. It will offer sufficient configuration to support use cases 1-4 above. -Similar to `nimble-table-column-text`: -- it will offer attributes to control which field is displayed and placeholder text when that field isn't a number. -- it will sort and group by the field value, not the display value. -- it will allow sizing by fractional widths with a minimum pixel width. -- it will truncate using an ellipsis and show a tooltip on hover when the value is truncated +The API will be specified in a future update to this HLD. The primary formatting API will leverage the native browser [`Intl.NumberFormat` API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat) which gives highly configurable formatting with great documentation. It supports features like locale-specific formatting, decimal separators, thousands separators, digits of precision, and units. Since it doesn't support some unit strings required by clients, the column will also offer ways to set a fixed prefix or suffix on every number. -##### ``nimble-table-column-numeric` API +##### ``nimble-table-column-number` API _*Props/Attrs*_ - `field-name` - From 730c23e007d71db91b78b2b4d46612e69e632efe Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Wed, 3 May 2023 10:26:38 -0500 Subject: [PATCH 29/45] Spec updates --- .../table-column-formatted-text.md | 52 ++++--------------- 1 file changed, 11 insertions(+), 41 deletions(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index 137b93e3c5..9d948176c4 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -2,7 +2,7 @@ ## Overview -Clients will wish to display non-string text data in table columns for use cases like the following: +Clients will wish to display non-string data as text in table columns for use cases like the following: 1. integer data like counts, formatted to be displayed with no trailing decimals ("4", "100") 2. floating point data formatted to display values in standard ways ("3.1415", "1.04E47", "Infinity", "-0.03") @@ -16,7 +16,7 @@ Clients will wish to display non-string text data in table columns for use cases In all of the above cases: -- data should be sortable and groupable by its actual numeric value, not the string representation +- data should be sortable and groupable by its actual value, not the string representation - text styling like font and alignment should be provided by Nimble - columns should support i18n behaviors like decimal separators, date/time formats, and localized content - there should be an option to show "placeholder" text if no value is specified @@ -172,35 +172,10 @@ This is prototyped in the [formatted-text-column branch](https://github.com/ni/n Nimble could introduce `nimble-table-column-number` which formats a numeric field value and displays it as text. It will offer sufficient configuration to support use cases 1-4 above. -The API will be specified in a future update to this HLD. - -The primary formatting API will leverage the native browser [`Intl.NumberFormat` API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat) which gives highly configurable formatting with great documentation. It supports features like locale-specific formatting, decimal separators, thousands separators, digits of precision, and units. Since it doesn't support some unit strings required by clients, the column will also offer ways to set a fixed prefix or suffix on every number. - -##### ``nimble-table-column-number` API - -_*Props/Attrs*_ -- `field-name` - -- `placeholder` - The string value to use if the value of the field is `undefined`, `null`, `NaN`, or isn't of type `number`. Note that other "special" values like `Infinity` will be formatted and displayed. -- TODO: ALIGNMENT -- `prefix` - A string to append before the formatted value of each cell. It will not include any spacing. -- `suffix` - A string to append after the formatted value of each cell. It will not include any spacing. -- `number-format-locales` - Corresponds to the [`locales` parameter of `NumberFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat#parameters). Note that initially we will not support an array of locales; if this is necessary we could consider parsing this field as a comma-separated list. -- `number-format-options-*` - attributes that correspond to the properties of the [`options` parameter of `NumberFormat`]. Each property name will be converted from `camelCase` to `dash-case`. For example, `number-format-options-compact-display="long"` or `number-format-options-currency-display="narrowSymbol"`. - -For values being passed through to the `NumberFormat` API we will provide types similar to [the TypeScript types from the browser API](https://github.com/microsoft/TypeScript/blob/0f724c04308e20d93d397e82b11f82ad6f810c44/src/lib/es2020.intl.d.ts#L232). Default values if the attribute is not provided will match the `NumberFormat` API. - +The API will be specified in a future update to this document. Below is **an example API** that leverages the native browser [`Intl.NumberFormat` API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat): this is intended to help visualize what the API *could* look like, but isn't yet finalized. ```html - - Progress - - - Count - + - Voltage - + ``` - - #### Boolean Text Column -We will eventually provide an column type that maps boolean values to localized strings. This is an example API but the details will be updated in this document before implementation. +Nimble could introduce `nimble-table-column-boolean` which maps boolean values to localized strings. The API will be specified in a future update to this document but here is an example. ```html @@ -242,9 +215,9 @@ We will eventually provide an column type that maps boolean values to localized ``` -##### Example E: Enum Text Column +##### Enum Text Column -We will eventually provide an column type that maps enum values to localized strings. This is an example API but the details will be updated in this document before implementation. +Nimble could introduce a column type that maps enum values to localized strings. This is an example API but the details will be updated in this document before implementation. ```html @@ -277,8 +250,6 @@ I propose we **would not** encourage Blazor clients to write formatting code in ### Visual Appearance -### -TODO Items I asked Mert to include on hyperlink spec --- @@ -355,7 +326,6 @@ Nimble already has a mechanism for clients to provide custom columns by deriving - Potential cross-app inconsistency if formatting code isn't shared - ### States ### Accessibility @@ -379,4 +349,4 @@ Nimble already has a mechanism for clients to provide custom columns by deriving ## Open Issues 1. API to configure text alignment of column content and column headers (e.g. right align numeric columns but left align string columns). We'll update the HLD with a recommendation once we reach consensus on which alternatives to pursue (you're welcome to comment with ideas now though). -2. The APIs in this document are examples, not yet proposals. Once we agree on high-level direction I will do more prototyping to propose concrete APIs. +2. Resolve overlap between this document and the [Mapping Table Column proposal](https://github.com/ni/nimble/pull/1220/). From 9f4ff6b6649e66cd55b67927f944309999f5bff9 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Wed, 3 May 2023 10:46:43 -0500 Subject: [PATCH 30/45] Capture formatting function alternative --- .../specs/table-column-specs/table-column-formatted-text.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index 9d948176c4..472126a58e 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -260,9 +260,10 @@ I propose we **would not** encourage Blazor clients to write formatting code in #### Other ways to provide a formatting function 1. setting the formatting function as a property on a column element. -2. setting an [`Intl.NumberFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) object as a property on a column element. +2. registering a formatter with Nimble using a unique string name and then configuring the column to use that formatter by an attribute (described in more detail [in Milan's comment](https://github.com/ni/nimble/pull/1054#discussion_r1136319757)) +3. setting an [`Intl.NumberFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat) object as a property on a column element. -Both of these require JS code which finds a specific column element and configures it. This is difficult to achieve in Blazor. +All of these require JS code which finds a specific column element and configures it. This is difficult to achieve in Blazor. #### Use `table-column-text` From cb3b7bef9fa86767705a53754ca50b5513275a4e Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Wed, 3 May 2023 10:50:51 -0500 Subject: [PATCH 31/45] format --- .../table-column-formatted-text.md | 65 +++++++++---------- 1 file changed, 31 insertions(+), 34 deletions(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index 472126a58e..803815bb99 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -56,28 +56,31 @@ We may not choose to support all of the above initially but we should design our Nimble will provide base classes that can be derived from to define columns that call a formatting function to render their data as text. Clients which require app-specific formatting logic to support above use cases like 5 (custom unit logic) will define custom columns in their application that derive from these base classes. Nimble will also provide several columns that derive from these base classes and provide higher level formatting APIs for specific data types. We plan to provide column implementations that can handle the above use cases 1-4 (numeric formatting and static units) in a first pass with 6 and 7 (enum/boolean and date) coming later. These will be easier to use than the above custom column approach: - - the columns will be configurable via HTML attributes, saving clients from writing JS code (a particular challenge in Blazor) - - they provide strict type validation of the data field - - clients don't need to manage the lifecycle of registering a new column custom element in their application + +- the columns will be configurable via HTML attributes, saving clients from writing JS code (a particular challenge in Blazor) +- they provide strict type validation of the data field +- clients don't need to manage the lifecycle of registering a new column custom element in their application ### Formatted text column base classes -*Originally called "Alternative 2: Client specifies formatting function"* +_Originally called "Alternative 2: Client specifies formatting function"_ Nimble will provide abstract base classes, templates, and styles which handle rendering a string as text. Just like `nimble-table-column-text` today, these columns will: -- offer attributes to control which field is displayed and placeholder text when that field isn't a number. -- sort and group by the field value, not the display value. -- allow sizing by fractional widths with a minimum pixel width. -- truncate using an ellipsis and show a tooltip on hover when the value is truncated + +- offer attributes to control which field is displayed and placeholder text when that field isn't a number. +- sort and group by the field value, not the display value. +- allow sizing by fractional widths with a minimum pixel width. +- truncate using an ellipsis and show a tooltip on hover when the value is truncated The base classes provided will be: -- `TableColumnTextBase` - specifies the custom element logic to configure the column -- `TableColumnTextCellViewBase` - derives from `TableCellView` to specify the custom element logic that renders a cell -- `TableColumnTextGroupHeaderViewBase` - derives from `TableGroupHeaderView` to specify the custom element logic that renders a group row + +- `TableColumnTextBase` - specifies the custom element logic to configure the column +- `TableColumnTextCellViewBase` - derives from `TableCellView` to specify the custom element logic that renders a cell +- `TableColumnTextGroupHeaderViewBase` - derives from `TableGroupHeaderView` to specify the custom element logic that renders a group row Both clients and Nimble itself will derive from these base classes to specify the type of data that the column supports and how to convert it to a string. They will register the derived classes as custom elements using the same FAST APIs that Nimble itself uses. -*** Use column custom element in an application** +**Use column custom element in an application** ```html @@ -90,7 +93,7 @@ Both clients and Nimble itself will derive from these base classes to specify th ``` -***Define and register column custom element** +**Define and register column custom element** ```ts export class MyAppProgressColumn extends TableColumnTextBase { @@ -110,18 +113,16 @@ const myAppProgressColumn = MyAppProgressColumn.compose({ styles }); -DesignSystem.getOrCreate() - .withPrefix('my-app') - .register(myAppProgressColumn()); +DesignSystem.getOrCreate().withPrefix('my-app').register(myAppProgressColumn()); export const myAppProgressColumnTag = DesignSystem.tagFor(MyAppProgressColumn); ``` -***Specify formatting of cells and group headers in their custom elements** +**\*Specify formatting of cells and group headers in their custom elements** ```ts export class MyAppProgressColumnCellView extends TableColumnTextCellViewBase< -TableColumnNumericTextCellRecord, -TableColumnNumericTextColumnConfig + TableColumnNumericTextCellRecord, + TableColumnNumericTextColumnConfig > { public override get text(): string { return `${100 * this.cellRecord.value}%`; @@ -137,8 +138,8 @@ TableColumnNumericTextColumnConfig } export class MyAppProgressColumnGroupHeaderView extends TableColumnTextGroupHeaderViewBase< -TableNumberFieldValue, -TableColumnNumericTextColumnConfig + TableNumberFieldValue, + TableColumnNumericTextColumnConfig > { public override get text(): string { return `${100 * this.groupHeaderValue}%`; @@ -158,10 +159,9 @@ TableColumnNumericTextColumnConfig This is prototyped in the [formatted-text-column branch](https://github.com/ni/nimble/compare/main...users/jattas/formatted-text-column?expand=1). - ### Nimble formatted text columns -*Originally called "Alternative 3: Nimble provides column implementation for common use cases"* +_Originally called "Alternative 3: Nimble provides column implementation for common use cases"_ #### Text column @@ -169,18 +169,18 @@ This is prototyped in the [formatted-text-column branch](https://github.com/ni/n #### Number column - Nimble could introduce `nimble-table-column-number` which formats a numeric field value and displays it as text. It will offer sufficient configuration to support use cases 1-4 above. -The API will be specified in a future update to this document. Below is **an example API** that leverages the native browser [`Intl.NumberFormat` API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat): this is intended to help visualize what the API *could* look like, but isn't yet finalized. +The API will be specified in a future update to this document. Below is **an example API** that leverages the native browser [`Intl.NumberFormat` API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat): this is intended to help visualize what the API _could_ look like, but isn't yet finalized. + ```html Count @@ -190,7 +190,7 @@ The API will be specified in a future update to this document. Below is **an exa field-name="voltage" number-format-locales="en-US" number-format-options-style="decimal" - number-format-options-use-grouping=false + number-format-options-use-grouping="false" suffix=" V" > Voltage @@ -198,7 +198,7 @@ The API will be specified in a future update to this document. Below is **an exa ``` -#### Boolean Text Column +#### Boolean Text Column Nimble could introduce `nimble-table-column-boolean` which maps boolean values to localized strings. The API will be specified in a future update to this document but here is an example. @@ -250,7 +250,6 @@ I propose we **would not** encourage Blazor clients to write formatting code in ### Visual Appearance - --- ## Implementation @@ -267,7 +266,7 @@ All of these require JS code which finds a specific column element and configure #### Use `table-column-text` -*Originally called "Alternative 1"* +_Originally called "Alternative 1"_ With the changes proposed in [HLD for programmatically sorting columns](../table-column-sort-hld.md) to allow a column to be sorted by a different data field than the one being used for display, many of the above use cases could be met with minor changes to the existing text column. Clients would write custom logic to populate their data with a new string field that contains formatted values. Then they would configure the table to display that string field while sorting by the original numeric field. @@ -308,10 +307,9 @@ table.setData(tableData); - Exposing `operand-data-record-name` to be set by client code rather than column definition - Exposing an API for clients to indicate their data should be styled as numeric data (right aligned) - #### Client provides custom column implementation for each use case -*Originally called "Alternative 4"* +_Originally called "Alternative 4"_ Nimble already has a mechanism for clients to provide custom columns by deriving from a base class, specifying the data fields / template / styling, and registering the column type with Nimble. We could ask clients to use this mechanism for text column types. @@ -326,7 +324,6 @@ Nimble already has a mechanism for clients to provide custom columns by deriving - Difficult to enforce styling differences between string and numeric columns (e.g. right vs left text alignment) - Potential cross-app inconsistency if formatting code isn't shared - ### States ### Accessibility From 04d2c35a7bcae7fd7dbe5be3385fd6ec1aaeb4a1 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Wed, 3 May 2023 15:51:30 -0500 Subject: [PATCH 32/45] Boolean and enum solved by mapping column --- .../table-column-formatted-text.md | 44 +++---------------- 1 file changed, 6 insertions(+), 38 deletions(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index 803815bb99..a0bce1d9a8 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -11,8 +11,7 @@ Clients will wish to display non-string data as text in table columns for use ca 5. numeric values with custom unit logic. Examples: - a file size column that could show the value 1000 as "1000 bytes" but the value 1024 as "1KB" - an elapsed time column that could show 63 seconds as "00:01:03" or "1 minute, 3 seconds" -6. enum and boolean values formatted as localized strings (0 -> "Fail", 1 -> "Pass") -7. date/time values formatted in various ways ("October 27", "yesterday", "2023-12-28 08:27") +6. date/time values formatted in various ways ("October 27", "yesterday", "2023-12-28 08:27") In all of the above cases: @@ -30,8 +29,6 @@ We may not choose to support all of the above initially but we should design our [Date/time column work item](https://github.com/ni/nimble/issues/1014) -[Boolean text column work item](https://github.com/ni/nimble/issues/1103) - [Table Column API](../table-columns-hld.md) [Table Spec](../README.md) @@ -46,6 +43,7 @@ We may not choose to support all of the above initially but we should design our - Editable numbers. This is not supported by the text column yet either. - Numeric formatting for `nimble-number-field`. While we may choose to expose similar APIs for its numeric formatting, the complexities of it being an editable input control make this out of scope for now. - Customizing the styling of the column content (other than possibly text alignment). This is not supported by the text column yet either. +- Enum and boolean values formatted as localized strings (0 -> "Fail", 1 -> "Pass"). These will likely use the [mapping column being discussed elsewhere](https://github.com/ni/nimble/pull/1220). --- @@ -55,7 +53,7 @@ We may not choose to support all of the above initially but we should design our Nimble will provide base classes that can be derived from to define columns that call a formatting function to render their data as text. Clients which require app-specific formatting logic to support above use cases like 5 (custom unit logic) will define custom columns in their application that derive from these base classes. -Nimble will also provide several columns that derive from these base classes and provide higher level formatting APIs for specific data types. We plan to provide column implementations that can handle the above use cases 1-4 (numeric formatting and static units) in a first pass with 6 and 7 (enum/boolean and date) coming later. These will be easier to use than the above custom column approach: +Nimble will also provide several columns that derive from these base classes and provide higher level formatting APIs for specific data types. We plan to provide column implementations that can handle the above use cases 1-4 (numeric formatting and static units) in a first pass with 6 (date) coming later. These will be easier to use than the above custom column approach: - the columns will be configurable via HTML attributes, saving clients from writing JS code (a particular challenge in Blazor) - they provide strict type validation of the data field @@ -198,39 +196,9 @@ The API will be specified in a future update to this document. Below is **an exa ``` -#### Boolean Text Column - -Nimble could introduce `nimble-table-column-boolean` which maps boolean values to localized strings. The API will be specified in a future update to this document but here is an example. - -```html - - - Test Result - - -``` +##### Date Column -##### Enum Text Column - -Nimble could introduce a column type that maps enum values to localized strings. This is an example API but the details will be updated in this document before implementation. - -```html - - - Status - Pass - Fail - - -``` +Nimble could introduce `nimble-table-column-date-text` which maps date-time values to localized strings. The API will be specified in a future update to this document. It will need to consider cases like date formatting (both for locale and other reasons) and how to provide localized strings. ### API @@ -347,4 +315,4 @@ Nimble already has a mechanism for clients to provide custom columns by deriving ## Open Issues 1. API to configure text alignment of column content and column headers (e.g. right align numeric columns but left align string columns). We'll update the HLD with a recommendation once we reach consensus on which alternatives to pursue (you're welcome to comment with ideas now though). -2. Resolve overlap between this document and the [Mapping Table Column proposal](https://github.com/ni/nimble/pull/1220/). +2. Column names From 06212b45d24e6d86bae71cf678c08d0cbdd7bef3 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Wed, 3 May 2023 15:56:44 -0500 Subject: [PATCH 33/45] Minor edits --- .../table-column-formatted-text.md | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index a0bce1d9a8..ba0fa72a90 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -39,10 +39,10 @@ We may not choose to support all of the above initially but we should design our ### Non-goals -- Combinations of the use cases listed above in a single column. This will be needed in cases where the source data isn't uniformly typed (e.g. SLE tag values or notebook outputs). This HLD focuses on uniform data types; future HLDs will discuss ways to configure multiple types of columns to be conditionally displayed together. +- Combinations of the use cases listed above in a single column. This will be needed in cases where the source data isn't uniformly typed (e.g. SLE tag values or notebook outputs). This HLD focuses on uniform data types; future HLDs may discuss ways to configure multiple types of columns to be conditionally displayed together. - Editable numbers. This is not supported by the text column yet either. - Numeric formatting for `nimble-number-field`. While we may choose to expose similar APIs for its numeric formatting, the complexities of it being an editable input control make this out of scope for now. -- Customizing the styling of the column content (other than possibly text alignment). This is not supported by the text column yet either. +- Customizing the styling of the column content (other than text alignment). This is not supported by the text column yet either. - Enum and boolean values formatted as localized strings (0 -> "Fail", 1 -> "Pass"). These will likely use the [mapping column being discussed elsewhere](https://github.com/ni/nimble/pull/1220). --- @@ -61,8 +61,6 @@ Nimble will also provide several columns that derive from these base classes and ### Formatted text column base classes -_Originally called "Alternative 2: Client specifies formatting function"_ - Nimble will provide abstract base classes, templates, and styles which handle rendering a string as text. Just like `nimble-table-column-text` today, these columns will: - offer attributes to control which field is displayed and placeholder text when that field isn't a number. @@ -159,8 +157,6 @@ This is prototyped in the [formatted-text-column branch](https://github.com/ni/n ### Nimble formatted text columns -_Originally called "Alternative 3: Nimble provides column implementation for common use cases"_ - #### Text column `nimble-table-column-text` will continue to present the same API it does today, but will derive from the base classes described above. @@ -234,8 +230,6 @@ All of these require JS code which finds a specific column element and configure #### Use `table-column-text` -_Originally called "Alternative 1"_ - With the changes proposed in [HLD for programmatically sorting columns](../table-column-sort-hld.md) to allow a column to be sorted by a different data field than the one being used for display, many of the above use cases could be met with minor changes to the existing text column. Clients would write custom logic to populate their data with a new string field that contains formatted values. Then they would configure the table to display that string field while sorting by the original numeric field. ```html @@ -277,8 +271,6 @@ table.setData(tableData); #### Client provides custom column implementation for each use case -_Originally called "Alternative 4"_ - Nimble already has a mechanism for clients to provide custom columns by deriving from a base class, specifying the data fields / template / styling, and registering the column type with Nimble. We could ask clients to use this mechanism for text column types. **Pros:** @@ -314,5 +306,5 @@ Nimble already has a mechanism for clients to provide custom columns by deriving ## Open Issues -1. API to configure text alignment of column content and column headers (e.g. right align numeric columns but left align string columns). We'll update the HLD with a recommendation once we reach consensus on which alternatives to pursue (you're welcome to comment with ideas now though). +1. API to configure text alignment of column content and column headers (e.g. right align numeric columns but left align string columns and numeric columns with non-uniform formatting). We'll update the HLD with a recommendation once we reach consensus on which alternatives to pursue (you're welcome to comment with ideas now though). 2. Column names From 49aded340a03c8484e6803e99d058ef9e5a04856 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Wed, 3 May 2023 16:11:34 -0500 Subject: [PATCH 34/45] Column naming --- .../table-column-formatted-text.md | 26 ++++++++++++++----- 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index ba0fa72a90..e2199fee05 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -157,13 +157,22 @@ This is prototyped in the [formatted-text-column branch](https://github.com/ni/n ### Nimble formatted text columns +Nimble will provide several columns that derive from the above base classes and provide higher level text formatting APIs for specific data types. + +#### Column naming + +Columns which render as text will use the following naming scheme: `nimble-table-column[-type]-text`. + - All columns start with `nimble-table-column-`. + - The `-type` section distinguishes between columns that render as text but require different configuration (e.g. `-numeric` or `-date`). We omit it for `nimble-table-column-text` since it seems redundant and would be a low-value breaking change. + - Adding `-text` allows for future column types that render the same data in different ways with different configuration. e.g. `numeric-progress`, `numeric-input`. + #### Text column `nimble-table-column-text` will continue to present the same API it does today, but will derive from the base classes described above. -#### Number column +#### Numeric column -Nimble could introduce `nimble-table-column-number` which formats a numeric field value and displays it as text. It will offer sufficient configuration to support use cases 1-4 above. +Nimble could introduce `nimble-table-column-numeric-text` which formats a numeric field value and displays it as text. It will offer sufficient configuration to support use cases 1-4 above. The API will be specified in a future update to this document. Below is **an example API** that leverages the native browser [`Intl.NumberFormat` API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/NumberFormat/NumberFormat): this is intended to help visualize what the API _could_ look like, but isn't yet finalized. @@ -194,7 +203,11 @@ The API will be specified in a future update to this document. Below is **an exa ##### Date Column -Nimble could introduce `nimble-table-column-date-text` which maps date-time values to localized strings. The API will be specified in a future update to this document. It will need to consider cases like date formatting (both for locale and other reasons) and how to provide localized strings. +Nimble could introduce `nimble-table-column-date-text` which maps date-time values to localized strings. The API will be specified in a future update to this document. It will need to consider cases like date formatting (both for locale and other reasons) and how to provide localized strings, possibly by exposing [the native browser `Intl.DateTimeFormat` API](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat). + +--- + +_These sections will be populated in a future update_ ### API @@ -210,8 +223,6 @@ _Type Reference_ ### Blazor integration -I propose we **would not** encourage Blazor clients to write formatting code in .NET due to performance concerns. - ### Visual Appearance --- @@ -284,6 +295,10 @@ Nimble already has a mechanism for clients to provide custom columns by deriving - Difficult to enforce styling differences between string and numeric columns (e.g. right vs left text alignment) - Potential cross-app inconsistency if formatting code isn't shared +--- + +_These sections will be populated in a future update_ + ### States ### Accessibility @@ -307,4 +322,3 @@ Nimble already has a mechanism for clients to provide custom columns by deriving ## Open Issues 1. API to configure text alignment of column content and column headers (e.g. right align numeric columns but left align string columns and numeric columns with non-uniform formatting). We'll update the HLD with a recommendation once we reach consensus on which alternatives to pursue (you're welcome to comment with ideas now though). -2. Column names From 450193981d09eac1f21c6d6eddde385837ab226f Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Wed, 3 May 2023 16:13:10 -0500 Subject: [PATCH 35/45] formatting --- .../table-column-specs/table-column-formatted-text.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index e2199fee05..c997c9c6a7 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -162,9 +162,10 @@ Nimble will provide several columns that derive from the above base classes and #### Column naming Columns which render as text will use the following naming scheme: `nimble-table-column[-type]-text`. - - All columns start with `nimble-table-column-`. - - The `-type` section distinguishes between columns that render as text but require different configuration (e.g. `-numeric` or `-date`). We omit it for `nimble-table-column-text` since it seems redundant and would be a low-value breaking change. - - Adding `-text` allows for future column types that render the same data in different ways with different configuration. e.g. `numeric-progress`, `numeric-input`. + +- All columns start with `nimble-table-column-`. +- The `-type` section distinguishes between columns that render as text but require different configuration (e.g. `-numeric` or `-date`). We omit it for `nimble-table-column-text` since it seems redundant and would be a low-value breaking change. +- Adding `-text` allows for future column types that render the same data in different ways with different configuration. e.g. `numeric-progress`, `numeric-input`. #### Text column From 52ca2c0b7f76214a1e33e04bedf2aacd5d8f91f2 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Wed, 3 May 2023 16:41:49 -0500 Subject: [PATCH 36/45] Extra * --- .../specs/table-column-specs/table-column-formatted-text.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index c997c9c6a7..a8edbfd993 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -113,7 +113,7 @@ DesignSystem.getOrCreate().withPrefix('my-app').register(myAppProgressColumn()); export const myAppProgressColumnTag = DesignSystem.tagFor(MyAppProgressColumn); ``` -**\*Specify formatting of cells and group headers in their custom elements** +**Specify formatting of cells and group headers in their custom elements** ```ts export class MyAppProgressColumnCellView extends TableColumnTextCellViewBase< From 8255146e49821d2eac21cf48abca4ea9247ff31f Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Wed, 3 May 2023 16:55:36 -0500 Subject: [PATCH 37/45] text alignment plan --- .../specs/table-column-specs/table-column-formatted-text.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index a8edbfd993..4d3de8b397 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -322,4 +322,4 @@ _These sections will be populated in a future update_ ## Open Issues -1. API to configure text alignment of column content and column headers (e.g. right align numeric columns but left align string columns and numeric columns with non-uniform formatting). We'll update the HLD with a recommendation once we reach consensus on which alternatives to pursue (you're welcome to comment with ideas now though). +1. API to configure text alignment of column content and column headers (e.g. right align numeric columns but left align string columns and numeric columns with non-uniform formatting). We'll update the HLD with a recommendation when we start working on columns that need it (you're welcome to comment with ideas now though). From a4b6367e3c358720ecdffa6ef824b1eb425f1ed1 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Thu, 4 May 2023 19:59:38 -0500 Subject: [PATCH 38/45] Add notes to alignment open issue --- .../specs/table-column-specs/table-column-formatted-text.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index 4d3de8b397..dc3a593501 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -322,4 +322,4 @@ _These sections will be populated in a future update_ ## Open Issues -1. API to configure text alignment of column content and column headers (e.g. right align numeric columns but left align string columns and numeric columns with non-uniform formatting). We'll update the HLD with a recommendation when we start working on columns that need it (you're welcome to comment with ideas now though). +1. API to configure text alignment of column content, placeholder text, and column headers (e.g. right align numeric columns but left align string columns and numeric columns with non-uniform formatting; [more discussion here](https://github.com/ni/nimble/issues/887)). We'll update the HLD with a recommendation when we start working on columns that need it (you're welcome to comment with ideas now though). From 9a68ab05e7e0def9e857b251b77620b0f04fdb13 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Wed, 10 May 2023 14:51:27 -0500 Subject: [PATCH 39/45] De-emphasize app-defined columns --- .../table-column-specs/table-column-formatted-text.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index dc3a593501..81911ed29f 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -51,9 +51,13 @@ We may not choose to support all of the above initially but we should design our ### Summary -Nimble will provide base classes that can be derived from to define columns that call a formatting function to render their data as text. Clients which require app-specific formatting logic to support above use cases like 5 (custom unit logic) will define custom columns in their application that derive from these base classes. +Nimble will provide base classes that can be derived from to define columns that call a formatting function to render their data as text. -Nimble will also provide several columns that derive from these base classes and provide higher level formatting APIs for specific data types. We plan to provide column implementations that can handle the above use cases 1-4 (numeric formatting and static units) in a first pass with 6 (date) coming later. These will be easier to use than the above custom column approach: +Nimble will provide several columns that derive from these base classes and provide higher level formatting APIs for specific data types. We plan to provide column implementations that can handle the above use cases 1-4 (numeric formatting and static units) in a first pass with 6 (date) coming later. + +Clients which require app-specific formatting logic to support above use cases like 5 (custom unit logic) will define custom columns in their application that derive from these base classes. + +We'll strongly encourage clients to prefer columns defined in Nimble as these will be easier to use than custom columns defined in their application: - the columns will be configurable via HTML attributes, saving clients from writing JS code (a particular challenge in Blazor) - they provide strict type validation of the data field From cb7b604aea970d6203bc60623be1be5774978000 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Wed, 10 May 2023 14:54:49 -0500 Subject: [PATCH 40/45] NaN --- .../specs/table-column-specs/table-column-formatted-text.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index 81911ed29f..023bde73fd 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -67,7 +67,7 @@ We'll strongly encourage clients to prefer columns defined in Nimble as these wi Nimble will provide abstract base classes, templates, and styles which handle rendering a string as text. Just like `nimble-table-column-text` today, these columns will: -- offer attributes to control which field is displayed and placeholder text when that field isn't a number. +- offer attributes to control which field is displayed and placeholder text when that field isn't of type "number" (values like Infinity and NaN are considered numbers and will be displayed as such). - sort and group by the field value, not the display value. - allow sizing by fractional widths with a minimum pixel width. - truncate using an ellipsis and show a tooltip on hover when the value is truncated From 2c42d2977850ce4ddd959b4d42cb92ffef30bde4 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Wed, 10 May 2023 14:57:12 -0500 Subject: [PATCH 41/45] test cases --- .../specs/table-column-specs/table-column-formatted-text.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index 023bde73fd..fb7853c225 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -318,6 +318,10 @@ _These sections will be populated in a future update_ ### Test Plan +This will be filled out in more detail, but some reminders: +- handle number edge cases (-Inf, Inf, -0, +0, NaN, Number.MAX_SAFE_INTEGER + n, Number.MIN_SAFE_INTEGER -n) as numbers +- handle non-number edge cases (strings containing numbers, undefined, null) + ### Tooling ### Documentation From 091f5d79894df147256a0d260b6dc8cb48fd46c2 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Wed, 10 May 2023 17:06:33 -0500 Subject: [PATCH 42/45] Naming guidelines --- packages/nimble-components/CONTRIBUTING.md | 11 +++++++ .../src/table/specs/table-columns-hld.md | 31 +++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/packages/nimble-components/CONTRIBUTING.md b/packages/nimble-components/CONTRIBUTING.md index 3d351ac673..4545396d2e 100644 --- a/packages/nimble-components/CONTRIBUTING.md +++ b/packages/nimble-components/CONTRIBUTING.md @@ -404,6 +404,17 @@ Nimble includes three NI-brand aligned themes (i.e. `light`, `dark`, & `color`). When creating a new component, create a `*-matrix.stories.ts` Storybook file to confirm that the component reflects the design intent across all themes and states. +## Component naming + +Component custom element names are specified in `index.ts` when registering the element. Use the following structure when naming components. + +`nimble[-category][-variant]-presentation` + +1. All Nimble custom elements are prefixed with `nimble-` to avoid name collisions with other component libraries. Applications should choose their own unique prefix if they define their own elements. +2. **category** can be used to group similar components together alphabetically. Examples include `icon` and `table-column`. +3. **variant** can be used to distinguish alternate configurations of one presentation. For example, `anchor-`, `card-`, `menu-`, and `toggle-` are all variants of the `button` presentation. The primary configuration can omit the `variant` segment (e.g. `nimble-button`). +4. **presentation** describes the visual presentation of the component. For example, `button`, `tab`, or `text-field`. + ## Token naming Public names for theme-aware tokens are specified in `src/theme-provider/design-token-names.ts`. Use the following structure when creating new tokens. diff --git a/packages/nimble-components/src/table/specs/table-columns-hld.md b/packages/nimble-components/src/table/specs/table-columns-hld.md index 3852c77a5b..6eecd81c59 100644 --- a/packages/nimble-components/src/table/specs/table-columns-hld.md +++ b/packages/nimble-components/src/table/specs/table-columns-hld.md @@ -69,6 +69,37 @@ template: ``` +### Column Type Philosophy + +These guidelines capture how we decide when to create a new column type and how we name those column types. + +New columns can be created for any of the following use cases: +1. a new visual presentation is needed. For example, displaying a number in a progress bar or as text would be two different columns. +2. the same presentation requires significantly different configuration for different use cases. For example, displaying a text representation of a number and a date require different formatting options so they would be different columns. + +Note that displaying data of different types but with the same presentation and configuration should not typically require a new column type. For example, a single column type maps string, numeric, and boolean enumerated values to a text presentation. + +Columns should follow the [Nimble components naming scheme](/packages/nimble-components/CONTRIBUTING.md#component-naming) with these rules: +- the "category" is `table-column` +- the "presentation" describes the cell visual. For example, `text`, `anchor`, or `progress` +- the "variant" can be different configurations of those presentations. For example, `numeric-text` or `date-text`. + +Some potential column names following this convention are listed below. + +``` +nimble-table-column-anchor +nimble-table-column-text +nimble-table-column-numeric-text +nimble-table-column-date-text +nimble-table-column-progress +nimble-table-column-text-field +nimble-table-column-number-field +nimble-table-column-mapping +nimble-table-column-icon +``` + +Note: Despite currently being presented as text, the mapping column is not `nimble-table-column-mapping-text` because it may render with alternate presentations in the future (e.g. icon + text) so "mapping" is considered the presentation. + ### Framework Integration Column elements, and the associated elements used in table cells, will always be FAST-based custom elements. Framework-specific constructs/content are not supported. Standard column types (e.g. text-field, link, icon, etc) will be provided by Nimble. For non-standard column types, clients will be expected to implement a custom column type, which the rest of this document describes in detail. From d5b945f9ea477072e01c1c9f4a6cdde217b12c63 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Wed, 10 May 2023 17:07:43 -0500 Subject: [PATCH 43/45] Formatting --- .../table-column-specs/table-column-formatted-text.md | 7 ++++--- .../nimble-components/src/table/specs/table-columns-hld.md | 2 ++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index fb7853c225..732fef0c1f 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -53,7 +53,7 @@ We may not choose to support all of the above initially but we should design our Nimble will provide base classes that can be derived from to define columns that call a formatting function to render their data as text. -Nimble will provide several columns that derive from these base classes and provide higher level formatting APIs for specific data types. We plan to provide column implementations that can handle the above use cases 1-4 (numeric formatting and static units) in a first pass with 6 (date) coming later. +Nimble will provide several columns that derive from these base classes and provide higher level formatting APIs for specific data types. We plan to provide column implementations that can handle the above use cases 1-4 (numeric formatting and static units) in a first pass with 6 (date) coming later. Clients which require app-specific formatting logic to support above use cases like 5 (custom unit logic) will define custom columns in their application that derive from these base classes. @@ -319,8 +319,9 @@ _These sections will be populated in a future update_ ### Test Plan This will be filled out in more detail, but some reminders: -- handle number edge cases (-Inf, Inf, -0, +0, NaN, Number.MAX_SAFE_INTEGER + n, Number.MIN_SAFE_INTEGER -n) as numbers -- handle non-number edge cases (strings containing numbers, undefined, null) + +- handle number edge cases (-Inf, Inf, -0, +0, NaN, Number.MAX_SAFE_INTEGER + n, Number.MIN_SAFE_INTEGER -n) as numbers +- handle non-number edge cases (strings containing numbers, undefined, null) ### Tooling diff --git a/packages/nimble-components/src/table/specs/table-columns-hld.md b/packages/nimble-components/src/table/specs/table-columns-hld.md index 6eecd81c59..e193afcd01 100644 --- a/packages/nimble-components/src/table/specs/table-columns-hld.md +++ b/packages/nimble-components/src/table/specs/table-columns-hld.md @@ -74,12 +74,14 @@ template: These guidelines capture how we decide when to create a new column type and how we name those column types. New columns can be created for any of the following use cases: + 1. a new visual presentation is needed. For example, displaying a number in a progress bar or as text would be two different columns. 2. the same presentation requires significantly different configuration for different use cases. For example, displaying a text representation of a number and a date require different formatting options so they would be different columns. Note that displaying data of different types but with the same presentation and configuration should not typically require a new column type. For example, a single column type maps string, numeric, and boolean enumerated values to a text presentation. Columns should follow the [Nimble components naming scheme](/packages/nimble-components/CONTRIBUTING.md#component-naming) with these rules: + - the "category" is `table-column` - the "presentation" describes the cell visual. For example, `text`, `anchor`, or `progress` - the "variant" can be different configurations of those presentations. For example, `numeric-text` or `date-text`. From facf34cbcb2690f1f68539b6fca1b23303e3e4c7 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Wed, 10 May 2023 20:54:23 -0500 Subject: [PATCH 44/45] Naming guidance in HLD Co-authored-by: Milan Raj --- .../table-column-specs/table-column-formatted-text.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index 732fef0c1f..13fa10cde7 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -165,11 +165,11 @@ Nimble will provide several columns that derive from the above base classes and #### Column naming -Columns which render as text will use the following naming scheme: `nimble-table-column[-type]-text`. - -- All columns start with `nimble-table-column-`. -- The `-type` section distinguishes between columns that render as text but require different configuration (e.g. `-numeric` or `-date`). We omit it for `nimble-table-column-text` since it seems redundant and would be a low-value breaking change. -- Adding `-text` allows for future column types that render the same data in different ways with different configuration. e.g. `numeric-progress`, `numeric-input`. +Follows the [/packages/nimble-components/src/table/specs +/table-columns-hld.md#column-type-philosophy](Column Type Philosophy) where: +- category: `table-column` +- presentation: `text` +- variants: Different variants are allowed for configurations that vary significantly / don't make sense to add to `table-column-text`, ie for a `table-column-numeric-text` or `table-column-date-text` #### Text column From 7c8c14a644ede72c99730fa6d4e0dc7d772a2c04 Mon Sep 17 00:00:00 2001 From: Jesse Attas Date: Wed, 10 May 2023 21:17:46 -0500 Subject: [PATCH 45/45] Link and formatting --- .../table-column-specs/table-column-formatted-text.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md index 13fa10cde7..d99190b28c 100644 --- a/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md +++ b/packages/nimble-components/src/table/specs/table-column-specs/table-column-formatted-text.md @@ -165,11 +165,12 @@ Nimble will provide several columns that derive from the above base classes and #### Column naming -Follows the [/packages/nimble-components/src/table/specs -/table-columns-hld.md#column-type-philosophy](Column Type Philosophy) where: -- category: `table-column` -- presentation: `text` -- variants: Different variants are allowed for configurations that vary significantly / don't make sense to add to `table-column-text`, ie for a `table-column-numeric-text` or `table-column-date-text` +Follows the [Column Type Philosophy](/packages/nimble-components/src/table/specs +/table-columns-hld.md#column-type-philosophy) where: + +- category: `table-column` +- presentation: `text` +- variants: Different variants are allowed for configurations that vary significantly / don't make sense to add to `table-column-text`, ie for a `table-column-numeric-text` or `table-column-date-text` #### Text column