From 2b65bf755f5fd0613cd14e7b18c02bd2e27541d0 Mon Sep 17 00:00:00 2001 From: Alexander Polyankin <alexander.polyankin@metabase.com> Date: Thu, 20 Jul 2023 15:00:37 +0300 Subject: [PATCH] Fix passing invalid props to Icon and Link (#32527) --- frontend/src/metabase/components/Badge/Badge.jsx | 2 +- frontend/src/metabase/components/Badge/Badge.styled.tsx | 7 ++----- .../src/metabase/components/tree/TreeNode.styled.tsx | 5 +---- .../components/BookmarkToggle/BookmarkToggle.styled.tsx | 5 +---- frontend/src/metabase/core/components/Icon/Icon.tsx | 8 ++++++-- .../src/metabase/core/components/Link/Link.styled.tsx | 5 ++--- frontend/src/metabase/lib/styling/emotion.ts | 5 ----- .../nav/components/AppBar/AppBarToggle.styled.tsx | 5 +---- .../src/metabase/nav/components/SearchBar.styled.tsx | 5 +---- .../MainNavbar/SidebarItems/SidebarItems.styled.tsx | 9 +++------ package.json | 1 + 11 files changed, 19 insertions(+), 38 deletions(-) delete mode 100644 frontend/src/metabase/lib/styling/emotion.ts diff --git a/frontend/src/metabase/components/Badge/Badge.jsx b/frontend/src/metabase/components/Badge/Badge.jsx index 85735265525..f14a6f34b1f 100644 --- a/frontend/src/metabase/components/Badge/Badge.jsx +++ b/frontend/src/metabase/components/Badge/Badge.jsx @@ -42,7 +42,7 @@ function Badge({ isSingleLine={isSingleLine} {...props} > - {icon && <BadgeIcon {...getIconProps(icon)} $hasMargin={!!children} />} + {icon && <BadgeIcon {...getIconProps(icon)} hasMargin={!!children} />} {children && ( <BadgeText className="text-wrap" isSingleLine={isSingleLine}> {children} diff --git a/frontend/src/metabase/components/Badge/Badge.styled.tsx b/frontend/src/metabase/components/Badge/Badge.styled.tsx index 8656e2d9454..a91a136992d 100644 --- a/frontend/src/metabase/components/Badge/Badge.styled.tsx +++ b/frontend/src/metabase/components/Badge/Badge.styled.tsx @@ -4,7 +4,6 @@ import { HTMLAttributes } from "react"; import { color } from "metabase/lib/colors"; import { Icon } from "metabase/core/components/Icon"; import Link, { LinkProps } from "metabase/core/components/Link"; -import { shouldForwardNonTransientProp } from "metabase/lib/styling/emotion"; interface RawMaybeLinkProps { to?: string; @@ -41,10 +40,8 @@ export const MaybeLink = styled(RawMaybeLink)` } `; -export const BadgeIcon = styled(Icon, { - shouldForwardProp: shouldForwardNonTransientProp, -})<{ $hasMargin: boolean }>` - margin-right: ${props => (props.$hasMargin ? "5px" : 0)}; +export const BadgeIcon = styled(Icon)<{ hasMargin: boolean }>` + margin-right: ${props => (props.hasMargin ? "5px" : 0)}; `; export const BadgeText = styled.span<{ isSingleLine: boolean }>` diff --git a/frontend/src/metabase/components/tree/TreeNode.styled.tsx b/frontend/src/metabase/components/tree/TreeNode.styled.tsx index 5a78b404595..92869c4a5ee 100644 --- a/frontend/src/metabase/components/tree/TreeNode.styled.tsx +++ b/frontend/src/metabase/components/tree/TreeNode.styled.tsx @@ -2,7 +2,6 @@ import styled from "@emotion/styled"; import { css } from "@emotion/react"; import { color, lighten } from "metabase/lib/colors"; import { Icon, IconProps } from "metabase/core/components/Icon"; -import { shouldForwardNonTransientProp } from "metabase/lib/styling/emotion"; interface TreeNodeRootProps { isSelected: boolean; @@ -38,9 +37,7 @@ interface ExpandToggleIconProps { isExpanded: boolean; } -export const ExpandToggleIcon = styled(Icon, { - shouldForwardProp: shouldForwardNonTransientProp, -})<ExpandToggleIconProps & IconProps>` +export const ExpandToggleIcon = styled(Icon)<ExpandToggleIconProps & IconProps>` transition: transform 200ms; ${props => diff --git a/frontend/src/metabase/core/components/BookmarkToggle/BookmarkToggle.styled.tsx b/frontend/src/metabase/core/components/BookmarkToggle/BookmarkToggle.styled.tsx index f1209a3da10..971496afbeb 100644 --- a/frontend/src/metabase/core/components/BookmarkToggle/BookmarkToggle.styled.tsx +++ b/frontend/src/metabase/core/components/BookmarkToggle/BookmarkToggle.styled.tsx @@ -3,7 +3,6 @@ import { keyframes } from "@emotion/react"; import { color } from "metabase/lib/colors"; import { Icon } from "metabase/core/components/Icon"; import Button from "metabase/core/components/Button"; -import { shouldForwardNonTransientProp } from "metabase/lib/styling/emotion"; const expandKeyframes = keyframes` 50% { @@ -23,9 +22,7 @@ export interface BookmarkIconProps { onAnimationEnd: () => void; } -export const BookmarkIcon = styled(Icon, { - shouldForwardProp: shouldForwardNonTransientProp, -})<BookmarkIconProps>` +export const BookmarkIcon = styled(Icon)<BookmarkIconProps>` color: ${props => (props.isBookmarked ? color("brand") : "")}; animation-name: ${props => props.isBookmarked ? expandKeyframes : shrinkKeyframes}; diff --git a/frontend/src/metabase/core/components/Icon/Icon.tsx b/frontend/src/metabase/core/components/Icon/Icon.tsx index f9c3d2626f8..aa6194c34ca 100644 --- a/frontend/src/metabase/core/components/Icon/Icon.tsx +++ b/frontend/src/metabase/core/components/Icon/Icon.tsx @@ -1,4 +1,5 @@ import React, { SVGAttributes, forwardRef } from "react"; +import isPropValid from "@emotion/is-prop-valid"; import cx from "classnames"; import Tooltip from "../Tooltip"; import { Icons } from "./icons"; @@ -15,10 +16,13 @@ export interface IconProps extends SVGAttributes<SVGSVGElement> { } export const Icon = forwardRef<SVGSVGElement, IconProps>(function Icon( - { name, className, size = defaultSize, tooltip, ...rest }: IconProps, + { name, className, size = defaultSize, tooltip, ...restProps }: IconProps, ref, ) { const IconComponent = (Icons[name] ?? Icons["unknown"]).component; + const validProps = Object.fromEntries( + Object.entries(restProps).filter(([key]) => isPropValid(key)), + ); const icon = ( <IconComponent @@ -28,7 +32,7 @@ export const Icon = forwardRef<SVGSVGElement, IconProps>(function Icon( className={cx(`Icon Icon-${name}`, className)} width={size} height={size} - {...rest} + {...validProps} /> ); diff --git a/frontend/src/metabase/core/components/Link/Link.styled.tsx b/frontend/src/metabase/core/components/Link/Link.styled.tsx index 9ce7312c50e..78a8b4ac56b 100644 --- a/frontend/src/metabase/core/components/Link/Link.styled.tsx +++ b/frontend/src/metabase/core/components/Link/Link.styled.tsx @@ -1,14 +1,13 @@ import styled from "@emotion/styled"; import { css } from "@emotion/react"; +import isPropValid from "@emotion/is-prop-valid"; import { Link } from "react-router"; import { color as metabaseColor } from "metabase/lib/colors"; -import { shouldForwardNonTransientProp } from "metabase/lib/styling/emotion"; import { focusOutlineStyle } from "metabase/core/style/input"; - import type { LinkProps } from "./types"; export const LinkRoot = styled(Link, { - shouldForwardProp: shouldForwardNonTransientProp, + shouldForwardProp: isPropValid, })<LinkProps>` opacity: ${props => (props.disabled ? "0.4" : "")}; pointer-events: ${props => (props.disabled ? "none" : "")}; diff --git a/frontend/src/metabase/lib/styling/emotion.ts b/frontend/src/metabase/lib/styling/emotion.ts deleted file mode 100644 index 9fd3588ba7b..00000000000 --- a/frontend/src/metabase/lib/styling/emotion.ts +++ /dev/null @@ -1,5 +0,0 @@ -import isPropValid from "@emotion/is-prop-valid"; - -export function shouldForwardNonTransientProp(propName: string): boolean { - return !propName.startsWith("$") && isPropValid(propName); -} diff --git a/frontend/src/metabase/nav/components/AppBar/AppBarToggle.styled.tsx b/frontend/src/metabase/nav/components/AppBar/AppBarToggle.styled.tsx index 78e7c4adfea..46362fd17aa 100644 --- a/frontend/src/metabase/nav/components/AppBar/AppBarToggle.styled.tsx +++ b/frontend/src/metabase/nav/components/AppBar/AppBarToggle.styled.tsx @@ -2,7 +2,6 @@ import styled from "@emotion/styled"; import { css } from "@emotion/react"; import { color } from "metabase/lib/colors"; import { Icon } from "metabase/core/components/Icon"; -import { shouldForwardNonTransientProp } from "metabase/lib/styling/emotion"; import { AppBarLeftContainer } from "./AppBarLarge.styled"; interface SidebarButtonProps { @@ -33,9 +32,7 @@ interface SidebarIconProps { isLogoVisible?: boolean; } -export const SidebarIcon = styled(Icon, { - shouldForwardProp: shouldForwardNonTransientProp, -})<SidebarIconProps>` +export const SidebarIcon = styled(Icon)<SidebarIconProps>` color: ${color("brand")}; display: block; transform: translateY(2px) translateX(2px); diff --git a/frontend/src/metabase/nav/components/SearchBar.styled.tsx b/frontend/src/metabase/nav/components/SearchBar.styled.tsx index 739c5c3b5eb..9aebeaef39b 100644 --- a/frontend/src/metabase/nav/components/SearchBar.styled.tsx +++ b/frontend/src/metabase/nav/components/SearchBar.styled.tsx @@ -11,7 +11,6 @@ import { breakpointMaxSmall, breakpointMinSmall, } from "metabase/styled-components/theme"; -import { shouldForwardNonTransientProp } from "metabase/lib/styling/emotion"; const activeInputCSS = css` border-radius: 6px; @@ -106,9 +105,7 @@ export const SearchInput = styled.input<{ isActive: boolean }>` const ICON_MARGIN = "10px"; -export const SearchIcon = styled(Icon, { - shouldForwardProp: shouldForwardNonTransientProp, -})<{ isActive: boolean }>` +export const SearchIcon = styled(Icon)<{ isActive: boolean }>` ${breakpointMaxSmall} { transition: margin 0.3s; diff --git a/frontend/src/metabase/nav/containers/MainNavbar/SidebarItems/SidebarItems.styled.tsx b/frontend/src/metabase/nav/containers/MainNavbar/SidebarItems/SidebarItems.styled.tsx index 273d0b1e625..9ae72d50a3a 100644 --- a/frontend/src/metabase/nav/containers/MainNavbar/SidebarItems/SidebarItems.styled.tsx +++ b/frontend/src/metabase/nav/containers/MainNavbar/SidebarItems/SidebarItems.styled.tsx @@ -8,12 +8,9 @@ import Link from "metabase/core/components/Link"; import { NAV_SIDEBAR_WIDTH } from "metabase/nav/constants"; -import { darken, color, alpha } from "metabase/lib/colors"; -import { shouldForwardNonTransientProp } from "metabase/lib/styling/emotion"; +import { alpha, color, darken } from "metabase/lib/colors"; -export const SidebarIcon = styled(Icon, { - shouldForwardProp: shouldForwardNonTransientProp, -})<{ +export const SidebarIcon = styled(Icon)<{ color?: string | null; isSelected: boolean; }>` @@ -91,8 +88,8 @@ const itemContentStyle = css` export const FullWidthButton = styled.button<{ isSelected: boolean }>` cursor: pointer; - ${itemContentStyle} + ${itemContentStyle} ${TreeNode.NameContainer} { font-weight: 700; color: ${props => getTextColor(props.isSelected)}; diff --git a/package.json b/package.json index 91602956455..f074fbb1926 100644 --- a/package.json +++ b/package.json @@ -13,6 +13,7 @@ "@dnd-kit/core": "^6.0.8", "@dnd-kit/modifiers": "^6.0.1", "@dnd-kit/sortable": "^7.0.2", + "@emotion/is-prop-valid": "^1.1.1", "@emotion/react": "^11.7.1", "@emotion/styled": "^11.6.0", "@mantine/core": "^6.0.13", -- GitLab