diff --git a/packages/ibm-products/src/components/Guidebanner/Guidebanner.js b/packages/ibm-products/src/components/Guidebanner/Guidebanner.tsx similarity index 79% rename from packages/ibm-products/src/components/Guidebanner/Guidebanner.js rename to packages/ibm-products/src/components/Guidebanner/Guidebanner.tsx index a5eddb9a53..a4dd9b8551 100644 --- a/packages/ibm-products/src/components/Guidebanner/Guidebanner.js +++ b/packages/ibm-products/src/components/Guidebanner/Guidebanner.tsx @@ -1,12 +1,12 @@ /** - * Copyright IBM Corp. 2023, 2023 + * Copyright IBM Corp. 2023, 2024 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. */ // Import portions of React that are needed. -import React, { useRef, useState } from 'react'; +import React, { ReactNode, useRef, useState } from 'react'; import PropTypes from 'prop-types'; import cx from 'classnames'; import { blue90, purple70 } from '@carbon/colors'; @@ -20,6 +20,60 @@ import { pkg } from '../../settings'; const blockClass = `${pkg.prefix}--guidebanner`; const componentName = 'Guidebanner'; +interface GuidebannerProps { + /** + * Provide the contents of the Guidebanner. + * One or more GuidebannerElement components are required. + */ + children: ReactNode; + /** + * Provide an optional class to be applied to the containing node. + */ + className?: string; + /** + * Tooltip text and aria label for the Close button icon. + */ + closeIconDescription?: string; + /** + * Text label for the Collapse button. + */ + collapseButtonLabel?: string; + /** + * When true, the Guidebanner will initialize in a collapsed state, + * showing the title and the Expand button. + * + * When expanded, it will show the GuidebannerElement child components and the Collapse button. + */ + collapsible?: boolean; + /** + * Text label for the Expand button. + */ + expandButtonLabel?: string; + /** + * Tooltip text and aria label for the Next button icon. + */ + nextIconDescription?: string; + /** + * If defined, a Close button will render in the top-right corner and a + * callback function will be triggered when button is clicked. + */ + onClose?: () => void; + /** + * Tooltip text and aria label for the Back button icon. + */ + previousIconDescription?: string; + /** + * Title text. + */ + title: string; + /** + * If true, insert 1 rem of "space" on the left of the component. + * This will allow the component's content to line up with other + * content on the page under special circumstances. + */ + withLeftGutter?: boolean; +} + const defaults = { collapsible: false, withLeftGutter: false, @@ -35,7 +89,7 @@ const defaults = { * The guide banner sits at the top of a page, or page-level tab, * to introduce foundational concepts related to the page's content. */ -export let Guidebanner = React.forwardRef( +export let Guidebanner = React.forwardRef( ( { children, @@ -54,8 +108,8 @@ export let Guidebanner = React.forwardRef( }, ref ) => { - const scrollRef = useRef(); - const toggleRef = useRef(); + const scrollRef = useRef(null); + const toggleRef = useRef(null); const [scrollPosition, setScrollPosition] = useState(0); const [showNavigation, setShowNavigation] = useState(false); const [isCollapsed, setIsCollapsed] = useState(collapsible ? true : false); @@ -67,6 +121,7 @@ export let Guidebanner = React.forwardRef( return (
{isCollapsed ? expandButtonLabel : collapseButtonLabel} @@ -201,9 +255,10 @@ Guidebanner.propTypes = { } React.Children.forEach(prop, (child) => { if (child.type.displayName !== 'GuidebannerElement') { - // If not GuidebannerElement, then show: - // React component name(child.type?.name) or - // HTML element name(child.type). + // If child element is not `GuidebannerElement`, then show: + // Carbon Products component's `displayName` (child.type.displayName) or + // React component's `name` (child.type.name) or + // HTML element's tag name (child.type). error = new Error( `\`Guidebanner\` only accepts children of type \`GuidebannerElement\`, found \`${ child.type?.displayName || child.type?.name || child.type diff --git a/packages/ibm-products/src/components/Guidebanner/GuidebannerElement.js b/packages/ibm-products/src/components/Guidebanner/GuidebannerElement.tsx similarity index 74% rename from packages/ibm-products/src/components/Guidebanner/GuidebannerElement.js rename to packages/ibm-products/src/components/Guidebanner/GuidebannerElement.tsx index c323ee44c8..f5aef678bd 100644 --- a/packages/ibm-products/src/components/Guidebanner/GuidebannerElement.js +++ b/packages/ibm-products/src/components/Guidebanner/GuidebannerElement.tsx @@ -1,12 +1,12 @@ /** - * Copyright IBM Corp. 2023, 2023 + * Copyright IBM Corp. 2023, 2024 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. */ // Import portions of React that are needed. -import React from 'react'; +import React, { ReactNode } from 'react'; import PropTypes from 'prop-types'; import cx from 'classnames'; import { getDevtoolsProps } from '../../global/js/utils/devtools'; @@ -16,21 +16,39 @@ import { pkg } from '../../settings'; const blockClass = `${pkg.prefix}--guidebanner__element`; const componentName = 'GuidebannerElement'; +interface GuidebannerElementProps { + /** + * An optional button can be rendered below the description. + * This can be a link, button, Coachmark button, etc. + */ + button?: ReactNode; + /** + * Provide an optional class to be applied to the containing node. + */ + className?: string; + /** + * The description of the element. + */ + description: ReactNode; + /** + * The title of the element. + */ + title?: string; +} + /** * The GuidebannerElement is a required child component of the Guidebanner, * and acts as a container for a CarouselItem. */ -export let GuidebannerElement = ({ - button, - className, - description, - title, - ...rest -}) => { +export let GuidebannerElement = React.forwardRef< + HTMLDivElement, + GuidebannerElementProps +>(({ button, className, description, title, ...rest }, ref) => { return (
{title &&

{title}

} @@ -38,7 +56,7 @@ export let GuidebannerElement = ({ {button &&
{button}
}
); -}; +}); // Return a placeholder if not released and not enabled by feature flag GuidebannerElement = pkg.checkComponentEnabled( diff --git a/packages/ibm-products/src/components/Guidebanner/GuidebannerElementButton.js b/packages/ibm-products/src/components/Guidebanner/GuidebannerElementButton.tsx similarity index 59% rename from packages/ibm-products/src/components/Guidebanner/GuidebannerElementButton.js rename to packages/ibm-products/src/components/Guidebanner/GuidebannerElementButton.tsx index 6adccac9f2..f43202afab 100644 --- a/packages/ibm-products/src/components/Guidebanner/GuidebannerElementButton.js +++ b/packages/ibm-products/src/components/Guidebanner/GuidebannerElementButton.tsx @@ -1,12 +1,12 @@ /** - * Copyright IBM Corp. 2023, 2023 + * Copyright IBM Corp. 2023, 2024 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. */ // Import portions of React that are needed. -import React from 'react'; +import React, { ReactNode } from 'react'; import PropTypes from 'prop-types'; import cx from 'classnames'; import { Button } from '@carbon/react'; @@ -18,23 +18,73 @@ import { pkg } from '../../settings'; const blockClass = `${pkg.prefix}--guidebanner__element-button`; const componentName = 'GuidebannerElementButton'; +interface GuidebannerElementButtonProps { + /** + * Provide the contents of the GuidebannerElementLink. + */ + children: ReactNode; + + /** + * Provide an optional class to be applied to the containing node. + */ + className?: string; + + /** + * Provide a description for the icon. + */ + iconDescription?: string; + + /** + * If type is "primary", then return a tertiary button with the "crossroads" icon, + * else return a ghost button. + */ + type?: string; +} + +const defaults = { + iconDescription: 'Crossroads', +}; + /** * One of two buttons styled specifically for the GuidebannerElement. */ -export let GuidebannerElementButton = ({ - children, - className, - type, - ...rest -}) => { - if (type === 'primary') { +export let GuidebannerElementButton = React.forwardRef< + Button, + GuidebannerElementButtonProps +>( + ( + { + children, + className, + iconDescription = defaults.iconDescription, + type, + ...rest + }: GuidebannerElementButtonProps, + ref + ) => { + if (type === 'primary') { + return ( + + ); + } + return ( ); } - - return ( - - ); -}; +); // Return a placeholder if not released and not enabled by feature flag GuidebannerElementButton = pkg.checkComponentEnabled( diff --git a/packages/ibm-products/src/components/Guidebanner/GuidebannerElementLink.js b/packages/ibm-products/src/components/Guidebanner/GuidebannerElementLink.tsx similarity index 76% rename from packages/ibm-products/src/components/Guidebanner/GuidebannerElementLink.js rename to packages/ibm-products/src/components/Guidebanner/GuidebannerElementLink.tsx index 29ba0e0b64..fd9e1426d5 100644 --- a/packages/ibm-products/src/components/Guidebanner/GuidebannerElementLink.js +++ b/packages/ibm-products/src/components/Guidebanner/GuidebannerElementLink.tsx @@ -1,12 +1,12 @@ /** - * Copyright IBM Corp. 2023, 2023 + * Copyright IBM Corp. 2023, 2024 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. */ // Import portions of React that are needed. -import React from 'react'; +import React, { ReactNode } from 'react'; import PropTypes from 'prop-types'; import cx from 'classnames'; import { Link } from '@carbon/react'; @@ -17,15 +17,31 @@ import { pkg } from '../../settings'; const blockClass = `${pkg.prefix}--guidebanner__element-link`; const componentName = 'GuidebannerElementLink'; +interface GuidebannerElementLinkProps { + /** + * Provide the contents of the GuidebannerElementLink. + */ + children: ReactNode; + + /** + * Provide an optional class to be applied to the containing node. + */ + className?: string; +} + /** * A link styled specifically for the GuidebannerElement. */ -export let GuidebannerElementLink = ({ children, className, ...rest }) => { +export let GuidebannerElementLink = React.forwardRef< + Link, + GuidebannerElementLinkProps +>(({ children, className, ...rest }: GuidebannerElementLinkProps, ref) => { return ( { {children} ); -}; +}); // Return a placeholder if not released and not enabled by feature flag GuidebannerElementLink = pkg.checkComponentEnabled(