UNPKG

@carbon/ibm-products

Version:
176 lines (174 loc) 7.16 kB
/** * Copyright IBM Corp. 2020, 2026 * * 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 { __toESM } from "../../_virtual/_rolldown/runtime.js"; import { require_classnames } from "../../node_modules/classnames/index.js"; import { pkg } from "../../settings.js"; import { useControllableState } from "../../global/js/hooks/useControllableState.js"; import { getDevtoolsProps } from "../../global/js/utils/devtools.js"; import uuidv4 from "../../global/js/utils/uuidv4.js"; import { blue90, purple70 } from "../../node_modules/@carbon/colors/es/index.js"; import { Carousel } from "../Carousel/Carousel.js"; import React, { useRef, useState } from "react"; import PropTypes from "prop-types"; import { Button, IconButton } from "@carbon/react"; import { CaretLeft, CaretRight, Close, Idea } from "@carbon/react/icons"; //#region src/components/Guidebanner/Guidebanner.tsx /** * Copyright IBM Corp. 2023, 2025 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. */ var import_classnames = /* @__PURE__ */ __toESM(require_classnames()); const blockClass = `${pkg.prefix}--guidebanner`; const componentName = "Guidebanner"; const defaults = { collapsible: false, withLeftGutter: false, closeIconDescription: "Close", collapseButtonLabel: "Read less", expandButtonLabel: "Read more", nextIconDescription: "Next", previousIconDescription: "Back" }; /** * The guide banner sits at the top of a page, or page-level tab, * to introduce foundational concepts related to the page's content. */ const Guidebanner = React.forwardRef((props, ref) => { const { children, className, collapsible = defaults.collapsible, onClose, withLeftGutter = defaults.withLeftGutter, closeIconDescription = defaults.closeIconDescription, collapseButtonLabel = defaults.collapseButtonLabel, expandButtonLabel = defaults.expandButtonLabel, nextIconDescription = defaults.nextIconDescription, previousIconDescription = defaults.previousIconDescription, title, onChange, open: userOpen, ...rest } = props; const scrollRef = useRef(null); const toggleRef = useRef(null); const [scrollPosition, setScrollPosition] = useState(0); const [showNavigation, setShowNavigation] = useState(false); const [open, setOpen] = useControllableState(userOpen ?? false, onChange); const handleClickToggle = () => { setOpen(!open); }; const carouselContentId = `${uuidv4()}--carousel-content-id`; return /* @__PURE__ */ React.createElement("div", { ...rest, "aria-owns": open ? carouselContentId : void 0, className: (0, import_classnames.default)(blockClass, className, collapsible && `${blockClass}__collapsible`, !open && `${blockClass}__collapsible-collapsed`, withLeftGutter && `${blockClass}__with-left-gutter`), ref, ...getDevtoolsProps(componentName) }, /* @__PURE__ */ React.createElement(Idea, { size: 20, className: `${blockClass}__icon-idea` }), /* @__PURE__ */ React.createElement("div", { className: `${blockClass}__title` }, title), /* @__PURE__ */ React.createElement(Carousel, { id: carouselContentId, className: `${blockClass}__carousel`, fadedEdgeColor: { left: blue90, right: purple70 }, ref: scrollRef, onChangeIsScrollable: (value) => { setShowNavigation(value); }, onScroll: (scrollPercent) => { setScrollPosition(scrollPercent); }, isScrollMode: true }, children), /* @__PURE__ */ React.createElement("div", { className: (0, import_classnames.default)([collapsible || showNavigation ? `${blockClass}__navigation` : null]) }, collapsible && /* @__PURE__ */ React.createElement(Button, { kind: "ghost", size: "md", className: `${blockClass}__toggle-button`, onClick: handleClickToggle, ref: toggleRef, "aria-controls": !open ? carouselContentId : void 0, "aria-expanded": open }, open ? collapseButtonLabel : expandButtonLabel), showNavigation && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("span", { className: (0, import_classnames.default)(`${blockClass}__back-button`, [scrollPosition === 0 ? `${blockClass}__back-button--disabled` : null]) }, /* @__PURE__ */ React.createElement(IconButton, { align: "top", disabled: scrollPosition === 0, kind: "ghost", label: previousIconDescription, onClick: () => { scrollRef.current.scrollPrev(); }, size: "md" }, /* @__PURE__ */ React.createElement(CaretLeft, { size: 16 }))), /* @__PURE__ */ React.createElement("span", { className: (0, import_classnames.default)(`${blockClass}__next-button`, [scrollPosition === 1 ? `${blockClass}__next-button--disabled` : null]) }, /* @__PURE__ */ React.createElement(IconButton, { align: "top-right", disabled: scrollPosition === 1, kind: "ghost", label: nextIconDescription, onClick: () => { scrollRef.current.scrollNext(); }, size: "md" }, /* @__PURE__ */ React.createElement(CaretRight, { size: 16 }))))), onClose && /* @__PURE__ */ React.createElement("span", { className: `${blockClass}__close-button` }, /* @__PURE__ */ React.createElement(IconButton, { align: "bottom-end", kind: "ghost", label: closeIconDescription, onClick: onClose, size: "md" }, /* @__PURE__ */ React.createElement(Close, { size: 16 })))); }); Guidebanner.displayName = componentName; Guidebanner.propTypes = { /** * Provide the contents of the Guidebanner. * One or more GuidebannerElement components are required. */ children: PropTypes.node, /** * Provide an optional class to be applied to the containing node. */ className: PropTypes.string, /** * Tooltip text and aria label for the Close button icon. */ closeIconDescription: PropTypes.string, /** * Text label for the Collapse button. */ collapseButtonLabel: PropTypes.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: PropTypes.bool, /** * Text label for the Expand button. */ expandButtonLabel: PropTypes.string, /** * Tooltip text and aria label for the Next button icon. */ nextIconDescription: PropTypes.string, /** * A handler for managing the controlled state of open prop. If not passed the open prop will not be honored and an uncontrolled state will be used. */ onChange: PropTypes.func, /** * If defined, a Close button will render in the top-right corner and a * callback function will be triggered when button is clicked. */ onClose: PropTypes.func, /** * Specify whether the Guidebanner is currently open. */ open: PropTypes.bool, /** * Tooltip text and aria label for the Back button icon. */ previousIconDescription: PropTypes.string, /** * Title text. */ title: PropTypes.string.isRequired, /** * 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: PropTypes.bool }; //#endregion export { Guidebanner };