diff --git a/src/components/NavEntry.tsx b/src/components/NavEntry.tsx index a2319d3..9751ba2 100644 --- a/src/components/NavEntry.tsx +++ b/src/components/NavEntry.tsx @@ -6,6 +6,8 @@ export interface TextContentEntry { data: { id: string section: string + tab?: string + sortValue?: number } } @@ -22,6 +24,7 @@ export const NavEntry = ({ entry, isActive }: NavEntryProps) => { section === 'components' || section === 'layouts' ? kebabCase(entryTitle) : id + return ( { const entries = navDataRaw .filter((entry) => entry.data.section === section) - .map(entry => ({ id: entry.id, data: { id: entry.data.id, section }} as TextContentEntry)) + .map(entry => ({ id: entry.id, data: { id: entry.data.id, section, sortValue: entry.data.sortValue }} as TextContentEntry)) - const sortedEntries = entries.sort((a, b) => - a.data.id.localeCompare(b.data.id), - ) - - let navEntries = sortedEntries + let uniqueEntries = entries if (section === 'components' || section === 'layouts') { // only display unique entry.data.id in the nav list if the section is components - navEntries = [ - ...sortedEntries + uniqueEntries = [ + ...entries .reduce((map, entry) => { if (!map.has(entry.data.id)) { map.set(entry.data.id, entry) @@ -61,7 +57,18 @@ sortedSections.map((section) => { ] } - navData[section] = navEntries; + // Sort alphabetically, unless a sort value is specified in the frontmatter + const sortedUniqueEntries = uniqueEntries.sort((a, b) => { + if (a.data.sortValue || b.data.sortValue) { + const aSortOrder = a.data.sortValue || 50 + const bSortOrder = b.data.sortValue || 50 + + return aSortOrder - bSortOrder + } + return a.data.id.localeCompare(b.data.id) + }) + + navData[section] = sortedUniqueEntries; }) --- diff --git a/src/components/section-gallery/SectionGallery.astro b/src/components/section-gallery/SectionGallery.astro new file mode 100644 index 0000000..ecee818 --- /dev/null +++ b/src/components/section-gallery/SectionGallery.astro @@ -0,0 +1,19 @@ +--- +import { SectionGallery as SectionGalleryBase } from './SectionGallery' + +const { illustrations, section, galleryItemsData, placeholderText, countText, initialLayout, hasGridText, hasGridImages, hasListText, hasListImages } = Astro.props +--- + + diff --git a/src/components/section-gallery/SectionGallery.css b/src/components/section-gallery/SectionGallery.css new file mode 100644 index 0000000..8e38a8c --- /dev/null +++ b/src/components/section-gallery/SectionGallery.css @@ -0,0 +1,20 @@ +/* Toolbar styles */ +.ws-section-gallery .pf-v6-c-toolbar { + margin-block-end: var(--pf-t--global--spacer--md); +} + +/* Avoid link styling on gallery/data list item names */ +.ws-section-gallery-item { + text-decoration: inherit; + color: inherit; +} + +/* Ensure cards within a row stretch vertically to fill row height */ +.ws-section-gallery .pf-v6-c-card { + height: 100%; +} + +/* Limit width for data list view only */ +.ws-section-gallery .pf-v6-c-data-list { + max-width: var(--pf-t--global--breakpoint--lg); +} diff --git a/src/components/section-gallery/SectionGallery.tsx b/src/components/section-gallery/SectionGallery.tsx new file mode 100644 index 0000000..3d02c90 --- /dev/null +++ b/src/components/section-gallery/SectionGallery.tsx @@ -0,0 +1,111 @@ +import { useState } from 'react' + +import { SectionGalleryToolbar } from './SectionGalleryToolbar' +import { SectionGalleryGridLayout } from './SectionGalleryGridLayout' +import { SectionGalleryListLayout } from './SectionGalleryListLayout' +import { snakeCase } from 'change-case' + +import './SectionGallery.css' + +export interface SectionGalleryItem { + /** Name of the gallery item. Should match the page name of the item for routing, or an item should provide a link property in the SectionGalleryItemData. */ + name: string + /** Image file import */ + img: any + /** Data of the gallery item */ + data: SectionGalleryItemData +} + +export interface SectionGalleryItemData { + /** Path to the item illustration */ // TODO: remove if img method is fine + illustration: string + /** Summary text of the item */ + summary: string + /** Label included in the item footer. Choose from a preset or pass a custom label. */ + label?: 'beta' | 'demo' | 'deprecated' + /** Link to the item, relative to the section, e.g. "/{section}/{page}" */ + link?: string +} + +interface SectionGalleryProps { + /** Collection of illustations for the gallery */ + illustrations?: any + /** Section where the gallery is located */ + section: string + /** Data of all gallery items */ + galleryItemsData: Record + /** Placeholder text for the gallery search input */ + placeholderText?: string + /** Text for the amount of gallery items */ + countText?: string + /** Starting layout for the gallery */ + initialLayout?: 'grid' | 'list' + /** Indicates the grid layout has item summary text */ + hasGridText?: boolean + /** Indicates the grid layout has item images */ + hasGridImages?: boolean + /** Indicates the list layout has item summary text */ + hasListText?: boolean + /** Indicates the list layout has item images */ + hasListImages?: boolean +} + +export const SectionGallery = ({ + illustrations, + section, + galleryItemsData, + placeholderText, + countText, + initialLayout = 'grid', + hasGridText = false, + hasGridImages = false, + hasListText = false, + hasListImages = false, +}: SectionGalleryProps) => { + const [searchTerm, setSearchTerm] = useState('') + const [layoutView, setLayoutView] = useState(initialLayout) + + const galleryItems: SectionGalleryItem[] = Object.entries(galleryItemsData) + .map(([galleryItem, galleryItemData]) => ({ + name: galleryItem, + img: illustrations ? illustrations[snakeCase(galleryItem)] : undefined, + data: galleryItemData, + })) + .sort((item1, item2) => item1.name.localeCompare(item2.name)) + + const nonCharsRegex = /[^A-Z0-9]+/gi + const filteringTerm = searchTerm.replace(nonCharsRegex, '') + const filteredItems: SectionGalleryItem[] = galleryItems.filter((item) => + new RegExp(filteringTerm).test(item.name.replace(nonCharsRegex, '')), + ) + + return ( +
+ + {layoutView === 'grid' && ( + + )} + {layoutView === 'list' && ( + + )} +
+ ) +} diff --git a/src/components/section-gallery/SectionGalleryGridLayout.tsx b/src/components/section-gallery/SectionGalleryGridLayout.tsx new file mode 100644 index 0000000..e19e3d7 --- /dev/null +++ b/src/components/section-gallery/SectionGalleryGridLayout.tsx @@ -0,0 +1,97 @@ +import React from 'react' +import { + Gallery, + GalleryItem, + Card, + CardHeader, + CardTitle, + CardBody, + CardFooter, + Label, + Content, +} from '@patternfly/react-core' +import { SectionGalleryItem } from './SectionGallery' +import { sentenceCase } from 'change-case' +import { convertToReactComponent } from '@patternfly/ast-helpers' + +interface SectionGalleryGridLayoutProps { + /** Section where the gallery is located */ + section: string + /** List of gallery items */ + galleryItems: SectionGalleryItem[] + /** Indicates the grid layout has item summary text */ + hasGridText: boolean + /** Indicates the grid layout has item images */ + hasGridImages: boolean +} + +export const SectionGalleryGridLayout = ({ + section, + galleryItems, + hasGridText, + hasGridImages, +}: SectionGalleryGridLayoutProps) => ( + + {galleryItems.map(({ name, img, data }, idx) => { + const itemLink = data.link || `/${section}/${name}` + + //TODO: rethink how JSX / enriched content is passed to framework + const summaryNoLinks = data.summary.replace( + /]*>([^<]+)<\/a>/gm, + '$1', + ) + const { code } = convertToReactComponent(`<>${summaryNoLinks}`) + const getSummaryComponent = new Function('React', code) + + return ( + + + + {sentenceCase(name)} + + {(hasGridImages || hasGridText) && ( + + {hasGridImages && img && ( + {`${name} // verify whether this img.src approach is correct + )} + {hasGridText && ( + + + {getSummaryComponent(React)} + + + )} + + )} + {data.label && ( + + {data.label === 'beta' && ( + + )} + {data.label === 'deprecated' && ( + + )} + {data.label === 'demo' && ( + + )} + + )} + + + ) + })} + +) diff --git a/src/components/section-gallery/SectionGalleryListLayout.tsx b/src/components/section-gallery/SectionGalleryListLayout.tsx new file mode 100644 index 0000000..eac04ad --- /dev/null +++ b/src/components/section-gallery/SectionGalleryListLayout.tsx @@ -0,0 +1,108 @@ +import React from 'react' +import { + DataList, + DataListItem, + DataListItemRow, + DataListItemCells, + DataListCell, + Split, + SplitItem, + Label, + Content, + ContentVariants, +} from '@patternfly/react-core' +import { SectionGalleryItem } from './SectionGallery' +import { sentenceCase } from 'change-case' +import { convertToReactComponent } from '@patternfly/ast-helpers' + +interface SectionGalleryListLayoutProps { + /** Section where the gallery is located */ + section: string + /** List of gallery items */ + galleryItems: SectionGalleryItem[] + /** Indicates the list layout has item summary text */ + hasListText: boolean + /** Indicates the list layout has item images */ + hasListImages: boolean +} + +export const SectionGalleryListLayout = ({ + section, + galleryItems, + hasListText, + hasListImages, +}: SectionGalleryListLayoutProps) => ( + {}} aria-label="gallery-list"> + {galleryItems.map(({ name, img, data }, idx) => { + const itemLink = data.link || `/${section}/${name}` + + //TODO: rethink how JSX / enriched content is passed to framework + const summaryNoLinks = data.summary.replace( + /]*>([^<]+)<\/a>/gm, + '$1', + ) + const { code } = convertToReactComponent(`<>${summaryNoLinks}`) + const getSummaryComponent = new Function('React', code) + + return ( + + + + +
+ {`${name} +
+ + ), + + + + + + {sentenceCase(name)} + + + + + {data.label === 'beta' && ( + + )} + {data.label === 'deprecated' && ( + + )} + {data.label === 'demo' && ( + + )} + + + {hasListText && ( + + + {getSummaryComponent(React)} + + + )} + , + ]} + /> +
+
+
+ ) + })} +
+) diff --git a/src/components/section-gallery/SectionGalleryToolbar.tsx b/src/components/section-gallery/SectionGalleryToolbar.tsx new file mode 100644 index 0000000..b581c9e --- /dev/null +++ b/src/components/section-gallery/SectionGalleryToolbar.tsx @@ -0,0 +1,93 @@ +import { CSSProperties, Dispatch, SetStateAction } from 'react' +import { + Button, + SearchInput, + Toolbar, + ToolbarContent, + ToolbarItem, + Content, + ContentVariants, + ToggleGroup, + ToggleGroupItem, +} from '@patternfly/react-core' +import ListIcon from '@patternfly/react-icons/dist/esm/icons/list-icon' +import ThIcon from '@patternfly/react-icons/dist/esm/icons/th-icon' + +interface SectionGalleryToolbarProps { + /** Total count of gallery items */ + galleryItemCount: number + /** Current search term */ + searchTerm: string + /** Setter for search term */ + setSearchTerm: Dispatch> + /** Current layout */ + layoutView: 'grid' | 'list' + /** Setter for layout */ + setLayoutView: Dispatch> + /** Placeholder text for the gallery search input */ + placeholderText?: string + /** Text for the amount of gallery items */ + countText?: string +} + +export const SectionGalleryToolbar = ({ + galleryItemCount, + searchTerm, + setSearchTerm, + layoutView, + setLayoutView, + placeholderText = 'Search by name', + countText = ' items', +}: SectionGalleryToolbarProps) => ( + + + + { + setSearchTerm(val) + }} + /> + + {searchTerm && ( + + + + )} + + + } + aria-label="grid icon button" + isSelected={layoutView === 'grid'} + onChange={() => setLayoutView('grid')} + > + } + aria-label="list icon button" + isSelected={layoutView === 'list'} + onChange={() => setLayoutView('list')} + > + + + + + {galleryItemCount} + {countText} + + + + +) diff --git a/src/content.config.ts b/src/content.config.ts index 5e0a1c5..c0fbadf 100644 --- a/src/content.config.ts +++ b/src/content.config.ts @@ -28,7 +28,8 @@ function defineContent(contentObj: CollectionDefinition) { subsection: z.string().optional(), title: z.string().optional(), propComponents: z.array(z.string()).optional(), - tab: z.string().optional().default(tabMap[name]), + tab: z.string().optional().default(tabMap[name]), // for component tabs + sortValue: z.number().optional(), // used for sorting nav entries, cssPrefix: z .union([ z.string().transform((val) => [val]), diff --git a/src/pages/[section]/[...page].astro b/src/pages/[section]/[...page].astro index 7ea8b78..5fca8e4 100644 --- a/src/pages/[section]/[...page].astro +++ b/src/pages/[section]/[...page].astro @@ -1,12 +1,13 @@ --- import { getCollection, render } from 'astro:content' -import { Title, Stack, StackItem } from '@patternfly/react-core' +import { Title, PageSection, Stack, StackItem } from '@patternfly/react-core' import MainLayout from '../../layouts/Main.astro' import { content } from '../../content' import { kebabCase } from 'change-case' import { componentTabs } from '../../globals' import PropsTables from '../../components/PropsTables.astro' import CSSTable from '../../components/CSSTable.astro' +import SectionGallery from '../../components/section-gallery/SectionGallery.astro' export async function getStaticPaths() { const collections = await Promise.all( @@ -30,9 +31,8 @@ const { entry, propComponents, cssPrefix } = Astro.props const { title, id, section } = entry.data const { Content } = await render(entry) -if (section === 'components') { - // if section is components, rewrite to first tab content - return Astro.rewrite(`/components/${kebabCase(id)}/${componentTabs[id][0]}`) +if(section === 'components' && componentTabs[id]) { // if section is components & tab exists, rewrite to first tab content + return Astro.rewrite(`/components/${kebabCase(id)}/${componentTabs[id][0]}`); } --- @@ -44,13 +44,17 @@ if (section === 'components') { ) } - - - - - - - - - + + + + + + + + + + + diff --git a/src/pages/[section]/[page]/[...tab].astro b/src/pages/[section]/[page]/[...tab].astro index 5b64518..4ee2cc2 100644 --- a/src/pages/[section]/[page]/[...tab].astro +++ b/src/pages/[section]/[page]/[...tab].astro @@ -36,28 +36,25 @@ export async function getStaticPaths() { ), ) - const flatCol = collections.flat().map((entry) => { - // Build tabs dictionary - let tab = entry.data.tab - if (tab) { - // check for demos/deprecated - if (entry.id.includes('demos')) { - tab = `${tab}-demos` - } else if (entry.id.includes('deprecated')) { - tab = `${tab}-deprecated` + const flatCol = collections.flat() + .filter((entry) => entry.data.tab) // only pages with a tab should match this route + .map((entry) => { + // Build tabs dictionary + let tab = entry.data.tab; + if(tab) { // check for demos/deprecated + if(entry.id.includes('demos')) { + tab = `${tab}-demos`; + } else if (entry.id.includes('deprecated')) { + tab = `${tab}-deprecated`; + } } - } - buildTab(entry, tab) + buildTab(entry, tab); - return { - params: { - page: kebabCase(entry.data.id), - section: entry.data.section, - tab, - }, - props: { entry, ...entry.data }, - } - }) + return { + params: { page: kebabCase(entry.data.id), section: entry.data.section, tab }, + props: { entry, ...entry.data }, + } + }) sortTabs() return flatCol diff --git a/textContent/AllComponents.mdx b/textContent/AllComponents.mdx new file mode 100644 index 0000000..48869a4 --- /dev/null +++ b/textContent/AllComponents.mdx @@ -0,0 +1,16 @@ +--- +id: All components +title: All components +section: components +sortValue: 1 +--- + +import { componentsData } from './components-data.js' + + diff --git a/textContent/components-data.js b/textContent/components-data.js new file mode 100644 index 0000000..cd14f14 --- /dev/null +++ b/textContent/components-data.js @@ -0,0 +1,476 @@ +// Updated format for section gallery component data. Now is an object containing JSX, to avoid having to parse JSON into JSX +// Added the label & a optional fields +// illustration field may not be necessary now +export const componentsData = { + 'about-modal': { + illustration: './images/component-illustrations/about-modal.png', + summary: + 'An about modal displays information about an application, like product version numbers and any appropriate legal text.', + }, + accordion: { + illustration: './images/component-illustrations/accordion.png', + summary: + 'An accordion is a vertically stacked list that can be expanded and collapsed to reveal and hide nested content.', + }, + 'action-list': { + illustration: './images/component-illustrations/action-list.png', + summary: + 'An action list is a group of actions, controls, or buttons with built-in spacing.', + }, + alert: { + illustration: './images/component-illustrations/alert.png', + summary: + 'An alert is a non-intrusive notification that shares brief, important messages with users.', + }, + 'application-launcher': { + illustration: './images/component-illustrations/application-launcher.png', + summary: + 'An application launcher is a menu that allows users to launch a separate web application in a new browser window.', + label: 'demo', + }, + avatar: { + illustration: './images/component-illustrations/avatar.png', + summary: + 'An avatar is a visual representation of a user, which can contain an image or placeholder graphic.', + }, + 'back-to-top': { + illustration: './images/component-illustrations/back-to-top.png', + summary: + 'The back to top component is a shortcut that allows users to quickly navigate to the top of a page via a button.', + }, + backdrop: { + illustration: './images/component-illustrations/backdrop.png', + summary: + 'A backdrop is a screen that covers the main content of a page when a modal is opened, to prevent page interaction until the modal is dismissed.', + }, + 'background-image': { + illustration: './images/component-illustrations/background-image.png', + summary: + 'A background image is an image that fills the background of a page.', + }, + badge: { + illustration: './images/component-illustrations/badge.png', + summary: 'A badge is an annotation that displays a numeric value.', + }, + banner: { + illustration: './images/component-illustrations/banner.png', + summary: + 'A banner is a short message that is shared with users in an unobtrusive, full-width container that cannot be dismissed.', + }, + brand: { + illustration: './images/component-illustrations/brand.png', + summary: + 'A brand is a visual representation of a product—typically its logo.', + }, + breadcrumb: { + illustration: './images/component-illustrations/breadcrumb.png', + summary: + 'A breadcrumb is a secondary navigation method that shows where users are in an application, to help them navigate more efficiently.', + }, + button: { + illustration: './images/component-illustrations/button.png', + summary: + 'A button is an object that communicates and triggers an action when it is clicked or selected.', + }, + 'calendar-month': { + illustration: './images/component-illustrations/calendar-month.png', + summary: + 'A calendar month component allows users to select and navigate between days, months, and years.', + }, + card: { + illustration: './images/component-illustrations/card.png', + summary: + 'A card is a content container that displays entry-level information—typically within dashboards, galleries, and catalogs.', + }, + checkbox: { + illustration: './images/component-illustrations/checkbox.png', + summary: + 'A checkbox is an input control that allows users to select a single item or multiple items from a list.', + }, + chip: { + illustration: './images/component-illustrations/chip.png', + summary: + "A chip is used to communicate a value or a set of attribute-value pairs within workflows that involve filtering a set of objects.

Note: The chip component has been deprecated. Our new recommendation is to use the label component instead.", + label: 'deprecated', + }, + 'clipboard-copy': { + illustration: './images/component-illustrations/clipboard-copy.png', + summary: + 'The clipboard copy component allows users to quickly and easily copy content to their clipboard.', + }, + 'code-block': { + illustration: './images/component-illustrations/code-block.png', + summary: + "A code block contains 2 or more lines of read-only code, which can be copied to a user's clipboard.", + }, + 'code-editor': { + illustration: './images/component-illustrations/code-editor.png', + summary: + "A code editor is a versatile Monaco-based text editor that supports various programming languages.", + }, + content: { + illustration: './images/component-illustrations/context-selector.png', + summary: + 'A content component contains a block of styled HTML content.', + }, + 'context-selector': { + illustration: './images/component-illustrations/context-selector.png', + summary: + "A context selector is a dropdown menu placed in the global navigation, which allows you to switch a user's application context to display relevant data and resources.", + label: 'demo', + }, + 'custom-menus': { + illustration: './images/component-illustrations/custom-menus.png', + summary: + "Custom menus can be created to address a variety of unique use cases, by combining menus and menu toggles.", + label: 'demo', + }, + 'data-list': { + illustration: './images/component-illustrations/data-list.png', + summary: + 'A data list displays large data sets and interactive content in a flexible layout.', + }, + 'date-picker': { + illustration: './images/component-illustrations/date-picker.png', + summary: + 'A date picker allows users to either manually enter a date or select a date from a calendar.', + }, + 'date-and-time-picker': { + illustration: './images/component-illustrations/date-and-time-picker.png', + summary: + "A date and time picker allows users to select both a specific date and a time, by combining date picker and time picker components.", + label: 'demo', + }, + 'description-list': { + illustration: './images/component-illustrations/description-list.png', + summary: + 'A description list displays terms and their corresponding descriptions.', + }, + divider: { + illustration: './images/component-illustrations/divider.png', + summary: + 'A divider is a horizontal or vertical line that is placed between screen elements to create visual divisions and content groupings.', + }, + 'drag-and-drop': { + illustration: './images/component-illustrations/drag-and-drop.png', + summary: + 'The drag and drop component allows users to reposition, rearrange, and group items into more relevant and appropriate layouts.', + }, + drawer: { + illustration: './images/component-illustrations/drawer.png', + summary: + 'A drawer is a sliding panel that enters from outside of the viewport, which can be configured to either overlay content or create a sidebar by pushing content.', + }, + dropdown: { + illustration: './images/component-illustrations/dropdown.png', + summary: + 'A dropdown displays a menu of actions that trigger a process and as that navigate to a new location.', + label: 'beta', + }, + 'dual-list-selector': { + illustration: './images/component-illustrations/dual-list-selector.png', + summary: + 'A dual list selector displays 2 interactive lists: a list of selected items and a list of available, selectable items. Users can move items between the lists.', + }, + 'empty-state': { + illustration: './images/component-illustrations/empty-state.png', + summary: + 'An empty state is a screen that is not yet populated with data or information—typically containing a short message and next steps for users.', + }, + 'expandable-section': { + illustration: './images/component-illustrations/expandable-section.png', + summary: + 'An expandable section is a content section with a text toggle that reveals content that is hidden by default.', + }, + 'multiple-file-upload': { + illustration: './images/component-illustrations/file-upload-multiple.png', + summary: + 'A multiple file upload component allows users to select and upload multiple files to a specific location.', + }, + 'simple-file-upload': { + illustration: './images/component-illustrations/file-upload.png', + summary: + 'A simple file upload component allows users to select and upload a single file to a specific location.', + }, + 'form-control': { + illustration: './images/component-illustrations/form-control.png', + summary: + 'A form control is a form element that guides users and accepts user input, such as text areas and selection menus.', + }, + form: { + illustration: './images/component-illustrations/form.png', + summary: + 'A form is a group of related elements that allow users to provide data and configure options in a variety of contexts, such as within modals, wizards, and pages.', + }, + 'form-select': { + illustration: './images/component-illustrations/form-select.png', + summary: + 'A form select is a form element that embeds browser-native menus.', + }, + 'helper-text': { + illustration: './images/component-illustrations/helper-text.png', + summary: + 'Helper text is a text-based support method that adds additional context to field inputs.', + }, + hint: { + illustration: './images/component-illustrations/hint.png', + summary: + 'A hint is an in-app message that shares reminders, explanations, or calls to action within a page or modal.', + }, + icon: { + illustration: './images/component-illustrations/icon.png', + summary: + "An icon component is a container that supports icons of varying dimensions and styles, as well as spinners.", + }, + 'inline-edit': { + illustration: './images/component-illustrations/inline-edit.png', + summary: + 'An inline edit component allows users to switch between read-only and edits views of description lists, page text elements, or tables—within the context of their current view.', + }, + 'input-group': { + illustration: './images/component-illustrations/input-group.png', + summary: + 'An input group combines multiple related controls or inputs to appear as a single control.', + }, + 'jump-links': { + illustration: './images/component-illustrations/jump-links.png', + summary: + 'When clicked, jump links allow users to navigate to sections within a page without scrolling.', + }, + label: { + illustration: './images/component-illustrations/label.png', + summary: + 'A label is a descriptive annotation that adds context to an element for clarity and convenience.', + }, + list: { + illustration: './images/component-illustrations/list.png', + summary: + 'A list component embeds a formatted list—bulleted or numbered—into page content.', + }, + 'login-page': { + illustration: './images/component-illustrations/login-page.png', + summary: + 'A login page allows a user to access an application by entering a username and password, or by authenticating using a social media login.', + }, + masthead: { + illustration: './images/component-illustrations/masthead.png', + summary: + 'A masthead contains and organizes global properties like a logo, navigation, and settings for easy and consistent access across all pages of an application.', + }, + 'menu-toggle': { + illustration: './images/component-illustrations/menu-toggle.png', + summary: + 'A menu toggle is a selectable control that opens and closes a menu.', + }, + menu: { + illustration: './images/component-illustrations/menu.png', + summary: + 'A menu is a list of options or actions that users can choose from.', + }, + modal: { + illustration: './images/component-illustrations/modal.png', + summary: + 'A modal is a window that overlays a page to display important information, without requiring users to navigate to a new page.', + }, + navigation: { + illustration: './images/component-illustrations/navigation.png', + summary: + "A navigation component organizes and communicates an application's structure and content in a central location, making it easy to find information and accomplish tasks.", + }, + 'notification-badge': { + illustration: './images/component-illustrations/notification-badge.png', + summary: + 'A notification badge is a visual indicator that alerts users about incoming notifications.', + }, + 'notification-drawer': { + illustration: './images/component-illustrations/notification-drawer.png', + summary: + "A notification drawer contains an application's notifications, which users can view and manage without having to navigate to a new screen.", + }, + 'number-input': { + illustration: './images/component-illustrations/number-input.png', + summary: + 'A number input combines a text input field with buttons to provide users with a quick and effective way to enter and modify a numeric value.', + }, + 'options-menu': { + illustration: './images/component-illustrations/options-menu.png', + summary: 'An options menu contains a set of optional settings.', + label: 'demo', + }, + 'overflow-menu': { + illustration: './images/component-illustrations/overflow-menu.png', + summary: + 'An overflow menu groups a set of actions into a responsive horizontal list to help declutter the UI.', + }, + page: { + illustration: './images/component-illustrations/page.png', + summary: + 'A page component defines the basic layout of a page, with either vertical or horizontal navigation.', + }, + pagination: { + illustration: './images/component-illustrations/pagination.png', + summary: + 'A pagination component allows users to navigate through large content views that have been split across multiple pages.', + }, + panel: { + illustration: './images/component-illustrations/panel.png', + summary: + 'A panel is a customizable container that can contain other components in flexible content layouts.', + }, + 'password-generator': { + illustration: './images/component-illustrations/password-generator.png', + summary: + 'This demo demonstrates how to create an input field that generates unique passwords.', + label: 'demo', + }, + 'password-strength': { + illustration: './images/component-illustrations/password-strength.png', + summary: + 'This demo demonstrates how to validate and display feedback about password strength.', + label: 'demo', + }, + popover: { + illustration: './images/component-illustrations/popover.png', + summary: + 'A popover is a small overlay window that provides additional information about an on-screen element.', + }, + 'progress-stepper': { + illustration: './images/component-illustrations/progress-stepper.png', + summary: + "A progress stepper displays a timeline of tasks in a workflow and tracks a user's progress through the workflow.", + }, + progress: { + illustration: './images/component-illustrations/progress.png', + summary: + 'A progress component is a horizontal bar that indicates the completion status of an ongoing process or task.', + }, + radio: { + illustration: './images/component-illustrations/radio.png', + summary: + "A radio is a button that's used to present users with mutually exclusive choices.", + }, + 'search-input': { + illustration: './images/component-illustrations/search-input.png', + summary: + 'A search input is a type of input field that can be used to search, find, or filter.', + }, + select: { + illustration: './images/component-illustrations/select.png', + summary: + 'A select component is a menu that enables users to select 1 or more items from a list.', + label: 'beta', + }, + sidebar: { + illustration: './images/component-illustrations/sidebar.png', + summary: + 'A sidebar is a panel that splits content into a secondary area within a page.', + }, + 'simple-list': { + illustration: './images/component-illustrations/simple-list.png', + summary: 'A simple list displays selectable items within a page.', + }, + skeleton: { + illustration: './images/component-illustrations/skeleton.png', + summary: + 'A skeleton is a type of loading state that allows you to expose content incrementally.', + }, + 'skip-to-content': { + illustration: './images/component-illustrations/skip-to-content.png', + summary: + 'A skip to content component allows users to bypass navigation when using a screen reader or keyboard', + }, + slider: { + illustration: './images/component-illustrations/slider.png', + summary: + 'A slider is an interactive element that allows users to quickly set and adjust a numeric value from a defined range of values.', + }, + spinner: { + illustration: './images/component-illustrations/spinner.png', + summary: + 'A spinner is an animated visual that indicates when a quick action is in progress.', + }, + switch: { + illustration: './images/component-illustrations/switch.png', + summary: + 'A switch is a control that toggles the state of a setting between on and off.', + }, + 'tab-content': { + illustration: './images/component-illustrations/tab-content.png', + summary: + 'A tab content component is used to contain content within a tab.', + }, + table: { + illustration: './images/component-illustrations/table.png', + summary: + 'A table displays large data sets in a simple grid with column headers.', + }, + tabs: { + illustration: './images/component-illustrations/tabs.png', + summary: 'Tabs group similar content within sub-views of a page.', + }, + 'text-area': { + illustration: './images/component-illustrations/text-area.png', + summary: + 'A text area allows users to enter a longer paragraph of text.', + }, + 'text-input-group': { + illustration: './images/component-illustrations/text-input-group.png', + summary: + "A text input group is a more custom, flexible, and composable version of a text input that includes elements like icons and buttons.", + }, + 'text-input': { + illustration: './images/component-illustrations/text-input.png', + summary: 'A text input components allows users to input short text.', + }, + tile: { + illustration: './images/component-illustrations/tile.png', + summary: + 'A tile is a container that allows users to select a static option.', + label: 'deprecated', + }, + 'time-picker': { + illustration: './images/component-illustrations/time-picker.png', + summary: + 'A time picker component allows users to select a time from a list of options.', + }, + timestamp: { + illustration: './images/component-illustrations/timestamp.png', + summary: + 'A timestamp is a consistently formatted visual that displays date and time values.', + }, + title: { + illustration: './images/component-illustrations/title.png', + summary: + 'A title component applies top and bottom margins, font-weight, font-size, and line-height to page and section headings.', + }, + 'toggle-group': { + illustration: './images/component-illustrations/toggle-group.png', + summary: + 'A toggle group is a set of controls that can be used to quickly switch between actions or states.', + }, + toolbar: { + illustration: './images/component-illustrations/toolbar.png', + summary: + 'A toolbar is a responsive container that displays controls that allow users to manage and manipulate a data set.', + }, + tooltip: { + illustration: './images/component-illustrations/tooltip.png', + summary: + 'A tooltip is a small, temporary, overlay window that provides additional information about an on-screen element.', + }, + 'tree-view': { + illustration: './images/component-illustrations/tree-view.png', + summary: + 'A tree view is a structure that displays data in a hierarchical view.', + }, + truncate: { + illustration: './images/component-illustrations/truncate.png', + summary: + 'A truncate component can be used to shorten character strings—typically when the string overflows its container.', + }, + wizard: { + illustration: './images/component-illustrations/wizard.png', + summary: + 'A wizard is a guided workflow that helps users complete complex tasks, create objects, or follow a series of steps.', + }, +} diff --git a/textContent/examples/Accordion/Accordion.mdx b/textContent/examples/Accordion/Accordion.mdx index f2b6c90..ca4b182 100644 --- a/textContent/examples/Accordion/Accordion.mdx +++ b/textContent/examples/Accordion/Accordion.mdx @@ -10,6 +10,7 @@ propComponents: 'AccordionToggle', AccordionExpandableContentBody, ] +tab: react --- ## Examples