import { ComponentPropsWithoutRef, ReactNode } from 'react';
import { mergeClasses } from '../Button/utils';
import './panel.css';
// Stand-in for v2's `PaddingScale` (`@libs/types/layout-types`), which the
// published package does not export.
export type PanelPadding = 'condensed' | 'none' | 'spacious' | 'standard';
export type PanelVariant =
| 'agentic-default'
| 'agentic-raised'
| 'agentic-sunken'
| 'critical'
| 'default'
| 'discovery'
| 'info'
| 'overlay'
| 'raised'
| 'success'
| 'sunken'
| 'warning';
export type PanelAgenticVariant =
'agentic-default' | 'agentic-raised' | 'agentic-sunken';
interface PanelBaseProps extends Omit<
ComponentPropsWithoutRef<'div'>,
'children'
> {
/**
* Panel content.
*/
children: ReactNode;
/**
* Additional class names
*/
className?: string;
/**
* Padding for the panel.
*/
padding?: PanelPadding;
}
interface PanelAgenticProps extends PanelBaseProps {
/**
* Shimmer the agentic border, to show the agent is working. Set to `false`
* once the agent has finished. Only available on the `agentic-*` variants.
* Off for reduced motion.
*/
isAnimated?: boolean;
/**
* Which variant of panel to render. The `agentic-*` variants have the fill
* and shadow of the matching variant (`default`, `raised`, `sunken`) with
* the AI gradient (`--pds-gradient-ai-active`) as the border, to mark
* content an agent produced or is acting on.
*/
variant: PanelAgenticVariant;
}
interface PanelStandardProps extends PanelBaseProps {
isAnimated?: never;
/**
* Which variant of panel to render.
*/
variant?: Exclude<PanelVariant, PanelAgenticVariant>;
}
/**
* Prop types for Panel. `isAnimated` is only accepted with an `agentic-*`
* variant.
*/
export type PanelProps = PanelAgenticProps | PanelStandardProps;
/**
* Panel UI component
*/
export const Panel = ({
children,
className,
isAnimated,
padding = 'standard',
variant = 'default',
...props
}: PanelProps) => {
// Set up classes.
const baseClass = 'pds-panel';
// `agentic-<surface>` renders the surface's own class plus `--agentic`, so
// the fill and shadow come from the existing variant.
const isAgentic = variant.startsWith('agentic-');
const surface = isAgentic ? variant.replace('agentic-', '') : variant;
const variantClass =
surface !== 'default' ? `${baseClass}--${surface}` : null;
const agenticClass = isAgentic ? `${baseClass}--agentic` : null;
const animatedClass =
isAgentic && isAnimated !== false ? `${baseClass}--animated` : null;
const contentClass = `${baseClass}__content`;
const paddingClass =
padding !== 'standard' ? `${contentClass}--pad-${padding}` : null;
// Render the output
return (
<div
className={mergeClasses([
baseClass,
variantClass,
agenticClass,
animatedClass,
className ?? '',
])}
{...props}
>
<div className={mergeClasses([contentClass, paddingClass])}>
{children}
</div>
</div>
);
};
Panel
The PDS v2 Panel (src/components/panels/Panel, branch v2.x) with one addition: the agentic-default, agentic-raised and agentic-sunken variants: each existing surface with the AI gradient as the border.
Extends a PDS componentOpen in Storybook