Grafana/ui: Add noMargin prop to Card and Field (#105223)

* Card: Add noMargin prop to remove the bottom margin

* Add noMargin to Field
This commit is contained in:
Alex Khomenko
2025-05-14 07:58:15 +03:00
committed by GitHub
parent f0d6375b3b
commit f18727b3c1
3 changed files with 26 additions and 8 deletions
@@ -27,6 +27,8 @@ export interface Props extends Omit<CardContainerProps, 'disableEvents' | 'disab
isSelected?: boolean;
/** If true, the padding of the Card will be smaller */
isCompact?: boolean;
/** Remove the bottom margin */
noMargin?: boolean;
}
export interface CardInterface extends FC<Props> {
@@ -59,6 +61,7 @@ export const Card: CardInterface = ({
isSelected,
isCompact,
className,
noMargin,
...htmlProps
}) => {
const hasHeadingComponent = useMemo(
@@ -68,7 +71,7 @@ export const Card: CardInterface = ({
const disableHover = disabled || (!onClick && !href);
const onCardClick = onClick && !disabled ? onClick : undefined;
const styles = useStyles2(getCardContainerStyles, disabled, disableHover, isSelected, isCompact);
const styles = useStyles2(getCardContainerStyles, disabled, disableHover, isSelected, isCompact, noMargin);
return (
<CardContainer
@@ -76,6 +79,7 @@ export const Card: CardInterface = ({
disableHover={disableHover}
isSelected={isSelected}
className={cx(styles.container, className)}
noMargin={noMargin}
{...htmlProps}
>
<CardContext.Provider value={{ href, onClick: onCardClick, disabled, isSelected }}>
@@ -46,6 +46,8 @@ export interface CardContainerProps extends HTMLAttributes<HTMLOrSVGElement>, Ca
isSelected?: boolean;
/** Custom container styles */
className?: string;
/** Remove the bottom margin */
noMargin?: boolean;
}
/** @deprecated Using `CardContainer` directly is discouraged and should be replaced with `Card` */
@@ -56,9 +58,17 @@ export const CardContainer = ({
isSelected,
className,
href,
noMargin,
...props
}: CardContainerProps) => {
const { oldContainer } = useStyles2(getCardContainerStyles, disableEvents, disableHover, isSelected);
const { oldContainer } = useStyles2(
getCardContainerStyles,
disableEvents,
disableHover,
isSelected,
undefined,
noMargin
);
return (
<div {...props} className={cx(oldContainer, className)}>
@@ -72,7 +82,8 @@ export const getCardContainerStyles = (
disabled = false,
disableHover = false,
isSelected?: boolean,
isCompact?: boolean
isCompact?: boolean,
noMargin = false
) => {
const isSelectable = isSelected !== undefined;
@@ -93,7 +104,7 @@ export const getCardContainerStyles = (
padding: theme.spacing(isCompact ? 1 : 2),
background: theme.colors.background.secondary,
borderRadius: theme.shape.radius.default,
marginBottom: '8px',
marginBottom: theme.spacing(noMargin ? 0 : 1),
pointerEvents: disabled ? 'none' : 'auto',
[theme.transitions.handleMotion('no-preference', 'reduce')]: {
transition: theme.transitions.create(['background-color', 'box-shadow', 'border-color', 'color'], {
@@ -125,7 +136,7 @@ export const getCardContainerStyles = (
borderRadius: theme.shape.radius.default,
position: 'relative',
pointerEvents: disabled ? 'none' : 'auto',
marginBottom: theme.spacing(1),
marginBottom: theme.spacing(noMargin ? 0 : 1),
[theme.transitions.handleMotion('no-preference', 'reduce')]: {
transition: theme.transitions.create(['background-color', 'box-shadow', 'border-color', 'color'], {
duration: theme.transitions.duration.short,
@@ -39,6 +39,8 @@ export interface FieldProps extends HTMLAttributes<HTMLDivElement> {
* https://developer.mozilla.org/en-US/docs/Web/HTML/Element/label#attr-for
*/
htmlFor?: string;
/** Remove the bottom margin */
noMargin?: boolean;
}
export const Field = React.forwardRef<HTMLDivElement, FieldProps>(
@@ -56,11 +58,12 @@ export const Field = React.forwardRef<HTMLDivElement, FieldProps>(
className,
validationMessageHorizontalOverflow,
htmlFor,
noMargin,
...otherProps
}: FieldProps,
ref
) => {
const styles = useStyles2(getFieldStyles);
const styles = useStyles2(getFieldStyles, noMargin);
const inputId = htmlFor ?? getChildId(children);
const labelElement =
@@ -115,11 +118,11 @@ function deleteUndefinedProps<T extends Object>(obj: T): Partial<T> {
return obj;
}
export const getFieldStyles = (theme: GrafanaTheme2) => ({
export const getFieldStyles = (theme: GrafanaTheme2, noMargin?: boolean) => ({
field: css({
display: 'flex',
flexDirection: 'column',
marginBottom: theme.spacing(2),
marginBottom: theme.spacing(noMargin ? 0 : 2),
}),
fieldHorizontal: css({
flexDirection: 'row',