@patternfly/documentation-framework 2.0.0-alpha.5 → 2.0.0-alpha.50

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.
Files changed (53) hide show
  1. package/CHANGELOG.md +423 -0
  2. package/app.js +12 -11
  3. package/components/autoLinkHeader/autoLinkHeader.css +2 -2
  4. package/components/autoLinkHeader/autoLinkHeader.js +18 -13
  5. package/components/cssVariables/cssSearch.js +3 -4
  6. package/components/cssVariables/cssVariables.css +4 -4
  7. package/components/cssVariables/cssVariables.js +83 -84
  8. package/components/example/example.css +29 -29
  9. package/components/example/example.js +34 -6
  10. package/components/footer/footer.css +15 -15
  11. package/components/footer/footer.js +13 -13
  12. package/components/functionsTable/functionsTable.js +57 -0
  13. package/components/gdprBanner/gdprBanner.css +2 -2
  14. package/components/gdprBanner/gdprBanner.js +3 -3
  15. package/components/inlineAlert/inlineAlert.js +1 -1
  16. package/components/propsTable/propsTable.js +85 -79
  17. package/components/sectionGallery/sectionDataListLayout.js +67 -0
  18. package/components/sectionGallery/sectionGallery.css +44 -0
  19. package/components/sectionGallery/sectionGallery.js +53 -0
  20. package/components/sectionGallery/sectionGalleryLayout.js +37 -0
  21. package/components/sectionGallery/sectionGalleryToolbar.js +30 -0
  22. package/components/sectionGallery/sectionGalleryWrapper.js +89 -0
  23. package/components/sideNav/sideNav.css +12 -12
  24. package/components/sideNav/sideNav.js +41 -13
  25. package/components/tableOfContents/tableOfContents.css +17 -17
  26. package/components/topNav/topNav.css +12 -12
  27. package/helpers/getTitle.js +2 -2
  28. package/layouts/sideNavLayout/sideNavLayout.css +7 -11
  29. package/layouts/sideNavLayout/sideNavLayout.js +57 -40
  30. package/package.json +28 -25
  31. package/pages/404/404.css +2 -2
  32. package/pages/404/index.js +1 -1
  33. package/pages/global-css-variables.md +16 -16
  34. package/routes.js +20 -8
  35. package/scripts/cli/build.js +6 -0
  36. package/scripts/cli/cli.js +2 -0
  37. package/scripts/cli/generate.js +2 -2
  38. package/scripts/cli/start.js +6 -8
  39. package/scripts/md/parseMD.js +46 -11
  40. package/scripts/md/styled-tags.js +8 -4
  41. package/scripts/tsDocgen.js +119 -91
  42. package/scripts/typeDocGen.js +209 -0
  43. package/scripts/webpack/webpack.base.config.js +34 -32
  44. package/scripts/webpack/webpack.client.config.js +11 -8
  45. package/scripts/webpack/webpack.server.config.js +8 -5
  46. package/scripts/writeScreenshots.js +3 -3
  47. package/templates/html.ejs +1 -3
  48. package/templates/mdx.css +155 -160
  49. package/templates/mdx.js +122 -51
  50. package/templates/patternfly-docs/content/extensions/extension/design-guidelines/design-guidelines.md +2 -0
  51. package/templates/patternfly-docs/content/extensions/extension/examples/basic.md +2 -0
  52. package/versions.json +29 -9
  53. package/pages/red-hat-font.md +0 -40
@@ -13,9 +13,9 @@ export const GdprBanner = () => {
13
13
  }
14
14
 
15
15
  return !isBannerOpen ? null : (
16
- <div className="ws-gdpr-banner-container pf-l-flex">
17
- <div id="ws-gdpr-banner" className="pf-l-flex pf-u-py-md pf-m-align-items-center">
18
- <p id="ws-gdpr-banner-text" className="pf-u-ml-xl">
16
+ <div className="ws-gdpr-banner-container pf-v5-l-flex">
17
+ <div id="ws-gdpr-banner" className="pf-v5-l-flex pf-v5-u-py-md pf-m-align-items-center">
18
+ <p id="ws-gdpr-banner-text" className="pf-v5-u-ml-xl">
19
19
  We use cookies on our websites to deliver our online services.
20
20
  Details about how we use cookies and how you may disable them are set out in our <a href="//www.redhat.com/en/about/privacy-policy">Privacy Statement</a>.
21
21
  By using this website you agree to our use of cookies.
@@ -9,7 +9,7 @@ export const InlineAlert = ({
9
9
  <Alert
10
10
  variant={variant}
11
11
  title={title}
12
- className="pf-u-my-md"
12
+ className="pf-v5-u-my-md"
13
13
  style={{ marginBottom: '1rem' }}
14
14
  isInline
15
15
  component="h2"
@@ -2,90 +2,96 @@ import React from "react";
2
2
  import { Badge } from "@patternfly/react-core";
3
3
  import {
4
4
  Table,
5
- TableHeader,
6
- TableBody,
7
- cellWidth,
5
+ Caption,
6
+ Thead,
7
+ Th,
8
+ Tr,
9
+ Tbody,
10
+ Td,
11
+ TableText
8
12
  } from "@patternfly/react-table";
9
13
  import { AutoLinkHeader } from "../autoLinkHeader/autoLinkHeader";
10
14
  import { PropTypeWithLinks } from "./propTypeWithLinks";
11
15
  import { css } from "@patternfly/react-styles";
12
16
  import accessibleStyles from "@patternfly/react-styles/css/utilities/Accessibility/accessibility";
13
17
 
14
- export const PropsTable = ({ title, description, rows, allPropComponents }) => {
15
- const columns = [
16
- { title: "Name", transforms: [cellWidth(20)] },
17
- { title: "Type", transforms: [cellWidth(20)] },
18
- { title: "Default", transforms: [] },
19
- { title: "Description", transforms: [] },
20
- ];
21
-
22
- return (
23
- <React.Fragment>
24
- <AutoLinkHeader size="h3">{title}</AutoLinkHeader>
25
- <Table
26
- className="pf-u-mt-md pf-u-mb-lg"
27
- variant="compact"
28
- aria-label={title}
29
- caption={
30
- <div>
31
- {description && <div className="pf-u-mb-md">{description}</div>}
32
- <div>
33
- <span className="ws-prop-required">*</span>required
34
- </div>
35
- </div>
36
- }
37
- cells={columns}
38
- gridBreakPoint="grid-lg"
39
- rows={rows
40
- // Sort required rows first
18
+ export const PropsTable = ({ title, description, rows, allPropComponents }) => (
19
+ <React.Fragment>
20
+ <AutoLinkHeader size="h3">{title}</AutoLinkHeader>
21
+ <Table className="pf-v5-u-mt-md pf-v5-u-mb-lg" variant="compact" aria-label={title} gridBreakPoint="grid-lg">
22
+ <Caption>
23
+ {description && <div className="pf-v5-u-mb-md">{description}</div>}
24
+ <div>
25
+ <span className="ws-prop-required">*</span>required
26
+ </div>
27
+ </Caption>
28
+ <Thead>
29
+ <Tr>
30
+ <Th width={20}>Name</Th>
31
+ <Th width={20}>Type</Th>
32
+ <Th>Default</Th>
33
+ <Th>Description</Th>
34
+ </Tr>
35
+ </Thead>
36
+ <Tbody>
37
+ {rows
41
38
  .sort((a, b) => (a.required === b.required ? 0 : a.required ? -1 : 1))
42
- .map((row, idx) => ({
43
- cells: [
44
- <div className="pf-m-break-word">
45
- {row.deprecated && "Deprecated: "}
46
- {row.name}
47
- {row.required ? (
48
- <React.Fragment key={`${row.name}-required-prop`}>
49
- <span
50
- aria-hidden="true"
51
- key={`${row.name}-asterisk`}
52
- className="ws-prop-required"
53
- >
54
- *
55
- </span>
56
- <span
57
- key={`${row.name}-required`}
58
- className={css(accessibleStyles.screenReader)}
59
- >
60
- required
61
- </span>
62
- </React.Fragment>
63
- ) : (
64
- ""
65
- )}
66
- {row.beta && (
67
- <Badge
68
- key={`${row.name}-${idx}`}
69
- className="ws-beta-badge pf-u-ml-sm"
39
+ .map((row, idx) => (
40
+ <Tr key={idx}>
41
+ <Td>
42
+ <TableText wrapModifier="breakWord">
43
+ {row.deprecated && "Deprecated: "}
44
+ {row.name}
45
+ {row.required ? (
46
+ <React.Fragment key={`${row.name}-required-prop`}>
47
+ <span
48
+ aria-hidden="true"
49
+ key={`${row.name}-asterisk`}
50
+ className="ws-prop-required"
70
51
  >
71
- Beta
72
- </Badge>
73
- )}
74
- </div>,
75
- <div className="pf-m-break-word">
76
- <PropTypeWithLinks
77
- type={row.type}
78
- allPropComponents={allPropComponents}
79
- />
80
- </div>,
81
- <div className="pf-m-break-word">{row.defaultValue}</div>,
82
- <div className="pf-m-break-word">{row.description}</div>,
83
- ],
84
- }))}
85
- >
86
- <TableHeader />
87
- <TableBody />
88
- </Table>
89
- </React.Fragment>
90
- );
91
- };
52
+ *
53
+ </span>
54
+ <span
55
+ key={`${row.name}-required`}
56
+ className={css(accessibleStyles.screenReader)}
57
+ >
58
+ required
59
+ </span>
60
+ </React.Fragment>
61
+ ) : (
62
+ ""
63
+ )}
64
+ {row.beta && (
65
+ <Badge
66
+ key={`${row.name}-${idx}`}
67
+ className="ws-beta-badge pf-v5-u-ml-sm"
68
+ >
69
+ Beta
70
+ </Badge>
71
+ )}
72
+ </TableText>
73
+ </Td>
74
+ <Td>
75
+ <TableText wrapModifier="breakWord">
76
+ <PropTypeWithLinks
77
+ type={row.type}
78
+ allPropComponents={allPropComponents}
79
+ />
80
+ </TableText>
81
+ </Td>
82
+ <Td>
83
+ <TableText wrapModifier="breakWord">
84
+ {row.defaultValue}
85
+ </TableText>
86
+ </Td>
87
+ <Td>
88
+ <TableText wrapModifier="breakWord">
89
+ {row.description}
90
+ </TableText>
91
+ </Td>
92
+ </Tr>
93
+ ))}
94
+ </Tbody>
95
+ </Table>
96
+ </React.Fragment>
97
+ );
@@ -0,0 +1,67 @@
1
+ import React from "react";
2
+ import { DataList, DataListItem, DataListItemRow, DataListItemCells, DataListCell, Split, SplitItem, TextContent, Text, TextVariants, Label } from "@patternfly/react-core";
3
+ import { Link } from '../link/link';
4
+ import { convertToReactComponent } from "@patternfly/ast-helpers";
5
+
6
+ // convert summary text in drawer from string to jsx
7
+ const SummaryComponent = ({ id, itemsData }) => {
8
+ const itemDasherized = id.split(' ').join('-').toLowerCase();
9
+ const summary = itemsData?.[itemDasherized]?.summary;
10
+ if (!summary) {
11
+ return null;
12
+ }
13
+ // Remove anchor tags to avoid <a> in summary nested within <a> of Link card/datalistitem
14
+ const summaryNoLinks = summary.replace(/<Link[^>]*>([^<]+)<\/Link>/gm, '$1');
15
+ const { code } = convertToReactComponent(`<>${summaryNoLinks}</>`);
16
+ const getSummaryComponent = new Function('React', code);
17
+ return getSummaryComponent(React);
18
+ }
19
+
20
+ export const SectionDataListLayout = ({ galleryItems, layoutView }) => {
21
+ if (layoutView !== 'list') {
22
+ return null;
23
+ }
24
+
25
+ return (
26
+ <DataList onSelectDataListItem={() => {}}>
27
+ {galleryItems.map(({ idx, slug, illustration, itemName, title, isBeta, id, galleryItemsData }) => (
28
+ <Link to={slug} key={idx} className="ws-section-gallery-item">
29
+ <DataListItem>
30
+ <DataListItemRow>
31
+ <DataListItemCells dataListCells={[
32
+ <DataListCell width={1} key="illustration">
33
+ {illustration && (
34
+ <div>
35
+ <img src={illustration} alt={`${itemName} illustration`} />
36
+ </div>
37
+ )}
38
+ </DataListCell>,
39
+ <DataListCell width={5} key="text-description">
40
+ <Split className="pf-v5-u-mb-md">
41
+ <SplitItem isFilled>
42
+ <TextContent>
43
+ <Text component={TextVariants.h2}>
44
+ <span>
45
+ {title}
46
+ </span>
47
+ </Text>
48
+ </TextContent>
49
+ </SplitItem>
50
+ <SplitItem>
51
+ {isBeta && <Label color="gold">Beta feature</Label>}
52
+ </SplitItem>
53
+ </Split>
54
+ <TextContent>
55
+ <Text>
56
+ { id ? <SummaryComponent id={id} itemsData={galleryItemsData} /> : null }
57
+ </Text>
58
+ </TextContent>
59
+ </DataListCell>
60
+ ]} />
61
+ </DataListItemRow>
62
+ </DataListItem>
63
+ </Link>
64
+ ))}
65
+ </DataList>
66
+ )
67
+ };
@@ -0,0 +1,44 @@
1
+ ..ws-mdx-content-content {
2
+ max-width: initial !important;
3
+ }
4
+
5
+ .ws-section-gallery {
6
+ /* top placement */
7
+ margin-top: calc(var(--pf-v5-c-page__main-section--PaddingTop) * -1);
8
+ }
9
+
10
+ /* Toolbar styles */
11
+ .ws-section-gallery .pf-v5-c-toolbar {
12
+ margin-left: calc(var(--pf-v5-c-page__main-section--PaddingLeft) * -1);
13
+ border-bottom: var(--pf-v5-c-page__sidebar--m-light--BorderRightWidth) solid var(--pf-v5-c-page__sidebar--m-light--BorderRightColor);
14
+ margin-bottom: var(--pf-v5-global--spacer--md);
15
+ width: calc(100% + var(--pf-v5-c-page__main-section--PaddingLeft) + var(--pf-v5-c-page__main-section--PaddingRight));
16
+ /* avoid hoverable data list items overlapping toolbar */
17
+ z-index: calc(var(--pf-v5-global--ZIndex--xs) + 2);
18
+ }
19
+
20
+ /* Match toolbar left-padding to gallery left-padding */
21
+ .ws-section-gallery .pf-v5-c-toolbar .pf-v5-c-toolbar__content {
22
+ --pf-v5-c-toolbar__content--PaddingLeft: var(--pf-v5-c-page__main-section--PaddingLeft);
23
+ }
24
+
25
+ /* Avoid toolbar wrap on smaller screens */
26
+ .ws-section-gallery .pf-v5-c-toolbar__content-section {
27
+ flex-wrap: nowrap;
28
+ }
29
+
30
+ /* Avoid link styling on gallery/data list item names */
31
+ .ws-section-gallery-item {
32
+ text-decoration: inherit;
33
+ color: inherit;
34
+ }
35
+
36
+ /* Ensure same height for all cards in a gallery row */
37
+ .ws-section-gallery .pf-v5-c-card {
38
+ height: 100%;
39
+ }
40
+
41
+ /* Limit width for data list view only */
42
+ .ws-section-gallery .pf-v5-c-data-list {
43
+ max-width: 956px;
44
+ }
@@ -0,0 +1,53 @@
1
+ import React from "react";
2
+
3
+ import './sectionGallery.css';
4
+ import { SectionGalleryToolbar } from "./sectionGalleryToolbar";
5
+ import { SectionGalleryLayout } from "./sectionGalleryLayout";
6
+ import { SectionDataListLayout } from "./sectionDataListLayout";
7
+ import { SectionGalleryWrapper } from "./sectionGalleryWrapper";
8
+
9
+ /**
10
+ * Helper component returns gallery of items with search toolbar and switchable gallery/data list views.
11
+ * @param {Object} illustrations - Object of preview images mapped to their snake_case item display name
12
+ * @param {string} section - Name of the navigation section to create the gallery within
13
+ * @param {Object} galleryItemsData - Object containing the image location & summary text mapped to the gallery item's hyphenated-name
14
+ * @param {string} [placeholderText=Search by name] - Optional text to be displayed as placeholder for SearchInput
15
+ * @param {string} [countText= items] - Optional text to be displayed after the number of search results
16
+ */
17
+
18
+ export const SectionGallery = ({
19
+ illustrations,
20
+ section,
21
+ subsection = null,
22
+ includeSubsections = false,
23
+ parseSubsections = false,
24
+ galleryItemsData,
25
+ placeholderText,
26
+ countText
27
+ }) => (
28
+ <SectionGalleryWrapper
29
+ illustrations={illustrations}
30
+ section={section}
31
+ subsection={subsection}
32
+ includeSubsections={includeSubsections}
33
+ parseSubsections={parseSubsections}
34
+ galleryItemsData={galleryItemsData}
35
+ >
36
+ {(sectionGalleryItems, searchTerm, setSearchTerm, layoutView, setLayoutView) => {
37
+ return (
38
+ <>
39
+ <SectionGalleryToolbar
40
+ galleryItems={sectionGalleryItems}
41
+ searchTerm={searchTerm}
42
+ setSearchTerm={setSearchTerm}
43
+ layoutView={layoutView}
44
+ setLayoutView={setLayoutView}
45
+ placeholderText={placeholderText}
46
+ countText={countText}
47
+ />
48
+ <SectionGalleryLayout galleryItems={sectionGalleryItems} layoutView={layoutView} />
49
+ <SectionDataListLayout galleryItems={sectionGalleryItems} layoutView={layoutView} />
50
+ </>
51
+ )}}
52
+ </SectionGalleryWrapper>
53
+ );
@@ -0,0 +1,37 @@
1
+ import React from "react";
2
+ import { Gallery, GalleryItem, Card, CardTitle, CardBody, CardFooter, Label } from "@patternfly/react-core";
3
+ import { Link } from '../link/link';
4
+
5
+ export const SectionGalleryLayout = ({ galleryItems, layoutView }) => {
6
+ if (layoutView !== 'grid') {
7
+ return null;
8
+ }
9
+
10
+ return (
11
+ <Gallery hasGutter>
12
+ {galleryItems.map(({idx, slug, id, itemName, illustration, isBeta}) => (
13
+ <GalleryItem span={4} key={idx}>
14
+ <Link to={slug} className="ws-section-gallery-item">
15
+ <Card
16
+ id={id}
17
+ key={idx}
18
+ isSelectableRaised
19
+ >
20
+ <CardTitle>{itemName}</CardTitle>
21
+ {illustration && (
22
+ <CardBody>
23
+ <img src={illustration} alt={`${itemName} illustration`} />
24
+ </CardBody>
25
+ )}
26
+ {isBeta && (
27
+ <CardFooter>
28
+ <Label color="blue">Beta feature</Label>
29
+ </CardFooter>
30
+ )}
31
+ </Card>
32
+ </Link>
33
+ </GalleryItem>
34
+ ))}
35
+ </Gallery>
36
+ )
37
+ };
@@ -0,0 +1,30 @@
1
+ import React from "react";
2
+ import { Button, SearchInput, Toolbar, ToolbarContent, ToolbarGroup, ToolbarItem, Text, TextVariants, ToggleGroup, ToggleGroupItem } from '@patternfly/react-core';
3
+ import ListIcon from '@patternfly/react-icons/dist/esm/icons/list-icon';
4
+ import ThIcon from'@patternfly/react-icons/dist/esm/icons/th-icon';
5
+
6
+ export const SectionGalleryToolbar = ({ galleryItems, searchTerm, setSearchTerm, layoutView, setLayoutView, placeholderText ="Search by name", countText=" items" }) => (
7
+ <Toolbar isSticky>
8
+ <ToolbarContent>
9
+ <ToolbarItem variant="search-filter" widths={{default: '100%', md: '320px'}}>
10
+ <SearchInput onClear={false} value={searchTerm} placeholder={placeholderText} onChange={(_evt, val) => setSearchTerm(val)} />
11
+ </ToolbarItem>
12
+ {searchTerm && (
13
+ <ToolbarItem>
14
+ <Button variant="link" onClick={() => setSearchTerm('')}>Reset</Button>
15
+ </ToolbarItem>
16
+ )}
17
+ <ToolbarGroup variant="icon-button-group">
18
+ <ToolbarItem>
19
+ <ToggleGroup>
20
+ <ToggleGroupItem icon={<ThIcon />} aria-label="grid icon button" isSelected={layoutView === 'grid'} onChange={() => setLayoutView('grid')}></ToggleGroupItem>
21
+ <ToggleGroupItem icon={<ListIcon />} aria-label="list icon button" isSelected={layoutView === 'list'} onChange={() => setLayoutView('list')}></ToggleGroupItem>
22
+ </ToggleGroup>
23
+ </ToolbarItem>
24
+ </ToolbarGroup>
25
+ <ToolbarItem variant="pagination" spacer={{default: 'spacerMd', md: 'spacerNone'}} style={{'--pf-v5-c-toolbar__item--MinWidth': "max-content"}}>
26
+ <Text component={TextVariants.small}>{ galleryItems.length }{ countText }</Text>
27
+ </ToolbarItem>
28
+ </ToolbarContent>
29
+ </Toolbar>
30
+ );
@@ -0,0 +1,89 @@
1
+ import React from "react";
2
+ import { groupedRoutes } from '../../routes';
3
+
4
+ export const SectionGalleryWrapper = ({section, subsection, galleryItemsData, illustrations, includeSubsections, parseSubsections, children }) => {
5
+ let sectionRoutes = subsection ? groupedRoutes[section][subsection] : groupedRoutes[section];
6
+ if (!includeSubsections || parseSubsections) {
7
+ const sectionRoutesArr = Object.entries(sectionRoutes);
8
+ // loop through galleryItems object and build new object to handle subsections
9
+ sectionRoutes = sectionRoutesArr.reduce((acc, [navName, routeData]) => {
10
+ // exit immediately if current item is isSubsection flag
11
+ if (navName === 'isSubsection') {
12
+ return acc;
13
+ }
14
+ // add current item
15
+ if (includeSubsections || !routeData.isSubsection) {
16
+ acc[navName] = routeData;
17
+ }
18
+ // drill down into current item if subsection and parseSubsections === true
19
+ if (parseSubsections && routeData.isSubsection) {
20
+ // loop through each subsection item & add
21
+ Object.entries(routeData).map(([subitemName, subitemData]) => {
22
+ if (subitemName !== 'isSubsection') {
23
+ acc[subitemName] = subitemData;
24
+ }
25
+ })
26
+ }
27
+ return acc;
28
+ }, {})
29
+ }
30
+
31
+ const [searchTerm, setSearchTerm] = React.useState('');
32
+ const [layoutView, setLayoutView] = React.useState('grid');
33
+ const filteredItems = Object.entries(sectionRoutes)
34
+ .filter(([itemName, { slug }]) => (
35
+ // exclude current gallery page from results
36
+ slug !== location.pathname &&
37
+ itemName
38
+ .toLowerCase()
39
+ .includes(searchTerm.toLowerCase())
40
+ ));
41
+ const sectionGalleryItems = filteredItems
42
+ .sort(([itemName1], [itemName2]) => itemName1.localeCompare(itemName2))
43
+ .map(([itemName, itemData], idx) => {
44
+ // Convert to lowercase-camelcase ex: File upload - multiple ==> file_upload_multiple
45
+ const illustrationName = itemName
46
+ .replace('-', '')
47
+ .replace(' ',' ')
48
+ .split(' ')
49
+ .join('_')
50
+ .toLowerCase();
51
+ const illustration = illustrations[illustrationName] || illustrations.default_placeholder;
52
+ const { title, id, sources, isSubsection = false } = itemData;
53
+ // Display beta label if tab other than a '-next' tab is marked Beta
54
+ const isBeta = !isSubsection && sources && sources.some(src => src.beta && !src.source.includes('-next'));
55
+ let slug = itemData.slug;
56
+ if (!slug && isSubsection) {
57
+ // Update slug to link to first page in subsection
58
+ const subsectionItems = Object.entries(itemData).filter(([name, _data]) => name !== 'isSubsection');
59
+ const sortedSubsectionItems = subsectionItems.sort((
60
+ [name1, {sortValue: sortValue1 = 50}],
61
+ [name2, {sortValue: sortValue2 = 50}]
62
+ ) => {
63
+ if (sortValue1 === sortValue2) {
64
+ return name1.localeCompare(name2);
65
+ }
66
+ return sortValue1 > sortValue2 ? 1 : -1;
67
+ });
68
+ const firstSubsectionItem = sortedSubsectionItems[0];
69
+ slug = firstSubsectionItem[1].slug;
70
+ }
71
+
72
+ return {
73
+ idx,
74
+ slug,
75
+ itemName,
76
+ illustration,
77
+ isBeta,
78
+ title,
79
+ id,
80
+ galleryItemsData
81
+ };
82
+ });
83
+
84
+ return (
85
+ <div className="ws-section-gallery">
86
+ { children(sectionGalleryItems, searchTerm, setSearchTerm, layoutView, setLayoutView) }
87
+ </div>
88
+ )
89
+ };
@@ -1,21 +1,21 @@
1
- .ws-page-sidebar .pf-c-nav {
2
- --pf-c-nav__link--before--BorderBottomWidth: 0;
3
- --pf-c-nav--m-light__link--hover--BackgroundColor: var(--pf-global--BackgroundColor--light-200);
4
- --pf-c-nav--m-light__link--focus--BackgroundColor: var(--pf-global--BackgroundColor--light-200);
5
- --pf-c-nav--m-light__link--m-current--BackgroundColor: var(--pf-global--BackgroundColor--light-200);
6
- --pf-c-nav--m-light__link--active--BackgroundColor: var(--pf-global--BackgroundColor--light-200);
7
- --pf-c-nav__link--m-current--BackgroundColor: var(--pf-global--BackgroundColor--200);
1
+ .ws-page-sidebar .pf-v5-c-nav {
2
+ --pf-v5-c-nav__link--before--BorderBottomWidth: 0;
3
+ --pf-v5-c-nav--m-light__link--hover--BackgroundColor: var(--pf-v5-global--BackgroundColor--light-200);
4
+ --pf-v5-c-nav--m-light__link--focus--BackgroundColor: var(--pf-v5-global--BackgroundColor--light-200);
5
+ --pf-v5-c-nav--m-light__link--m-current--BackgroundColor: var(--pf-v5-global--BackgroundColor--light-200);
6
+ --pf-v5-c-nav--m-light__link--active--BackgroundColor: var(--pf-v5-global--BackgroundColor--light-200);
7
+ --pf-v5-c-nav__link--m-current--BackgroundColor: var(--pf-v5-global--BackgroundColor--200);
8
8
  }
9
9
 
10
- .ws-side-nav-list .pf-c-nav__item.pf-m-expandable::before {
10
+ .ws-side-nav-list .pf-v5-c-nav__item.pf-m-expandable::before {
11
11
  border-bottom: 0;
12
12
  }
13
13
 
14
- .pf-c-nav__subsection-title {
15
- color: var(--ws-toc-link--Color, var(--pf-global--Color--300));
16
- font-size: var(--pf-global--FontSize--sm);
14
+ .pf-v5-c-nav__subsection-title {
15
+ color: var(--ws-toc-link--Color, var(--pf-v5-global--Color--300));
16
+ font-size: var(--pf-v5-global--FontSize--sm);
17
17
  }
18
18
 
19
19
  #ws-sticky-nav-tabs {
20
- z-index: var(--pf-global--ZIndex--2xl);
20
+ z-index: var(--pf-v5-global--ZIndex--2xl);
21
21
  }
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { Link } from '../link/link';
3
- import { Nav, NavList, NavExpandable, PageContextConsumer, capitalize } from '@patternfly/react-core';
3
+ import { Label, Nav, NavList, NavExpandable, PageContextConsumer, capitalize, Flex, FlexItem } from '@patternfly/react-core';
4
4
  import { css } from '@patternfly/react-styles';
5
5
  import { Location } from '@reach/router';
6
6
  import { makeSlug } from '../../helpers';
@@ -12,26 +12,39 @@ const getIsActive = (location, section, subsection = null) => {
12
12
  return location.pathname.startsWith(`${process.env.pathPrefix}${slug}`);
13
13
  }
14
14
 
15
- const NavItem = ({ text, href }) => {
15
+ const defaultValue = 50;
16
+
17
+ const NavItem = ({ text, href, isDeprecated, isBeta, isDemo }) => {
16
18
  const isMobileView = window.innerWidth < Number.parseInt(globalBreakpointXl.value, 10);
17
19
  return (
18
20
  <PageContextConsumer key={href + text}>
19
21
  {({onNavToggle, isNavOpen }) => (
20
- <li key={href + text} className="pf-c-nav__item" onClick={() => isMobileView && onNavToggle()}>
22
+ <li key={href + text} className="pf-v5-c-nav__item" onClick={() => isMobileView && onNavToggle && onNavToggle()}>
21
23
  <Link
22
24
  to={href}
23
25
  getProps={({ isCurrent, href, location }) => {
24
26
  const { pathname } = location;
25
27
  return {
26
28
  className: css(
27
- 'pf-c-nav__link',
29
+ 'pf-v5-c-nav__link',
28
30
  (isCurrent || pathname.startsWith(href + '/')) && 'pf-m-current'
29
31
  )
30
32
  }}
31
33
  }
32
34
  tabIndex={isNavOpen ? undefined : -1}
33
35
  >
34
- {text}
36
+ <Flex spaceItems={{ default: 'spaceItemsSm'}}>
37
+ <FlexItem>{text}</FlexItem>
38
+ {(isBeta || isDemo || isDeprecated) && (
39
+ <FlexItem>
40
+ {isBeta && (<Label color="blue" isCompact>Beta</Label>)}
41
+ {!isBeta && isDeprecated && (<Label color="grey" isCompact>Deprecated</Label>)}
42
+ {!isBeta && !isDeprecated && isDemo && (<Label color="purple" isCompact>Demo</Label>)}
43
+ </FlexItem>
44
+ )}
45
+ </Flex>
46
+
47
+
35
48
  </Link>
36
49
  </li>
37
50
  )}
@@ -67,14 +80,29 @@ const ExpandableNav = ({groupedRoutes, location, section, subsection = null}) =>
67
80
  }}
68
81
  >
69
82
  {Object.entries(routes || {})
70
- .filter(([id, { hideNavItem }]) => !Boolean(hideNavItem) && (id !== 'isSubsection'))
71
- .map(([id, { slug, isSubsection = false }]) => ({ text: id, href: slug, isSubsection }))
72
- .sort(({ text: text1 }, { text: text2 }) => text1.localeCompare(text2))
83
+ .filter(([id, navObj]) => !Boolean(navObj.hideNavItem) && (Object.entries(navObj).length > 0))
84
+ .map(([id, { slug, isSubsection = false, sortValue = defaultValue, subsectionSortValue = defaultValue, sources }]) => ({ text: id, href: slug, isSubsection, sortValue: (isSubsection ? subsectionSortValue : sortValue), sources }))
85
+ .sort(({text: text1, sortValue: sortValue1}, {text: text2, sortValue: sortValue2}) => {
86
+ if (sortValue1 === sortValue2) {
87
+ return text1.localeCompare(text2);
88
+ }
89
+ return sortValue1 > sortValue2 ? 1 : -1;
90
+ })
73
91
  .map(navObj => navObj.isSubsection
74
- ? ExpandableNav({groupedRoutes, location, section, subsection: navObj.text})
75
- : NavItem(navObj)
76
- )
77
- }
92
+ ? ExpandableNav({groupedRoutes, location, section, subsection: navObj.text})
93
+ : NavItem({
94
+ ...navObj,
95
+ isDeprecated: navObj.href?.includes('components') && navObj.sources.some(source => (
96
+ source.source === "react-deprecated" || source.source === "html-deprecated")
97
+ && !navObj.sources.some(source => source.source === "react" || source.source === "html")
98
+ ),
99
+ isBeta: navObj.sources.some(source => source.beta),
100
+ isDemo: navObj.sources.some(source => (
101
+ source.source === "react-demos" || source.source === "html-demos")
102
+ && !navObj.sources.some(source => source.source === "react" || source.source === "html")
103
+ )
104
+ })
105
+ )}
78
106
  </NavExpandable>
79
107
  );
80
108
  }
@@ -94,7 +122,7 @@ export const SideNav = ({ groupedRoutes = {}, navItems = [] }) => {
94
122
  lastElement.scrollIntoView({ block: 'center' });
95
123
  }
96
124
  }, []);
97
-
125
+
98
126
  return (
99
127
  <Nav aria-label="Side Nav" theme="light">
100
128
  <NavList className="ws-side-nav-list">