Skip to content

1852 - Grid layout settings as parameters #1976

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

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions docs/documentation/docs/controls/GridLayout.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,5 +147,10 @@ The grid layout control can be configured with the following properties:
| items | any[] | yes | The array of items you wish to display. |
| listProps | IListProps | no | Provides additional list properties to customize the underlying list. |
| onRenderGridItem | function | yes | onRenderGridItem handler for the grid layout. Use this handler to specify how you wish to render each grid item |
| itemPadding | number | no | Gap between items. |
| itemMinWidth | number | no | Minimum width for each item. |
| itemMaxWidth | number | no | Maximum width for each item. |
| compactThreshold | number | no | Threshold width below which the compact layout is activated. |
| rowsPerPage | number | no | Number of rows displayed per page. |

![](https://telemetry.sharepointpnp.com/sp-dev-fx-controls-react/wiki/controls/gridlayout)
50 changes: 25 additions & 25 deletions src/controls/gridLayout/GridLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,6 @@ import { IGridLayoutProps, IGridLayoutState } from './GridLayout.types';

import * as telemetry from '../../common/telemetry';

// Get the constants from the SCSS so that we don't hard-code look and feel elements
const ROWS_PER_PAGE: number = +styles.rowsPerPage;
const MAX_ROW_HEIGHT: number = +styles.maxWidth;
const PADDING: number = +styles.padding;
const MIN_WIDTH: number = +styles.minWidth;
const COMPACT_THRESHOLD: number = +styles.compactThreshold;

/**
* Grid layout component
*/
Expand All @@ -31,6 +24,13 @@ export class GridLayout extends React.Component<IGridLayoutProps, IGridLayoutSta
telemetry.track('ReactGridLayout');
}

//Get constants from SCSS if they are not passed in props
private ROWS_PER_PAGE: number = this.props.rowsPerPage ?? +styles.rowsPerPage;
private MAX_WIDTH: number = this.props.itemMaxWidth ?? +styles.maxWidth;
private MIN_WIDTH: number = this.props.itemMinWidth ?? +styles.minWidth;
private PADDING: number = this.props.itemPadding ?? +styles.padding;
private COMPACT_THRESHOLD: number = this.props.compactThreshold ?? +styles.compactThreshold;

// Number of columns in a row
private _columnCount: number;

Expand All @@ -49,17 +49,17 @@ export class GridLayout extends React.Component<IGridLayoutProps, IGridLayoutSta
public render(): React.ReactElement<IGridLayoutProps> {
return (
<div className={styles.gridLayout} role="group" aria-label={this.props.ariaLabel}>
<FocusZone>
<List
role="presentation"
className={styles.gridLayoutList}
items={this.props.items}
getItemCountForPage={this._getItemCountForPage}
getPageHeight={this._getPageHeight}
onRenderCell={this._onRenderCell}
{...this.props.listProps}
/>
</FocusZone>
<FocusZone>
<List
role="presentation"
className={styles.gridLayoutList}
items={this.props.items}
getItemCountForPage={this._getItemCountForPage}
getPageHeight={this._getPageHeight}
onRenderCell={this._onRenderCell}
{...this.props.listProps}
/>
</FocusZone>
</div>
);
}
Expand All @@ -69,19 +69,19 @@ export class GridLayout extends React.Component<IGridLayoutProps, IGridLayoutSta
*/
private _getItemCountForPage = (itemIndex: number, surfaceRect: IRectangle): number => {
if (itemIndex === 0) {
this._isCompact = surfaceRect.width < COMPACT_THRESHOLD;
this._isCompact = surfaceRect.width < this.COMPACT_THRESHOLD;
if (this._isCompact) {
this._columnCount = 1;
this._columnWidth = surfaceRect.width;
return this.props.items.length;
} else {
this._columnCount = Math.ceil(surfaceRect.width / (MAX_ROW_HEIGHT));
this._columnWidth = Math.max(MIN_WIDTH, Math.floor(surfaceRect.width / this._columnCount) + Math.floor(PADDING / this._columnCount));
this._columnCount = Math.ceil(surfaceRect.width / (this.MAX_WIDTH));
this._columnWidth = Math.max(this.MIN_WIDTH, Math.floor(surfaceRect.width / this._columnCount) + Math.floor(this.PADDING / this._columnCount));
this._rowHeight = this._columnWidth;
}
}

return this._columnCount * ROWS_PER_PAGE;
return this._columnCount * this.ROWS_PER_PAGE;
}

