Skip to content

feat(table): S2 tableview custom column menu #7617

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Apr 12, 2025

Conversation

snowystinger
Copy link
Member

@snowystinger snowystinger commented Jan 16, 2025

Closes
Based on DNM - on hold: Implement Table Column custom actions
RSP Component Milestones (view)

Some requirements we should consider, grouping multiple ways to sort. See acrobat.com's tables.

✅ Pull Request Checklist:

  • Included link to corresponding React Spectrum GitHub Issue.
  • Added/updated unit tests and storybook for this change (for new code or code which already has tests).
  • Filled out test instructions.
  • Updated documentation (if it already exists for this component).
  • Looked at the Accessibility Practices for this feature - Aria Practices

📝 Test Instructions:

🧢 Your Project:

@snowystinger snowystinger marked this pull request as ready for review January 16, 2025 05:06
@snowystinger snowystinger changed the title feature(table): S2 tableview custom column menu feat(table): S2 tableview custom column menu Jan 16, 2025
@rspbot
Copy link

rspbot commented Jan 16, 2025

ktabors

This comment was marked as resolved.

@rspbot
Copy link

rspbot commented Jan 16, 2025

ktabors
ktabors previously approved these changes Jan 17, 2025
reidbarber
reidbarber previously approved these changes Jan 17, 2025
Copy link
Member

@reidbarber reidbarber left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@snowystinger snowystinger dismissed stale reviews from reidbarber and ktabors via d027c92 January 20, 2025 00:50
<MenuSection aria-label='Sort or resize?'>
<Collection items={items}>
{(item) => <MenuItem>{item?.label}</MenuItem>}
</Collection>
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

best way to add other sort options here (for other columns like doc cloud has?)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Discussion so far, this is ok for the different/ other sorts to be separate, they are likely not as closely related

@rspbot
Copy link

rspbot commented Jan 20, 2025

width={150}
minWidth={150}
isRowHeader={column.isRowHeader}
menu={
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bit strange that this doesn't actually accept a <Menu>. We should discuss options for the API here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, that's another option to handle it
was trying to answer #7617 (comment) as well

if it accepted a Menu, I guess we could do a custom renderer to inject our three menu items, still not a good way to ensure groups that make sense though

maybe people have to provide a menu with specific ids on certain children if they want resize/sort?

open to other ideas, not sold on what I currently have

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Marked current api as UNSTABLE, also changed to menuItems

Other API considerations have been

           // use a MenuTrigger around Column, but how to inject extra children??? also, prevent context leak into Resizer
            menuItems={[ // seems silly, may as well use jsx
              {id: 'filter', label: 'Filter', icon: <Filter />},
              {id: 'hide column', label: 'Hide column'},
              {id: 'manage columns', label: 'Manage columns'}
            ]}

            menu={(extraChildren) => {
              return (
                // too much control? what if our children are omitted
                <Menu>
                  {extraChildren}
                  <MenuSection>
                    <MenuItem onAction={action('filter')}><Filter /><Text slot="label">Filter</Text></MenuItem>
                  </MenuSection>
                  <MenuSection>
                    <MenuItem onAction={action('hide column')}><Text slot="label">Hide column</Text></MenuItem>
                    <MenuItem onAction={action('manage columns')}><Text slot="label">Manage columns</Text></MenuItem>
                  </MenuSection>
                </Menu>
              );
            }}

            menu={
              // how to inject extra children? S2 context to inject them? create a new component, ColumnMenu?
              <Menu>
                <MenuSection>
                  <MenuItem onAction={action('filter')}><Filter /><Text slot="label">Filter</Text></MenuItem>
                </MenuSection>
                <MenuSection>
                  <MenuItem onAction={action('hide column')}><Text slot="label">Hide column</Text></MenuItem>
                  <MenuItem onAction={action('manage columns')}><Text slot="label">Manage columns</Text></MenuItem>
                </MenuSection>
              </Menu>
            }

            menuItems={
              // current implementation
              <>
                <MenuSection>
                  <MenuItem onAction={action('filter')}><Filter /><Text slot="label">Filter</Text></MenuItem>

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Design is fine (for now) if our default items are in their own section at the top. We've decided that without needing to interleave/change order of menuitems, it's better to not give an API which allows people to omit our default options as this could be a problem for accessibility.

# Conflicts:
#	packages/@react-spectrum/s2/src/TableView.tsx
@rspbot
Copy link

rspbot commented Mar 18, 2025

@rspbot
Copy link

rspbot commented Mar 19, 2025

@rspbot
Copy link

rspbot commented Mar 19, 2025

@rspbot
Copy link

rspbot commented Mar 19, 2025

@rspbot
Copy link

rspbot commented Mar 19, 2025

@LFDanLu LFDanLu moved this from 🩺 To Triage to 👀 In Review in RSP Component Milestones Mar 19, 2025
@LFDanLu LFDanLu self-assigned this Mar 20, 2025
children: ReactNode
children: ReactNode,
/** Menu fragment to be rendered inside the column header's menu. */
UNSTABLE_menuItems?: ReactNode
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably ok since users could use Collection to pass a dynamic menuItems renderer and I figure menus will be pretty small for the header menu, but this only accepting ReactNode and not a render function as well gave me pause

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, if they want to make it dynamic, then they can use a Collection, but I wasn't planning on composing to expose the render props since most s2 components dont' do that

Comment on lines +791 to +794
<MenuSection aria-label={stringFormatter.format('table.standardColumnMenu')}>
<Collection items={items}>
{(item) => <MenuItem>{item?.label}</MenuItem>}
</Collection>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah, yep, our storybook was using the incorrect prop name and then converting it, I missed that, it's fixed now

@@ -25,6 +25,7 @@
"table.sortAscending": "Sort Ascending",
"table.sortDescending": "Sort Descending",
"table.resizeColumn": "Resize column",
"table.standardColumnMenu": "Default column actions",
Copy link
Member Author

@snowystinger snowystinger Mar 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Need a better menu section name/label

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe could just say "defaultColumnActions", but this is just for referring to the translations so its probably ok IMO

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm does the section have to have it's own label? is that required by aria? Maybe I'd just say "Column actions" - default is kind of an implementation detail no?

@rspbot
Copy link

rspbot commented Mar 24, 2025

@rspbot
Copy link

rspbot commented Mar 31, 2025

@rspbot
Copy link

rspbot commented Mar 31, 2025

## API Changes

@react-spectrum/s2

/@react-spectrum/s2:Column

 Column {
+  UNSTABLE_menuItems?: ReactNode
   align?: 'start' | 'center' | 'end' = 'start'
   allowsResizing?: boolean
   allowsSorting?: boolean
   children: ReactNode
     defaultClassName: string | undefined
 })) => string
   defaultWidth?: ColumnSize | null
   id?: Key
   isRowHeader?: boolean
   maxWidth?: ColumnStaticSize | null
   minWidth?: ColumnStaticSize | null
   showDivider?: boolean
   style?: CSSProperties | ((ColumnRenderProps & {
     defaultStyle: CSSProperties
 })) => CSSProperties | undefined
   textValue?: string
   width?: ColumnSize | null
 }

/@react-spectrum/s2:ColumnProps

 ColumnProps {
+  UNSTABLE_menuItems?: ReactNode
   align?: 'start' | 'center' | 'end' = 'start'
   allowsResizing?: boolean
   allowsSorting?: boolean
   children: ReactNode
     defaultClassName: string | undefined
 })) => string
   defaultWidth?: ColumnSize | null
   id?: Key
   isRowHeader?: boolean
   maxWidth?: ColumnStaticSize | null
   minWidth?: ColumnStaticSize | null
   showDivider?: boolean
   style?: CSSProperties | ((ColumnRenderProps & {
     defaultStyle: CSSProperties
 })) => CSSProperties | undefined
   textValue?: string
   width?: ColumnSize | null
 }

@@ -25,6 +25,7 @@
"table.sortAscending": "Sort Ascending",
"table.sortDescending": "Sort Descending",
"table.resizeColumn": "Resize column",
"table.standardColumnMenu": "Default column actions",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe could just say "defaultColumnActions", but this is just for referring to the translations so its probably ok IMO

</Collection>
</MenuSection>
)}
{menuItems}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What happens if the menuItems are not wrapped in a MenuSection by the user? Does that still work?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It still works, dividers for the sections wouldn't be there, but that's the only thing. Since the default ones we add are in a section though, people don't need to worry about forgetting to be divided from those

disabledKeys: ['Foo 5']
}
};

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should look at potentially combining some of the stories since these are also our docs

Copy link
Member

@devongovett devongovett left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good enough for testing!

@devongovett devongovett added this pull request to the merge queue Apr 12, 2025
Merged via the queue into main with commit 23faef4 Apr 12, 2025
30 checks passed
@devongovett devongovett deleted the s2-tableview-custom-column-menu branch April 12, 2025 00:57
@github-project-automation github-project-automation bot moved this from 👀 In Review to ✅ Done in RSP Component Milestones Apr 12, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Development

Successfully merging this pull request may close these issues.

6 participants