From 2fb67cc1c5b54565f7620fa48e7297b112c939d5 Mon Sep 17 00:00:00 2001 From: mollykreis <20542556+mollykreis@users.noreply.github.com> Date: Thu, 5 Jan 2023 11:36:27 -0600 Subject: [PATCH 01/15] first pass at spec --- .../src/table/specs/README.md | 12 +- .../src/table/specs/action-menu-hld.md | 106 ++++++++++++++++++ .../table/specs/spec-images/sleActionMenu.png | Bin 0 -> 37256 bytes .../src/table/specs/table-columns-hld.md | 6 + 4 files changed, 118 insertions(+), 6 deletions(-) create mode 100644 packages/nimble-components/src/table/specs/action-menu-hld.md create mode 100644 packages/nimble-components/src/table/specs/spec-images/sleActionMenu.png diff --git a/packages/nimble-components/src/table/specs/README.md b/packages/nimble-components/src/table/specs/README.md index 70cb4e31ec..815ef39980 100644 --- a/packages/nimble-components/src/table/specs/README.md +++ b/packages/nimble-components/src/table/specs/README.md @@ -128,24 +128,24 @@ The various APIs/features of the `nimble-table` will be split up amongst several - Attribute on table to represent parentId? - Define event/property APIs needed for dealing with lazily-loaded hierarchical data (possibly out of scope of initial release) - Describe the UI representation of hierarchical data (there should be a design doc to reference) -- Action Menu - - Define how the action menu gets associated with a particular column - - Define the table-level(column-level?) API(s) for applying an action menu to the table (slot, properties, etc...) +- [Action Menu](action-menu-hld.md) _Properties_ -Placeholder +- `data` - An array of key/value pairs where each item in the array represents one row of data. For more information about the `data` property, refer to the [data API spec](table-data-api.md). _Events_ -- `data` - An array of key/value pairs where each item in the array represents one row of data. For more information about the `data` property, refer to the [data API spec](table-data-api.md). +- `action-menu-opening` - An event that is emitted immediately prior to the action menu opening. This can be used to update the items in the menu so that they are in the correct state for the row(s) the menu is assoociated with. The event details include the following: + - `rowIds` - string array - the IDs of the rows that the menu is associated with + - `columnId` - string, possibly undefined - The ID of the column that the menu is associated with. A column ID is optional on a column definition. If the menu is associated with a column without an ID, `columnId` will be undefined in the event details. ### Anatomy _Slots_ - default - the column elements -- `action-menu` (Placeholder for action menu) +- `action-menu` - A menu element that is associated with row action menus. For more information about the action menu, refer to the [action menu HLD](action-menu-hld.md). ### Security diff --git a/packages/nimble-components/src/table/specs/action-menu-hld.md b/packages/nimble-components/src/table/specs/action-menu-hld.md new file mode 100644 index 0000000000..74d7a990a2 --- /dev/null +++ b/packages/nimble-components/src/table/specs/action-menu-hld.md @@ -0,0 +1,106 @@ +# Nimble Table Action Menu API + +## Problem Statement + +In some tables, such as many tables within SLE, there is a need to put a menu within a row of the table. + +### Out of scope of this HLD + +- The interaction of the menu opening and closing in coordintaion with row selection is out of scope for this HLD. This interaction will be discussed when row selection is defined. + +## Links To Relevant Work Items and Reference Material + +[Table Spec](./README.md) + +Example action menu in SLE +![SLE action menu](./spec-images/sleActionMenu.png) + +## Implementation / Design + +### Client-facing API +There are two pieces of configuration that must be provided by a client in order to use the action menu: +1. Specifying which column, or columns, the action menu will be visible within. +2. Specifying the menu and its items to show when the menu-button is open. + +The nimble design system will be opinionated about many details of the menu button. Therefore, a client will not be able to configure the exact details of the menu-button itself, such as: +- The appearance mode of the menu button +- The icon shown within the button +- When the button becomes visible (e.g. always visible, visible on hover/selection only, etc.) + +If the need arises to have configuration for the items listed above, or other details that are not listed, that can be evaluated at a later time. + +#### Specifying a column to include a menu-button + +A client can specify that a column should have a menu-button within it by adding the `show-menu` attribute on the column definition. In the example below, the menu will be added to the _First name_ column only, but the attribute can be added to multiple columns if desired. + +```HTML + + First name + Last name + +``` + +### Providing a menu + +Because only one menu can be open on the page at a time, the client can provide a single menu that will be associated with the correct button when it is open. The menu is provided by the client by slotting a `nimble-menu` in the `action-menu` slot as show below: + +```HTML + + First name + Last name + + + My first action + My second action + My last action + + +``` + +If an application requires different menu items for different rows, the client is responsible for making sure that the items in the menu are correct for the item(s) that the menu is associated. This can be done by handling the `action-menu-opening` event on the table and updating the menu items as appropriate. The `action-menu-opening` event will include the following in its details: +- `rowIds` - string array - the IDs of the rows that the menu is associated with +- `columnId` - string, possibly undefined - The ID of the column that the menu is associated with. A column ID is optional on a column definition. If the menu is associated with a column without an ID, `columnId` will be undefined in the event details. + +### Implementation + +#### Slot Forwarding + +In order for the menu slotted within the table to be slotted within a cell's menu-button, the menu needs to be "forwarded" from the table to a row and then to a cell. We are calling this process "slot forwarding". This means that every row will have a slot for an menu, but only the row with the open menu will have something slotted within it. Similarly, every cell in a column with a menu will have a slot for a menu, but only the cell with an open menu will have something slotted within it. Events will be used to track when row and cell have the menu associated with them, and the templates will dynamically rename their slots to ensure the menu is slotted in the correct elements. + +For example, the table's template will look something like this +```HTML + +``` + +#### Updates To `nimble-menu-button` + +To implement the design described above, a few small changes need to be made to the existing menu button. This include: +- Add an `opening` event to the menu button that gets fired immediately before the menu is opened. This new event will allow the table to slot the menu into the correct row and cell prior to the menu actually opening. This is important to ensure that the menu items can be focused correctly upon the menu opening. +- Update the code within the menu button that gets the slotted menu. Currently, it only looks for the first item in the `menu` slot. With the design above, the menu element will be nested within a few `slot` elements, so the code will be updated to handle both DOM structures. + + +### Framework Integration + +There are no framework-specific integration work necessary with this design. One large benefit of the approach to slot a menu within the table is that applications written within frameworks, such as Angular, can use Angular mechanisms to build the menu/menu-items and handle events associated with the menu. + +## Alternative Implementations / Designs + +### Provide column IDs to the table to specify columns with menus + +Rather than configuring a column to have a menu by adding an attribute to the column definition, a column could be configured to have a menu by adding a property to the table that is the array of column IDs that should have a column. This is not ideal for a few different reasons: +- It requires columns to have IDs when this may not otherwise be necessary +- It is more error prone because mistakes could be made keeping the configuration of column IDs in sync between the column definitions and table configuration + +## Open Issues +- Can the action menu be opened for multiple rows at the same time? This doesn't become possible until the table supports selection, but it can impact the API. To be the most future-proof, the API is designed such that the `action-menu-opening` event includes an array of row ids. +- The details of the design still need to be finalized by the designers, but these details should have minimal impact on the implementation. Some items that need to be finalized are: + - What icon will be used for the menu? Will it still be the three dots in a horizontal line? + - What is the exact interaction with the menu being visible on hover? + - Is the space of the menu-button always reserved within a column, or does the space collapse when the button is hidden? + - How does the menu interact with row selection? This is a future-looking question because the table does not currently support slection. diff --git a/packages/nimble-components/src/table/specs/spec-images/sleActionMenu.png b/packages/nimble-components/src/table/specs/spec-images/sleActionMenu.png new file mode 100644 index 0000000000000000000000000000000000000000..9a4b44071f570bb8b0eea421f1e9297045aea7a6 GIT binary patch literal 37256 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 { + @attr({ attribute: 'column-id' }) + columnId?: string; + + @attr({ attribute: 'show-menu', mode: 'boolean' }) + showMenu: boolean; + // This method returns the relevant, static configuration a column requires its cellTemplate // to have access to getColumnConfig(): TColumnConfig {} From e044fe10be0a4086756ecece2c46b4b6c388fa9c Mon Sep 17 00:00:00 2001 From: mollykreis <20542556+mollykreis@users.noreply.github.com> Date: Thu, 5 Jan 2023 12:17:11 -0600 Subject: [PATCH 02/15] minor updates --- .../src/table/specs/README.md | 4 +- .../src/table/specs/action-menu-hld.md | 49 +++++++++---------- 2 files changed, 26 insertions(+), 27 deletions(-) diff --git a/packages/nimble-components/src/table/specs/README.md b/packages/nimble-components/src/table/specs/README.md index 815ef39980..c3559932a6 100644 --- a/packages/nimble-components/src/table/specs/README.md +++ b/packages/nimble-components/src/table/specs/README.md @@ -136,8 +136,8 @@ _Properties_ _Events_ -- `action-menu-opening` - An event that is emitted immediately prior to the action menu opening. This can be used to update the items in the menu so that they are in the correct state for the row(s) the menu is assoociated with. The event details include the following: - - `rowIds` - string array - the IDs of the rows that the menu is associated with +- `action-menu-opening` - An event that is emitted immediately prior to the action menu opening. This can be used to update the items in the menu so that they are in the correct state for the row(s) the menu is associated with. The event details include the following: + - `rowIds` - string array - The IDs of the rows that the menu is associated with. - `columnId` - string, possibly undefined - The ID of the column that the menu is associated with. A column ID is optional on a column definition. If the menu is associated with a column without an ID, `columnId` will be undefined in the event details. ### Anatomy diff --git a/packages/nimble-components/src/table/specs/action-menu-hld.md b/packages/nimble-components/src/table/specs/action-menu-hld.md index 74d7a990a2..27f3a82f47 100644 --- a/packages/nimble-components/src/table/specs/action-menu-hld.md +++ b/packages/nimble-components/src/table/specs/action-menu-hld.md @@ -2,11 +2,11 @@ ## Problem Statement -In some tables, such as many tables within SLE, there is a need to put a menu within a row of the table. +In some tables, such as many tables within SLE, there is a need to put a menu within a row of the table. The `nimble-table` should provide a way for clients to accomplish this to avoid code duplication and promote consistency. ### Out of scope of this HLD -- The interaction of the menu opening and closing in coordintaion with row selection is out of scope for this HLD. This interaction will be discussed when row selection is defined. +- The interaction of the menu opening and closing in coordination with row selection is out of scope for this HLD. This interaction will be discussed when row selection is defined. ## Links To Relevant Work Items and Reference Material @@ -19,19 +19,19 @@ Example action menu in SLE ### Client-facing API There are two pieces of configuration that must be provided by a client in order to use the action menu: -1. Specifying which column, or columns, the action menu will be visible within. -2. Specifying the menu and its items to show when the menu-button is open. +1. Specifying which column, or columns, the action menu will be visible within +2. Specifying the menu and its items to show when the menu button is open -The nimble design system will be opinionated about many details of the menu button. Therefore, a client will not be able to configure the exact details of the menu-button itself, such as: -- The appearance mode of the menu button +The nimble design system will be opinionated about many details of the menu button within a table. Therefore, a client will not be able to configure the exact details of the menu button itself, such as: +- The appearance mode of the button - The icon shown within the button - When the button becomes visible (e.g. always visible, visible on hover/selection only, etc.) -If the need arises to have configuration for the items listed above, or other details that are not listed, that can be evaluated at a later time. +If the need arises to have configuration for the items listed above, or other details that are not listed, that can be evaluated and the API can be extended. -#### Specifying a column to include a menu-button +#### Specifying a column to include a menu button -A client can specify that a column should have a menu-button within it by adding the `show-menu` attribute on the column definition. In the example below, the menu will be added to the _First name_ column only, but the attribute can be added to multiple columns if desired. +A client can specify that a column should have an action menu within it by adding the `show-menu` attribute on the column definition. In the example below, the menu will be added to the _First name_ column only. The `show-menu` attribute can be added to multiple columns if multiple action menus are desired within a row. ```HTML @@ -57,17 +57,17 @@ Because only one menu can be open on the page at a time, the client can provide ``` -If an application requires different menu items for different rows, the client is responsible for making sure that the items in the menu are correct for the item(s) that the menu is associated. This can be done by handling the `action-menu-opening` event on the table and updating the menu items as appropriate. The `action-menu-opening` event will include the following in its details: -- `rowIds` - string array - the IDs of the rows that the menu is associated with +If an application requires different menu items for different rows, the client is responsible for ensuring that the items in the menu are correct for the item(s) that the menu is associated. This can be done by handling the `action-menu-opening` event on the table and updating the menu items as appropriate. The `action-menu-opening` event will include the following in its details: +- `rowIds` - string array - The IDs of the rows that the menu is associated with. - `columnId` - string, possibly undefined - The ID of the column that the menu is associated with. A column ID is optional on a column definition. If the menu is associated with a column without an ID, `columnId` will be undefined in the event details. ### Implementation #### Slot Forwarding -In order for the menu slotted within the table to be slotted within a cell's menu-button, the menu needs to be "forwarded" from the table to a row and then to a cell. We are calling this process "slot forwarding". This means that every row will have a slot for an menu, but only the row with the open menu will have something slotted within it. Similarly, every cell in a column with a menu will have a slot for a menu, but only the cell with an open menu will have something slotted within it. Events will be used to track when row and cell have the menu associated with them, and the templates will dynamically rename their slots to ensure the menu is slotted in the correct elements. +In order for the menu slotted within the table to be slotted within a cell's `nimble-menu-button`, the menu needs to be "forwarded" from the table to a row and then to a cell. Every row will have a slot for an menu, but only the row with the open menu will have something slotted within it. Similarly, every cell in a column with a menu will have a slot for a menu, but only the cell with an open menu will have something slotted within it. Events will be used to know when the row and cell the menu is associated with needs to change, and the templates will dynamically rename their slots to ensure the menu is slotted in the correct elements. -For example, the table's template will look something like this +For example, the table's template will look something like this: ```HTML ``` -#### Updates To `nimble-menu-button` - -To implement the design described above, a few small changes need to be made to the existing menu button. This include: -- Add an `opening` event to the menu button that gets fired immediately before the menu is opened. This new event will allow the table to slot the menu into the correct row and cell prior to the menu actually opening. This is important to ensure that the menu items can be focused correctly upon the menu opening. -- Update the code within the menu button that gets the slotted menu. Currently, it only looks for the first item in the `menu` slot. With the design above, the menu element will be nested within a few `slot` elements, so the code will be updated to handle both DOM structures. +#### Updates to `nimble-menu-button` +To implement the design described above, a few small changes need to be made to the existing `nimble-menu-button`: +- Add an `opening` event that gets fired immediately before the menu is opened. This new event will allow the table to slot the menu into the correct row and cell prior to the menu actually opening. This is important to ensure that the menu items can be focused correctly upon the menu opening. +- Update the code that gets the slotted menu. Currently, the code only looks for the first element in the `menu` slot. With the design above, the menu element will be nested within a few `slot` elements, so the code will be updated to handle both DOM structures. ### Framework Integration -There are no framework-specific integration work necessary with this design. One large benefit of the approach to slot a menu within the table is that applications written within frameworks, such as Angular, can use Angular mechanisms to build the menu/menu-items and handle events associated with the menu. +There is no framework-specific integration work necessary with this design. One large benefit of the approach to slot a menu within the table is that applications written within frameworks can use framework-specific mechanisms to build the menu/menu-items and handle events associated with the menu. ## Alternative Implementations / Designs ### Provide column IDs to the table to specify columns with menus -Rather than configuring a column to have a menu by adding an attribute to the column definition, a column could be configured to have a menu by adding a property to the table that is the array of column IDs that should have a column. This is not ideal for a few different reasons: -- It requires columns to have IDs when this may not otherwise be necessary -- It is more error prone because mistakes could be made keeping the configuration of column IDs in sync between the column definitions and table configuration +Rather than configuring a column to have a menu by adding an attribute to the column definition, a column could be configured to have a menu by adding a property to the table that is the array of column IDs that should have a menu. This is not ideal for a few different reasons: +- It requires columns to have IDs when this may not otherwise be necessary. +- It is more error prone because mistakes could be made keeping the configuration of column IDs in sync between the column definitions and table configuration. ## Open Issues -- Can the action menu be opened for multiple rows at the same time? This doesn't become possible until the table supports selection, but it can impact the API. To be the most future-proof, the API is designed such that the `action-menu-opening` event includes an array of row ids. -- The details of the design still need to be finalized by the designers, but these details should have minimal impact on the implementation. Some items that need to be finalized are: +- Can the action menu be opened for multiple rows at the same time? This doesn't become possible until the table supports row selection, but it can impact the API. To be the most future-proof, the API is designed such that the `action-menu-opening` event includes an array of row IDs rather than a single row ID string. +- The details of the visual/interaction design still need to be finalized by the designers, but these details should have minimal impact on the implementation. Some items that need to be finalized are: - What icon will be used for the menu? Will it still be the three dots in a horizontal line? - What is the exact interaction with the menu being visible on hover? - Is the space of the menu-button always reserved within a column, or does the space collapse when the button is hidden? - - How does the menu interact with row selection? This is a future-looking question because the table does not currently support slection. + - How does the menu interact with row selection? This is a future-looking question because the table does not currently support selection. From 5405d5286044a34e4836b78960ea13e8de583f55 Mon Sep 17 00:00:00 2001 From: mollykreis <20542556+mollykreis@users.noreply.github.com> Date: Thu, 5 Jan 2023 12:34:21 -0600 Subject: [PATCH 03/15] format --- .../src/table/specs/action-menu-hld.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/packages/nimble-components/src/table/specs/action-menu-hld.md b/packages/nimble-components/src/table/specs/action-menu-hld.md index 27f3a82f47..481b03c462 100644 --- a/packages/nimble-components/src/table/specs/action-menu-hld.md +++ b/packages/nimble-components/src/table/specs/action-menu-hld.md @@ -18,14 +18,17 @@ Example action menu in SLE ## Implementation / Design ### Client-facing API + There are two pieces of configuration that must be provided by a client in order to use the action menu: + 1. Specifying which column, or columns, the action menu will be visible within 2. Specifying the menu and its items to show when the menu button is open The nimble design system will be opinionated about many details of the menu button within a table. Therefore, a client will not be able to configure the exact details of the menu button itself, such as: -- The appearance mode of the button -- The icon shown within the button -- When the button becomes visible (e.g. always visible, visible on hover/selection only, etc.) + +- The appearance mode of the button +- The icon shown within the button +- When the button becomes visible (e.g. always visible, visible on hover/selection only, etc.) If the need arises to have configuration for the items listed above, or other details that are not listed, that can be evaluated and the API can be extended. @@ -58,6 +61,7 @@ Because only one menu can be open on the page at a time, the client can provide ``` If an application requires different menu items for different rows, the client is responsible for ensuring that the items in the menu are correct for the item(s) that the menu is associated. This can be done by handling the `action-menu-opening` event on the table and updating the menu items as appropriate. The `action-menu-opening` event will include the following in its details: + - `rowIds` - string array - The IDs of the rows that the menu is associated with. - `columnId` - string, possibly undefined - The ID of the column that the menu is associated with. A column ID is optional on a column definition. If the menu is associated with a column without an ID, `columnId` will be undefined in the event details. @@ -68,6 +72,7 @@ If an application requires different menu items for different rows, the client i In order for the menu slotted within the table to be slotted within a cell's `nimble-menu-button`, the menu needs to be "forwarded" from the table to a row and then to a cell. Every row will have a slot for an menu, but only the row with the open menu will have something slotted within it. Similarly, every cell in a column with a menu will have a slot for a menu, but only the cell with an open menu will have something slotted within it. Events will be used to know when the row and cell the menu is associated with needs to change, and the templates will dynamically rename their slots to ensure the menu is slotted in the correct elements. For example, the table's template will look something like this: + ```HTML