Skip to content

Commit 7871f1c

Browse files
fix: Updates overview pages across website. (#4880)
* fix: Updates foudnation and styles overview page. * fix: Update extensions overview * fix: Updates patterns overview * fix: Update AI and content design overview pages. * Finishes top-level overview pages * Fix build error * Update charts overview and revert styles directory to try and fix build issue * fix: put back a few files to see if it fixes the build * Revert chart colors page name for now --------- Co-authored-by: nicolethoen <[email protected]>
1 parent 81261fa commit 7871f1c

File tree

150 files changed

+941
-638
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

150 files changed

+941
-638
lines changed

packages/documentation-framework/components/sectionGallery/sectionGallery.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ export const SectionGallery = ({
3535
hasGridImages = true,
3636
hasListText = true,
3737
hasListImages = true,
38-
isFullWidth = true
38+
isFullWidth = true,
39+
onlyShowInGalleryData = false
3940
}) => (
4041
<SectionGalleryWrapper
4142
illustrations={illustrations}
@@ -46,6 +47,7 @@ export const SectionGallery = ({
4647
galleryItemsData={galleryItemsData}
4748
initialLayout={initialLayout}
4849
isFullWidth={isFullWidth}
50+
onlyShowInGalleryData={onlyShowInGalleryData}
4951
>
5052
{(sectionGalleryItems, searchTerm, setSearchTerm, layoutView, setLayoutView) => (
5153
<>

packages/documentation-framework/components/sectionGallery/sectionGalleryWrapper.js

Lines changed: 138 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,26 @@ import React from 'react';
22
import { useLocation } from '@reach/router';
33
import { groupedRoutes } from '../../routes';
44

5+
/**
6+
* Converts a hyphenated or lowercase string to sentence case
7+
* Example: "design-tokens" -> "Design tokens"
8+
* Example: "colors" -> "Colors"
9+
*/
10+
const toSentenceCase = (str) => {
11+
if (!str) return str;
12+
return str
13+
.split('-')
14+
.map((word, index) => {
15+
if (index === 0) {
16+
// Capitalize first letter of first word only
17+
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
18+
}
19+
// Keep all other words lowercase
20+
return word.toLowerCase();
21+
})
22+
.join(' ');
23+
};
24+
525
export const SectionGalleryWrapper = ({
626
section,
727
subsection,
@@ -11,6 +31,7 @@ export const SectionGalleryWrapper = ({
1131
parseSubsections,
1232
initialLayout,
1333
isFullWidth,
34+
onlyShowInGalleryData = false,
1435
children,
1536
}) => {
1637
let sectionRoutes = subsection
@@ -24,12 +45,50 @@ export const SectionGalleryWrapper = ({
2445
</div>
2546
);
2647
}
27-
if (!includeSubsections || parseSubsections) {
48+
49+
// If includeSubsections is true and we're at the section level (not a specific subsection),
50+
// we need to include subsections themselves as items (not their contents)
51+
if (includeSubsections && !subsection && groupedRoutes[section]) {
52+
const allRoutes = {};
53+
// First, add top-level items (non-subsections)
54+
Object.entries(sectionRoutes).forEach(([navName, routeData]) => {
55+
if (navName === 'isSubsection' || navName === 'sortValue' || navName === 'subsectionSortValue') {
56+
return;
57+
}
58+
if (typeof routeData !== 'object' || routeData === null) {
59+
return;
60+
}
61+
// Only add if it's not a subsection
62+
if (!routeData.isSubsection) {
63+
allRoutes[navName] = routeData;
64+
}
65+
});
66+
67+
// Then, add subsections themselves as single items (not their contents)
68+
Object.entries(groupedRoutes[section]).forEach(([navName, routeData]) => {
69+
if (navName === 'isSubsection' || navName === 'sortValue' || navName === 'subsectionSortValue') {
70+
return;
71+
}
72+
if (typeof routeData !== 'object' || routeData === null) {
73+
return;
74+
}
75+
// If this is a subsection, add the subsection itself as an item
76+
if (routeData.isSubsection) {
77+
allRoutes[navName] = routeData;
78+
}
79+
});
80+
81+
sectionRoutes = allRoutes;
82+
} else if (!includeSubsections || parseSubsections) {
2883
const sectionRoutesArr = Object.entries(sectionRoutes);
2984
// loop through galleryItems object and build new object to handle subsections
3085
sectionRoutes = sectionRoutesArr.reduce((acc, [navName, routeData]) => {
31-
// exit immediately if current item is isSubsection flag
32-
if (navName === 'isSubsection') {
86+
// exit immediately if current item is isSubsection flag or other metadata properties
87+
if (navName === 'isSubsection' || navName === 'sortValue' || navName === 'subsectionSortValue') {
88+
return acc;
89+
}
90+
// Skip primitive values (metadata properties like sortValue are numbers)
91+
if (typeof routeData !== 'object' || routeData === null) {
3392
return acc;
3493
}
3594
// add current item
@@ -40,8 +99,11 @@ export const SectionGalleryWrapper = ({
4099
if (parseSubsections && routeData.isSubsection) {
41100
// loop through each subsection item & add
42101
Object.entries(routeData).map(([subitemName, subitemData]) => {
43-
if (subitemName !== 'isSubsection') {
44-
acc[subitemName] = subitemData;
102+
if (subitemName !== 'isSubsection' && subitemName !== 'sortValue' && subitemName !== 'subsectionSortValue') {
103+
// Skip primitive values
104+
if (typeof subitemData === 'object' && subitemData !== null) {
105+
acc[subitemName] = subitemData;
106+
}
45107
}
46108
});
47109
}
@@ -53,11 +115,32 @@ export const SectionGalleryWrapper = ({
53115
const [searchTerm, setSearchTerm] = React.useState('');
54116
const [layoutView, setLayoutView] = React.useState(initialLayout);
55117
const filteredItems = Object.entries(sectionRoutes).filter(
56-
([itemName, { slug }]) =>
118+
([itemName, itemData]) => {
119+
// Skip metadata properties
120+
if (itemName === 'isSubsection' || itemName === 'sortValue' || itemName === 'subsectionSortValue') {
121+
return false;
122+
}
123+
// Skip primitive values (metadata properties)
124+
if (typeof itemData !== 'object' || itemData === null) {
125+
return false;
126+
}
127+
// For subsections, slug will be computed later from first page
128+
// For regular items, they must have a slug
129+
if (!itemData.isSubsection && !itemData.slug) {
130+
return false;
131+
}
132+
const slug = itemData.slug;
133+
// For subsections without slug yet, we'll compute it later, so don't filter by slug
134+
if (!slug) {
135+
return itemName.toLowerCase().includes(searchTerm.toLowerCase());
136+
}
57137
// exclude current gallery page from results - check for trailing /
58-
!location.pathname.endsWith(slug) &&
59-
!location.pathname.endsWith(`${slug}/`) &&
60-
itemName.toLowerCase().includes(searchTerm.toLowerCase())
138+
return (
139+
!location.pathname.endsWith(slug) &&
140+
!location.pathname.endsWith(`${slug}/`) &&
141+
itemName.toLowerCase().includes(searchTerm.toLowerCase())
142+
);
143+
}
61144
);
62145
const sectionGalleryItems = filteredItems
63146
.sort(([itemName1], [itemName2]) => itemName1.localeCompare(itemName2))
@@ -76,8 +159,35 @@ export const SectionGalleryWrapper = ({
76159
}
77160
const { sources, isSubsection = false } = itemData;
78161
// Subsections don't have title or id, default to itemName aka sidenav text
79-
const title = itemData.title || itemName;
80-
const id = itemData.id || title;
162+
// Convert itemName to sentence case if no title is provided
163+
let title = itemData.title || toSentenceCase(itemName);
164+
let id = itemData.id || title;
165+
166+
// For extensions section, try to extract extension name from slug to match JSON keys
167+
// This handles cases where extensions have id: Overview or other IDs but we need to match JSON keys
168+
// The JSON keys are dasherized (e.g., "component-groups"), so we extract from slug
169+
if (section === 'extensions' && itemData.slug && galleryItemsData) {
170+
// Extract extension name from slug like /extensions/topology/overview -> topology
171+
// or /extensions/component-groups/overview -> component-groups
172+
// Also handle /extensions/react-topology/... -> topology (remove react- prefix)
173+
const slugParts = itemData.slug.split('/').filter(Boolean);
174+
if (slugParts.length >= 2 && slugParts[0] === 'extensions') {
175+
let extensionName = slugParts[1]; // e.g., "component-groups" or "react-topology"
176+
// Remove "react-" prefix if present (e.g., "react-topology" -> "topology")
177+
if (extensionName.startsWith('react-')) {
178+
extensionName = extensionName.replace(/^react-/, '');
179+
}
180+
// Check if this extension name exists in galleryItemsData
181+
if (galleryItemsData[extensionName]) {
182+
// Use extension name as id for JSON lookup (TextSummary converts to dasherized)
183+
id = extensionName;
184+
// Update title to extension name in sentence case if id was "Overview" or matches itemName
185+
if (itemData.id === 'Overview' || itemName === 'Overview' || !itemData.title) {
186+
title = toSentenceCase(extensionName);
187+
}
188+
}
189+
}
190+
}
81191
// Display beta label if tab other than a '-next' tab is marked Beta
82192
const isDeprecated =
83193
!isSubsection &&
@@ -138,6 +248,23 @@ export const SectionGalleryWrapper = ({
138248
id,
139249
galleryItemsData,
140250
};
251+
})
252+
.filter((item) => {
253+
// If onlyShowInGalleryData is true, filter to only items that exist in galleryItemsData
254+
if (!onlyShowInGalleryData || !galleryItemsData) {
255+
return true;
256+
}
257+
// Try matching by itemName first (already in dasherized format from routes)
258+
if (galleryItemsData[item.itemName]) {
259+
return true;
260+
}
261+
// Convert id to dasherized format to match JSON keys (lowercase, spaces to hyphens)
262+
const dasherizedId = item.id
263+
.split(' ')
264+
.join('-')
265+
.toLowerCase();
266+
// Check if this item exists in galleryItemsData
267+
return galleryItemsData[dasherizedId] !== undefined;
141268
});
142269

143270
return (

packages/documentation-site/patternfly-docs/content/AI/about-generative-ui.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@ import { Alert } from "@patternfly/react-core";
1010

1111
## What is generative UI?
1212

13-
Generative UI (GenUI) refers to a user interface design approach where AI is leveraged to dynamically create and adapt UI elements based on context, user needs, and data. Unlike traditional, static UIs, GenUI can produce layouts, components, and visual styles in real-time, offering more flexible and personalized user experiences.
13+
**Generative UI (GenUI)** refers to a user interface design approach where AI is leveraged to dynamically create and adapt UI elements based on context, user needs, and data. Unlike traditional, static UIs, GenUI can produce layouts, components, and visual styles in real-time, offering more flexible and personalized user experiences.
1414

15-
## PatternFly's exploration: Compass
15+
---
16+
17+
## Compass: PatternFly's GenUI exploration
1618

1719
Generative UI represents a significant opportunity for PatternFly to explore new patterns, layouts, and styles that support AI-driven interface generation. PatternFly has been calling this proof of concept Compass. It investigates how the design system can evolve to support generative UI use cases.
1820

19-
<Alert isInline variant="info" title="Compass is best suited for use as a POC in other proof-of-concept generative UI use cases. It is not yet production quality code and should be used for exploration and experimentation purposes only." />
21+
<Alert isInline variant="info" title="Beta feature">Compass is best suited for use as a POC in other proof-of-concept generative UI use cases. It is not yet production quality code and should be used for exploration and experimentation purposes only.</Alert>
2022

2123
### AI-enabled seed app
2224

0 commit comments

Comments
 (0)