From f18727b3c11607c372e9d5ae31fcf36c71550645 Mon Sep 17 00:00:00 2001 From: Alex Khomenko Date: Wed, 14 May 2025 07:58:15 +0300 Subject: [PATCH] Grafana/ui: Add noMargin prop to Card and Field (#105223) * Card: Add noMargin prop to remove the bottom margin * Add noMargin to Field --- .../grafana-ui/src/components/Card/Card.tsx | 6 +++++- .../src/components/Card/CardContainer.tsx | 19 +++++++++++++++---- .../grafana-ui/src/components/Forms/Field.tsx | 9 ++++++--- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/packages/grafana-ui/src/components/Card/Card.tsx b/packages/grafana-ui/src/components/Card/Card.tsx index 49637c5a695..fd89529d484 100644 --- a/packages/grafana-ui/src/components/Card/Card.tsx +++ b/packages/grafana-ui/src/components/Card/Card.tsx @@ -27,6 +27,8 @@ export interface Props extends Omit { @@ -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 ( diff --git a/packages/grafana-ui/src/components/Card/CardContainer.tsx b/packages/grafana-ui/src/components/Card/CardContainer.tsx index 2d461dabf6f..b4ed6b5d0a8 100644 --- a/packages/grafana-ui/src/components/Card/CardContainer.tsx +++ b/packages/grafana-ui/src/components/Card/CardContainer.tsx @@ -46,6 +46,8 @@ export interface CardContainerProps extends HTMLAttributes, 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 (
@@ -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, diff --git a/packages/grafana-ui/src/components/Forms/Field.tsx b/packages/grafana-ui/src/components/Forms/Field.tsx index 10db5c83bfc..22f1748b9d8 100644 --- a/packages/grafana-ui/src/components/Forms/Field.tsx +++ b/packages/grafana-ui/src/components/Forms/Field.tsx @@ -39,6 +39,8 @@ export interface FieldProps extends HTMLAttributes { * 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( @@ -56,11 +58,12 @@ export const Field = React.forwardRef( 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(obj: T): Partial { 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',