diff --git a/src/providers/Authentication.tsx b/src/providers/Authentication.tsx index c981f7f..4aa858b 100644 --- a/src/providers/Authentication.tsx +++ b/src/providers/Authentication.tsx @@ -1,21 +1,48 @@ import { ReactNode, createContext, useState } from "react"; +/** + * A simple mock user + */ type User = { + /** + * The full name of the user + */ name: string; + /** + * A url to a user avatar image + */ avatar?: string; + /** + * A username + */ username?: string; }; +/** + * Stubbed out authentication context + */ export const AuthenticationContext = createContext<{ + /** + * The current user. unauthenticated session if null. + */ currentUser: User | null; + /** + * Method to log a user in + */ login: (userData: User) => void; + /** + * Method to log a user out + */ logout: () => void; }>({ currentUser: null, - login: (_) => {}, + login: (_userData: User) => {}, logout: () => {}, }); +/** + * Stubbed out authentication provider + */ export function AuthenticationProvider({ children }: { children?: ReactNode }) { const [currentUser, setCurrentUser] = useState(null); diff --git a/src/stories/ui/components/Cards.stories.tsx b/src/stories/ui/components/Cards.stories.tsx index 0c1c675..b2f4ca4 100644 --- a/src/stories/ui/components/Cards.stories.tsx +++ b/src/stories/ui/components/Cards.stories.tsx @@ -58,7 +58,7 @@ export const Default: StoryObj< /> ) : undefined } - interaction={ + interactionProps={ _interaction ? { "aria-label": "Visit something nice about this card", diff --git a/src/ui/components/Cards/Cards.tsx b/src/ui/components/Cards/Cards.tsx index f1353db..f2e90ba 100644 --- a/src/ui/components/Cards/Cards.tsx +++ b/src/ui/components/Cards/Cards.tsx @@ -18,18 +18,39 @@ import { AnchorOrButton, AnchorOrButtonProps } from "ui/utils/AnchorOrButton"; import "./cards.css"; export type CardProps = ComponentPropsWithoutRef<"div"> & { + /** + * The initial direction of the card. + * All cards become vertical on mobile. + */ direction?: "horizontal" | "vertical"; - interaction?: Omit & { + /** + * The interaction props for the Card. + * If present, the card itself is pressable. + * AnchorOrButtonProps extend either button or anchor behavior. + */ + interactionProps?: Omit & { "aria-label": string; }; + /** + * An asset for the card. + * Can be an Icon or an Image instance. + */ asset?: React.ReactNode; + /** + * Style variation of the card. + * stroke and padded both add spacing around the card, default is unpadded. + */ variant?: "default" | "stroke" | "padded"; }; + +/** + * The basic card generic component that can be used to create vanity card components. + */ export function Card({ children, className, direction = "vertical", - interaction, + interactionProps, variant = "default", asset, ...props @@ -44,20 +65,42 @@ export function Card({
{asset &&
{asset}
}
{children}
- {interaction && ( - + {interactionProps && ( + )}
); } export type PricingCardProps = { + /** + * The heading for the price point + */ heading: string; + /** + * The price excluding currency + */ price: number; + /** + * A list of items to appear in a bulleted list + */ items: string[]; + /** + * The text labeling the action button + */ action: string; + /** + * The action of the button. + */ onAction: () => void; }; + +/** + * A card that demonstrates price point and value, often in comparison to other cards. + */ export function PricingCard({ heading, action, @@ -86,11 +129,27 @@ export function PricingCard({ } export type ProductInfoCardProps = Pick & { + /** + * The product name + */ heading: string; + /** + * The price excluding currency + */ price: number; + /** + * The text labeling the action button + */ action: string; + /** + * The action for the button + */ onAction: () => void; }; + +/** + * A card that demonstrates product information with a CTA + */ export function ProductInfoCard({ asset, heading, @@ -113,12 +172,31 @@ export function ProductInfoCard({ } export type TestimonialCardProps = { + /** + * The testimonial quote + */ heading: string; + /** + * The name of the author + */ name: string; + /** + * The username of the author + */ username: string; + /** + * The initials of the author + */ initials?: AvatarProps["initials"]; + /** + * An image url for the author + */ src?: AvatarProps["src"]; }; + +/** + * A card demonstrating a quotation from someone + */ export function TestimonialCard({ heading, name,