-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
091d308
commit 238e409
Showing
10 changed files
with
262 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@hopper-ui/components": patch | ||
--- | ||
|
||
Added Card component |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from "./src/index.ts"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
.hop-Card { | ||
/* Internal Variables */ | ||
--width: 100%; | ||
--border-radius: var(--hop-shape-rounded-md); | ||
|
||
/* Main */ | ||
--hop-Card-main-border: var(--hop-space-10) solid var(--hop-neutral-border-weak); | ||
--hop-Card-main-background-color: var(--hop-neutral-surface); | ||
|
||
/* Second */ | ||
--hop-Card-second-border: none; | ||
--hop-Card-second-background-color: var(--hop-neutral-surface-weakest); | ||
|
||
inline-size: var(--width); | ||
border-radius: var(--border-radius); | ||
} | ||
|
||
.hop-Card--main { | ||
background-color: var(--hop-Card-main-background-color); | ||
border: var(--hop-Card-main-border); | ||
} | ||
|
||
.hop-Card--second-level { | ||
background-color: var(--hop-Card-second-background-color); | ||
border: var(--hop-Card-second-border); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import { useStyledSystem, type StyledComponentProps } from "@hopper-ui/styled-system"; | ||
import clsx from "clsx"; | ||
import { forwardRef, type CSSProperties, type ForwardedRef } from "react"; | ||
import { HeaderContext, useContextProps } from "react-aria-components"; | ||
|
||
import { ContentContext, FooterContext } from "../../layout/index.ts"; | ||
import { cssModule, SlotProvider, type BaseComponentDOMProps } from "../../utils/index.ts"; | ||
|
||
import { CardContext } from "./CardContext.ts"; | ||
|
||
import styles from "./Card.module.css"; | ||
|
||
export const GlobalCardCssSelector = "hop-Card"; | ||
|
||
export interface CardProps extends StyledComponentProps<BaseComponentDOMProps> { | ||
variant?: "main" | "second-level"; | ||
} | ||
|
||
const Card = (props: CardProps, ref: ForwardedRef<HTMLElement>) => { | ||
[props, ref] = useContextProps(props, ref, CardContext); | ||
const { stylingProps, ...ownProps } = useStyledSystem(props); | ||
const { | ||
className, | ||
children, | ||
style, | ||
slot, | ||
variant = "main", | ||
...otherProps | ||
} = ownProps; | ||
|
||
const classNames = clsx( | ||
GlobalCardCssSelector, | ||
cssModule( | ||
styles, | ||
"hop-Card", | ||
variant | ||
), | ||
stylingProps.className, | ||
className | ||
); | ||
|
||
const mergedStyles: CSSProperties = { | ||
...style, | ||
...stylingProps.style | ||
}; | ||
|
||
return ( | ||
<section | ||
ref={ref} | ||
className={classNames} | ||
style={mergedStyles} | ||
slot={slot ?? undefined} | ||
{...otherProps} | ||
> | ||
<SlotProvider values={[ | ||
[HeaderContext, { | ||
className: styles["hop-Card__header"] | ||
}], | ||
[ContentContext, { | ||
className: styles["hop-Card__content"] | ||
}], | ||
[FooterContext, { | ||
className: styles["hop-Card__footer"] | ||
}] | ||
]} | ||
> | ||
{children} | ||
</SlotProvider> | ||
</section> | ||
); | ||
}; | ||
|
||
/** | ||
* The Card component represents a Card within a Hopper container such as a Modal or Card. | ||
* | ||
* [View Documentation](TODO) | ||
*/ | ||
const _Card = forwardRef<HTMLElement, CardProps>(Card); | ||
_Card.displayName = "Card"; | ||
|
||
export { _Card as Card }; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
import { createContext } from "react"; | ||
import type { ContextValue } from "react-aria-components"; | ||
|
||
import type { CardProps } from "./Card.tsx"; | ||
|
||
export const CardContext = createContext<ContextValue<CardProps, HTMLElement>>({}); | ||
|
||
CardContext.displayName = "CardContext"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export * from "./Card.tsx"; | ||
export * from "./CardContext.ts"; | ||
|
64 changes: 64 additions & 0 deletions
64
packages/components/src/Card/tests/chromatic/Card.stories.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
import type { Meta, StoryObj } from "@storybook/react"; | ||
|
||
import { Header } from "../../../Header/index.ts"; | ||
import { Content, Footer } from "../../../layout/index.ts"; | ||
import { Card } from "../../src/Card.tsx"; | ||
|
||
const meta = { | ||
title: "Components/Card", | ||
component: Card | ||
} satisfies Meta<typeof Card>; | ||
|
||
export default meta; | ||
|
||
type Story = StoryObj<typeof meta>; | ||
|
||
export const Main = { | ||
render: props => ( | ||
<Card {...props}> | ||
<Header> | ||
Header | ||
</Header> | ||
<Content> | ||
Content | ||
</Content> | ||
<Footer> | ||
Footer | ||
</Footer> | ||
</Card> | ||
) | ||
} satisfies Story; | ||
|
||
export const SecondLevel = { | ||
render: props => ( | ||
<Card variant="second-level" {...props}> | ||
<Header> | ||
Header | ||
</Header> | ||
<Content> | ||
Content | ||
</Content> | ||
<Footer> | ||
Footer | ||
</Footer> | ||
</Card> | ||
) | ||
} satisfies Story; | ||
|
||
export const EmbeddedCard = { | ||
render: props => ( | ||
<Card variant="second-level" {...props}> | ||
<Header> | ||
Header | ||
</Header> | ||
<Content> | ||
<Card> | ||
Embedded | ||
</Card> | ||
</Content> | ||
<Footer> | ||
Footer | ||
</Footer> | ||
</Card> | ||
) | ||
} satisfies Story; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
/** | ||
* @jest-environment node | ||
*/ | ||
import { renderToString } from "react-dom/server"; | ||
|
||
import { Card } from "../../src/Card.tsx"; | ||
|
||
describe("Card", () => { | ||
it("should render on the server", () => { | ||
const renderOnServer = () => | ||
renderToString( | ||
<Card>Text</Card> | ||
); | ||
|
||
expect(renderOnServer).not.toThrow(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
import { render, screen } from "@hopper-ui/test-utils"; | ||
import { createRef } from "react"; | ||
|
||
import { Card } from "../../src/Card.tsx"; | ||
import { CardContext } from "../../src/CardContext.ts"; | ||
|
||
describe("Card", () => { | ||
it("should render with default class", () => { | ||
render(<Card data-testid="Card">12</Card>); | ||
|
||
const element = screen.getByTestId("Card"); | ||
expect(element).toHaveClass("hop-Card"); | ||
}); | ||
|
||
it("should support custom class", () => { | ||
render(<Card data-testid="Card" className="test">12</Card>); | ||
|
||
const element = screen.getByTestId("Card"); | ||
expect(element).toHaveClass("hop-Card"); | ||
expect(element).toHaveClass("test"); | ||
}); | ||
|
||
it("should support custom style", () => { | ||
render(<Card data-testid="Card" marginTop="stack-sm" style={{ marginBottom: "13px" }} >12</Card>); | ||
|
||
const element = screen.getByTestId("Card"); | ||
expect(element).toHaveStyle({ marginTop: "var(--hop-space-stack-sm)", marginBottom: "13px" }); | ||
}); | ||
|
||
it("should support DOM props", () => { | ||
render(<Card data-testid="Card" data-foo="bar">12</Card>); | ||
|
||
const element = screen.getByTestId("Card"); | ||
expect(element).toHaveAttribute("data-foo", "bar"); | ||
}); | ||
|
||
it("should support slots", () => { | ||
render( | ||
<CardContext.Provider value={{ slots: { test: { "aria-label": "test" } } }}> | ||
<Card data-testid="Card" slot="test">12</Card> | ||
</CardContext.Provider> | ||
); | ||
|
||
const element = screen.getByTestId("Card"); | ||
expect(element).toHaveAttribute("slot", "test"); | ||
expect(element).toHaveAttribute("aria-label", "test"); | ||
}); | ||
|
||
it("should support refs", () => { | ||
const ref = createRef<HTMLElement>(); | ||
render(<Card data-testid="Card" ref={ref}>12</Card>); | ||
|
||
expect(ref.current).not.toBeNull(); | ||
expect(ref.current instanceof HTMLElement).toBeTruthy(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters