diff --git a/static/app/components/gridEditable/index.stories.tsx b/static/app/components/gridEditable/index.stories.tsx index 9be3830724ab7d..90a63aee9de643 100644 --- a/static/app/components/gridEditable/index.stories.tsx +++ b/static/app/components/gridEditable/index.stories.tsx @@ -280,4 +280,61 @@ export default Storybook.story('GridEditable', story => { ); }); + + story('Enforcing Cell to fit Content', () => { + const newData = [ + ...data, + { + name: 'Something very long', + category: + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent fringilla ultricies turpis, quis lobortis leo varius ut. Maecenas venenatis purus a sodales facilisis.', + }, + ] as ExampleDataItem[]; + return ( + +

+ Passing + will set the width of + the grid to fit around the content. +

+

+ will by default resize the columns to + fit within it's container. So columns of long width may take up multiple lines + or be cut off, which might not be desired (ex. when the table has many columns + or is placed into a small container). One way to control column width this is to + provide + , which applies + the same width to all columns. However, this does not account for varying widths + between columns, unlike this prop does. +

+ +
+
Without fit content is forced in multiple lines or cut off
+ +
+
+
With fit the content forces the table to expand (scroll)
+ +
+
+
+ ); + }); }); diff --git a/static/app/components/gridEditable/index.tsx b/static/app/components/gridEditable/index.tsx index 8e34def0f1fbac..2543995f2cccee 100644 --- a/static/app/components/gridEditable/index.tsx +++ b/static/app/components/gridEditable/index.tsx @@ -1,4 +1,4 @@ -import type {ReactNode} from 'react'; +import type {CSSProperties, ReactNode} from 'react'; import {Component, createRef, Fragment} from 'react'; import EmptyStateWarning from 'sentry/components/emptyStateWarning'; @@ -98,23 +98,24 @@ type GridEditableProps = { bodyStyle?: React.CSSProperties; emptyMessage?: React.ReactNode; error?: unknown | null; + + fit?: 'max-content'; /** * Inject a set of buttons into the top of the grid table. * The controlling component is responsible for handling any actions * in these buttons and updating props to the GridEditable instance. */ headerButtons?: () => React.ReactNode; + height?: CSSProperties['height']; - height?: string | number; highlightedRowKey?: number; isLoading?: boolean; minimumColWidth?: number; - onRowMouseOut?: (row: DataRow, key: number, event: React.MouseEvent) => void; - onRowMouseOver?: (row: DataRow, key: number, event: React.MouseEvent) => void; + onRowMouseOver?: (row: DataRow, key: number, event: React.MouseEvent) => void; /** * Whether columns in the grid can be resized. * @@ -123,6 +124,7 @@ type GridEditableProps = { resizable?: boolean; scrollable?: boolean; stickyHeader?: boolean; + /** * GridEditable (mostly) do not maintain any internal state and relies on the * parent component to tell it how/what to render and will mutate the view @@ -457,6 +459,7 @@ class GridEditable< 'aria-label': ariaLabel, bodyStyle, stickyHeader, + fit, } = this.props; const showHeader = title || headerButtons; return ( @@ -477,6 +480,7 @@ class GridEditable< scrollable={scrollable} height={height} ref={this.refGrid} + fit={fit} > {this.renderGridHead()} {this.renderGridBody()} diff --git a/static/app/components/gridEditable/styles.tsx b/static/app/components/gridEditable/styles.tsx index 337bb81dccad7a..c6158c59550caa 100644 --- a/static/app/components/gridEditable/styles.tsx +++ b/static/app/components/gridEditable/styles.tsx @@ -1,3 +1,4 @@ +import type {CSSProperties} from 'react'; import {css} from '@emotion/react'; import styled from '@emotion/styled'; @@ -57,7 +58,7 @@ export const Body = styled( showVerticalScrollbar?: boolean; }) => ( - {children} + {children} ) )` @@ -79,7 +80,11 @@ export const Body = styled( * , , are ignored by CSS Grid. * The entire layout is determined by the usage of and . */ -export const Grid = styled('table')<{height?: string | number; scrollable?: boolean}>` +export const Grid = styled('table')<{ + fit?: 'max-content'; + height?: CSSProperties['height']; + scrollable?: boolean; +}>` position: inherit; display: grid; @@ -103,6 +108,8 @@ export const Grid = styled('table')<{height?: string | number; scrollable?: bool max-height: ${typeof p.height === 'number' ? p.height + 'px' : p.height}; ` : ''} + + width: ${p => p.fit} `; /** @@ -332,3 +339,7 @@ export const GridResizer = styled('div')<{dataRows: number}>` opacity: 0.4; } `; + +const StyledPanelBody = styled(PanelBody)` + height: 100%; +`;