@patternfly/react-docs 7.6.0-prerelease.6 → 7.6.0-prerelease.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +4 -0
- package/package.json +12 -13
- package/patternfly-docs/generated/components/about-modal/react.js +149 -0
- package/patternfly-docs/generated/components/accordion/react.js +262 -0
- package/patternfly-docs/generated/components/action-list/react.js +144 -0
- package/patternfly-docs/generated/components/alert/react-demos.js +56 -0
- package/patternfly-docs/generated/components/alert/react.js +1433 -0
- package/patternfly-docs/generated/components/avatar/react.js +166 -0
- package/patternfly-docs/generated/components/back-to-top/react-demos.js +60 -0
- package/patternfly-docs/generated/components/back-to-top/react.js +77 -0
- package/patternfly-docs/generated/components/backdrop/react.js +64 -0
- package/patternfly-docs/generated/components/background-image/react.js +62 -0
- package/patternfly-docs/generated/components/badge/react.js +97 -0
- package/patternfly-docs/generated/components/banner/react-demos.js +57 -0
- package/patternfly-docs/generated/components/banner/react.js +148 -0
- package/patternfly-docs/generated/components/brand/react.js +142 -0
- package/patternfly-docs/generated/components/breadcrumb/react.js +206 -0
- package/patternfly-docs/generated/components/button/react-demos.js +57 -0
- package/patternfly-docs/generated/components/button/react.js +826 -0
- package/patternfly-docs/generated/components/card/react-demos.js +201 -0
- package/patternfly-docs/generated/components/card/react.js +1015 -0
- package/patternfly-docs/generated/components/charts/area-chart/-Victory.js +1350 -0
- package/patternfly-docs/generated/components/charts/bar-chart/-Victory.js +1334 -0
- package/patternfly-docs/generated/components/charts/box-plot-chart/-Victory.js +1282 -0
- package/patternfly-docs/generated/components/charts/bullet-chart/-Victory.js +848 -0
- package/patternfly-docs/generated/components/charts/colors-for-charts/-Victory.js +192 -0
- package/patternfly-docs/generated/components/charts/donut-chart/-Victory.js +426 -0
- package/patternfly-docs/generated/components/charts/donut-utilization-chart/-Victory.js +804 -0
- package/patternfly-docs/generated/components/charts/legends/-Victory.js +3230 -0
- package/patternfly-docs/generated/components/charts/line-chart/-Victory.js +1178 -0
- package/patternfly-docs/generated/components/charts/line-chart/ECharts.js +525 -0
- package/patternfly-docs/generated/components/charts/patterns/-Victory.js +3382 -0
- package/patternfly-docs/generated/components/charts/pie-chart/-Victory.js +377 -0
- package/patternfly-docs/generated/components/charts/resize-observer/-Victory.js +2475 -0
- package/patternfly-docs/generated/components/charts/sankey-chart/ECharts.js +538 -0
- package/patternfly-docs/generated/components/charts/scatter-chart/-Victory.js +1551 -0
- package/patternfly-docs/generated/components/charts/skeletons/-Victory.js +4115 -0
- package/patternfly-docs/generated/components/charts/sparkline-chart/-Victory.js +955 -0
- package/patternfly-docs/generated/components/charts/stack-chart/-Victory.js +1173 -0
- package/patternfly-docs/generated/components/charts/threshold-chart/-Victory.js +1166 -0
- package/patternfly-docs/generated/components/charts/tooltips/-Victory.js +413 -0
- package/patternfly-docs/generated/components/chip/react-deprecated.js +323 -0
- package/patternfly-docs/generated/components/clipboard-copy/react.js +373 -0
- package/patternfly-docs/generated/components/code-block/react.js +148 -0
- package/patternfly-docs/generated/components/code-editor/react.js +659 -0
- package/patternfly-docs/generated/components/compass/react-demos.js +147 -0
- package/patternfly-docs/generated/components/compass/react.js +440 -0
- package/patternfly-docs/generated/components/content/react.js +248 -0
- package/patternfly-docs/generated/components/data-list/react-demos.js +90 -0
- package/patternfly-docs/generated/components/data-list/react.js +709 -0
- package/patternfly-docs/generated/components/date-and-time/calendar-month/react.js +283 -0
- package/patternfly-docs/generated/components/date-and-time/date-and-time-picker/react-demos.js +64 -0
- package/patternfly-docs/generated/components/date-and-time/date-picker/react-demos.js +83 -0
- package/patternfly-docs/generated/components/date-and-time/date-picker/react.js +395 -0
- package/patternfly-docs/generated/components/date-and-time/time-picker/react.js +241 -0
- package/patternfly-docs/generated/components/description-list/react-demos.js +58 -0
- package/patternfly-docs/generated/components/description-list/react.js +743 -0
- package/patternfly-docs/generated/components/divider/react.js +126 -0
- package/patternfly-docs/generated/components/drag-and-drop/react-demos.js +351 -0
- package/patternfly-docs/generated/components/drag-and-drop/react-deprecated.js +184 -0
- package/patternfly-docs/generated/components/drag-and-drop/react.js +137 -0
- package/patternfly-docs/generated/components/drawer/react.js +598 -0
- package/patternfly-docs/generated/components/dual-list-selector/react-deprecated.js +772 -0
- package/patternfly-docs/generated/components/dual-list-selector/react.js +594 -0
- package/patternfly-docs/generated/components/empty-state/react.js +199 -0
- package/patternfly-docs/generated/components/expandable-section/react-demos.js +65 -0
- package/patternfly-docs/generated/components/expandable-section/react.js +408 -0
- package/patternfly-docs/generated/components/file-upload/multiple-file-upload/react-demos.js +52 -0
- package/patternfly-docs/generated/components/file-upload/multiple-file-upload/react.js +398 -0
- package/patternfly-docs/generated/components/file-upload/simple-file-upload/react.js +749 -0
- package/patternfly-docs/generated/components/forms/checkbox/react.js +222 -0
- package/patternfly-docs/generated/components/forms/form/react.js +1106 -0
- package/patternfly-docs/generated/components/forms/form-select/react.js +208 -0
- package/patternfly-docs/generated/components/forms/radio/react.js +212 -0
- package/patternfly-docs/generated/components/forms/text-area/react.js +160 -0
- package/patternfly-docs/generated/components/forms/text-input/react.js +216 -0
- package/patternfly-docs/generated/components/helper-text/react-demos.js +180 -0
- package/patternfly-docs/generated/components/helper-text/react.js +164 -0
- package/patternfly-docs/generated/components/hero/react.js +88 -0
- package/patternfly-docs/generated/components/hint/react.js +169 -0
- package/patternfly-docs/generated/components/icon/react.js +215 -0
- package/patternfly-docs/generated/components/input-group/react.js +182 -0
- package/patternfly-docs/generated/components/jump-links/react-demos.js +154 -0
- package/patternfly-docs/generated/components/jump-links/react.js +212 -0
- package/patternfly-docs/generated/components/label/react-demos.js +57 -0
- package/patternfly-docs/generated/components/label/react.js +417 -0
- package/patternfly-docs/generated/components/list/react.js +175 -0
- package/patternfly-docs/generated/components/login-page/react.js +587 -0
- package/patternfly-docs/generated/components/masthead/react-demos.js +79 -0
- package/patternfly-docs/generated/components/masthead/react.js +291 -0
- package/patternfly-docs/generated/components/menus/application-launcher/react-demos.js +769 -0
- package/patternfly-docs/generated/components/menus/context-selector/react-demos.js +665 -0
- package/patternfly-docs/generated/components/menus/custom-menus/react-demos.js +187 -0
- package/patternfly-docs/generated/components/menus/dropdown/react-templates.js +163 -0
- package/patternfly-docs/generated/components/menus/dropdown/react.js +998 -0
- package/patternfly-docs/generated/components/menus/menu/react.js +1540 -0
- package/patternfly-docs/generated/components/menus/menu-toggle/react.js +747 -0
- package/patternfly-docs/generated/components/menus/options-menu/react-demos.js +508 -0
- package/patternfly-docs/generated/components/menus/select/react-templates.js +257 -0
- package/patternfly-docs/generated/components/menus/select/react.js +998 -0
- package/patternfly-docs/generated/components/modal/react-deprecated.js +554 -0
- package/patternfly-docs/generated/components/modal/react.js +597 -0
- package/patternfly-docs/generated/components/navigation/react-demos.js +356 -0
- package/patternfly-docs/generated/components/navigation/react.js +409 -0
- package/patternfly-docs/generated/components/notification-badge/react.js +196 -0
- package/patternfly-docs/generated/components/notification-drawer/react-demos.js +107 -0
- package/patternfly-docs/generated/components/notification-drawer/react.js +394 -0
- package/patternfly-docs/generated/components/number-input/react.js +210 -0
- package/patternfly-docs/generated/components/overflow-menu/react.js +274 -0
- package/patternfly-docs/generated/components/page/react-demos.js +149 -0
- package/patternfly-docs/generated/components/page/react.js +1352 -0
- package/patternfly-docs/generated/components/pagination/react.js +492 -0
- package/patternfly-docs/generated/components/panel/react.js +236 -0
- package/patternfly-docs/generated/components/popover/react.js +390 -0
- package/patternfly-docs/generated/components/progress/react-demos.js +59 -0
- package/patternfly-docs/generated/components/progress/react.js +283 -0
- package/patternfly-docs/generated/components/progress-stepper/react-demos.js +45 -0
- package/patternfly-docs/generated/components/progress-stepper/react.js +219 -0
- package/patternfly-docs/generated/components/search-input/react-demos.js +113 -0
- package/patternfly-docs/generated/components/search-input/react.js +263 -0
- package/patternfly-docs/generated/components/sidebar/react.js +236 -0
- package/patternfly-docs/generated/components/simple-list/react.js +200 -0
- package/patternfly-docs/generated/components/skeleton/react-demos.js +44 -0
- package/patternfly-docs/generated/components/skeleton/react.js +122 -0
- package/patternfly-docs/generated/components/skip-to-content/react.js +73 -0
- package/patternfly-docs/generated/components/slider/react.js +309 -0
- package/patternfly-docs/generated/components/spinner/react.js +111 -0
- package/patternfly-docs/generated/components/switch/react.js +163 -0
- package/patternfly-docs/generated/components/table/react-demos.js +355 -0
- package/patternfly-docs/generated/components/table/react-deprecated.js +1350 -0
- package/patternfly-docs/generated/components/table/react.js +3241 -0
- package/patternfly-docs/generated/components/tabs/react-demos.js +108 -0
- package/patternfly-docs/generated/components/tabs/react.js +1359 -0
- package/patternfly-docs/generated/components/text-input-group/react-demos.js +152 -0
- package/patternfly-docs/generated/components/text-input-group/react.js +278 -0
- package/patternfly-docs/generated/components/tile/react-deprecated.js +242 -0
- package/patternfly-docs/generated/components/timestamp/react.js +283 -0
- package/patternfly-docs/generated/components/title/react.js +94 -0
- package/patternfly-docs/generated/components/toggle-group/react.js +299 -0
- package/patternfly-docs/generated/components/toolbar/react-demos.js +66 -0
- package/patternfly-docs/generated/components/toolbar/react.js +932 -0
- package/patternfly-docs/generated/components/tooltip/react.js +241 -0
- package/patternfly-docs/generated/components/tree-view/react.js +429 -0
- package/patternfly-docs/generated/components/truncate/react.js +211 -0
- package/patternfly-docs/generated/components/wizard/react-demos.js +87 -0
- package/patternfly-docs/generated/components/wizard/react-deprecated.js +788 -0
- package/patternfly-docs/generated/components/wizard/react.js +986 -0
- package/patternfly-docs/generated/developer-guides/open-ui-automation/react.js +285 -0
- package/patternfly-docs/generated/foundations-and-styles/layouts/bullseye/react.js +70 -0
- package/patternfly-docs/generated/foundations-and-styles/layouts/flex/react.js +506 -0
- package/patternfly-docs/generated/foundations-and-styles/layouts/gallery/react.js +94 -0
- package/patternfly-docs/generated/foundations-and-styles/layouts/grid/react.js +272 -0
- package/patternfly-docs/generated/foundations-and-styles/layouts/level/react.js +87 -0
- package/patternfly-docs/generated/foundations-and-styles/layouts/split/react.js +124 -0
- package/patternfly-docs/generated/foundations-and-styles/layouts/stack/react.js +112 -0
- package/patternfly-docs/generated/index.js +1769 -0
- package/patternfly-docs/generated/patterns/card-view/react-demos.js +78 -0
- package/patternfly-docs/generated/patterns/filters/react-demos.js +141 -0
- package/patternfly-docs/generated/patterns/password-generator/react-demos.js +51 -0
- package/patternfly-docs/generated/patterns/password-strength/react-demos.js +61 -0
- package/patternfly-docs/generated/patterns/primary-detail/react-demos.js +124 -0
- package/patternfly-docs/generated/patterns/right-to-left/react-demos.js +81 -0
- package/LICENSE +0 -21
|
@@ -0,0 +1,1350 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { AutoLinkHeader, Example, Link as PatternflyThemeLink } from '@patternfly/documentation-framework/components';
|
|
3
|
+
import { Fragment, isValidElement, useCallback, useEffect, useRef, useState } from 'react';
|
|
4
|
+
import SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon';
|
|
5
|
+
import RhUiCodeIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-code-icon';
|
|
6
|
+
import RhUiBranchFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-branch-fill-icon';
|
|
7
|
+
import CodeIcon from '@patternfly/react-icons/dist/esm/icons/code-icon';
|
|
8
|
+
import CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon';
|
|
9
|
+
import LeafIcon from '@patternfly/react-icons/dist/esm/icons/leaf-icon';
|
|
10
|
+
import FolderIcon from '@patternfly/react-icons/dist/esm/icons/folder-icon';
|
|
11
|
+
import FolderOpenIcon from '@patternfly/react-icons/dist/esm/icons/folder-open-icon';
|
|
12
|
+
import RhMicronsSortDownLargeToSmallIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-sort-down-large-to-small-icon';
|
|
13
|
+
import {
|
|
14
|
+
Select as NewSelect,
|
|
15
|
+
SelectGroup as NewSelectGroup,
|
|
16
|
+
SelectList as NewSelectList,
|
|
17
|
+
SelectOption as NewSelectOption,
|
|
18
|
+
} from '@patternfly/react-core/dist/esm/components/Select';
|
|
19
|
+
import { css } from '@patternfly/react-styles';
|
|
20
|
+
import styles from '@patternfly/react-styles/css/components/Table/table';
|
|
21
|
+
import spacing from '@patternfly/react-styles/css/utilities/Spacing/spacing';
|
|
22
|
+
import t_global_color_brand_default from '@patternfly/react-tokens/dist/esm/t_global_color_brand_default';
|
|
23
|
+
const pageData = {
|
|
24
|
+
"id": "Table",
|
|
25
|
+
"section": "components",
|
|
26
|
+
"subsection": "",
|
|
27
|
+
"deprecated": true,
|
|
28
|
+
"template": false,
|
|
29
|
+
"beta": false,
|
|
30
|
+
"demo": false,
|
|
31
|
+
"newImplementationLink": false,
|
|
32
|
+
"source": "react-deprecated",
|
|
33
|
+
"tabName": null,
|
|
34
|
+
"slug": "/components/table/react-deprecated",
|
|
35
|
+
"sourceLink": "https://github.com/patternfly/patternfly-react/blob/main/packages/react-table/src/deprecated/components/Table/examples/Table.md",
|
|
36
|
+
"relPath": "packages/react-table/src/deprecated/components/Table/examples/Table.md",
|
|
37
|
+
"propComponents": [
|
|
38
|
+
{
|
|
39
|
+
"name": "Table",
|
|
40
|
+
"description": "",
|
|
41
|
+
"props": [
|
|
42
|
+
{
|
|
43
|
+
"name": "actionResolver",
|
|
44
|
+
"type": "(rowData: IRowData, extraData: IExtraData) => (IAction | ISeparator)[]",
|
|
45
|
+
"description": "Resolver for the given action"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"name": "actions",
|
|
49
|
+
"type": "(IAction | ISeparator)[]",
|
|
50
|
+
"description": "Actions to add to the Table"
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
"name": "actionsMenuAppendTo",
|
|
54
|
+
"type": "HTMLElement | (() => HTMLElement) | 'inline' | 'parent'",
|
|
55
|
+
"description": "The container to append the dropdown menu to. Defaults to 'inline'.\nIf your menu is being cut off you can append it to an element higher up the DOM tree.\nSome examples:\nactionsMenuAppendTo=\"parent\"\nactionsMenuAppendTo={() => document.body}\nactionsMenuAppendTo={document.getElementById('target')}",
|
|
56
|
+
"defaultValue": "'inline'"
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
"name": "actionsToggle",
|
|
60
|
+
"type": "(props: CustomActionsToggleProps) => React.ReactNode",
|
|
61
|
+
"description": "The toggle of the actions menu dropdown. A KebabToggle or DropdownToggle component"
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"name": "areActionsDisabled",
|
|
65
|
+
"type": "(rowData: IRowData, extraData: IExtraData) => boolean",
|
|
66
|
+
"description": "Specifies if the Kebab for actions is disabled"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
"name": "aria-label",
|
|
70
|
+
"type": "string",
|
|
71
|
+
"description": "Adds an accessible name for the Table",
|
|
72
|
+
"defaultValue": "undefined"
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
"name": "bodyWrapper",
|
|
76
|
+
"type": "Function",
|
|
77
|
+
"description": "Wrapper for the body"
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"name": "borders",
|
|
81
|
+
"type": "boolean",
|
|
82
|
+
"description": "Render borders\nBorders can only currently be disabled if the variant is set to 'compact'\nhttps://github.com/patternfly/patternfly/issues/3650",
|
|
83
|
+
"defaultValue": "true"
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
"name": "canCollapseAll",
|
|
87
|
+
"type": "boolean",
|
|
88
|
+
"description": "Enables or disables the ability to expand all",
|
|
89
|
+
"defaultValue": "false"
|
|
90
|
+
},
|
|
91
|
+
{
|
|
92
|
+
"name": "canSelectAll",
|
|
93
|
+
"type": "boolean",
|
|
94
|
+
"description": "Enables or disables the ability to select all - this is mutually exclusive with radio button select variant",
|
|
95
|
+
"defaultValue": "true"
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
"name": "canSortFavorites",
|
|
99
|
+
"type": "boolean",
|
|
100
|
+
"description": "Along with the onSort prop, enables favorites sorting, defaults to true",
|
|
101
|
+
"defaultValue": "true"
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"name": "caption",
|
|
105
|
+
"type": "React.ReactNode",
|
|
106
|
+
"description": "Component used for caption",
|
|
107
|
+
"defaultValue": "undefined"
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
"name": "cells",
|
|
111
|
+
"type": "(ICell | string)[]",
|
|
112
|
+
"description": "Cell/column data",
|
|
113
|
+
"required": true
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"name": "children",
|
|
117
|
+
"type": "React.ReactNode",
|
|
118
|
+
"description": "Content rendered inside the Table",
|
|
119
|
+
"defaultValue": "null"
|
|
120
|
+
},
|
|
121
|
+
{
|
|
122
|
+
"name": "className",
|
|
123
|
+
"type": "string",
|
|
124
|
+
"description": "Additional classes added to the Table",
|
|
125
|
+
"defaultValue": "''"
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
"name": "collapseAllAriaLabel",
|
|
129
|
+
"type": "string",
|
|
130
|
+
"description": "An optional alternative aria label for the expand collapse all table header",
|
|
131
|
+
"defaultValue": "''"
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
"name": "contentId",
|
|
135
|
+
"type": "string",
|
|
136
|
+
"description": "ID for content",
|
|
137
|
+
"defaultValue": "'expanded-content'"
|
|
138
|
+
},
|
|
139
|
+
{
|
|
140
|
+
"name": "dropdownDirection",
|
|
141
|
+
"type": "'up' | 'down'",
|
|
142
|
+
"description": "The desired direction to show the dropdown when clicking on the actions Kebab. Can only be used together with `actions` property",
|
|
143
|
+
"defaultValue": "'down'"
|
|
144
|
+
},
|
|
145
|
+
{
|
|
146
|
+
"name": "dropdownPosition",
|
|
147
|
+
"type": "'right' | 'left'",
|
|
148
|
+
"description": "The desired position to show the dropdown when clicking on the actions Kebab. Can only be used together with `actions` property",
|
|
149
|
+
"defaultValue": "'right'"
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
"name": "expandId",
|
|
153
|
+
"type": "string",
|
|
154
|
+
"description": "ID for expand",
|
|
155
|
+
"defaultValue": "'expandable-toggle'"
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
"name": "gridBreakPoint",
|
|
159
|
+
"type": "'' | 'grid' | 'grid-md' | 'grid-lg' | 'grid-xl' | 'grid-2xl'",
|
|
160
|
+
"description": "Specifies the grid breakpoints",
|
|
161
|
+
"defaultValue": "TableGridBreakpoint.gridMd"
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"name": "header",
|
|
165
|
+
"type": "React.ReactNode",
|
|
166
|
+
"description": "Component to place in the header",
|
|
167
|
+
"defaultValue": "undefined"
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
"name": "isExpandable",
|
|
171
|
+
"type": "boolean",
|
|
172
|
+
"description": "Flag indicating this table contains expandable rows to maintain proper striping"
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
"name": "isHeaderSelectDisabled",
|
|
176
|
+
"type": "boolean",
|
|
177
|
+
"description": "Flag indicating the select all checkbox is disabled",
|
|
178
|
+
"defaultValue": "false"
|
|
179
|
+
},
|
|
180
|
+
{
|
|
181
|
+
"name": "isNested",
|
|
182
|
+
"type": "boolean",
|
|
183
|
+
"description": "Flag indicating this table is nested within another table",
|
|
184
|
+
"defaultValue": "false"
|
|
185
|
+
},
|
|
186
|
+
{
|
|
187
|
+
"name": "isStickyHeader",
|
|
188
|
+
"type": "boolean",
|
|
189
|
+
"description": "If set to true, the table header sticks to the top of its container",
|
|
190
|
+
"defaultValue": "false"
|
|
191
|
+
},
|
|
192
|
+
{
|
|
193
|
+
"name": "isStriped",
|
|
194
|
+
"type": "boolean",
|
|
195
|
+
"description": "Flag indicating this table is striped"
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
"name": "isTreeTable",
|
|
199
|
+
"type": "boolean",
|
|
200
|
+
"description": "Flag indicating table is a tree table",
|
|
201
|
+
"defaultValue": "false"
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
"name": "onCollapse",
|
|
205
|
+
"type": "(\n event: React.MouseEvent,\n rowIndex: number,\n isOpen: boolean,\n rowData: IRowData,\n extraData: IExtraData\n) => void",
|
|
206
|
+
"description": "Function triggered when an expandable content is collapsed. When this is used, one expandable toggle button will be positioned in the first cell of a non-expandable row, preceding an expandable row"
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
"name": "onExpand",
|
|
210
|
+
"type": "(\n event: React.MouseEvent,\n rowIndex: number,\n colIndex: number,\n isOpen: boolean,\n rowData: IRowData,\n extraData: IExtraData\n) => void",
|
|
211
|
+
"description": "Function triggered when a compound expandable item is clicked"
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
"name": "onFavorite",
|
|
215
|
+
"type": "(\n event: React.MouseEvent,\n isFavorited: boolean,\n rowIndex: number,\n rowData: IRowData,\n extraData: IExtraData\n) => void",
|
|
216
|
+
"description": "Enables favorites column\nCallback triggered when a row is favorited/unfavorited"
|
|
217
|
+
},
|
|
218
|
+
{
|
|
219
|
+
"name": "onRowEdit",
|
|
220
|
+
"type": "(\n event: React.MouseEvent<HTMLButtonElement>,\n type: RowEditType,\n isEditable?: boolean,\n rowIndex?: number,\n validationErrors?: RowErrors\n) => void",
|
|
221
|
+
"description": "Function triggered when a row's inline edit is activated. Adds a column for inline edit when present."
|
|
222
|
+
},
|
|
223
|
+
{
|
|
224
|
+
"name": "onSelect",
|
|
225
|
+
"type": "(\n event: React.FormEvent<HTMLInputElement>,\n isSelected: boolean,\n rowIndex: number,\n rowData: IRowData,\n extraData: IExtraData\n) => void",
|
|
226
|
+
"description": "Function triggered when a row's checkbox is selected. When this is used, one checkbox/radio button will be positioned in the first or second cell of a non-expandable row"
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
"name": "onSort",
|
|
230
|
+
"type": "(\n event: React.MouseEvent,\n columnIndex: number,\n sortByDirection: SortByDirection,\n extraData: IExtraColumnData\n) => void",
|
|
231
|
+
"description": "Function triggered when sort icon is clicked"
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
"name": "ouiaId",
|
|
235
|
+
"type": "number | string",
|
|
236
|
+
"description": "Value to overwrite the randomly generated data-ouia-component-id."
|
|
237
|
+
},
|
|
238
|
+
{
|
|
239
|
+
"name": "ouiaSafe",
|
|
240
|
+
"type": "boolean",
|
|
241
|
+
"description": "Set the value of data-ouia-safe. Only set to true when the component is in a static state, i.e. no animations are occurring. At all other times, this value must be false.",
|
|
242
|
+
"defaultValue": "true"
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
"name": "role",
|
|
246
|
+
"type": "string",
|
|
247
|
+
"description": "A valid WAI-ARIA role to be applied to the table element",
|
|
248
|
+
"defaultValue": "'grid'"
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
"name": "rowLabeledBy",
|
|
252
|
+
"type": "string",
|
|
253
|
+
"description": "label for row",
|
|
254
|
+
"defaultValue": "'simple-node'"
|
|
255
|
+
},
|
|
256
|
+
{
|
|
257
|
+
"name": "rows",
|
|
258
|
+
"type": "(IRow | string[])[]",
|
|
259
|
+
"description": "Row data",
|
|
260
|
+
"required": true
|
|
261
|
+
},
|
|
262
|
+
{
|
|
263
|
+
"name": "rowWrapper",
|
|
264
|
+
"type": "(props: RowWrapperProps) => React.JSX.Element",
|
|
265
|
+
"description": "Wrapper for the row"
|
|
266
|
+
},
|
|
267
|
+
{
|
|
268
|
+
"name": "selectVariant",
|
|
269
|
+
"type": "'checkbox' | 'radio'",
|
|
270
|
+
"description": "Specifies the type of the select element variant - can be one of checkbox or radio button",
|
|
271
|
+
"defaultValue": "'checkbox'"
|
|
272
|
+
},
|
|
273
|
+
{
|
|
274
|
+
"name": "sortBy",
|
|
275
|
+
"type": "ISortBy",
|
|
276
|
+
"description": "Specifies the initial sorting pattern for the table - asc/desc and the index of the column to sort by"
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
"name": "variant",
|
|
280
|
+
"type": "literal",
|
|
281
|
+
"description": "Style variant for the Table",
|
|
282
|
+
"defaultValue": "null"
|
|
283
|
+
}
|
|
284
|
+
]
|
|
285
|
+
},
|
|
286
|
+
{
|
|
287
|
+
"name": "TableHeader",
|
|
288
|
+
"description": "",
|
|
289
|
+
"props": [
|
|
290
|
+
{
|
|
291
|
+
"name": "className",
|
|
292
|
+
"type": "string",
|
|
293
|
+
"description": "Additional classes added to the TableHeader"
|
|
294
|
+
}
|
|
295
|
+
]
|
|
296
|
+
},
|
|
297
|
+
{
|
|
298
|
+
"name": "TableBody",
|
|
299
|
+
"description": "",
|
|
300
|
+
"props": [
|
|
301
|
+
{
|
|
302
|
+
"name": "className",
|
|
303
|
+
"type": "string",
|
|
304
|
+
"description": "Additional classes added to the TableBody",
|
|
305
|
+
"defaultValue": "''"
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
"name": "isEvenStriped",
|
|
309
|
+
"type": "boolean",
|
|
310
|
+
"description": "Flag indicating the <tbody> contains evenly striped rows."
|
|
311
|
+
},
|
|
312
|
+
{
|
|
313
|
+
"name": "isOddStriped",
|
|
314
|
+
"type": "boolean",
|
|
315
|
+
"description": "Flag indicating the <tbody> contains oddly striped rows."
|
|
316
|
+
},
|
|
317
|
+
{
|
|
318
|
+
"name": "onRowClick",
|
|
319
|
+
"type": "(\n event: React.KeyboardEvent | React.MouseEvent,\n row: IRow,\n rowProps: IExtraRowData,\n computedData: IComputedData\n) => void",
|
|
320
|
+
"description": "A click handler for the row",
|
|
321
|
+
"defaultValue": "(\n event: React.MouseEvent | React.KeyboardEvent,\n row: IRow,\n rowProps: IExtraRowData,\n computedData: IComputedData\n) =>\n /* eslint-enable @typescript-eslint/no-unused-vars */\n undefined as OnRowClick"
|
|
322
|
+
}
|
|
323
|
+
]
|
|
324
|
+
}
|
|
325
|
+
],
|
|
326
|
+
"cssPrefix": [
|
|
327
|
+
"pf-c-table"
|
|
328
|
+
],
|
|
329
|
+
"examples": [
|
|
330
|
+
"Basic",
|
|
331
|
+
"Custom row wrapper",
|
|
332
|
+
"Sortable & wrapping column headers",
|
|
333
|
+
"Sortable - custom control",
|
|
334
|
+
"Selectable with checkbox",
|
|
335
|
+
"Selectable radio input",
|
|
336
|
+
"Clickable rows, selectable rows, and header cell tooltips/popovers",
|
|
337
|
+
"Actions and first cell in body rows as th",
|
|
338
|
+
"Expandable",
|
|
339
|
+
"Compound expandable",
|
|
340
|
+
"With width and breakpoint visibility modifiers",
|
|
341
|
+
"Controlling text",
|
|
342
|
+
"Modifiers with table text",
|
|
343
|
+
"Empty state",
|
|
344
|
+
"Editable rows",
|
|
345
|
+
"Favoritable (implemented with sortable and selectable)",
|
|
346
|
+
"Tree table",
|
|
347
|
+
"Striped",
|
|
348
|
+
"Striped expandable",
|
|
349
|
+
"Striped custom tr"
|
|
350
|
+
]
|
|
351
|
+
};
|
|
352
|
+
pageData.liveContext = {
|
|
353
|
+
Fragment,
|
|
354
|
+
isValidElement,
|
|
355
|
+
useCallback,
|
|
356
|
+
useEffect,
|
|
357
|
+
useRef,
|
|
358
|
+
useState,
|
|
359
|
+
SearchIcon,
|
|
360
|
+
RhUiCodeIcon,
|
|
361
|
+
RhUiBranchFillIcon,
|
|
362
|
+
CodeIcon,
|
|
363
|
+
CubeIcon,
|
|
364
|
+
LeafIcon,
|
|
365
|
+
FolderIcon,
|
|
366
|
+
FolderOpenIcon,
|
|
367
|
+
RhMicronsSortDownLargeToSmallIcon,
|
|
368
|
+
NewSelect,
|
|
369
|
+
NewSelectGroup,
|
|
370
|
+
NewSelectList,
|
|
371
|
+
NewSelectOption,
|
|
372
|
+
css,
|
|
373
|
+
styles,
|
|
374
|
+
spacing,
|
|
375
|
+
t_global_color_brand_default
|
|
376
|
+
};
|
|
377
|
+
pageData.examples = {
|
|
378
|
+
'Basic': props =>
|
|
379
|
+
<Example {...pageData} {...props} {...{"code":"import { Fragment, useState } from 'react';\nimport { Table, TableHeader, TableBody, TableProps } from '@patternfly/react-table/deprecated';\nimport { ToggleGroup, ToggleGroupItem, ToggleGroupItemProps } from '@patternfly/react-core';\ninterface Repository {\n name: string;\n branches: string;\n prs: string;\n workspaces: string;\n lastCommit: string;\n}\n\ntype ExampleType = 'default' | 'compact' | 'compactBorderless';\n\nexport const LegacyTableBasic: React.FunctionComponent = () => {\n // In real usage, this data would come from some external source like an API via props.\n const repositories: Repository[] = [\n {\n name: 'Repository one',\n branches: 'Branch one',\n prs: 'PR one',\n workspaces: 'Workspace one',\n lastCommit: 'Commit one'\n },\n {\n name: 'Repository two',\n branches: 'Branch two',\n prs: 'PR two',\n workspaces: 'Workspace two',\n lastCommit: 'Commit two'\n },\n {\n name: 'Repository three',\n branches: 'Branch three',\n prs: 'PR three',\n workspaces: 'Workspace three',\n lastCommit: 'Commit three'\n }\n ];\n\n // This state is just for the ToggleGroup in this example and isn't necessary for table usage.\n const [exampleChoice, setExampleChoice] = useState<ExampleType>('default');\n const onExampleTypeChange: ToggleGroupItemProps['onChange'] = (event, _isSelected) => {\n const id = event.currentTarget.id;\n setExampleChoice(id as ExampleType);\n };\n\n const columns: TableProps['cells'] = ['Repositories', 'Branches', 'Pull requests', 'Workspaces', 'Last commit'];\n const rows: TableProps['rows'] = repositories.map((repo) => [\n repo.name,\n repo.branches,\n repo.prs,\n repo.workspaces,\n repo.lastCommit\n ]);\n\n return (\n <Fragment>\n <ToggleGroup aria-label=\"Default with single selectable\">\n <ToggleGroupItem\n text=\"Default\"\n buttonId=\"default\"\n isSelected={exampleChoice === 'default'}\n onChange={onExampleTypeChange}\n />\n <ToggleGroupItem\n text=\"Compact\"\n buttonId=\"compact\"\n isSelected={exampleChoice === 'compact'}\n onChange={onExampleTypeChange}\n />\n <ToggleGroupItem\n text=\"Compact borderless\"\n buttonId=\"compactBorderless\"\n isSelected={exampleChoice === 'compactBorderless'}\n onChange={onExampleTypeChange}\n />\n </ToggleGroup>\n <Table\n aria-label=\"Simple Table\"\n variant={exampleChoice !== 'default' ? 'compact' : undefined}\n borders={exampleChoice !== 'compactBorderless'}\n cells={columns}\n rows={rows}\n >\n <TableHeader />\n <TableBody />\n </Table>\n </Fragment>\n );\n};\n","title":"Basic","lang":"ts","className":""}}>
|
|
380
|
+
|
|
381
|
+
</Example>,
|
|
382
|
+
'Custom row wrapper': props =>
|
|
383
|
+
<Example {...pageData} {...props} {...{"code":"import { Table, TableHeader, TableBody, TableProps } from '@patternfly/react-table/deprecated';\nimport { css } from '@patternfly/react-styles';\nimport t_global_color_brand_default from '@patternfly/react-tokens/dist/esm/t_global_color_brand_default';\n\ninterface Repository {\n name: string;\n branches: string | null;\n prs: string | null;\n workspaces: string;\n lastCommit: string;\n}\n\nexport const LegacyTableMisc: React.FunctionComponent = () => {\n // In real usage, this data would come from some external source like an API via props.\n const repositories: Repository[] = [\n { name: 'one', branches: 'two', prs: 'three', workspaces: 'four', lastCommit: 'five' },\n { name: 'one - 2', branches: null, prs: null, workspaces: 'four - 2', lastCommit: 'five - 2' },\n { name: 'one - 3', branches: 'two - 3', prs: 'three - 3', workspaces: 'four - 3', lastCommit: 'five - 3' }\n ];\n\n const columns: TableProps['cells'] = ['Repositories', 'Branches', 'Pull requests', 'Workspaces', 'Last commit'];\n const rows: TableProps['rows'] = repositories.map((repo) => [\n repo.name,\n repo.branches || '',\n repo.prs || '',\n repo.workspaces,\n repo.lastCommit\n ]);\n\n const customRowWrapper: TableProps['rowWrapper'] = ({ trRef, className, rowProps, row: _row }) => {\n const isOddRow = rowProps ? !!((rowProps.rowIndex + 1) % 2) : true;\n const customStyle = {\n borderLeft: `3px solid ${t_global_color_brand_default.var}`\n };\n return (\n <tr\n ref={trRef as React.Ref<HTMLTableRowElement>}\n className={css(className, isOddRow ? 'odd-row-class' : 'even-row-class', 'custom-static-class')}\n style={isOddRow ? customStyle : {}}\n />\n );\n };\n\n return (\n <Table\n caption=\"Table with custom row wrapper that styles odd rows\"\n cells={columns}\n rows={rows}\n rowWrapper={customRowWrapper}\n >\n <TableHeader />\n <TableBody />\n </Table>\n );\n};\n","title":"Custom row wrapper","lang":"ts","className":""}}>
|
|
384
|
+
|
|
385
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
386
|
+
{`Custom row wrappers are passed to the `}
|
|
387
|
+
|
|
388
|
+
<code {...{"className":"ws-code "}}>
|
|
389
|
+
{`Table`}
|
|
390
|
+
</code>
|
|
391
|
+
{` component via the `}
|
|
392
|
+
|
|
393
|
+
<code {...{"className":"ws-code "}}>
|
|
394
|
+
{`rowWrapper`}
|
|
395
|
+
</code>
|
|
396
|
+
{` prop.
|
|
397
|
+
Each `}
|
|
398
|
+
|
|
399
|
+
<code {...{"className":"ws-code "}}>
|
|
400
|
+
{`rowWrapper`}
|
|
401
|
+
</code>
|
|
402
|
+
{` should return a tr element.`}
|
|
403
|
+
</p>
|
|
404
|
+
|
|
405
|
+
<Example {...{"code":"rowWrapper?: (props: RowWrapperProps) => JSX.Element;","className":""}}>
|
|
406
|
+
|
|
407
|
+
</Example>
|
|
408
|
+
|
|
409
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
410
|
+
{`RowWrapperProps:`}
|
|
411
|
+
</p>
|
|
412
|
+
|
|
413
|
+
<Example {...{"code":"interface RowWrapperProps {\n trRef?: React.Ref<any> | Function;\n className?: string;\n onScroll?: React.UIEventHandler;\n onResize?: React.UIEventHandler;\n row?: IRow;\n rowProps?: {\n rowIndex: number;\n rowKey: string;\n };\n children?: React.ReactNode;\n ouiaId?: number | string;\n}","className":""}}>
|
|
414
|
+
|
|
415
|
+
</Example>
|
|
416
|
+
</Example>,
|
|
417
|
+
'Sortable & wrapping column headers': props =>
|
|
418
|
+
<Example {...pageData} {...props} {...{"code":"import { useState } from 'react';\nimport { sortable, info, cellWidth, wrappable } from '@patternfly/react-table';\nimport { Table, TableHeader, TableBody, TableProps } from '@patternfly/react-table/deprecated';\n\ninterface Repository {\n name: string;\n branches: string;\n prs: string;\n workspaces: string;\n lastCommit: string;\n}\n\nexport const LegacyTableSortable: React.FunctionComponent = () => {\n // In real usage, this data would come from some external source like an API via props.\n const repositories: Repository[] = [\n { name: 'one', branches: 'two', prs: 'a', workspaces: 'four', lastCommit: 'five' },\n { name: 'a', branches: 'two', prs: 'k', workspaces: 'four', lastCommit: 'five' },\n { name: 'p', branches: 'two', prs: 'b', workspaces: 'four', lastCommit: 'five' }\n ];\n\n // Index of the currently sorted column\n // Note: if you intend to make columns reorderable, you may instead want to use a non-numeric key\n // as the identifier of the sorted column. See the \"Compound expandable\" example.\n const [activeSortIndex, setActiveSortIndex] = useState<number | null>(null);\n\n // Sort direction of the currently sorted column\n const [activeSortDirection, setActiveSortDirection] = useState<'asc' | 'desc' | null>(null);\n\n // Since OnSort specifies sorted columns by index, we need sortable values for our object by column index.\n // This example is trivial since our data objects just contain strings, but if the data was more complex\n // this would be a place to return simplified string or number versions of each column to sort by.\n const getSortableRowValues = (repo: Repository): (string | number)[] => {\n const { name, branches, prs, workspaces, lastCommit } = repo;\n return [name, branches, prs, workspaces, lastCommit];\n };\n\n // Note that we perform the sort as part of the component's render logic and not in onSort.\n // We shouldn't store the list of data in state because we don't want to have to sync that with props.\n let sortedRepositories = repositories;\n if (activeSortIndex !== null) {\n sortedRepositories = repositories.sort((a, b) => {\n const aValue = getSortableRowValues(a)[activeSortIndex];\n const bValue = getSortableRowValues(b)[activeSortIndex];\n if (typeof aValue === 'number') {\n // Numeric sort\n if (activeSortDirection === 'asc') {\n return (aValue as number) - (bValue as number);\n }\n return (bValue as number) - (aValue as number);\n } else {\n // String sort\n if (activeSortDirection === 'asc') {\n return (aValue as string).localeCompare(bValue as string);\n }\n return (bValue as string).localeCompare(aValue as string);\n }\n });\n }\n\n const columns: TableProps['cells'] = [\n { title: 'Repositories', transforms: [sortable] },\n {\n title: 'Branches',\n transforms: [\n info({\n tooltip: 'More information about branches'\n }),\n sortable\n ]\n },\n { title: 'Pull requests', transforms: [sortable] },\n {\n title: 'Workspaces - Also this long header will wrap since we have applied the wrappable transform',\n transforms: [sortable, wrappable, cellWidth(20)]\n },\n {\n title: 'Last commit',\n transforms: [\n info({\n tooltip: 'More information about commits'\n })\n ]\n }\n ];\n const rows: TableProps['rows'] = sortedRepositories.map((repo) => [\n repo.name,\n repo.branches,\n repo.prs,\n repo.workspaces,\n repo.lastCommit\n ]);\n\n return (\n <Table\n aria-label=\"Sortable Table\"\n sortBy={{\n index: activeSortIndex,\n direction: activeSortDirection,\n defaultDirection: 'asc' // starting sort direction when first sorting a column. Defaults to 'asc'\n }}\n onSort={(_event, index, direction) => {\n setActiveSortIndex(index);\n setActiveSortDirection(direction);\n }}\n cells={columns}\n rows={rows}\n >\n <TableHeader />\n <TableBody />\n </Table>\n );\n};\n","title":"Sortable & wrapping column headers","lang":"ts","className":""}}>
|
|
419
|
+
|
|
420
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
421
|
+
{`To implement sortable columns:`}
|
|
422
|
+
</p>
|
|
423
|
+
|
|
424
|
+
<ol {...{"className":"pf-v6-c-content--ol pf-m-editorial ws-ol "}}>
|
|
425
|
+
|
|
426
|
+
|
|
427
|
+
|
|
428
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
429
|
+
{`Import and apply the `}
|
|
430
|
+
|
|
431
|
+
<code {...{"className":"ws-code "}}>
|
|
432
|
+
{`sortable`}
|
|
433
|
+
</code>
|
|
434
|
+
{` transform to the desired column.`}
|
|
435
|
+
</li>
|
|
436
|
+
|
|
437
|
+
|
|
438
|
+
|
|
439
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
440
|
+
{`Pass a managed `}
|
|
441
|
+
|
|
442
|
+
<code {...{"className":"ws-code "}}>
|
|
443
|
+
{`sortBy`}
|
|
444
|
+
</code>
|
|
445
|
+
{` prop to the `}
|
|
446
|
+
|
|
447
|
+
<code {...{"className":"ws-code "}}>
|
|
448
|
+
{`Table`}
|
|
449
|
+
</code>
|
|
450
|
+
{` component.
|
|
451
|
+
`}
|
|
452
|
+
|
|
453
|
+
<code {...{"className":"ws-code "}}>
|
|
454
|
+
{`\`sortBy\` - Specifies the initial sorting pattern for the table - asc/desc and the index of the column to sort by`}
|
|
455
|
+
</code>
|
|
456
|
+
</li>
|
|
457
|
+
|
|
458
|
+
|
|
459
|
+
|
|
460
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
461
|
+
{`Pass an `}
|
|
462
|
+
|
|
463
|
+
<code {...{"className":"ws-code "}}>
|
|
464
|
+
{`onSort`}
|
|
465
|
+
</code>
|
|
466
|
+
{` callback to the `}
|
|
467
|
+
|
|
468
|
+
<code {...{"className":"ws-code "}}>
|
|
469
|
+
{`Table`}
|
|
470
|
+
</code>
|
|
471
|
+
{` component
|
|
472
|
+
`}
|
|
473
|
+
|
|
474
|
+
<code {...{"className":"ws-code "}}>
|
|
475
|
+
{`\`onSort\` - (event: React.MouseEvent, columnIndex: number, sortByDirection: SortByDirection, extraData: IExtraColumnData) => void;`}
|
|
476
|
+
</code>
|
|
477
|
+
</li>
|
|
478
|
+
|
|
479
|
+
|
|
480
|
+
</ol>
|
|
481
|
+
|
|
482
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
483
|
+
{`Note: If you want to add a tooltip/popover to a sortable header, in the `}
|
|
484
|
+
|
|
485
|
+
<code {...{"className":"ws-code "}}>
|
|
486
|
+
{`transforms`}
|
|
487
|
+
</code>
|
|
488
|
+
{` array the `}
|
|
489
|
+
|
|
490
|
+
<code {...{"className":"ws-code "}}>
|
|
491
|
+
{`info`}
|
|
492
|
+
</code>
|
|
493
|
+
{` transform has to precede the `}
|
|
494
|
+
|
|
495
|
+
<code {...{"className":"ws-code "}}>
|
|
496
|
+
{`sortable`}
|
|
497
|
+
</code>
|
|
498
|
+
{` transform.`}
|
|
499
|
+
</p>
|
|
500
|
+
|
|
501
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
502
|
+
{`The built in display for sorting is not fully responsive, as the column headers will be displayed per row when the screen size is small. The example below showcases how sorting may have a custom control display that can be used for small screen sizes.`}
|
|
503
|
+
</p>
|
|
504
|
+
</Example>,
|
|
505
|
+
'Sortable - custom control': props =>
|
|
506
|
+
<Example {...pageData} {...props} {...{"code":"import { Fragment, useState } from 'react';\nimport { sortable, info } from '@patternfly/react-table';\nimport { Table, TableHeader, TableBody, TableProps } from '@patternfly/react-table/deprecated';\nimport { Toolbar, ToolbarContent, ToolbarItem, MenuToggle, MenuToggleElement } from '@patternfly/react-core';\nimport {\n Select as NewSelect,\n SelectGroup as NewSelectGroup,\n SelectList as NewSelectList,\n SelectOption as NewSelectOption\n} from '@patternfly/react-core/dist/esm/components/Select';\n\nimport RhMicronsSortDownLargeToSmallIcon from '@patternfly/react-icons/dist/esm/icons/rh-microns-sort-down-large-to-small-icon';\n\ninterface Repository {\n name: string;\n branches: string;\n prs: string;\n workspaces: string;\n lastCommit: string;\n}\n\nexport const LegacyTableSortableCustom: React.FunctionComponent = () => {\n // In real usage, this data would come from some external source like an API via props.\n const repositories: Repository[] = [\n { name: 'one', branches: 'two', prs: 'a', workspaces: 'four', lastCommit: 'five' },\n { name: 'a', branches: 'two', prs: 'k', workspaces: 'four', lastCommit: 'five' },\n { name: 'p', branches: 'two', prs: 'b', workspaces: 'four', lastCommit: 'five' }\n ];\n\n const columnNames = {\n name: 'Repositories',\n branches: 'Branches',\n prs: 'Pull requests',\n workspaces: 'Workspaces',\n lastCommit: 'Last commit'\n };\n\n const [isSortDropdownOpen, setIsSortDropdownOpen] = useState(false);\n\n // Index of the currently sorted column\n // Note: if you intend to make columns reorderable, you may instead want to use a non-numeric key\n // as the identifier of the sorted column. See the \"Compound expandable\" example.\n const [activeSortIndex, setActiveSortIndex] = useState<number | null>(null);\n\n // Sort direction of the currently sorted column\n const [activeSortDirection, setActiveSortDirection] = useState<'asc' | 'desc' | null>(null);\n\n // Sort dropdown expansion\n // const [isSortDropdownOpen, setIsSortDropdownOpen] = useState(false);\n\n // Since OnSort specifies sorted columns by index, we need sortable values for our object by column index.\n // This example is trivial since our data objects just contain strings, but if the data was more complex\n // this would be a place to return simplified string or number versions of each column to sort by.\n const getSortableRowValues = (repo: Repository): (string | number)[] => {\n const { name, branches, prs, workspaces, lastCommit } = repo;\n return [name, branches, prs, workspaces, lastCommit];\n };\n\n // Note that we perform the sort as part of the component's render logic and not in onSort.\n // We shouldn't store the list of data in state because we don't want to have to sync that with props.\n let sortedRepositories = repositories;\n if (activeSortIndex !== null) {\n sortedRepositories = repositories.sort((a, b) => {\n const aValue = getSortableRowValues(a)[activeSortIndex];\n const bValue = getSortableRowValues(b)[activeSortIndex];\n if (typeof aValue === 'number') {\n // Numeric sort\n if (activeSortDirection === 'asc') {\n return (aValue as number) - (bValue as number);\n }\n return (bValue as number) - (aValue as number);\n } else {\n // String sort\n if (activeSortDirection === 'asc') {\n return (aValue as string).localeCompare(bValue as string);\n }\n return (bValue as string).localeCompare(aValue as string);\n }\n });\n }\n\n const columns: TableProps['cells'] = [\n { title: 'Repositories', transforms: [sortable] },\n {\n title: 'Branches',\n transforms: [\n info({\n tooltip: 'More information about branches'\n }),\n sortable\n ]\n },\n { title: 'Pull requests', transforms: [sortable] },\n {\n title: 'Workspaces',\n transforms: [sortable]\n },\n {\n title: 'Last commit',\n transforms: [\n info({\n tooltip: 'More information about commits'\n }),\n sortable\n ]\n }\n ];\n const rows: TableProps['rows'] = sortedRepositories.map((repo) => [\n repo.name,\n repo.branches,\n repo.prs,\n repo.workspaces,\n repo.lastCommit\n ]);\n\n return (\n <Fragment>\n <Toolbar id=\"toolbar\">\n <ToolbarContent>\n <ToolbarItem>\n <NewSelect\n isOpen={isSortDropdownOpen}\n selected={[activeSortDirection, activeSortIndex]}\n onOpenChange={(isOpen) => setIsSortDropdownOpen(isOpen)}\n onSelect={(event, value) => {\n if (value === 'asc' || value === 'desc') {\n setActiveSortDirection(value as 'desc' | 'asc');\n } else {\n setActiveSortIndex(value as number);\n setActiveSortDirection(activeSortDirection !== null ? activeSortDirection : 'asc');\n }\n }}\n toggle={(toggleRef: React.Ref<MenuToggleElement>) => (\n <MenuToggle\n ref={toggleRef}\n onClick={() => setIsSortDropdownOpen(!isSortDropdownOpen)}\n isExpanded={isSortDropdownOpen}\n variant=\"plain\"\n aria-label=\"Sort columns\"\n icon={<RhMicronsSortDownLargeToSmallIcon />}\n />\n )}\n >\n <NewSelectGroup label=\"Sort column\">\n <NewSelectList>\n {Object.values(columnNames).map((column, columnIndex) => (\n <NewSelectOption key={column} value={columnIndex} isSelected={activeSortIndex === columnIndex}>\n {column}\n </NewSelectOption>\n ))}\n </NewSelectList>\n </NewSelectGroup>\n <NewSelectGroup label=\"Sort direction\">\n <NewSelectList>\n <NewSelectOption isSelected={activeSortDirection === 'asc'} value=\"asc\" key=\"ascending\">\n Ascending\n </NewSelectOption>\n <NewSelectOption isSelected={activeSortDirection === 'desc'} value=\"desc\" key=\"descending\">\n Descending\n </NewSelectOption>\n </NewSelectList>\n </NewSelectGroup>\n </NewSelect>\n </ToolbarItem>\n </ToolbarContent>\n </Toolbar>\n <Table\n aria-label=\"Sortable Table with Custom Toolbar\"\n sortBy={{\n index: activeSortIndex,\n direction: activeSortDirection\n }}\n onSort={(_event, index, direction) => {\n setActiveSortIndex(index);\n setActiveSortDirection(direction);\n }}\n cells={columns}\n rows={rows}\n >\n <TableHeader />\n <TableBody />\n </Table>\n </Fragment>\n );\n};\n","title":"Sortable - custom control","lang":"ts","className":""}}>
|
|
507
|
+
|
|
508
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
509
|
+
{`Sorting a table may also be controlled with a toolbar. This toolbar item may also be hidden at large screen sizes and only displayed when the screen size is small to support responsive tables.`}
|
|
510
|
+
</p>
|
|
511
|
+
</Example>,
|
|
512
|
+
'Selectable with checkbox': props =>
|
|
513
|
+
<Example {...pageData} {...props} {...{"code":"import { useEffect, useState } from 'react';\nimport { headerCol } from '@patternfly/react-table';\nimport { Table, TableHeader, TableBody, TableProps } from '@patternfly/react-table/deprecated';\nimport { Checkbox } from '@patternfly/react-core';\nimport spacing from '@patternfly/react-styles/css/utilities/Spacing/spacing';\n\ninterface Repository {\n name: string;\n branches: string;\n prs: string;\n workspaces: string;\n lastCommit: string;\n}\n\nexport const LegacyTableSelectable: React.FunctionComponent = () => {\n // In real usage, this data would come from some external source like an API via props.\n const repositories: Repository[] = [\n { name: 'one', branches: 'two', prs: 'a', workspaces: 'four', lastCommit: 'five' },\n { name: 'a', branches: 'two', prs: 'k', workspaces: 'four', lastCommit: 'five' },\n { name: 'b', branches: 'two', prs: 'k', workspaces: 'four', lastCommit: 'five' },\n { name: 'c', branches: 'two', prs: 'k', workspaces: 'four', lastCommit: 'five' },\n { name: 'd', branches: 'two', prs: 'k', workspaces: 'four', lastCommit: 'five' },\n { name: 'e', branches: 'two', prs: 'b', workspaces: 'four', lastCommit: 'five' }\n ];\n\n const isRepoSelectable = (repo: Repository) => repo.name !== 'a'; // Arbitrary logic for this example\n const selectableRepos = repositories.filter(isRepoSelectable);\n\n // In this example, selected rows are tracked by the repo names from each row. This could be any unique identifier.\n // This is to prevent state from being based on row order index in case we later add sorting.\n const [selectedRepoNames, setSelectedRepoNames] = useState<string[]>([]);\n const setRepoSelected = (repo: Repository, isSelecting = true) =>\n setSelectedRepoNames((prevSelected) => {\n const otherSelectedRepoNames = prevSelected.filter((r) => r !== repo.name);\n return isSelecting && isRepoSelectable(repo) ? [...otherSelectedRepoNames, repo.name] : otherSelectedRepoNames;\n });\n const selectAllRepos = (isSelecting = true) =>\n setSelectedRepoNames(isSelecting ? selectableRepos.map((r) => r.name) : []);\n const isRepoSelected = (repo: Repository) => selectedRepoNames.includes(repo.name);\n\n const [canSelectAll, setCanSelectAll] = useState(true);\n\n // To allow shift+click to select/deselect multiple rows\n const [recentSelectedRowIndex, setRecentSelectedRowIndex] = useState<number | null>(null);\n const [shifting, setShifting] = useState(false);\n\n const onSelectRepo = (repo: Repository, rowIndex: number, isSelecting: boolean) => {\n // If the user is shift + selecting the checkboxes, then all intermediate checkboxes should be selected\n if (shifting && recentSelectedRowIndex !== null) {\n const numberSelected = rowIndex - recentSelectedRowIndex;\n const intermediateIndexes =\n numberSelected > 0\n ? Array.from(new Array(numberSelected + 1), (_x, i) => i + recentSelectedRowIndex)\n : Array.from(new Array(Math.abs(numberSelected) + 1), (_x, i) => i + rowIndex);\n intermediateIndexes.forEach((index) => setRepoSelected(repositories[index], isSelecting));\n } else {\n setRepoSelected(repo, isSelecting);\n }\n setRecentSelectedRowIndex(rowIndex);\n };\n\n useEffect(() => {\n const onKeyDown = (e: KeyboardEvent) => {\n if (e.key === 'Shift') {\n setShifting(true);\n }\n };\n const onKeyUp = (e: KeyboardEvent) => {\n if (e.key === 'Shift') {\n setShifting(false);\n }\n };\n\n document.addEventListener('keydown', onKeyDown);\n document.addEventListener('keyup', onKeyUp);\n\n return () => {\n document.removeEventListener('keydown', onKeyDown);\n document.removeEventListener('keyup', onKeyUp);\n };\n }, []);\n\n const columns: TableProps['cells'] = [\n { title: 'Repositories', cellTransforms: [headerCol()] },\n 'Branches',\n { title: 'Pull requests' },\n 'Workspaces',\n 'Last commit'\n ];\n const rows: TableProps['rows'] = repositories.map((repo) => ({\n cells: [repo.name, repo.branches, repo.prs, repo.workspaces, repo.lastCommit],\n selected: isRepoSelected(repo),\n disableSelection: !isRepoSelectable(repo)\n }));\n\n return (\n <div>\n <Checkbox\n label=\"Can select all\"\n className={spacing.mbLg}\n isChecked={canSelectAll}\n onChange={(_event, checked) => setCanSelectAll(checked)}\n aria-label=\"toggle select all checkbox\"\n id=\"toggle-select-all\"\n name=\"toggle-select-all\"\n />\n <Table\n onSelect={(_event, isSelecting, rowIndex) => {\n if (rowIndex === -1) {\n selectAllRepos(isSelecting);\n } else {\n const repo = repositories[rowIndex];\n onSelectRepo(repo, rowIndex, isSelecting);\n }\n }}\n canSelectAll={canSelectAll}\n aria-label=\"Selectable Table\"\n cells={columns}\n rows={rows}\n >\n <TableHeader />\n <TableBody />\n </Table>\n </div>\n );\n};\n","title":"Selectable with checkbox","lang":"ts","className":""}}>
|
|
514
|
+
|
|
515
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
516
|
+
{`To enable row selection, set the `}
|
|
517
|
+
|
|
518
|
+
<code {...{"className":"ws-code "}}>
|
|
519
|
+
{`onSelect`}
|
|
520
|
+
</code>
|
|
521
|
+
{` callback prop on the Table.`}
|
|
522
|
+
</p>
|
|
523
|
+
|
|
524
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
525
|
+
{`To control whether a row is selected or not, the Table looks for `}
|
|
526
|
+
|
|
527
|
+
<code {...{"className":"ws-code "}}>
|
|
528
|
+
{`selected: true | falsy`}
|
|
529
|
+
</code>
|
|
530
|
+
{` on the row definition.`}
|
|
531
|
+
</p>
|
|
532
|
+
|
|
533
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
534
|
+
{`To disable selection for a row, set `}
|
|
535
|
+
|
|
536
|
+
<code {...{"className":"ws-code "}}>
|
|
537
|
+
{`disableSelection: true`}
|
|
538
|
+
</code>
|
|
539
|
+
{` on the row definition.`}
|
|
540
|
+
</p>
|
|
541
|
+
|
|
542
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
543
|
+
{`To include a 'select all' checkbox in the header row, pass `}
|
|
544
|
+
|
|
545
|
+
<code {...{"className":"ws-code "}}>
|
|
546
|
+
{`true`}
|
|
547
|
+
</code>
|
|
548
|
+
{` to the`}
|
|
549
|
+
|
|
550
|
+
<code {...{"className":"ws-code "}}>
|
|
551
|
+
{`canSelectAll`}
|
|
552
|
+
</code>
|
|
553
|
+
{` prop on the Table.`}
|
|
554
|
+
</p>
|
|
555
|
+
|
|
556
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
557
|
+
{`Note: this example also demonstrates the use of the `}
|
|
558
|
+
|
|
559
|
+
<code {...{"className":"ws-code "}}>
|
|
560
|
+
{`headerCol`}
|
|
561
|
+
</code>
|
|
562
|
+
{` transformation being applied to the first
|
|
563
|
+
column via the `}
|
|
564
|
+
|
|
565
|
+
<code {...{"className":"ws-code "}}>
|
|
566
|
+
{`cellTransforms`}
|
|
567
|
+
</code>
|
|
568
|
+
{` in the column definition. `}
|
|
569
|
+
|
|
570
|
+
<code {...{"className":"ws-code "}}>
|
|
571
|
+
{`headerCol`}
|
|
572
|
+
</code>
|
|
573
|
+
{` transforms the column so that instead
|
|
574
|
+
of using `}
|
|
575
|
+
|
|
576
|
+
<code {...{"className":"ws-code "}}>
|
|
577
|
+
{`td`}
|
|
578
|
+
</code>
|
|
579
|
+
{` elements, the cells in that column use `}
|
|
580
|
+
|
|
581
|
+
<code {...{"className":"ws-code "}}>
|
|
582
|
+
{`th`}
|
|
583
|
+
</code>
|
|
584
|
+
{` elements.`}
|
|
585
|
+
</p>
|
|
586
|
+
|
|
587
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
588
|
+
|
|
589
|
+
<strong {...{"className":""}}>
|
|
590
|
+
{`Note:`}
|
|
591
|
+
</strong>
|
|
592
|
+
{` This example has a `}
|
|
593
|
+
|
|
594
|
+
<code {...{"className":"ws-code "}}>
|
|
595
|
+
{`shift + select`}
|
|
596
|
+
</code>
|
|
597
|
+
{` feature where holding shift while
|
|
598
|
+
checking checkboxes will check intermediate rows' checkboxes.`}
|
|
599
|
+
</p>
|
|
600
|
+
</Example>,
|
|
601
|
+
'Selectable radio input': props =>
|
|
602
|
+
<Example {...pageData} {...props} {...{"code":"import { useState } from 'react';\nimport { headerCol } from '@patternfly/react-table';\nimport { Table, TableHeader, TableBody, TableProps } from '@patternfly/react-table/deprecated';\n\ninterface Repository {\n name: string;\n branches: string;\n prs: string;\n workspaces: string;\n lastCommit: string;\n}\n\nexport const LegacyTableSelectableRadio: React.FunctionComponent = () => {\n // In real usage, this data would come from some external source like an API via props.\n const repositories: Repository[] = [\n { name: 'one', branches: 'two', prs: 'a', workspaces: 'four', lastCommit: 'five' },\n { name: 'a', branches: 'two', prs: 'k', workspaces: 'four', lastCommit: 'five' },\n { name: 'p', branches: 'two', prs: 'b', workspaces: 'four', lastCommit: 'five' }\n ];\n\n const isRepoSelectable = (repo: Repository) => repo.name !== 'a'; // Arbitrary logic for this example\n\n // In this example, selected rows are tracked by the repo names from each row. This could be any unique identifier.\n // This is to prevent state from being based on row order index in case we later add sorting.\n const [selectedRepoName, setSelectedRepoName] = useState<string | null>(null);\n\n const columns: TableProps['cells'] = [\n { title: 'Repositories', cellTransforms: [headerCol('selectable-radio')] },\n 'Branches',\n { title: 'Pull requests' },\n 'Workspaces',\n 'Last commit'\n ];\n const rows: TableProps['rows'] = repositories.map((repo) => ({\n cells: [repo.name, repo.branches, repo.prs, repo.workspaces, repo.lastCommit],\n selected: selectedRepoName === repo.name,\n disableSelection: !isRepoSelectable(repo)\n }));\n\n return (\n <Table\n onSelect={(_event, _isSelecting, rowIndex) => {\n const repo = repositories[rowIndex];\n setSelectedRepoName(repo.name);\n }}\n selectVariant=\"radio\"\n aria-label=\"Selectable Table with Radio Buttons\"\n cells={columns}\n rows={rows}\n >\n <TableHeader />\n <TableBody />\n </Table>\n );\n};\n","title":"Selectable radio input","lang":"ts","className":""}}>
|
|
603
|
+
|
|
604
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
605
|
+
{`To enable row radio selection, set the `}
|
|
606
|
+
|
|
607
|
+
<code {...{"className":"ws-code "}}>
|
|
608
|
+
{`onSelect`}
|
|
609
|
+
</code>
|
|
610
|
+
{` callback prop on the Table, and set
|
|
611
|
+
`}
|
|
612
|
+
|
|
613
|
+
<code {...{"className":"ws-code "}}>
|
|
614
|
+
{`RowSelectVariant.radio`}
|
|
615
|
+
</code>
|
|
616
|
+
{` or `}
|
|
617
|
+
|
|
618
|
+
<code {...{"className":"ws-code "}}>
|
|
619
|
+
{`"radio"`}
|
|
620
|
+
</code>
|
|
621
|
+
{` as the `}
|
|
622
|
+
|
|
623
|
+
<code {...{"className":"ws-code "}}>
|
|
624
|
+
{`selectVariant`}
|
|
625
|
+
</code>
|
|
626
|
+
{` prop on the Table.`}
|
|
627
|
+
</p>
|
|
628
|
+
|
|
629
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
630
|
+
{`To disable selection for a row, set `}
|
|
631
|
+
|
|
632
|
+
<code {...{"className":"ws-code "}}>
|
|
633
|
+
{`disableSelection: true`}
|
|
634
|
+
</code>
|
|
635
|
+
{` on the row definition.`}
|
|
636
|
+
</p>
|
|
637
|
+
</Example>,
|
|
638
|
+
'Clickable rows, selectable rows, and header cell tooltips/popovers': props =>
|
|
639
|
+
<Example {...pageData} {...props} {...{"code":"import { useState } from 'react';\nimport { info, textCenter, ICell } from '@patternfly/react-table';\nimport { Table, TableHeader, TableBody, TableProps } from '@patternfly/react-table/deprecated';\nimport styles from '@patternfly/react-styles/css/components/Table/table';\n\ninterface Repository {\n name: string;\n branches: string | null;\n prs: string | null;\n workspaces: string;\n lastCommit: string;\n}\n\nexport const LegacyTableClickable: React.FunctionComponent = () => {\n // In real usage, this data would come from some external source like an API via props.\n const repositories: Repository[] = [\n {\n name: 'Repository one',\n branches: 'Branch one',\n prs: 'PR one',\n workspaces: 'Workspace one',\n lastCommit: 'Commit one'\n },\n { name: 'one - 2', branches: null, prs: null, workspaces: 'four - 2', lastCommit: 'five - 2' },\n {\n name: 'one - 3',\n branches: 'two - 3',\n prs: 'three - 3',\n workspaces: 'four - 3',\n lastCommit: 'five - 3 (not centered)'\n }\n ];\n\n // In this example, selected rows are tracked by the repo names from each row. This could be any unique identifier.\n // This is to prevent state from being based on row order index in case we later add sorting.\n const [selectedRepoName, setSelectedRepoName] = useState('');\n const columns: TableProps['cells'] = [\n {\n title: 'Repositories',\n transforms: [\n info({\n tooltip: 'More information about repositories',\n className: 'repositories-info-tip',\n tooltipProps: {\n isContentLeftAligned: true\n }\n })\n ]\n },\n 'Branches',\n {\n title: 'Pull requests',\n transforms: [\n info({\n popover: (\n <div>\n More <strong>information</strong> on pull requests\n </div>\n ),\n ariaLabel: 'More information on pull requests',\n popoverProps: {\n headerContent: 'Pull requests',\n footerContent: <a href=\"#\">Click here for even more info</a>\n }\n })\n ]\n },\n 'Workspaces',\n {\n title: 'Last commit',\n transforms: [textCenter],\n cellTransforms: [textCenter]\n }\n ];\n const rows: TableProps['rows'] = repositories.map((repo) => {\n let cells: (string | ICell)[] = [repo.name, repo.branches || '', repo.prs || '', repo.workspaces, repo.lastCommit];\n // These rows have arbitrary differences for this example, but these could be based on some other conditions\n if (repo.name === 'one - 2') {\n cells = [\n {\n title: <div>{repo.name}</div>,\n props: { title: 'hover title', colSpan: 3 }\n },\n repo.workspaces,\n repo.lastCommit\n ];\n } else if (repo.name === 'five - 3 (not centrered)') {\n cells = [\n repo.name,\n repo.branches || '',\n repo.prs || '',\n repo.workspaces,\n {\n title: repo.lastCommit,\n props: { textCenter: false }\n }\n ];\n }\n return {\n cells,\n isClickable: true,\n isRowSelected: selectedRepoName === repo.name\n };\n });\n\n return (\n <Table caption=\"Row click handler table\" cells={columns} rows={rows}>\n <TableHeader className={styles.modifiers.nowrap} />\n <TableBody\n onRowClick={(_event, row, rowProps) => {\n if (rowProps) {\n const repo = repositories[rowProps.rowIndex];\n setSelectedRepoName(repo.name);\n }\n }}\n />\n </Table>\n );\n};\n","title":"Clickable rows, selectable rows, and header cell tooltips/popovers","lang":"ts","className":""}}>
|
|
640
|
+
|
|
641
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
642
|
+
{`This selectable rows feature is intended for use when a table is used to present a list of objects in a Primary-detail view.`}
|
|
643
|
+
</p>
|
|
644
|
+
</Example>,
|
|
645
|
+
'Actions and first cell in body rows as th': props =>
|
|
646
|
+
<Example {...pageData} {...props} {...{"code":"/* eslint-disable no-console */\nimport { Fragment, useState } from 'react';\nimport {\n Button,\n Checkbox,\n MenuToggle,\n ToggleGroup,\n ToggleGroupItem,\n ToggleGroupItemProps,\n Toolbar,\n ToolbarContent,\n ToolbarItem\n} from '@patternfly/react-core';\nimport {\n CustomActionsToggleProps,\n fitContent,\n headerCol,\n IActions,\n IActionsResolver,\n TableText\n} from '@patternfly/react-table';\nimport { Table, TableBody, TableHeader, TableProps } from '@patternfly/react-table/deprecated';\n\ninterface Repository {\n name: string;\n branches: string;\n prs: string;\n workspaces: string;\n lastCommit: string;\n singleAction: string;\n}\n\ntype ExampleType = 'actions' | 'actionResolver';\n\nexport const LegacyTableActions: React.FunctionComponent = () => {\n // In real usage, this data would come from some external source like an API via props.\n const repositories: Repository[] = [\n { name: 'a', branches: 'two', prs: '1', workspaces: 'four', lastCommit: 'five', singleAction: 'Start' },\n { name: 'disable actions', branches: 'two', prs: '3', workspaces: 'four', lastCommit: 'five', singleAction: '' },\n { name: 'green actions', branches: 'two', prs: '4', workspaces: 'four', lastCommit: 'five', singleAction: 'Start' },\n {\n name: 'extra action props',\n branches: 'two',\n prs: '5',\n workspaces: 'four',\n lastCommit: 'five',\n singleAction: 'Start'\n },\n { name: 'blue actions', branches: 'two', prs: '6', workspaces: 'four', lastCommit: 'five', singleAction: 'Start' }\n ];\n\n // This state is just for the ToggleGroup in this example and isn't necessary for Table usage.\n const [propToUse, setPropToUse] = useState<ExampleType>('actions');\n const onPropToUseChange: ToggleGroupItemProps['onChange'] = (event, _isSelected) => {\n const id = event.currentTarget.id;\n setPropToUse(id as ExampleType);\n };\n\n const [useCustomToggle, setUseCustomToggle] = useState(false);\n\n const customActionsToggle = (props: CustomActionsToggleProps) => (\n <MenuToggle ref={props.toggleRef} onClick={props.onToggle} isDisabled={props.isDisabled}>\n Actions\n </MenuToggle>\n );\n\n const columns: TableProps['cells'] = [\n { title: 'Repositories', cellTransforms: [headerCol('actions')] },\n 'Branches',\n 'Pull requests',\n 'Workspaces',\n 'Last commit',\n { title: '', dataLabel: 'Action', cellTransforms: [fitContent] }\n ];\n\n const rows: TableProps['rows'] = repositories.map((repo) => {\n let singleActionButton: React.ReactNode = null;\n if (repo.singleAction !== '') {\n singleActionButton = (\n <TableText>\n <Button variant=\"secondary\">{repo.singleAction}</Button>\n </TableText>\n );\n }\n\n const cells = [repo.name, repo.branches, repo.prs, repo.workspaces, repo.lastCommit, singleActionButton];\n\n // These rows have arbitrary differences for this example, but these could be based on some other conditions\n if (repo.name === 'disable actions') {\n return { cells, disableActions: true };\n }\n if (repo.name === 'green actions') {\n return { cells, type: 'green' };\n }\n if (repo.name === 'extra action props') {\n return { cells, actionProps: { 'data-specific-attr': 'some-value' } };\n }\n if (repo.name === 'blue actions') {\n return { cells, type: 'blue' };\n }\n return { cells };\n });\n\n const actions: IActions = [\n {\n title: 'Some action',\n onClick: (_event, rowId, rowData, extra) => console.log('clicked on Some action, on row: ', rowId, rowData, extra)\n },\n {\n title: <a href=\"#\">Link action</a>\n },\n {\n isSeparator: true\n },\n {\n title: 'Third action',\n onClick: (_event, rowId, rowData, extra) =>\n console.log('clicked on Third action, on row: ', rowId, rowData, extra)\n }\n ];\n\n /**\n * Use actions or actionResolver, not both\n */\n const actionResolver: IActionsResolver = (rowData, { rowIndex }) => {\n if (rowIndex === 1) {\n return [];\n }\n\n const thirdAction: IActions = [\n {\n isSeparator: true\n },\n {\n title: `${rowData.type} action`,\n onClick: (_event, rowId, rowData, extra) =>\n console.log(`clicked on ${rowData.type} action, on row ${rowId} of type ${rowData.type}`, extra)\n }\n ];\n\n return [\n {\n title: 'actionResolver action',\n onClick: (_event, rowId, rowData, extra) =>\n console.log(`clicked on Some action, on row ${rowId} of type ${rowData.type}`, extra)\n },\n {\n title: <div>Another action</div>,\n onClick: (_event, rowId, rowData, extra) =>\n console.log(`clicked on Another action, on row ${rowId} of type ${rowData.type}`, extra)\n },\n ...(rowData.type ? thirdAction : [])\n ];\n };\n\n return (\n <Fragment>\n <Toolbar>\n <ToolbarContent>\n <ToolbarItem>\n <ToggleGroup aria-label=\"actions or actionResolver\">\n <ToggleGroupItem\n text=\"Use actions prop\"\n buttonId=\"actions\"\n isSelected={propToUse === 'actions'}\n onChange={onPropToUseChange}\n />\n <ToggleGroupItem\n text=\"Use actionResolver prop\"\n buttonId=\"actionResolver\"\n isSelected={propToUse === 'actionResolver'}\n onChange={onPropToUseChange}\n />\n </ToggleGroup>\n </ToolbarItem>\n <ToolbarItem>\n <Checkbox\n label=\"Use custom actions toggle\"\n isChecked={useCustomToggle}\n onChange={(_event, checked) => setUseCustomToggle(checked)}\n aria-label=\"toggle use of custom actions toggle\"\n id=\"toggle-custom-actions-toggle\"\n name=\"toggle-custom-actions-toggle\"\n />\n </ToolbarItem>\n </ToolbarContent>\n </Toolbar>\n <Table\n aria-label=\"Actions table\"\n cells={columns}\n rows={rows}\n {...(propToUse === 'actions' && { actions })}\n {...(propToUse === 'actionResolver' && { actionResolver })}\n areActionsDisabled={(rowData) => !!rowData.disableActions}\n dropdownPosition=\"left\"\n dropdownDirection=\"down\"\n actionsToggle={useCustomToggle ? customActionsToggle : undefined}\n >\n <TableHeader />\n <TableBody />\n </Table>\n </Fragment>\n );\n};\n","title":"Actions and first cell in body rows as th","lang":"ts","className":""}}>
|
|
647
|
+
|
|
648
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
649
|
+
{`To use actions you can either specify an array of actions and pass that into the `}
|
|
650
|
+
|
|
651
|
+
<code {...{"className":"ws-code "}}>
|
|
652
|
+
{`Table`}
|
|
653
|
+
</code>
|
|
654
|
+
{`'s `}
|
|
655
|
+
|
|
656
|
+
<code {...{"className":"ws-code "}}>
|
|
657
|
+
{`actions`}
|
|
658
|
+
</code>
|
|
659
|
+
{` prop, or for more control you can use the `}
|
|
660
|
+
|
|
661
|
+
<code {...{"className":"ws-code "}}>
|
|
662
|
+
{`actionResolver`}
|
|
663
|
+
</code>
|
|
664
|
+
{` callback prop to add actions conditionally.`}
|
|
665
|
+
</p>
|
|
666
|
+
|
|
667
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
668
|
+
{`If actions menus are getting clipped by other items on the page, such as sticky columns or rows, the `}
|
|
669
|
+
|
|
670
|
+
<code {...{"className":"ws-code "}}>
|
|
671
|
+
{`Table`}
|
|
672
|
+
</code>
|
|
673
|
+
{` can be passed a `}
|
|
674
|
+
|
|
675
|
+
<code {...{"className":"ws-code "}}>
|
|
676
|
+
{`actionsMenuAppendTo`}
|
|
677
|
+
</code>
|
|
678
|
+
{` prop to adjust where the actions menu is appended.`}
|
|
679
|
+
</p>
|
|
680
|
+
</Example>,
|
|
681
|
+
'Expandable': props =>
|
|
682
|
+
<Example {...pageData} {...props} {...{"code":"import { Fragment, useState } from 'react';\nimport { TableVariant, expandable, IRowCell } from '@patternfly/react-table';\nimport { Table, TableHeader, TableBody, TableProps } from '@patternfly/react-table/deprecated';\nimport { Checkbox } from '@patternfly/react-core';\n\ninterface Repository {\n name: string;\n branches: string;\n prs: string;\n workspaces: string;\n details?: {\n detail1?: string;\n detail2?: string;\n detail3?: string;\n detailFormat: 0 | 1 | 2 | 3;\n };\n}\n\nexport const LegacyTableExpandable: React.FunctionComponent = () => {\n // In real usage, this data would come from some external source like an API via props.\n const repositories: Repository[] = [\n { name: 'one', branches: 'two', prs: 'a', workspaces: 'four' },\n {\n name: 'parent 1',\n branches: 'two',\n prs: 'k',\n workspaces: 'four',\n // This `details` structure is just for this example. You can drive expanded content from any kind of data.\n details: { detailFormat: 0, detail1: 'single cell' }\n },\n {\n name: 'parent 2',\n branches: 'two',\n prs: 'b',\n workspaces: 'four',\n details: { detailFormat: 1, detail1: 'single cell - fullWidth' }\n },\n {\n name: 'parent 3',\n branches: '2',\n prs: 'b',\n workspaces: 'four',\n details: { detailFormat: 2, detail1: 'single cell - noPadding' }\n },\n {\n name: 'parent 4',\n branches: '2',\n prs: 'b',\n workspaces: 'four',\n details: { detailFormat: 3, detail1: 'single cell - fullWidth & noPadding' }\n },\n {\n name: 'parent 5',\n branches: '2',\n prs: 'b',\n workspaces: 'four',\n details: {\n detailFormat: 0,\n detail1: \"spans 'Repositories and 'Branches'\",\n detail2: \"spans 'Pull requests' and 'Workspaces', and 'Last commit'\"\n }\n },\n {\n name: 'parent 6',\n branches: '2',\n prs: 'b',\n workspaces: 'four',\n details: {\n detailFormat: 1,\n detail1: \"fullWidth, spans the collapsible column and 'Repositories'\",\n detail2: \"fullWidth, spans 'Branches' and 'Pull requests'\",\n detail3: 'fullWidth, spans the empty column'\n }\n }\n ];\n\n // In this example, expanded rows are tracked by the repo names from each row. This could be any unique identifier.\n // This is to prevent state from being based on row order index in case we later add sorting.\n // Note that this behavior is very similar to selection state.\n const initialExpandedRepoNames = repositories.filter((repo) => !!repo.details).map((repo) => repo.name); // Default to all expanded\n const [expandedRepoNames, setExpandedRepoNames] = useState<string[]>(initialExpandedRepoNames);\n const setRepoExpanded = (repo: Repository, isExpanding = true) =>\n setExpandedRepoNames((prevExpanded) => {\n const otherExpandedRepoNames = prevExpanded.filter((r) => r !== repo.name);\n return isExpanding ? [...otherExpandedRepoNames, repo.name] : otherExpandedRepoNames;\n });\n const isRepoExpanded = (repo: Repository) => expandedRepoNames.includes(repo.name);\n\n const [isExampleCompact, setIsExampleCompact] = useState(true);\n\n // We want to be able to reference the original data object based on row index. But because an expanded\n // row takes up two row indexes, repositories[rowIndex] will not be accurate like it would in a normal table.\n // One solution to this is to create an array of data objects indexed by the displayed row index.\n const reposByRowIndex: (Repository | null)[] = [];\n\n const columns: TableProps['cells'] = [\n {\n title: 'Repositories',\n cellFormatters: [expandable]\n },\n 'Branches',\n { title: 'Pull requests' },\n { title: '' /* deliberately empty */, dataLabel: 'Label for mobile view' }\n ];\n const rows: TableProps['rows'] = [];\n repositories.forEach((repo) => {\n rows.push({\n ...(repo.details ? { isOpen: isRepoExpanded(repo) } : {}),\n cells: [repo.name, repo.branches, repo.prs, repo.workspaces]\n });\n reposByRowIndex.push(repo);\n if (repo.details) {\n // Some arbitrary examples of how you could customize the child row based on your needs\n const { detail1, detail2, detail3, detailFormat } = repo.details;\n const numColumns = 5;\n const childIsFullWidth = [1, 3].includes(detailFormat);\n const childHasNoPadding = [2, 3].includes(detailFormat);\n let detailColSpans = [1, 1, 1];\n if (detail1 && !detail2 && !detail3) {\n detailColSpans = [childIsFullWidth ? numColumns : numColumns + 1]; // Account for toggle column\n } else if (detail1 && detail2 && !detail3) {\n detailColSpans = [2, childIsFullWidth ? 3 : 4];\n } else if (detail1 && detail2 && detail3) {\n detailColSpans = [2, 2, childIsFullWidth ? 1 : 2];\n }\n const cells: IRowCell[] = [];\n [detail1, detail2, detail3].forEach((detail, index) => {\n if (detail) {\n cells.push({\n title: detail1,\n props: {\n colSpan: detailColSpans[index]\n }\n });\n }\n });\n rows.push({\n parent: rows.length - 1,\n cells,\n fullWidth: childIsFullWidth,\n noPadding: childHasNoPadding\n });\n reposByRowIndex.push(null);\n }\n });\n\n return (\n <Fragment>\n <Checkbox\n label=\"Compact\"\n isChecked={isExampleCompact}\n onChange={(_event, checked) => setIsExampleCompact(checked)}\n aria-label=\"toggle compact variation\"\n id=\"toggle-compact\"\n name=\"toggle-compact\"\n />\n <Table\n aria-label=\"Expandable table\"\n variant={isExampleCompact ? TableVariant.compact : undefined}\n onCollapse={(_event, rowIndex, isOpen) => {\n if (reposByRowIndex[rowIndex]) {\n setRepoExpanded(reposByRowIndex[rowIndex], isOpen);\n }\n }}\n rows={rows}\n cells={columns}\n expandId=\"expandable-table-toggle\"\n contentId=\"expandable-table-content\"\n >\n <TableHeader />\n <TableBody />\n </Table>\n </Fragment>\n );\n};\n","title":"Expandable","lang":"ts","className":""}}>
|
|
683
|
+
|
|
684
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
685
|
+
{`To make an exapandable row, define a child row with the `}
|
|
686
|
+
|
|
687
|
+
<code {...{"className":"ws-code "}}>
|
|
688
|
+
{`parent`}
|
|
689
|
+
</code>
|
|
690
|
+
{` field set to its parent's row index.
|
|
691
|
+
The parent row can have an `}
|
|
692
|
+
|
|
693
|
+
<code {...{"className":"ws-code "}}>
|
|
694
|
+
{`isOpen`}
|
|
695
|
+
</code>
|
|
696
|
+
{` field for managing the expanded state of the parent row.`}
|
|
697
|
+
</p>
|
|
698
|
+
|
|
699
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
700
|
+
{`Also, pass an `}
|
|
701
|
+
|
|
702
|
+
<code {...{"className":"ws-code "}}>
|
|
703
|
+
{`onCollapse`}
|
|
704
|
+
</code>
|
|
705
|
+
{` event handler via the prop on the Table`}
|
|
706
|
+
</p>
|
|
707
|
+
</Example>,
|
|
708
|
+
'Compound expandable': props =>
|
|
709
|
+
<Example {...pageData} {...props} {...{"code":"import { Fragment, useState } from 'react';\nimport { Table, TableHeader, TableBody, TableProps } from '@patternfly/react-table/deprecated';\nimport { compoundExpand } from '@patternfly/react-table';\n\nimport RhUiCodeIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-code-icon';\nimport RhUiBranchFillIcon from '@patternfly/react-icons/dist/esm/icons/rh-ui-branch-fill-icon';\nimport CubeIcon from '@patternfly/react-icons/dist/esm/icons/cube-icon';\nimport spacing from '@patternfly/react-styles/css/utilities/Spacing/spacing';\n\ninterface Repository {\n name: string;\n branches: number;\n prs: number;\n workspaces: number;\n lastCommit: string;\n}\n\nexport const LegacyTableCompoundExpandable: React.FunctionComponent = () => {\n // In real usage, this data would come from some external source like an API via props.\n const repositories: Repository[] = [\n { name: 'siemur/test-space', branches: 10, prs: 4, workspaces: 4, lastCommit: '20 minutes' },\n { name: 'siemur/test-space-2', branches: 3, prs: 4, workspaces: 4, lastCommit: '20 minutes' }\n ];\n\n // In this example, expanded cells are tracked by the repo and property names from each row. This could be any pair of unique identifiers.\n // This is to prevent state from being based on row and column order index in case we later add sorting and rearranging columns.\n // Note that these columnKeys must be in the same order as the `columns` below, because columnIndex will be used to look up the matching key.\n type ColumnKey = 'name' | 'branches' | 'prs' | 'workspaces' | 'lastCommit'; // For typechecking\n const columnKeys: ColumnKey[] = ['name', 'branches', 'prs', 'workspaces', 'lastCommit']; // For indexed order\n const [expandedCells, setExpandedCells] = useState<Record<string, ColumnKey>>({\n 'siemur/test-space': 'branches' // Default to the first cell of the first row being expanded\n });\n const setCellExpanded = (repo: Repository, columnKey: ColumnKey, isExpanding = true) => {\n const newExpandedCells = { ...expandedCells };\n if (isExpanding) {\n newExpandedCells[repo.name] = columnKey;\n } else {\n delete newExpandedCells[repo.name];\n }\n setExpandedCells(newExpandedCells);\n };\n\n // We want to be able to reference the original data object based on row index. But because parent/child rows are\n // multiple elements in the rows array, repositories[rowIndex] will not be accurate like it would in a normal table.\n // One solution to this is to create an array of data objects indexed by the displayed row index.\n const reposByRowIndex: (Repository | null)[] = [];\n\n const columns: TableProps['cells'] = [\n 'Repositories',\n {\n title: 'Branches',\n cellTransforms: [compoundExpand]\n },\n {\n title: 'Pull requests',\n cellTransforms: [compoundExpand]\n },\n {\n title: 'Workspaces',\n cellTransforms: [compoundExpand]\n },\n 'Last Commit',\n {\n title: '',\n dataLabel: 'Action'\n }\n ];\n const rows: TableProps['rows'] = [];\n repositories.forEach((repo) => {\n const expandedCellKey = expandedCells[repo.name];\n const isRowExpanded = !!expandedCellKey;\n rows.push({\n isOpen: isRowExpanded,\n cells: [\n { title: <a href=\"#\">{repo.name}</a>, props: { component: 'th' } },\n {\n title: (\n <Fragment>\n <RhUiBranchFillIcon key=\"icon\" /> {repo.branches}\n </Fragment>\n ),\n props: {\n isOpen: expandedCellKey === 'branches',\n ariaControls: `compound-expansion-table-${repo.name}-1`\n }\n },\n {\n title: (\n <Fragment>\n <RhUiCodeIcon key=\"icon\" /> {repo.prs}\n </Fragment>\n ),\n props: {\n isOpen: expandedCellKey === 'prs',\n ariaControls: `compound-expansion-table-${repo.name}-2`\n }\n },\n {\n title: (\n <Fragment>\n <CubeIcon key=\"icon\" /> {repo.branches}\n </Fragment>\n ),\n props: {\n isOpen: expandedCellKey === 'workspaces',\n ariaControls: `compound-expansion-table-${repo.name}-3`\n }\n },\n repo.lastCommit,\n { title: <a href=\"#\">Open in Github</a> }\n ]\n });\n reposByRowIndex.push(repo);\n const parentIndex = rows.length - 1;\n rows.push({\n parent: parentIndex,\n compoundParent: 1,\n cells: [\n {\n title: (\n <div className={spacing.mMd} id={`compound-expansion-table-${repo.name}-1`}>\n Expanded content for {repo.name}: Branches goes here!\n </div>\n ),\n props: { colSpan: 6, className: 'pf-m-no-padding' }\n }\n ]\n });\n reposByRowIndex.push(null);\n rows.push({\n parent: parentIndex,\n compoundParent: 2,\n cells: [\n {\n title: (\n <div className={spacing.mMd} id={`compound-expansion-table-${repo.name}-2`}>\n Expanded content for {repo.name}: Pull requests goes here!\n </div>\n ),\n props: { colSpan: 6, className: 'pf-m-no-padding' }\n }\n ]\n });\n reposByRowIndex.push(null);\n rows.push({\n parent: parentIndex,\n compoundParent: 3,\n cells: [\n {\n title: (\n <div className={spacing.mMd} id={`compound-expansion-table-${repo.name}-3`}>\n Expanded content for {repo.name}: Workspaces goes here!\n </div>\n ),\n props: { colSpan: 6, className: 'pf-m-no-padding' }\n }\n ]\n });\n reposByRowIndex.push(null);\n });\n\n return (\n <Table\n aria-label=\"Compound expandable table\"\n onExpand={(_event, rowIndex, colIndex, isOpen) => {\n if (reposByRowIndex[rowIndex]) {\n setCellExpanded(reposByRowIndex[rowIndex], columnKeys[colIndex], !isOpen);\n }\n }}\n rows={rows}\n cells={columns}\n expandId=\"compound-expandable-table-toggle\"\n contentId=\"compound-expandable-table-content\"\n >\n <TableHeader />\n <TableBody />\n </Table>\n );\n};\n","title":"Compound expandable","lang":"ts","className":""}}>
|
|
710
|
+
|
|
711
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
712
|
+
{`To build a compound expandable table:`}
|
|
713
|
+
</p>
|
|
714
|
+
|
|
715
|
+
<ol {...{"className":"pf-v6-c-content--ol pf-m-editorial ws-ol "}}>
|
|
716
|
+
|
|
717
|
+
|
|
718
|
+
|
|
719
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
720
|
+
{`Pass the `}
|
|
721
|
+
|
|
722
|
+
<code {...{"className":"ws-code "}}>
|
|
723
|
+
{`compoundExpand`}
|
|
724
|
+
</code>
|
|
725
|
+
{` transformation via the `}
|
|
726
|
+
|
|
727
|
+
<code {...{"className":"ws-code "}}>
|
|
728
|
+
{`cellTransforms`}
|
|
729
|
+
</code>
|
|
730
|
+
{` field in the column definition for each column that will have an expanded section.`}
|
|
731
|
+
</li>
|
|
732
|
+
|
|
733
|
+
|
|
734
|
+
|
|
735
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
736
|
+
{`For each expandable parent row, the cells in the expandable columns should:`}
|
|
737
|
+
|
|
738
|
+
|
|
739
|
+
|
|
740
|
+
<ol {...{"className":"pf-v6-c-content--ol pf-m-editorial ws-ol "}}>
|
|
741
|
+
|
|
742
|
+
|
|
743
|
+
|
|
744
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
745
|
+
{`have a managed `}
|
|
746
|
+
|
|
747
|
+
<code {...{"className":"ws-code "}}>
|
|
748
|
+
{`isOpen`}
|
|
749
|
+
</code>
|
|
750
|
+
{` prop passed to the cell definition`}
|
|
751
|
+
</li>
|
|
752
|
+
|
|
753
|
+
|
|
754
|
+
|
|
755
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
756
|
+
{`have an `}
|
|
757
|
+
|
|
758
|
+
<code {...{"className":"ws-code "}}>
|
|
759
|
+
{`ariaControls`}
|
|
760
|
+
</code>
|
|
761
|
+
{` value which matches the `}
|
|
762
|
+
|
|
763
|
+
<code {...{"className":"ws-code "}}>
|
|
764
|
+
{`id`}
|
|
765
|
+
</code>
|
|
766
|
+
{` of it’s child row`}
|
|
767
|
+
</li>
|
|
768
|
+
|
|
769
|
+
|
|
770
|
+
</ol>
|
|
771
|
+
|
|
772
|
+
|
|
773
|
+
</li>
|
|
774
|
+
|
|
775
|
+
|
|
776
|
+
|
|
777
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
778
|
+
{`For each expandable child row, the row definition needs:`}
|
|
779
|
+
|
|
780
|
+
|
|
781
|
+
|
|
782
|
+
<ol {...{"className":"pf-v6-c-content--ol pf-m-editorial ws-ol "}}>
|
|
783
|
+
|
|
784
|
+
|
|
785
|
+
|
|
786
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
787
|
+
{`A `}
|
|
788
|
+
|
|
789
|
+
<code {...{"className":"ws-code "}}>
|
|
790
|
+
{`parent`}
|
|
791
|
+
</code>
|
|
792
|
+
{` field set to its parent’s row index`}
|
|
793
|
+
</li>
|
|
794
|
+
|
|
795
|
+
|
|
796
|
+
|
|
797
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
798
|
+
{`A `}
|
|
799
|
+
|
|
800
|
+
<code {...{"className":"ws-code "}}>
|
|
801
|
+
{`compoundParent`}
|
|
802
|
+
</code>
|
|
803
|
+
{` field set to the cell index which will control the expanding/collapsing of this row`}
|
|
804
|
+
</li>
|
|
805
|
+
|
|
806
|
+
|
|
807
|
+
</ol>
|
|
808
|
+
|
|
809
|
+
|
|
810
|
+
</li>
|
|
811
|
+
|
|
812
|
+
|
|
813
|
+
|
|
814
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
815
|
+
{`An `}
|
|
816
|
+
|
|
817
|
+
<code {...{"className":"ws-code "}}>
|
|
818
|
+
{`onExpand`}
|
|
819
|
+
</code>
|
|
820
|
+
{` event handler prop should be passed to the Table.`}
|
|
821
|
+
</li>
|
|
822
|
+
|
|
823
|
+
|
|
824
|
+
</ol>
|
|
825
|
+
</Example>,
|
|
826
|
+
'With width and breakpoint visibility modifiers': props =>
|
|
827
|
+
<Example {...pageData} {...props} {...{"code":"import { Table, TableHeader, TableBody, TableProps } from '@patternfly/react-table/deprecated';\nimport { classNames, cellWidth, Visibility } from '@patternfly/react-table';\n\ninterface Repository {\n name: string;\n branches: string;\n prs: string;\n workspaces: string;\n lastCommit: string;\n}\n\nexport const LegacyTableCellWidth: React.FunctionComponent = () => {\n // In real usage, this data would come from some external source like an API via props.\n const repositories: Repository[] = [\n {\n name: 'one - 1',\n branches: 'two - 1 (visible only on md)',\n prs: 'three - 1 (hidden only on md)',\n workspaces: 'four - 1 (hidden on xs)',\n lastCommit: 'five - 1'\n },\n {\n name: 'one - 2',\n branches: 'two - 2 (visible only on md)',\n prs: 'three - 2 (hidden only on md)',\n workspaces: 'four - 2 (hidden on xs)',\n lastCommit: 'five - 2'\n }\n ];\n\n const columns: TableProps['cells'] = [\n { title: 'Header cell', transforms: [cellWidth(10)] },\n {\n title: 'Branches (visible only on md and 2Xl)',\n columnTransforms: [\n classNames(Visibility.hidden, Visibility.visibleOnMd, Visibility.hiddenOnLg, Visibility.visibleOn2Xl)\n ]\n },\n {\n title: 'Pull requests (hidden only on md)',\n columnTransforms: [classNames(Visibility.hiddenOnMd, Visibility.visibleOnLg)]\n },\n {\n title: 'Workspaces (hidden on xs)',\n columnTransforms: [classNames(Visibility.hidden, Visibility.visibleOnSm)]\n },\n {\n title: 'Last commit',\n transforms: [cellWidth(30)]\n }\n ];\n const rows: TableProps['rows'] = repositories.map((repo) => [\n repo.name,\n repo.branches,\n repo.prs,\n repo.workspaces,\n repo.lastCommit\n ]);\n\n return (\n <Table aria-label=\"Table with width and breakpoint visibility modifiers\" cells={columns} rows={rows}>\n <TableHeader />\n <TableBody />\n </Table>\n );\n};\n","title":"With width and breakpoint visibility modifiers","lang":"ts","className":""}}>
|
|
828
|
+
|
|
829
|
+
</Example>,
|
|
830
|
+
'Controlling text': props =>
|
|
831
|
+
<Example {...pageData} {...props} {...{"code":"import { cellWidth, truncate, breakWord, wrappable, fitContent, nowrap } from '@patternfly/react-table';\nimport { Table, TableHeader, TableBody, TableProps } from '@patternfly/react-table/deprecated';\n\n// This example has been simplified to focus on the text modifier props. In real usage,\n// you may want to derive your rows from typed underlying data and minimal state. See other examples.\n\nexport const LegacyTableControllingText: React.FunctionComponent = () => {\n const columns: TableProps['cells'] = [\n { title: 'Truncate (width 20%)', transforms: [cellWidth(20)], cellTransforms: [truncate] },\n { title: 'Break word', cellTransforms: [breakWord] },\n { title: 'Wrapping table header text. This th text will wrap instead of truncate.', transforms: [wrappable] },\n { title: 'Fit content', transforms: [fitContent] },\n { title: '', cellTransforms: [nowrap] }\n ];\n const rows: TableProps['rows'] = [\n [\n 'This text will truncate instead of wrap.',\n { title: <a href=\"#\">http://thisisaverylongurlthatneedstobreakusethebreakwordmodifier.org</a> },\n {\n title: (\n <p>\n By default,\n <code>thead</code> cells will truncate and\n <code>tbody</code> cells will wrap. Use\n <code>transforms</code> and/or <code>cellTransforms</code> to change the behavior.\n </p>\n )\n },\n \"This cell's content will adjust itself to the parent th width. This modifier only affects table layouts.\",\n { title: <a href=\"#\">No wrap</a> }\n ]\n ];\n\n return (\n <Table aria-label=\"Controlling text\" cells={columns} rows={rows}>\n <TableHeader />\n <TableBody />\n </Table>\n );\n};\n","title":"Controlling text","lang":"ts","className":""}}>
|
|
832
|
+
|
|
833
|
+
</Example>,
|
|
834
|
+
'Modifiers with table text': props =>
|
|
835
|
+
<Example {...pageData} {...props} {...{"code":"import { cellWidth, TableText } from '@patternfly/react-table';\nimport { Table, TableHeader, TableBody, TableProps } from '@patternfly/react-table/deprecated';\n\n// This example has been simplified to focus on the text modifier props. In real usage,\n// you may want to derive your rows from typed underlying data and minimal state. See other examples.\n\nexport const LegacyTableTextModifiers: React.FunctionComponent = () => {\n const columns: TableProps['cells'] = [\n { title: 'Truncating text', transforms: [cellWidth(30)] },\n { title: 'Wrapping table header text. This th text will wrap instead of truncate.' }\n ];\n const rows: TableProps['rows'] = [\n [\n { title: <TableText wrapModifier=\"truncate\">This text will truncate instead of wrap.</TableText> },\n {\n title: (\n <TableText wrapModifier=\"nowrap\">\n <a href=\"#\">This is a link that needs to be on one line and fully readable.</a>\n </TableText>\n )\n }\n ]\n ];\n\n return (\n <Table aria-label=\"Table text with modifiers\" cells={columns} rows={rows}>\n <TableHeader />\n <TableBody />\n </Table>\n );\n};\n","title":"Modifiers with table text","lang":"ts","className":""}}>
|
|
836
|
+
|
|
837
|
+
</Example>,
|
|
838
|
+
'Empty state': props =>
|
|
839
|
+
<Example {...pageData} {...props} {...{"code":"import { Table, TableHeader, TableBody, TableProps } from '@patternfly/react-table/deprecated';\nimport {\n Bullseye,\n EmptyState,\n EmptyStateVariant,\n EmptyStateBody,\n Button,\n EmptyStateFooter,\n EmptyStateActions\n} from '@patternfly/react-core';\nimport SearchIcon from '@patternfly/react-icons/dist/esm/icons/search-icon';\n\n// This example has been simplified to focus on the empty state. In real usage,\n// you may want to derive your rows from typed underlying data and minimal state. See other examples.\n\nexport const LegacyTableEmptyState: React.FunctionComponent = () => {\n const columns: TableProps['cells'] = ['Repositories', 'Branches', 'Pull requests', 'Workspaces', 'Last commit'];\n const rows: TableProps['rows'] = [\n {\n heightAuto: true,\n cells: [\n {\n props: { colSpan: 8 },\n title: (\n <Bullseye>\n <EmptyState\n headingLevel=\"h2\"\n titleText=\"No results found\"\n icon={SearchIcon}\n variant={EmptyStateVariant.sm}\n >\n <EmptyStateBody>Clear all filters and try again.</EmptyStateBody>\n <EmptyStateFooter>\n <EmptyStateActions>\n <Button variant=\"link\">Clear all filters</Button>\n </EmptyStateActions>\n </EmptyStateFooter>\n </EmptyState>\n </Bullseye>\n )\n }\n ]\n }\n ];\n\n return (\n <Table aria-label=\"Table text with modifiers\" cells={columns} rows={rows}>\n <TableHeader />\n <TableBody />\n </Table>\n );\n};\n","title":"Empty state","lang":"ts","className":""}}>
|
|
840
|
+
|
|
841
|
+
</Example>,
|
|
842
|
+
'Editable rows': props =>
|
|
843
|
+
<Example {...pageData} {...props} {...{"code":"import {\n Table,\n TableHeader,\n TableBody,\n TableVariant,\n cancelCellEdits,\n validateCellEdits,\n applyCellEdits,\n EditableTextCell,\n EditableSelectInputCell,\n} from '@patternfly/react-table';\n\nimport { SelectOption as NewSelectOption} from '@patternfly/react-core/dist/esm/components/Select';\n\nclass EditableRowsTable extends React.Component {\n constructor(props) {\n super(props);\n\n this.state = {\n columns: ['Text input col 1', 'Disabled text input col 2', 'Text input col 3', 'Text input col 4'],\n actions: [\n {\n title: 'Some action',\n onClick: (event, rowId, rowData, extra) => console.log('clicked on Some action, on row: ', rowId)\n }\n ],\n rows: [\n {\n rowEditBtnAriaLabel: (idx) => `Edit row ${idx}`,\n rowSaveBtnAriaLabel: (idx) => `Save edits for row ${idx}`,\n rowCancelBtnAriaLabel: (idx) => `Cancel edits for row ${idx}`,\n rowEditValidationRules: [\n {\n name: 'required',\n validator: (value) => value.trim() !== '',\n errorText: 'This field is required'\n }\n ],\n cells: [\n {\n title: (value, rowIndex, cellIndex, props) => (\n <EditableTextCell\n value={value}\n rowIndex={rowIndex}\n cellIndex={cellIndex}\n props={props}\n handleTextInputChange={this.handleTextInputChange}\n inputAriaLabel=\"Row 1 cell 1 content\"\n />\n ),\n props: {\n value: 'Row 1 cell 1 content',\n name: 'uniqueIdRow1Cell1'\n }\n },\n {\n title: (value, rowIndex, cellIndex, props) => (\n <EditableTextCell\n value={value}\n rowIndex={rowIndex}\n cellIndex={cellIndex}\n props={props}\n handleTextInputChange={this.handleTextInputChange}\n isDisabled\n inputAriaLabel=\"Row 1 cell 2 content\"\n />\n ),\n props: {\n value: 'Row 1 cell 2, disabled content',\n name: 'uniqueIdRow1Cell2'\n }\n },\n {\n title: (value, rowIndex, cellIndex, props) => (\n <EditableTextCell\n value={value}\n rowIndex={rowIndex}\n cellIndex={cellIndex}\n props={props}\n handleTextInputChange={this.handleTextInputChange}\n inputAriaLabel=\"Row 1 cell 3 content\"\n />\n ),\n props: {\n value: 'Row 1 cell 3 content',\n name: 'uniqueIdRow1Cell3'\n }\n },\n {\n title: (value, rowIndex, cellIndex, props) => (\n <EditableSelectInputCell\n value={value}\n rowIndex={rowIndex}\n cellIndex={cellIndex}\n props={props}\n onSelect={this.onSelect}\n isOpen={props.isSelectOpen}\n options={props.options.map((option, index) => (\n <NewSelectOption key={index} value={option.value} id={'uniqueIdRow1Cell4Option' + index}>\n {option.value}\n </NewSelectOption>\n ))}\n onToggle={(event) => {\n this.onToggle(props.isSelectOpen, rowIndex, cellIndex);\n }}\n selections={props.selected}\n />\n ),\n props: {\n value: ['Option 1'],\n name: 'uniqueIdRow1Cell4',\n isSelectOpen: props.isSelectOpen || false,\n selected: props.selected || ['Option 1'],\n options: [\n { value: 'Option 1' },\n { value: 'Option 2' },\n { value: 'Option 3' },\n { value: 'Option 4' },\n { value: 'Option 5' }\n ],\n editableSelectProps: {\n 'aria-label': 'Row 1 cell 4 content',\n onOpenChange: (isOpen: boolean) => this.onOpenChange(isOpen, 0, 3)\n }\n }\n }\n ]\n },\n {\n cells: [\n {\n title: (value, rowIndex, cellIndex, props) => (\n <EditableTextCell\n value={value}\n rowIndex={rowIndex}\n cellIndex={cellIndex}\n props={props}\n handleTextInputChange={this.handleTextInputChange}\n inputAriaLabel=\"Row 2 cell 1 content\"\n />\n ),\n props: {\n value: 'Row 2 cell 1 content',\n name: 'uniqueIdRow2Cell1'\n }\n },\n {\n title: (value, rowIndex, cellIndex, props) => (\n <EditableTextCell\n value={value}\n rowIndex={rowIndex}\n cellIndex={cellIndex}\n props={props}\n handleTextInputChange={this.handleTextInputChange}\n isDisabled\n inputAriaLabel=\"Row 2 cell 2 content\"\n />\n ),\n props: {\n value: 'Row 2 cell 2, disabled content',\n name: 'uniqueIdRow2Cell2'\n }\n },\n {\n title: (value, rowIndex, cellIndex, props) => (\n <EditableTextCell\n value={value}\n rowIndex={rowIndex}\n cellIndex={cellIndex}\n props={props}\n handleTextInputChange={this.handleTextInputChange}\n inputAriaLabel=\"Row 2 cell 3 content\"\n />\n ),\n props: {\n value: 'Row 2 cell 3 content',\n name: 'uniqueIdRow2Cell3'\n }\n },\n {\n title: (value, rowIndex, cellIndex, props) => (\n <EditableSelectInputCell\n value={value}\n rowIndex={rowIndex}\n cellIndex={cellIndex}\n props={props}\n onSelect={this.onSelect}\n clearSelection={this.clearSelection}\n isOpen={props.isSelectOpen}\n options={props.options.map((option, index) => {\n return (\n <NewSelectOption key={index} value={option.value} id={'uniqueIdRow2Cell4Option' + index}>\n {option.value}\n </NewSelectOption>\n );\n })}\n onToggle={(event) => {\n this.onToggle(props.isSelectOpen, rowIndex, cellIndex);\n }}\n selections={props.selected}\n />\n ),\n props: {\n value: ['Placeholder...'],\n name: 'uniqueIdRow2Cell4',\n isSelectOpen: props.isSelectOpen || false,\n selected: props.selected || [],\n isPlaceholder: true,\n options: [\n { value: 'Placeholder...', isPlaceholder: true},\n { value: 'Option 1' },\n { value: 'Option 2' },\n { value: 'Option 3' },\n { value: 'Option 4' },\n { value: 'Option 5' }\n ],\n editableSelectProps: {\n 'aria-label': 'Row 2 cell 4 content',\n toggleId: 'editable-toggle',\n onOpenChange: (isOpen: boolean) => this.onOpenChange(isOpen, 1, 3)\n\n }\n }\n }\n ]\n },\n {\n rowEditValidationRules: [\n {\n name: 'required',\n validator: (value) => value.trim() !== '',\n errorText: 'This field is required'\n },\n {\n name: 'notFoo',\n validator: (value) => value.trim().toLowerCase() !== 'foo',\n errorText: 'Value cannot be \"foo\"'\n },\n {\n name: 'minLength',\n validator: (value) => value.trim().length >= 7,\n errorText: 'Value must be at least 7 characters'\n },\n {\n name: 'notXyz',\n validator: (value) => value.trim().toLowerCase() !== 'xyz',\n errorText: 'Value cannot be xyz'\n }\n ],\n cells: [\n {\n title: (value, rowIndex, cellIndex, props) => (\n <EditableTextCell\n value={value}\n rowIndex={rowIndex}\n cellIndex={cellIndex}\n props={props}\n handleTextInputChange={this.handleTextInputChange}\n inputAriaLabel=\"Row 3 cell 1 content\"\n />\n ),\n props: {\n value: 'Row 3 cell 1 content',\n name: 'uniqueIdRow3Cell1'\n }\n },\n {\n title: (value, rowIndex, cellIndex, props) => (\n <EditableTextCell\n value={value}\n rowIndex={rowIndex}\n cellIndex={cellIndex}\n props={props}\n handleTextInputChange={this.handleTextInputChange}\n isDisabled\n inputAriaLabel=\"Row 3 cell 2 content\"\n />\n ),\n props: {\n value: 'Row 3 cell 2, disabled content',\n name: 'uniqueIdRow3Cell2'\n }\n },\n {\n title: (value, rowIndex, cellIndex, props) => (\n <EditableTextCell\n value={value}\n rowIndex={rowIndex}\n cellIndex={cellIndex}\n props={props}\n handleTextInputChange={this.handleTextInputChange}\n inputAriaLabel=\"Row 3 cell 3 content\"\n />\n ),\n props: {\n value: 'Row 3 cell 3 content',\n name: 'uniqueIdRow3Cell3'\n }\n },\n {\n title: (value, rowIndex, cellIndex, props) => (\n <EditableSelectInputCell\n value={value}\n rowIndex={rowIndex}\n cellIndex={cellIndex}\n props={props}\n onSelect={this.onSelect}\n clearSelection={this.clearSelection}\n isOpen={props.isSelectOpen}\n options={props.options.map((option, index) => (\n <NewSelectOption key={index} value={option.value} id={'uniqueIdRow3Cell4Option' + index}>\n {option.value}\n </NewSelectOption>\n ))}\n onToggle={(event) => {\n this.onToggle(props.isSelectOpen, rowIndex, cellIndex);\n }}\n selections={props.selected}\n />\n ),\n props: {\n value: ['Option 3'],\n name: 'uniqueIdRow3Cell4',\n isSelectOpen: props.isSelectOpen || false,\n selected: props.selected || ['Option 3'],\n isPlaceholder: false,\n options: [\n { value: 'Placeholder...', isPlaceholder: true},\n { value: 'Option 1' },\n { value: 'Option 2' },\n { value: 'Option 3' },\n { value: 'Option 4' },\n { value: 'Option 5' }\n ],\n editableSelectProps: {\n 'aria-label': 'Row 3 cell 4 content',\n onOpenChange: (isOpen: boolean) => this.onOpenChange(isOpen, 2, 3)\n\n }\n }\n }\n ]\n }\n ]\n };\n\n this.updateEditableRows = (evt, type, isEditable, rowIndex, validationErrors) => {\n let newRows = Array.from(this.state.rows);\n\n if (validationErrors && Object.keys(validationErrors).length) {\n newRows[rowIndex] = validateCellEdits(newRows[rowIndex], type, validationErrors);\n this.setState({ rows: newRows });\n return;\n }\n\n if (type === 'cancel') {\n newRows[rowIndex] = cancelCellEdits(newRows[rowIndex]);\n this.setState({ rows: newRows });\n return;\n }\n\n newRows[rowIndex] = applyCellEdits(newRows[rowIndex], type);\n\n this.setState({ rows: newRows });\n };\n\n this.handleTextInputChange = (newValue, evt, rowIndex, cellIndex) => {\n let newRows = Array.from(this.state.rows);\n newRows[rowIndex].cells[cellIndex].props.editableValue = newValue;\n this.setState({\n rows: newRows\n });\n };\n\n this.onSelect = (_event, newValue, rowIndex, cellIndex, isPlaceholder) => {\n const newRows = Array.from(this.state.rows);\n const newCellProps = newRows[rowIndex].cells[cellIndex].props;\n\n if (isPlaceholder) {\n newCellProps.editableValue = [];\n newCellProps.selected = [];\n } else {\n if (newCellProps.editableValue === undefined) {\n newCellProps.editableValue = [];\n }\n\n let newSelected = Array.from(newCellProps.selected);\n let newSelectOpen = false;\n\n switch (newCellProps.editableSelectProps.variant) {\n case 'typeaheadmulti':\n case 'checkbox': {\n if (!newSelected.includes(newValue)) {\n newSelected.push(newValue);\n } else {\n newSelected = newSelected.filter((el) => el !== newValue);\n }\n newSelectOpen = true;\n break;\n }\n default: {\n newSelected = newValue;\n }\n }\n\n newCellProps.editableValue = newSelected;\n newCellProps.selected = newSelected;\n newCellProps.isSelectOpen = newSelectOpen;\n }\n\n this.setState({\n rows: newRows\n });\n };\n\n this.clearSelection = (_event, rowIndex, cellIndex) => {\n const newRows = Array.from(this.state.rows);\n const newCellProps = newRows[rowIndex].cells[cellIndex].props;\n newCellProps.editableValue = [];\n newCellProps.selected = [];\n this.setState({\n rows: newRows\n });\n };\n\n // set open state if component closes menu on click (e.g. when you click outside of the menu)\n this.onOpenChange = (isOpen: boolean, rowIndex: string | number | undefined, cellIndex: string | number | undefined) => {\n const newRows = Array.from(this.state.rows);\n newRows[rowIndex].cells[cellIndex].props.isSelectOpen = isOpen;\n this.setState({\n rows: newRows\n });\n }\n\n this.onToggle = (isOpen, rowIndex, cellIndex) => {\n console.log('isOpen', isOpen);\n let newRows = Array.from(this.state.rows);\n newRows[rowIndex].cells[cellIndex].props.isSelectOpen = !newRows[rowIndex].cells[cellIndex].props.isSelectOpen;\n this.setState({\n rows: newRows\n });\n };\n }\n\n render() {\n const { columns, rows, actions } = this.state;\n\n return (\n <Table\n actions={actions}\n onRowEdit={this.updateEditableRows}\n aria-label=\"Editable Rows Table\"\n variant={TableVariant.compact}\n cells={columns}\n rows={rows}\n >\n <TableHeader />\n <TableBody />\n </Table>\n );\n }\n}","title":"Editable rows","lang":"js","className":""}}>
|
|
844
|
+
|
|
845
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
846
|
+
{`To make a table row editable:`}
|
|
847
|
+
</p>
|
|
848
|
+
|
|
849
|
+
<ol {...{"className":"pf-v6-c-content--ol pf-m-editorial ws-ol "}}>
|
|
850
|
+
|
|
851
|
+
|
|
852
|
+
|
|
853
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
854
|
+
{`Pass a callback to Table via the `}
|
|
855
|
+
|
|
856
|
+
<code {...{"className":"ws-code "}}>
|
|
857
|
+
{`onRowEdit`}
|
|
858
|
+
</code>
|
|
859
|
+
{` prop.`}
|
|
860
|
+
</li>
|
|
861
|
+
|
|
862
|
+
|
|
863
|
+
|
|
864
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
865
|
+
{`Define the title for the editable cells using the RowCellContent type function.`}
|
|
866
|
+
</li>
|
|
867
|
+
|
|
868
|
+
|
|
869
|
+
|
|
870
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
871
|
+
{`Have the function return an `}
|
|
872
|
+
|
|
873
|
+
<code {...{"className":"ws-code "}}>
|
|
874
|
+
{`EditableTextCell`}
|
|
875
|
+
</code>
|
|
876
|
+
{`.`}
|
|
877
|
+
</li>
|
|
878
|
+
|
|
879
|
+
|
|
880
|
+
|
|
881
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
882
|
+
{`Pass the `}
|
|
883
|
+
|
|
884
|
+
<code {...{"className":"ws-code "}}>
|
|
885
|
+
{`value`}
|
|
886
|
+
</code>
|
|
887
|
+
{` and `}
|
|
888
|
+
|
|
889
|
+
<code {...{"className":"ws-code "}}>
|
|
890
|
+
{`name`}
|
|
891
|
+
</code>
|
|
892
|
+
{` of the cell's input to the `}
|
|
893
|
+
|
|
894
|
+
<code {...{"className":"ws-code "}}>
|
|
895
|
+
{`EditableTextCell`}
|
|
896
|
+
</code>
|
|
897
|
+
{` via the cell's `}
|
|
898
|
+
|
|
899
|
+
<code {...{"className":"ws-code "}}>
|
|
900
|
+
{`props`}
|
|
901
|
+
</code>
|
|
902
|
+
{` field, which is
|
|
903
|
+
defined as being of type `}
|
|
904
|
+
|
|
905
|
+
<code {...{"className":"ws-code "}}>
|
|
906
|
+
{`EditableTextCellProps`}
|
|
907
|
+
</code>
|
|
908
|
+
{`.`}
|
|
909
|
+
</li>
|
|
910
|
+
|
|
911
|
+
|
|
912
|
+
</ol>
|
|
913
|
+
|
|
914
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
915
|
+
{`Example:`}
|
|
916
|
+
</p>
|
|
917
|
+
|
|
918
|
+
<Example {...{"code":"{\n title: (value, rowIndex, cellIndex, props) => (\n <EditableTextCell\n value={value}\n rowIndex={rowIndex}\n cellIndex={cellIndex}\n props={props}\n handleTextInputChange={this.handleTextInputChange}\n inputAriaLabel=\"Row 1 cell 1 content\"\n />\n ),\n props: {\n value: 'Row 1 cell 1 content',\n name: 'uniqueIdRow1Cell1'\n }\n},","className":""}}>
|
|
919
|
+
|
|
920
|
+
</Example>
|
|
921
|
+
</Example>,
|
|
922
|
+
'Favoritable (implemented with sortable and selectable)': props =>
|
|
923
|
+
<Example {...pageData} {...props} {...{"code":"import { useCallback, useState } from 'react';\nimport { sortable } from '@patternfly/react-table';\nimport { Table, TableHeader, TableBody, TableProps } from '@patternfly/react-table/deprecated';\nimport { Checkbox } from '@patternfly/react-core';\n\ninterface Repository {\n name: string;\n branches: string;\n prs: string;\n workspaces: string;\n lastCommit: string;\n}\n\nexport const LegacyTableFavoritable: React.FunctionComponent = () => {\n // In real usage, this data would come from some external source like an API via props.\n const repositories: Repository[] = [\n { name: 'one', branches: 'two', prs: 'a', workspaces: 'four', lastCommit: 'five' },\n { name: 'a', branches: 'two', prs: 'k', workspaces: 'four', lastCommit: 'five' },\n { name: 'p', branches: 'two', prs: 'b', workspaces: 'four', lastCommit: 'five' }\n ];\n\n // Index of the currently sorted column\n // Note: if you intend to make columns reorderable, you may instead want to use a non-numeric key\n // as the identifier of the sorted column. See the \"Compound expandable\" example.\n const [activeSortIndex, setActiveSortIndex] = useState<number | null>(null);\n\n // Sort direction of the currently sorted column\n const [activeSortDirection, setActiveSortDirection] = useState<'asc' | 'desc' | null>(null);\n\n // Favorite state is similar to selection state. See selectedRepoNames and associated code below.\n const [favoriteRepoNames, setFavoriteRepoNames] = useState<string[]>([]);\n const setRepoFavorited = (repo: Repository, isFavoriting = true) =>\n setFavoriteRepoNames((prevFavorites) => {\n const otherFavorites = prevFavorites.filter((r) => r !== repo.name);\n return isFavoriting ? [...otherFavorites, repo.name] : otherFavorites;\n });\n const isRepoFavorited = (repo: Repository) => favoriteRepoNames.includes(repo.name);\n\n // Since OnSort specifies sorted columns by index, we need sortable values for our object by column index.\n // Note: We also memoize the sortable values with useCallback to prevent rows jumping around when you change\n // the favorites while sorting on that column. Only updating the sort state will reorder the rows.\n const getSortableRowValues = useCallback(\n (repo: Repository): (boolean | string | number)[] => {\n const { name, branches, prs, workspaces, lastCommit } = repo;\n // Blank value for first column (select checkboxes)\n return ['', isRepoFavorited(repo), name, branches, prs, workspaces, lastCommit];\n },\n [activeSortIndex, activeSortDirection]\n );\n\n // Note that we perform the sort as part of the component's render logic and not in onSort.\n // We shouldn't store the list of data in state because we don't want to have to sync that with props.\n let sortedRepositories = repositories;\n if (activeSortIndex !== null) {\n sortedRepositories = repositories.sort((a, b) => {\n const aValue = getSortableRowValues(a)[activeSortIndex];\n const bValue = getSortableRowValues(b)[activeSortIndex];\n if (typeof aValue === 'number' || typeof aValue === 'boolean') {\n // Numeric sort\n if (activeSortDirection === 'asc') {\n return (aValue as number) - (bValue as number);\n }\n return (bValue as number) - (aValue as number);\n } else {\n // String sort\n if (activeSortDirection === 'asc') {\n return (aValue as string).localeCompare(bValue as string);\n }\n return (bValue as string).localeCompare(aValue as string);\n }\n });\n }\n\n const isRepoSelectable = (repo: Repository) => repo.name !== 'a'; // Arbitrary logic for this example\n const selectableRepos = repositories.filter(isRepoSelectable);\n\n // In this example, selected rows are tracked by the repo names from each row. This could be any unique identifier.\n // This is to prevent state from being based on row order index in case we later add sorting.\n const [selectedRepoNames, setSelectedRepoNames] = useState<string[]>([]);\n const setRepoSelected = (repo: Repository, isSelecting = true) =>\n setSelectedRepoNames((prevSelected) => {\n const otherSelectedRepoNames = prevSelected.filter((r) => r !== repo.name);\n return isSelecting && isRepoSelectable(repo) ? [...otherSelectedRepoNames, repo.name] : otherSelectedRepoNames;\n });\n const selectAllRepos = (isSelecting = true) =>\n setSelectedRepoNames(isSelecting ? selectableRepos.map((r) => r.name) : []);\n const isRepoSelected = (repo: Repository) => selectedRepoNames.includes(repo.name);\n\n const columns: TableProps['cells'] = [\n { title: 'Repositories', transforms: [sortable] },\n 'Branches',\n 'Pull requests',\n 'Workspaces',\n 'Last commit'\n ];\n const rows: TableProps['rows'] = sortedRepositories.map((repo) => {\n const favorited = isRepoFavorited(repo);\n return {\n favorited,\n // The favorites button has defaults that can be overriden\n favoritesProps: {\n 'aria-label': favorited ? 'Favorited' : 'Not favorited', // Defaults to 'Starred' / 'Not starred'\n id: `favorites-button-${repo.name}`, // Defaults to `favorites-button-${rowIndex}`\n 'aria-labelledby': `favorites-button-${repo.name}` // Defaults to `favorites-button-${rowIndex}`\n },\n selected: isRepoSelected(repo),\n disableSelection: !isRepoSelectable(repo),\n cells: [repo.name, repo.branches, repo.prs, repo.workspaces, repo.lastCommit]\n };\n });\n\n const [canSortFavorites, setCanSortFavorites] = useState(true);\n\n return (\n <div>\n <Checkbox\n label=\"Can sort favorites\"\n isChecked={canSortFavorites}\n onChange={(_event, checked) => setCanSortFavorites(checked)}\n aria-label=\"toggle can sort favorites checkbox\"\n id=\"toggle-can-sort-favorites\"\n name=\"toggle-can-sort-favorites\"\n />\n <Table\n // using this prop enables the favorites column\n onFavorite={(_event, isFavoriting, rowIndex) => {\n const repo = sortedRepositories[rowIndex];\n setRepoFavorited(repo, isFavoriting);\n }}\n // if the onSort prop is detected, favorites can be sorted\n // if you want to exclude favorites from sorting you can use this prop with a value of `false`\n canSortFavorites={canSortFavorites}\n onSelect={(_event, isSelecting, rowIndex) => {\n if (rowIndex === -1) {\n selectAllRepos(isSelecting);\n } else {\n const repo = sortedRepositories[rowIndex];\n setRepoSelected(repo, isSelecting);\n }\n }}\n onSort={(_event, index, direction) => {\n setActiveSortIndex(index);\n setActiveSortDirection(direction);\n }}\n sortBy={{\n index: activeSortIndex,\n direction: activeSortDirection\n }}\n aria-label=\"Favoritable Table\"\n cells={columns}\n rows={rows}\n >\n <TableHeader />\n <TableBody />\n </Table>\n </div>\n );\n};\n","title":"Favoritable (implemented with sortable and selectable)","lang":"ts","className":""}}>
|
|
924
|
+
|
|
925
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
926
|
+
{`To enable favoriting of a row, set the `}
|
|
927
|
+
|
|
928
|
+
<code {...{"className":"ws-code "}}>
|
|
929
|
+
{`onFavorite`}
|
|
930
|
+
</code>
|
|
931
|
+
{` callback prop on the Table.`}
|
|
932
|
+
</p>
|
|
933
|
+
|
|
934
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
935
|
+
{`To control whether a row is favorited or not, the Table looks for `}
|
|
936
|
+
|
|
937
|
+
<code {...{"className":"ws-code "}}>
|
|
938
|
+
{`favorited: true | falsy`}
|
|
939
|
+
</code>
|
|
940
|
+
{` on the row definition.`}
|
|
941
|
+
</p>
|
|
942
|
+
|
|
943
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
944
|
+
{`When you also pass a sort callback through the `}
|
|
945
|
+
|
|
946
|
+
<code {...{"className":"ws-code "}}>
|
|
947
|
+
{`onSort`}
|
|
948
|
+
</code>
|
|
949
|
+
{` prop, favorites sorting is also enabled.`}
|
|
950
|
+
</p>
|
|
951
|
+
|
|
952
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
953
|
+
{`If you want to exclude favorites from sorting, set `}
|
|
954
|
+
|
|
955
|
+
<code {...{"className":"ws-code "}}>
|
|
956
|
+
{`canSortFavorites={false}`}
|
|
957
|
+
</code>
|
|
958
|
+
{` on the Table.`}
|
|
959
|
+
</p>
|
|
960
|
+
</Example>,
|
|
961
|
+
'Tree table': props =>
|
|
962
|
+
<Example {...pageData} {...props} {...{"code":"import { useState } from 'react';\nimport { treeRow, IRow, OnTreeRowCollapse, OnCheckChange, OnToggleRowDetails } from '@patternfly/react-table';\nimport { Table, TableHeader, TableBody } from '@patternfly/react-table/deprecated';\nimport LeafIcon from '@patternfly/react-icons/dist/esm/icons/leaf-icon';\nimport FolderIcon from '@patternfly/react-icons/dist/esm/icons/folder-icon';\nimport FolderOpenIcon from '@patternfly/react-icons/dist/esm/icons/folder-open-icon';\n\ninterface RepositoriesTreeNode {\n name: string;\n branches: string;\n pullRequests: string;\n workspaces: string;\n children?: RepositoriesTreeNode[];\n}\n\nexport const LegacyTableTree: React.FunctionComponent = () => {\n // In real usage, this data would come from some external source like an API via props.\n const data: RepositoriesTreeNode[] = [\n {\n name: 'Repositories one',\n branches: 'Branch one',\n pullRequests: 'Pull request one',\n workspaces: 'Workplace one',\n children: [\n {\n name: 'Repositories two',\n branches: 'Branch two',\n pullRequests: 'Pull request two',\n workspaces: 'Workplace two',\n children: [\n {\n name: 'Repositories three',\n branches: 'Branch three',\n pullRequests: 'Pull request three',\n workspaces: 'Workplace three'\n },\n {\n name: 'Repositories four',\n branches: 'Branch four',\n pullRequests: 'Pull request four',\n workspaces: 'Workplace four'\n }\n ]\n },\n {\n name: 'Repositories five',\n branches: 'Branch five',\n pullRequests: 'Pull request five',\n workspaces: 'Workplace five'\n },\n {\n name: 'Repositories six',\n branches: 'Branch six',\n pullRequests: 'Pull request six',\n workspaces: 'Workplace six'\n }\n ]\n },\n {\n name: 'Repositories seven',\n branches: 'Branch seven',\n pullRequests: 'Pull request seven',\n workspaces: 'Workplace seven',\n children: [\n {\n name: 'Repositories eight',\n branches: 'Branch eight',\n pullRequests: 'Pull request eight',\n workspaces: 'Workplace eight'\n }\n ]\n },\n {\n name: 'Repositories nine',\n branches: 'Branch nine',\n pullRequests: 'Pull request nine',\n workspaces: 'Workplace nine'\n }\n ];\n\n const [expandedNodeNames, setExpandedNodeNames] = useState<string[]>(['Repositories one']);\n const [expandedDetailsNodeNames, setExpandedDetailsNodeNames] = useState<string[]>([]);\n const [selectedNodeNames, setSelectedNodeNames] = useState<string[]>([]);\n\n const getDescendants = (node: RepositoriesTreeNode): RepositoriesTreeNode[] =>\n [node].concat(...(node.children ? node.children.map(getDescendants) : []));\n const areAllDescendantsSelected = (node: RepositoriesTreeNode) =>\n getDescendants(node).every((n) => selectedNodeNames.includes(n.name));\n const areSomeDescendantsSelected = (node: RepositoriesTreeNode) =>\n getDescendants(node).some((n) => selectedNodeNames.includes(n.name));\n\n const isNodeChecked = (node: RepositoriesTreeNode) => {\n if (areAllDescendantsSelected(node)) {\n return true;\n }\n if (areSomeDescendantsSelected(node)) {\n return null;\n }\n return false;\n };\n\n // We index the tree nodes in the order of the table rows, for looking up by rowIndex\n const flattenedNodes: RepositoriesTreeNode[] = [];\n\n /**\n Recursive function which flattens the data into an array of flattened IRow objects\n params:\n - nodes - array of a single level of tree nodes\n - level - number representing how deeply nested the current row is\n - posinset - position of the row relative to this row's siblings\n - isHidden - defaults to false, true if this row's parent is expanded\n - currentRowIndex - position of the row relative to the entire table\n */\n const buildRows = (\n [node, ...remainingNodes]: RepositoriesTreeNode[],\n level = 1,\n posinset = 1,\n rowIndex = 0,\n isHidden = false\n ): IRow[] => {\n if (!node) {\n return [];\n }\n const isExpanded = expandedNodeNames.includes(node.name);\n const isDetailsExpanded = expandedDetailsNodeNames.includes(node.name);\n const isChecked = isNodeChecked(node);\n let icon = <LeafIcon />;\n if (node.children) {\n icon = isExpanded ? <FolderOpenIcon /> : <FolderIcon />;\n }\n flattenedNodes.push(node);\n\n const childRows =\n node.children && node.children.length\n ? buildRows(node.children, level + 1, 1, rowIndex + 1, !isExpanded || isHidden)\n : [];\n\n return [\n {\n cells: [node.name, node.branches, node.pullRequests, node.workspaces],\n props: {\n isExpanded,\n isDetailsExpanded,\n isHidden,\n 'aria-level': level,\n 'aria-posinset': posinset,\n 'aria-setsize': node.children ? node.children.length : 0,\n isChecked,\n icon\n }\n },\n ...childRows,\n ...buildRows(remainingNodes, level, posinset + 1, rowIndex + 1 + childRows.length, isHidden)\n ];\n };\n\n const onCollapse: OnTreeRowCollapse = (_event, rowIndex) => {\n const node = flattenedNodes[rowIndex];\n const isExpanded = expandedNodeNames.includes(node.name);\n setExpandedNodeNames((prevExpanded) => {\n const otherExpandedNodeNames = prevExpanded.filter((name) => name !== node.name);\n return isExpanded ? otherExpandedNodeNames : [...otherExpandedNodeNames, node.name];\n });\n };\n\n const onCheck: OnCheckChange = (_event, isChecking, rowIndex) => {\n const node = flattenedNodes[rowIndex];\n const nodeNamesToCheck = getDescendants(node).map((n) => n.name);\n setSelectedNodeNames((prevSelected) => {\n const otherSelectedNodeNames = prevSelected.filter((name) => !nodeNamesToCheck.includes(name));\n return !isChecking ? otherSelectedNodeNames : [...otherSelectedNodeNames, ...nodeNamesToCheck];\n });\n };\n\n const onToggleRowDetails: OnToggleRowDetails = (_event, rowIndex) => {\n const node = flattenedNodes[rowIndex];\n const isDetailsExpanded = expandedDetailsNodeNames.includes(node.name);\n setExpandedDetailsNodeNames((prevDetailsExpanded) => {\n const otherDetailsExpandedNodeNames = prevDetailsExpanded.filter((name) => name !== node.name);\n return isDetailsExpanded ? otherDetailsExpandedNodeNames : [...otherDetailsExpandedNodeNames, node.name];\n });\n };\n\n return (\n <Table\n isTreeTable\n aria-label=\"Tree table\"\n cells={[\n {\n title: 'Repositories',\n cellTransforms: [treeRow(onCollapse, onCheck, onToggleRowDetails)]\n },\n 'Branches',\n 'Pull requests',\n 'Workspaces'\n ]}\n rows={buildRows(data)}\n >\n <TableHeader />\n <TableBody />\n </Table>\n );\n};\n","title":"Tree table","lang":"ts","className":""}}>
|
|
963
|
+
|
|
964
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
965
|
+
{`To enable a tree table:`}
|
|
966
|
+
</p>
|
|
967
|
+
|
|
968
|
+
<ol {...{"className":"pf-v6-c-content--ol pf-m-editorial ws-ol "}}>
|
|
969
|
+
|
|
970
|
+
|
|
971
|
+
|
|
972
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
973
|
+
{`Pass the `}
|
|
974
|
+
|
|
975
|
+
<code {...{"className":"ws-code "}}>
|
|
976
|
+
{`isTreeTable`}
|
|
977
|
+
</code>
|
|
978
|
+
{` prop to the `}
|
|
979
|
+
|
|
980
|
+
<code {...{"className":"ws-code "}}>
|
|
981
|
+
{`Table`}
|
|
982
|
+
</code>
|
|
983
|
+
{` component`}
|
|
984
|
+
</li>
|
|
985
|
+
|
|
986
|
+
|
|
987
|
+
|
|
988
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
989
|
+
{`Pass the following props to each row:`}
|
|
990
|
+
|
|
991
|
+
|
|
992
|
+
|
|
993
|
+
<ul {...{"className":"pf-v6-c-content--ul pf-m-editorial ws-ul "}}>
|
|
994
|
+
|
|
995
|
+
|
|
996
|
+
|
|
997
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
998
|
+
|
|
999
|
+
<code {...{"className":"ws-code "}}>
|
|
1000
|
+
{`isExpanded`}
|
|
1001
|
+
</code>
|
|
1002
|
+
{` - Flag indicating the node is expanded and its children are visible`}
|
|
1003
|
+
</li>
|
|
1004
|
+
|
|
1005
|
+
|
|
1006
|
+
|
|
1007
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
1008
|
+
|
|
1009
|
+
<code {...{"className":"ws-code "}}>
|
|
1010
|
+
{`isDetailsExpanded`}
|
|
1011
|
+
</code>
|
|
1012
|
+
{` - (optional) Flag indicating the row's details are visible in responsive view`}
|
|
1013
|
+
</li>
|
|
1014
|
+
|
|
1015
|
+
|
|
1016
|
+
|
|
1017
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
1018
|
+
|
|
1019
|
+
<code {...{"className":"ws-code "}}>
|
|
1020
|
+
{`isHidden`}
|
|
1021
|
+
</code>
|
|
1022
|
+
{` - Flag indicating the node's parent is expanded and this node is visible`}
|
|
1023
|
+
</li>
|
|
1024
|
+
|
|
1025
|
+
|
|
1026
|
+
|
|
1027
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
1028
|
+
|
|
1029
|
+
<code {...{"className":"ws-code "}}>
|
|
1030
|
+
{`aria-level`}
|
|
1031
|
+
</code>
|
|
1032
|
+
{` - number representing how many levels deep this node is nested`}
|
|
1033
|
+
</li>
|
|
1034
|
+
|
|
1035
|
+
|
|
1036
|
+
|
|
1037
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
1038
|
+
|
|
1039
|
+
<code {...{"className":"ws-code "}}>
|
|
1040
|
+
{`aria-posinset`}
|
|
1041
|
+
</code>
|
|
1042
|
+
{` - number representing where in the order this node sits amongst its siblings`}
|
|
1043
|
+
</li>
|
|
1044
|
+
|
|
1045
|
+
|
|
1046
|
+
|
|
1047
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
1048
|
+
|
|
1049
|
+
<code {...{"className":"ws-code "}}>
|
|
1050
|
+
{`aria-setsize`}
|
|
1051
|
+
</code>
|
|
1052
|
+
{` - number representing the number of children this node has`}
|
|
1053
|
+
</li>
|
|
1054
|
+
|
|
1055
|
+
|
|
1056
|
+
|
|
1057
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
1058
|
+
|
|
1059
|
+
<code {...{"className":"ws-code "}}>
|
|
1060
|
+
{`isChecked`}
|
|
1061
|
+
</code>
|
|
1062
|
+
{` - (optional) boolean used if this row uses checkboxes, flag indicating the checkbox checked`}
|
|
1063
|
+
</li>
|
|
1064
|
+
|
|
1065
|
+
|
|
1066
|
+
|
|
1067
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
1068
|
+
|
|
1069
|
+
<code {...{"className":"ws-code "}}>
|
|
1070
|
+
{`icon`}
|
|
1071
|
+
</code>
|
|
1072
|
+
{` - (optional) ReactNode icon to display before the row title`}
|
|
1073
|
+
</li>
|
|
1074
|
+
|
|
1075
|
+
|
|
1076
|
+
|
|
1077
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
1078
|
+
|
|
1079
|
+
<code {...{"className":"ws-code "}}>
|
|
1080
|
+
{`toggleAriaLabel`}
|
|
1081
|
+
</code>
|
|
1082
|
+
{` - (optional) accessible label for the expand/collapse children rows toggle arrow`}
|
|
1083
|
+
</li>
|
|
1084
|
+
|
|
1085
|
+
|
|
1086
|
+
|
|
1087
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
1088
|
+
|
|
1089
|
+
<code {...{"className":"ws-code "}}>
|
|
1090
|
+
{`checkAriaLabel`}
|
|
1091
|
+
</code>
|
|
1092
|
+
{` - (optional) accessible label for the checkbox`}
|
|
1093
|
+
</li>
|
|
1094
|
+
|
|
1095
|
+
|
|
1096
|
+
|
|
1097
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
1098
|
+
|
|
1099
|
+
<code {...{"className":"ws-code "}}>
|
|
1100
|
+
{`showDetailsAriaLabel`}
|
|
1101
|
+
</code>
|
|
1102
|
+
{` - (optional) accessible label for the show row details button in the responsive view`}
|
|
1103
|
+
</li>
|
|
1104
|
+
|
|
1105
|
+
|
|
1106
|
+
</ul>
|
|
1107
|
+
|
|
1108
|
+
|
|
1109
|
+
</li>
|
|
1110
|
+
|
|
1111
|
+
|
|
1112
|
+
|
|
1113
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
1114
|
+
{`Use the `}
|
|
1115
|
+
|
|
1116
|
+
<code {...{"className":"ws-code "}}>
|
|
1117
|
+
{`treeRow`}
|
|
1118
|
+
</code>
|
|
1119
|
+
{` cellTransform in the first column of the table. `}
|
|
1120
|
+
|
|
1121
|
+
<code {...{"className":"ws-code "}}>
|
|
1122
|
+
{`treeRow`}
|
|
1123
|
+
</code>
|
|
1124
|
+
{` expects one or two callbacks as params.`}
|
|
1125
|
+
|
|
1126
|
+
|
|
1127
|
+
|
|
1128
|
+
<ul {...{"className":"pf-v6-c-content--ul pf-m-editorial ws-ul "}}>
|
|
1129
|
+
|
|
1130
|
+
|
|
1131
|
+
|
|
1132
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
1133
|
+
|
|
1134
|
+
<code {...{"className":"ws-code "}}>
|
|
1135
|
+
{`onCollapse`}
|
|
1136
|
+
</code>
|
|
1137
|
+
{` - Callback when user expands/collapses a row to reveal/hide the row's children.`}
|
|
1138
|
+
</li>
|
|
1139
|
+
|
|
1140
|
+
|
|
1141
|
+
|
|
1142
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
1143
|
+
|
|
1144
|
+
<code {...{"className":"ws-code "}}>
|
|
1145
|
+
{`onCheckChange`}
|
|
1146
|
+
</code>
|
|
1147
|
+
{` - (optional) Callback when user changes the checkbox on a row.`}
|
|
1148
|
+
</li>
|
|
1149
|
+
|
|
1150
|
+
|
|
1151
|
+
|
|
1152
|
+
<li {...{"className":"pf-v6-c-content--li pf-m-editorial ws-li "}}>
|
|
1153
|
+
|
|
1154
|
+
<code {...{"className":"ws-code "}}>
|
|
1155
|
+
{`onToggleRowDetails`}
|
|
1156
|
+
</code>
|
|
1157
|
+
{` - (optional) Callback when user shows/hides the row details in responsive view.`}
|
|
1158
|
+
</li>
|
|
1159
|
+
|
|
1160
|
+
|
|
1161
|
+
</ul>
|
|
1162
|
+
|
|
1163
|
+
|
|
1164
|
+
</li>
|
|
1165
|
+
|
|
1166
|
+
|
|
1167
|
+
</ol>
|
|
1168
|
+
|
|
1169
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
1170
|
+
{`Note: If this table is going to be tested using axe-core, the tests will flag the use of aria-level,
|
|
1171
|
+
aria-posinset, and aria-setsize as violations. This is an intentional choice at this time so that
|
|
1172
|
+
the voice over technologies will recognize the flat table structure as a tree.`}
|
|
1173
|
+
</p>
|
|
1174
|
+
</Example>,
|
|
1175
|
+
'Striped': props =>
|
|
1176
|
+
<Example {...pageData} {...props} {...{"code":"import { Table, TableHeader, TableBody, TableProps } from '@patternfly/react-table/deprecated';\ninterface Repository {\n name: string;\n branches: string;\n prs: string;\n workspaces: string;\n lastCommit: string;\n}\n\nexport const LegacyTableStriped: React.FunctionComponent = () => {\n // In real usage, this data would come from some external source like an API via props.\n const repositories: Repository[] = [\n {\n name: 'Repository one',\n branches: 'Branch one',\n prs: 'PR one',\n workspaces: 'Workspace one',\n lastCommit: 'Commit one'\n },\n {\n name: 'Repository two',\n branches: 'Branch two',\n prs: 'PR two',\n workspaces: 'Workspace two',\n lastCommit: 'Commit two'\n },\n {\n name: 'Repository three',\n branches: 'Branch three',\n prs: 'PR three',\n workspaces: 'Workspace three',\n lastCommit: 'Commit three'\n }\n ];\n\n const columns: TableProps['cells'] = ['Repositories', 'Branches', 'Pull requests', 'Workspaces', 'Last commit'];\n const rows: TableProps['rows'] = repositories.map((repo) => [\n repo.name,\n repo.branches,\n repo.prs,\n repo.workspaces,\n repo.lastCommit\n ]);\n\n return (\n <Table aria-label=\"Simple Table\" cells={columns} rows={rows} isStriped>\n <TableHeader />\n <TableBody />\n </Table>\n );\n};\n","title":"Striped","lang":"ts","className":""}}>
|
|
1177
|
+
|
|
1178
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
1179
|
+
{`To apply striping to a basic table, add the `}
|
|
1180
|
+
|
|
1181
|
+
<code {...{"className":"ws-code "}}>
|
|
1182
|
+
{`isStriped`}
|
|
1183
|
+
</code>
|
|
1184
|
+
{` property to `}
|
|
1185
|
+
|
|
1186
|
+
<code {...{"className":"ws-code "}}>
|
|
1187
|
+
{`Table`}
|
|
1188
|
+
</code>
|
|
1189
|
+
{`.`}
|
|
1190
|
+
</p>
|
|
1191
|
+
</Example>,
|
|
1192
|
+
'Striped expandable': props =>
|
|
1193
|
+
<Example {...pageData} {...props} {...{"code":"import { Fragment, useState } from 'react';\nimport { TableVariant, expandable, IRowCell } from '@patternfly/react-table';\nimport { Table, TableHeader, TableBody, TableProps } from '@patternfly/react-table/deprecated';\nimport { Checkbox } from '@patternfly/react-core';\n\ninterface Repository {\n name: string;\n branches: string;\n prs: string;\n workspaces: string;\n details?: {\n detail1?: string;\n detail2?: string;\n detail3?: string;\n detailFormat: 0 | 1 | 2 | 3;\n };\n}\n\nexport const LegacyTableStripedExpandable: React.FunctionComponent = () => {\n // In real usage, this data would come from some external source like an API via props.\n const repositories: Repository[] = [\n { name: 'one', branches: 'two', prs: 'a', workspaces: 'four' },\n {\n name: 'parent 1',\n branches: 'two',\n prs: 'k',\n workspaces: 'four',\n // This `details` structure is just for this example. You can drive expanded content from any kind of data.\n details: { detailFormat: 0, detail1: 'single cell' }\n },\n {\n name: 'parent 2',\n branches: 'two',\n prs: 'b',\n workspaces: 'four',\n details: { detailFormat: 1, detail1: 'single cell - fullWidth' }\n },\n {\n name: 'parent 3',\n branches: '2',\n prs: 'b',\n workspaces: 'four',\n details: { detailFormat: 2, detail1: 'single cell - noPadding' }\n },\n {\n name: 'parent 4',\n branches: '2',\n prs: 'b',\n workspaces: 'four',\n details: { detailFormat: 3, detail1: 'single cell - fullWidth & noPadding' }\n },\n {\n name: 'parent 5',\n branches: '2',\n prs: 'b',\n workspaces: 'four',\n details: {\n detailFormat: 0,\n detail1: \"spans 'Repositories and 'Branches'\",\n detail2: \"spans 'Pull requests' and 'Workspaces', and 'Last commit'\"\n }\n },\n {\n name: 'parent 6',\n branches: '2',\n prs: 'b',\n workspaces: 'four',\n details: {\n detailFormat: 1,\n detail1: \"fullWidth, spans the collapsible column and 'Repositories'\",\n detail2: \"fullWidth, spans 'Branches' and 'Pull requests'\",\n detail3: 'fullWidth, spans the empty column'\n }\n }\n ];\n\n // In this example, expanded rows are tracked by the repo names from each row. This could be any unique identifier.\n // This is to prevent state from being based on row order index in case we later add sorting.\n // Note that this behavior is very similar to selection state.\n const initialExpandedRepoNames = repositories.filter((repo) => !!repo.details).map((repo) => repo.name); // Default to all expanded\n const [expandedRepoNames, setExpandedRepoNames] = useState<string[]>(initialExpandedRepoNames);\n const setRepoExpanded = (repo: Repository, isExpanding = true) =>\n setExpandedRepoNames((prevExpanded) => {\n const otherExpandedRepoNames = prevExpanded.filter((r) => r !== repo.name);\n return isExpanding ? [...otherExpandedRepoNames, repo.name] : otherExpandedRepoNames;\n });\n const isRepoExpanded = (repo: Repository) => expandedRepoNames.includes(repo.name);\n\n const [isExampleCompact, setIsExampleCompact] = useState(true);\n\n // We want to be able to reference the original data object based on row index. But because an expanded\n // row takes up two row indexes, repositories[rowIndex] will not be accurate like it would in a normal table.\n // One solution to this is to create an array of data objects indexed by the displayed row index.\n const reposByRowIndex: (Repository | null)[] = [];\n\n const columns: TableProps['cells'] = [\n {\n title: 'Repositories',\n cellFormatters: [expandable]\n },\n 'Branches',\n { title: 'Pull requests' },\n { title: '' /* deliberately empty */, dataLabel: 'Label for mobile view' }\n ];\n const rows: TableProps['rows'] = [];\n repositories.forEach((repo) => {\n rows.push({\n ...(repo.details ? { isOpen: isRepoExpanded(repo) } : {}),\n cells: [repo.name, repo.branches, repo.prs, repo.workspaces]\n });\n reposByRowIndex.push(repo);\n if (repo.details) {\n // Some arbitrary examples of how you could customize the child row based on your needs\n const { detail1, detail2, detail3, detailFormat } = repo.details;\n const numColumns = 5;\n const childIsFullWidth = [1, 3].includes(detailFormat);\n const childHasNoPadding = [2, 3].includes(detailFormat);\n let detailColSpans = [1, 1, 1];\n if (detail1 && !detail2 && !detail3) {\n detailColSpans = [childIsFullWidth ? numColumns : numColumns + 1]; // Account for toggle column\n } else if (detail1 && detail2 && !detail3) {\n detailColSpans = [2, childIsFullWidth ? 3 : 4];\n } else if (detail1 && detail2 && detail3) {\n detailColSpans = [2, 2, childIsFullWidth ? 1 : 2];\n }\n const cells: IRowCell[] = [];\n [detail1, detail2, detail3].forEach((detail, index) => {\n if (detail) {\n cells.push({\n title: detail1,\n props: {\n colSpan: detailColSpans[index]\n }\n });\n }\n });\n rows.push({\n parent: rows.length - 1,\n cells,\n fullWidth: childIsFullWidth,\n noPadding: childHasNoPadding\n });\n reposByRowIndex.push(null);\n }\n });\n\n return (\n <Fragment>\n <Checkbox\n label=\"Compact\"\n isChecked={isExampleCompact}\n onChange={(_event, checked) => setIsExampleCompact(checked)}\n aria-label=\"toggle striped compact variation\"\n id=\"toggle-compact-striped\"\n name=\"toggle-compact-striped\"\n />\n <Table\n aria-label=\"Expandable table\"\n variant={isExampleCompact ? TableVariant.compact : undefined}\n onCollapse={(_event, rowIndex, isOpen) => {\n if (reposByRowIndex[rowIndex]) {\n setRepoExpanded(reposByRowIndex[rowIndex], isOpen);\n }\n }}\n rows={rows}\n cells={columns}\n isStriped\n isExpandable\n >\n <TableHeader />\n <TableBody />\n </Table>\n </Fragment>\n );\n};\n","title":"Striped expandable","lang":"ts","className":""}}>
|
|
1194
|
+
|
|
1195
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
1196
|
+
{`To apply striping to an expandable table, add the `}
|
|
1197
|
+
|
|
1198
|
+
<code {...{"className":"ws-code "}}>
|
|
1199
|
+
{`isStriped`}
|
|
1200
|
+
</code>
|
|
1201
|
+
{` and `}
|
|
1202
|
+
|
|
1203
|
+
<code {...{"className":"ws-code "}}>
|
|
1204
|
+
{`isExpandable`}
|
|
1205
|
+
</code>
|
|
1206
|
+
{` properties to `}
|
|
1207
|
+
|
|
1208
|
+
<code {...{"className":"ws-code "}}>
|
|
1209
|
+
{`Table`}
|
|
1210
|
+
</code>
|
|
1211
|
+
{`.`}
|
|
1212
|
+
</p>
|
|
1213
|
+
</Example>,
|
|
1214
|
+
'Striped custom tr': props =>
|
|
1215
|
+
<Example {...pageData} {...props} {...{"code":"import { Table, TableHeader, TableBody, TableProps } from '@patternfly/react-table/deprecated';\nimport { css } from '@patternfly/react-styles';\n\ninterface Repository {\n name: string;\n branches: string | null;\n prs: string | null;\n workspaces: string;\n lastCommit: string;\n}\n\nexport const LegacyTableStripedCustomTr: React.FunctionComponent = () => {\n // In real usage, this data would come from some external source like an API via props.\n const repositories: Repository[] = [\n { name: 'one', branches: 'two', prs: 'three', workspaces: 'four', lastCommit: 'five' },\n { name: 'one - 2', branches: null, prs: null, workspaces: 'four - 2', lastCommit: 'five - 2' },\n { name: 'one - 3', branches: 'two - 3', prs: 'three - 3', workspaces: 'four - 3', lastCommit: 'five - 3' }\n ];\n\n const columns: TableProps['cells'] = ['Repositories', 'Branches', 'Pull requests', 'Workspaces', 'Last commit'];\n const rows: TableProps['rows'] = repositories.map((repo) => [\n repo.name,\n repo.branches || '',\n repo.prs || '',\n repo.workspaces,\n repo.lastCommit\n ]);\n\n const customRowWrapper: TableProps['rowWrapper'] = ({ trRef, className, rowProps, row: _row }) => {\n const isOddRow = rowProps ? !!((rowProps.rowIndex + 1) % 2) : true;\n return <tr ref={trRef as React.Ref<HTMLTableRowElement>} className={css(className, isOddRow && 'pf-m-striped')} />;\n };\n\n return (\n <Table\n caption=\"Table with custom row wrapper that stripes odd rows\"\n cells={columns}\n rows={rows}\n rowWrapper={customRowWrapper}\n >\n <TableHeader />\n <TableBody />\n </Table>\n );\n};\n","title":"Striped custom tr","lang":"ts","className":""}}>
|
|
1216
|
+
|
|
1217
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
1218
|
+
{`To manually control striping, use a custom row wrapper that applies the `}
|
|
1219
|
+
|
|
1220
|
+
<code {...{"className":"ws-code "}}>
|
|
1221
|
+
{`pf-m-striped`}
|
|
1222
|
+
</code>
|
|
1223
|
+
{` css class for each desired row.`}
|
|
1224
|
+
</p>
|
|
1225
|
+
</Example>
|
|
1226
|
+
};
|
|
1227
|
+
|
|
1228
|
+
const Component = () => (
|
|
1229
|
+
<React.Fragment>
|
|
1230
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
1231
|
+
{`Note: Table lives in its own package at `}
|
|
1232
|
+
<PatternflyThemeLink {...{"to":"https://www.npmjs.com/package/@patternfly/react-table","className":""}}>
|
|
1233
|
+
{`@patternfly/react-table`}
|
|
1234
|
+
</PatternflyThemeLink>
|
|
1235
|
+
{`!`}
|
|
1236
|
+
</p>
|
|
1237
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
1238
|
+
<strong {...{"className":""}}>
|
|
1239
|
+
{`This implementation of `}
|
|
1240
|
+
<code {...{"className":"ws-code "}}>
|
|
1241
|
+
{`Table`}
|
|
1242
|
+
</code>
|
|
1243
|
+
{` has been deprecated. It is no longer supported or maintained.`}
|
|
1244
|
+
</strong>
|
|
1245
|
+
</p>
|
|
1246
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
1247
|
+
{`This deprecated `}
|
|
1248
|
+
<code {...{"className":"ws-code "}}>
|
|
1249
|
+
{`Table`}
|
|
1250
|
+
</code>
|
|
1251
|
+
{` component is configuration-based and takes a less declarative and more implicit approach to laying out the table structure, such as the rows and cells within it.`}
|
|
1252
|
+
</p>
|
|
1253
|
+
<AutoLinkHeader {...{"id":"table-columns","headingLevel":"h2","className":"ws-title ws-h2"}}>
|
|
1254
|
+
{`Table Columns`}
|
|
1255
|
+
</AutoLinkHeader>
|
|
1256
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
1257
|
+
{`Array items for columns provided to the `}
|
|
1258
|
+
<code {...{"className":"ws-code "}}>
|
|
1259
|
+
{`Table`}
|
|
1260
|
+
</code>
|
|
1261
|
+
{`'s `}
|
|
1262
|
+
<code {...{"className":"ws-code "}}>
|
|
1263
|
+
{`cells`}
|
|
1264
|
+
</code>
|
|
1265
|
+
{` prop, can be simple strings or objects.`}
|
|
1266
|
+
</p>
|
|
1267
|
+
<Example {...{"code":"cells: (ICell | string)[];","className":""}}>
|
|
1268
|
+
</Example>
|
|
1269
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
1270
|
+
<code {...{"className":"ws-code "}}>
|
|
1271
|
+
{`ICell`}
|
|
1272
|
+
</code>
|
|
1273
|
+
{` (excerpt):`}
|
|
1274
|
+
</p>
|
|
1275
|
+
<Example {...{"code":"interface ICell {\n /* cell contents */\n title?: React.ReactNode;\n /** transformations applied to the header cell */\n transforms?: ITransform[];\n /** transformations applied to the cells within the column's body */\n cellTransforms?: ITransform[];\n /** transformations applied to the entire column */\n columnTransforms?: ITransform[];\n /** Additional header props, it contains the info prop as well which can be used to add tooltip/popover */\n header?: HeaderType;\n /** Additional props passed into the rendered column header element */\n props?: any;\n /** Text to display when data from this column is rendered in mobile view */\n dataLabel?: string;\n}","className":""}}>
|
|
1276
|
+
</Example>
|
|
1277
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
1278
|
+
{`If you wish to enable other built in features, use `}
|
|
1279
|
+
<code {...{"className":"ws-code "}}>
|
|
1280
|
+
{`transforms`}
|
|
1281
|
+
</code>
|
|
1282
|
+
{` to apply them to
|
|
1283
|
+
column headers or `}
|
|
1284
|
+
<code {...{"className":"ws-code "}}>
|
|
1285
|
+
{`cellTransforms`}
|
|
1286
|
+
</code>
|
|
1287
|
+
{` to apply them to every cell in that column.`}
|
|
1288
|
+
</p>
|
|
1289
|
+
<Example {...{"code":"// simple\ncolumns: ['Repositories', 'Branches', 'Pull requests', 'Workspaces', 'Last commit']\n// with tooltip\ncolumns: [\n {\n title: 'Repositories',\n transforms: [\n info({\n tooltip: 'More information about repositories'\n })\n ]\n }\n]\n// center header and body cells within the column\ncolumns: [\n {\n title: 'Last commit',\n transforms: [textCenter],\n cellTransforms: [textCenter]\n }\n]","className":""}}>
|
|
1290
|
+
</Example>
|
|
1291
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
1292
|
+
{`Many of the subsequent examples demonstrate how to apply different transformations to enable `}
|
|
1293
|
+
<code {...{"className":"ws-code "}}>
|
|
1294
|
+
{`Table`}
|
|
1295
|
+
</code>
|
|
1296
|
+
{` features.`}
|
|
1297
|
+
</p>
|
|
1298
|
+
<AutoLinkHeader {...{"id":"table-rows","headingLevel":"h2","className":"ws-title ws-h2"}}>
|
|
1299
|
+
{`Table Rows`}
|
|
1300
|
+
</AutoLinkHeader>
|
|
1301
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
1302
|
+
{`Array items for rows provided to the `}
|
|
1303
|
+
<code {...{"className":"ws-code "}}>
|
|
1304
|
+
{`Table`}
|
|
1305
|
+
</code>
|
|
1306
|
+
{`'s `}
|
|
1307
|
+
<code {...{"className":"ws-code "}}>
|
|
1308
|
+
{`rows`}
|
|
1309
|
+
</code>
|
|
1310
|
+
{` prop, can be simple strings or objects.`}
|
|
1311
|
+
</p>
|
|
1312
|
+
<Example {...{"code":"rows: (IRow | string[])[]","className":""}}>
|
|
1313
|
+
</Example>
|
|
1314
|
+
<p {...{"className":"pf-v6-c-content--p pf-m-editorial ws-p "}}>
|
|
1315
|
+
<code {...{"className":"ws-code "}}>
|
|
1316
|
+
{`IRow`}
|
|
1317
|
+
</code>
|
|
1318
|
+
{` (excerpt):`}
|
|
1319
|
+
</p>
|
|
1320
|
+
<Example {...{"code":"interface IRow extends RowType {\n cells?: (React.ReactNode | IRowCell)[];\n props?: any;\n fullWidth?: boolean;\n noPadding?: boolean;\n}\ninterface IRowCell {\n title?: React.ReactNode | RowCellContent;\n props?: any;\n formatters?: IFormatter[];\n}","className":""}}>
|
|
1321
|
+
</Example>
|
|
1322
|
+
<AutoLinkHeader {...{"id":"table-examples","headingLevel":"h2","className":"ws-title ws-h2"}}>
|
|
1323
|
+
{`Table examples`}
|
|
1324
|
+
</AutoLinkHeader>
|
|
1325
|
+
{React.createElement(pageData.examples["Basic"])}
|
|
1326
|
+
{React.createElement(pageData.examples["Custom row wrapper"])}
|
|
1327
|
+
{React.createElement(pageData.examples["Sortable & wrapping column headers"])}
|
|
1328
|
+
{React.createElement(pageData.examples["Sortable - custom control"])}
|
|
1329
|
+
{React.createElement(pageData.examples["Selectable with checkbox"])}
|
|
1330
|
+
{React.createElement(pageData.examples["Selectable radio input"])}
|
|
1331
|
+
{React.createElement(pageData.examples["Clickable rows, selectable rows, and header cell tooltips/popovers"])}
|
|
1332
|
+
{React.createElement(pageData.examples["Actions and first cell in body rows as th"])}
|
|
1333
|
+
{React.createElement(pageData.examples["Expandable"])}
|
|
1334
|
+
{React.createElement(pageData.examples["Compound expandable"])}
|
|
1335
|
+
{React.createElement(pageData.examples["With width and breakpoint visibility modifiers"])}
|
|
1336
|
+
{React.createElement(pageData.examples["Controlling text"])}
|
|
1337
|
+
{React.createElement(pageData.examples["Modifiers with table text"])}
|
|
1338
|
+
{React.createElement(pageData.examples["Empty state"])}
|
|
1339
|
+
{React.createElement(pageData.examples["Editable rows"])}
|
|
1340
|
+
{React.createElement(pageData.examples["Favoritable (implemented with sortable and selectable)"])}
|
|
1341
|
+
{React.createElement(pageData.examples["Tree table"])}
|
|
1342
|
+
{React.createElement(pageData.examples["Striped"])}
|
|
1343
|
+
{React.createElement(pageData.examples["Striped expandable"])}
|
|
1344
|
+
{React.createElement(pageData.examples["Striped custom tr"])}
|
|
1345
|
+
</React.Fragment>
|
|
1346
|
+
);
|
|
1347
|
+
Component.displayName = 'ComponentsTableReactDeprecatedDocs';
|
|
1348
|
+
Component.pageData = pageData;
|
|
1349
|
+
|
|
1350
|
+
export default Component;
|