From 321b35c1d114ae8e11ff842c83feb16d62af4f5a Mon Sep 17 00:00:00 2001 From: Nate Stewart Date: Mon, 15 Jul 2024 05:34:10 +0000 Subject: [PATCH] feat: add cardgrid component and docs --- packages/examples-site/src/App.tsx | 4 +- .../src/pages/CardGridPage/index.tsx | 243 ++++++++++++++++++ .../examples-site/src/pages/Home/Home.tsx | 3 + packages/patterns/package.json | 1 + .../src/components/CardGrid/CardGrid.tsx | 115 +++++++++ .../patterns/src/components/CardGrid/index.ts | 1 + .../src/components/CardGrid/styled.ts | 28 ++ packages/patterns/src/index.ts | 1 + pnpm-lock.yaml | 12 + 9 files changed, 407 insertions(+), 1 deletion(-) create mode 100644 packages/examples-site/src/pages/CardGridPage/index.tsx create mode 100644 packages/patterns/src/components/CardGrid/CardGrid.tsx create mode 100644 packages/patterns/src/components/CardGrid/index.ts create mode 100644 packages/patterns/src/components/CardGrid/styled.ts diff --git a/packages/examples-site/src/App.tsx b/packages/examples-site/src/App.tsx index b23fcf6..75bf9f7 100644 --- a/packages/examples-site/src/App.tsx +++ b/packages/examples-site/src/App.tsx @@ -12,6 +12,7 @@ import { AlertsManager, createAlertsManager } from "@bigcommerce/big-design"; import PageCRUDList from "./pages/CRUDListPage/CRUDListPage"; import PageCRUDAddEdit from "./pages/CRUDAddEditPage/CRUDAddEditPage"; import PageAnchorNav from "./pages/AnchorNavPage/AnchorNavPage"; +import CardGridPage from "./pages/CardGridPage"; export const alertsManager = createAlertsManager(); @@ -28,7 +29,8 @@ const RouteFC = () => { { path: "/page-crud-list", element: }, { path: "/page-crud-add", element: }, { path: "/page-crud-edit/:sku", element: }, - { path: "/page-anchor-nav", element: } + { path: "/page-anchor-nav", element: }, + { path: "/cardgrid", element: } ]); return routes; }; diff --git a/packages/examples-site/src/pages/CardGridPage/index.tsx b/packages/examples-site/src/pages/CardGridPage/index.tsx new file mode 100644 index 0000000..6c36e47 --- /dev/null +++ b/packages/examples-site/src/pages/CardGridPage/index.tsx @@ -0,0 +1,243 @@ +import React, { FunctionComponent } from "react"; +import { Flex, FlexItem, Text, HR, Table } from "@bigcommerce/big-design"; +import { + CardGrid, + Page, + AdvancedPanel as Panel, +} from "bigcommerce-design-patterns"; +import { useNavigate } from "react-router"; +import { theme } from "@bigcommerce/big-design-theme"; + +import { CopyBlock, nord as codecolor } from "react-code-blocks"; + +const CardGridPage: FunctionComponent = () => { + const navigate = useNavigate(); + + const copyBlockProps = { + language: "jsx", + showLineNumbers: true, + startingLineNumber: 1, + wrapLines: true, + theme: codecolor, + customStyle: { + width: "100%", + minHeight: "45px", + }, + }; + + return ( + navigate("/")} + pageDescription={ + + Card grids are used to showcase relevant resources or actions in a condensed, + organized manner. + + } + > + + + + + + + +
+
+ + `} + /> + +
+
+ + + + + + ), + format: "action", + }, + { + name: "Grid Item 2", + description: + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean euismod bibendum laoreet. Proin gravida dolor sit amet.", + button: { + variant: "primary", + text: "Connect", + }, + icon: ( + + ), + format: "action", + }, + ]} + /> + + +
+
+ + + ), + format: "action", +}, +{ + name: "Grid Item 2", + description: + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean euismod bibendum laoreet.", + button: { + variant: "primary", + text: "Connect", + }, + icon: ( + + ), + format: "action", +}, +]} />`} + /> + +
+
+ + + + + + +
+
+ + `} + /> + +
+
+ + + propName, + }, + { + header: "Type", + hash: "type", + render: ({ type }) => type, + }, + { + header: "Default", + hash: "default", + render: ({ default: defaultValue }) => defaultValue.toString(), + }, + { + header: "Description", + hash: "description", + render: ({ description }) => description, + }, + { + header: "Required", + hash: "required", + render: ({ required }) => (required ? "Yes" : "No"), + }, + ]} + items={[ + { + propName: "items", + type: "array", + default: "-", + description: "Array of entries for content or actions. See above for examples for each. If you don't include the items prop, a loading skeleton will render.", + required: false, + }, + ]} + stickyHeader + /> + + + + ); +}; + +export default CardGridPage; diff --git a/packages/examples-site/src/pages/Home/Home.tsx b/packages/examples-site/src/pages/Home/Home.tsx index 8aa91b8..57be3e1 100644 --- a/packages/examples-site/src/pages/Home/Home.tsx +++ b/packages/examples-site/src/pages/Home/Home.tsx @@ -41,6 +41,9 @@ const PageHome: FunctionComponent = () => {
  • Info Illustrations
  • +
  • + Card Grid +
  • ); diff --git a/packages/patterns/package.json b/packages/patterns/package.json index bf96cd6..1df406e 100644 --- a/packages/patterns/package.json +++ b/packages/patterns/package.json @@ -25,6 +25,7 @@ "@bigcommerce/big-design-icons": "^0.24.0", "@bigcommerce/big-design-theme": "^0.19.2", "react": "^18.0.0", + "react-loading-skeleton": "^3.4.0", "styled-components": "^5.3.11" }, "devDependencies": { diff --git a/packages/patterns/src/components/CardGrid/CardGrid.tsx b/packages/patterns/src/components/CardGrid/CardGrid.tsx new file mode 100644 index 0000000..e95fc1e --- /dev/null +++ b/packages/patterns/src/components/CardGrid/CardGrid.tsx @@ -0,0 +1,115 @@ +import Skeleton from "react-loading-skeleton"; +import "react-loading-skeleton/dist/skeleton.css"; +import { + Box, + Button, + Grid, + Text, + Flex, + FlexItem, +} from "@bigcommerce/big-design"; +import { ChevronRightIcon } from "@bigcommerce/big-design-icons"; +import { StyledLinkBox, StyledLink } from "./styled"; + +export type CardGridItem = { + button?: { + variant: "primary" | "secondary" | "subtle" | "danger"; + text: string; + }; + name?: string; + description?: string; + format?: string; + href?: string; + icon?: React.ReactNode; +}; + +function CardGridItem({ + button, + name, + description, + format = "content", + href, + icon, +}: CardGridItem) { + if (format === "action") { + return ( + + + + {icon ? icon : } + + + {name ?? } + + + {button ? ( + + ) : ( + + )} + + + + {description ?? } + + ); + } + + // Default format is "content" + const itemContent = ( + <> + + + {name ?? } + + + {name ? : } + + + + {description ?? } + + ); + return href ? ( + + + {itemContent} + + + ) : ( + + {itemContent} + + ); +} + +export function CardGrid({ + items, + format, +}: { + items?: CardGridItem[]; + format?: "content" | "action"; +}) { + return ( + + {items ? ( + items.map((item) => ) + ) : ( + <> + + + + )} + + ); +} diff --git a/packages/patterns/src/components/CardGrid/index.ts b/packages/patterns/src/components/CardGrid/index.ts new file mode 100644 index 0000000..ba05e92 --- /dev/null +++ b/packages/patterns/src/components/CardGrid/index.ts @@ -0,0 +1 @@ +export { CardGrid, type CardGridItem } from './CardGrid'; diff --git a/packages/patterns/src/components/CardGrid/styled.ts b/packages/patterns/src/components/CardGrid/styled.ts new file mode 100644 index 0000000..22e6d34 --- /dev/null +++ b/packages/patterns/src/components/CardGrid/styled.ts @@ -0,0 +1,28 @@ +import { theme as defaultTheme } from "@bigcommerce/big-design-theme"; +import styled from "styled-components"; +import { Box } from "@bigcommerce/big-design"; + +export const StyledLinkBox = styled(Box)` + background-color: ${({ theme }) => theme.colors.transparent}; + cursor: pointer; + + &:hover { + background-color: ${({ theme }) => theme.colors.secondary10}; + color: ${({ theme }) => theme.colors.primary}; + } + + &:focus { + outline: 4px solid ${({ theme }) => theme.colors.primary20}; + } +`; + +StyledLinkBox.defaultProps = { theme: defaultTheme }; + +export const StyledLink = styled.a` + display: inline-grid; + text-decoration: none; + + +`; + +StyledLink.defaultProps = { theme: defaultTheme }; diff --git a/packages/patterns/src/index.ts b/packages/patterns/src/index.ts index 51ebe64..51a3b81 100644 --- a/packages/patterns/src/index.ts +++ b/packages/patterns/src/index.ts @@ -3,6 +3,7 @@ export * from './components/actionBar/ActionBar'; export * from './components/advancedPanel/AdvancedPanel'; export * from './components/anchorNav/AnchorNav'; +export * from './components/CardGrid'; export * from './components/contextSelector/ContextSelector'; export * from './components/featureTag/FeatureTag'; export * from './components/header/Header'; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b74ed3a..17c2abb 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -81,6 +81,9 @@ importers: react: specifier: ^18.0.0 version: 18.3.1 + react-loading-skeleton: + specifier: ^3.4.0 + version: 3.4.0(react@18.3.1) styled-components: specifier: ^5.3.11 version: 5.3.11(@babel/core@7.24.8)(react-dom@18.3.1(react@18.3.1))(react-is@18.3.1)(react@18.3.1) @@ -3163,6 +3166,11 @@ packages: react-is@18.3.1: resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==} + react-loading-skeleton@3.4.0: + resolution: {integrity: sha512-1oJEBc9+wn7BbkQQk7YodlYEIjgeR+GrRjD+QXkVjwZN7LGIcAFHrx4NhT7UHGBxNY1+zax3c+Fo6XQM4R7CgA==} + peerDependencies: + react: '>=16.8.0' + react-onclickoutside@6.13.1: resolution: {integrity: sha512-LdrrxK/Yh9zbBQdFbMTXPp3dTSN9B+9YJQucdDu3JNKRrbdU+H+/TVONJoWtOwy4II8Sqf1y/DTI6w/vGPYW0w==} peerDependencies: @@ -7481,6 +7489,10 @@ snapshots: react-is@18.3.1: {} + react-loading-skeleton@3.4.0(react@18.3.1): + dependencies: + react: 18.3.1 + react-onclickoutside@6.13.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: react: 18.3.1