/**
Expand All @@ -91,17 +91,17 @@ export class GridLayout extends React.Component<IGridLayoutProps, IGridLayoutSta
if (this._isCompact) {
return this.props.items.length * this._rowHeight;
}
return this._rowHeight * ROWS_PER_PAGE;
return this._rowHeight * this.ROWS_PER_PAGE;
}

/**
* Calls the passed onRenderCell
*/
private _onRenderCell = (item: any, index: number | undefined): JSX.Element => { // eslint-disable-line @typescript-eslint/no-explicit-any
const isCompact: boolean = this._isCompact;
const cellPadding: number = index % this._columnCount !== this._columnCount - 1 && !isCompact ? PADDING : 0;
const cellPadding: number = index % this._columnCount !== this._columnCount - 1 && !isCompact ? this.PADDING : 0;
const finalSize: ISize = { width: this._columnWidth, height: this._rowHeight };
const cellWidth: number = isCompact ? this._columnWidth + PADDING : this._columnWidth - PADDING;
const cellWidth: number = isCompact ? this._columnWidth + this.PADDING : this._columnWidth - this.PADDING;
return (
<div
style={{
Expand Down
35 changes: 35 additions & 0 deletions src/controls/gridLayout/GridLayout.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,41 @@ export interface IGridLayoutProps {
* The method to render each cell item
*/
onRenderGridItem: (item: any, finalSize: ISize, isCompact: boolean) => JSX.Element; // eslint-disable-line @typescript-eslint/no-explicit-any

/**
* Layout configuration props.
* All properties are optional; defaults are provided via styles (SCSS module).
*/

/**
* Gap between items.
* Default: 20.
*/
itemPadding?: number;

/**
* Minimum width for each item.
* Default: 210.
*/
itemMinWidth?: number;

/**
* Maximum width for each item.
* Default: 320
*/
itemMaxWidth?: number;

/**
* Threshold width below which the compact layout is activated.
* Default: 480.
*/
compactThreshold?: number;

/**
* Number of rows displayed per page.
* Default: 3.
*/
rowsPerPage?: number;
}

export interface IGridLayoutState {}
9 changes: 7 additions & 2 deletions src/webparts/controlsTest/components/ControlsTest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -955,7 +955,7 @@ export default class ControlsTest extends React.Component<IControlsTestProps, IC
<DocumentCard
type={isCompact ? DocumentCardType.compact : DocumentCardType.normal}
onClick={(ev: React.SyntheticEvent<HTMLElement>) => alert("You clicked on a grid item")}

style={{maxWidth: _finalSize.width}}
>
<DocumentCardPreview {...previewProps} />
{!isCompact && <DocumentCardLocation location={item.location} />}
Expand Down Expand Up @@ -2176,7 +2176,12 @@ export default class ControlsTest extends React.Component<IControlsTestProps, IC
ariaLabel={"List of content, use right and left arrow keys to navigate, arrow down to access details."}
items={sampleGridData}
onRenderGridItem={(item: any, finalSize: ISize, isCompact: boolean) => this._onRenderGridItem(item, finalSize, isCompact)}
/>
itemMinWidth={250}
itemMaxWidth={600}
itemPadding={60}
//compactThreshold={220}
//rowsPerPage={1}
/>
</div>
}
{controlVisibility.HoverReactionsBar &&
Expand Down