Skip to content

Commit

Permalink
Add Sidebar component
Browse files Browse the repository at this point in the history
  • Loading branch information
piotrkulpinski committed Jan 15, 2024
1 parent 43cd8d6 commit f1bcf97
Show file tree
Hide file tree
Showing 7 changed files with 123 additions and 19 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"@babel/preset-env": "7.23.7",
"@babel/preset-react": "7.23.3",
"@babel/preset-typescript": "^7.23.3",
"@curiousleaf/utils": "^1.0.12",
"@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-alert-dialog": "^1.0.5",
"@radix-ui/react-avatar": "^1.0.4",
Expand Down
14 changes: 7 additions & 7 deletions src/ui/AvatarGroup/AvatarGroup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,6 @@ export type AvatarGroupProps = HTMLAttributes<AvatarGroupElement> &
previousOnTop?: boolean
}

type AvatarGroupLabelProps = ComponentPropsWithoutRef<typeof Avatar> & {
/**
* The label to display.
*/
label?: ReactNode
}

export const AvatarGroupRoot = forwardRef<AvatarGroupElement, AvatarGroupProps>((props, ref) => {
const { children, className, size, ...rest } = props

Expand All @@ -52,6 +45,13 @@ export const AvatarGroupRoot = forwardRef<AvatarGroupElement, AvatarGroupProps>(
)
})

type AvatarGroupLabelProps = ComponentPropsWithoutRef<typeof Avatar> & {
/**
* The label to display.
*/
label?: ReactNode
}

const AvatarGroupLabel = forwardRef<AvatarElement, AvatarGroupLabelProps>(
({ children, className, label, ...rest }, ref) => {
return (
Expand Down
28 changes: 16 additions & 12 deletions src/ui/FeatureCard/FeatureCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { forwardRef, isValidElement } from "react"
import type { ButtonHTMLAttributes, HTMLAttributes } from "react"

import { useTheme } from "~/providers"
import { type VariantProps } from "~/shared/cva"
import { cx, type VariantProps } from "~/shared/cva"
import { Slottable } from "~/utils/Slottable"

import { featureCardCloserVariants, featureCardVariants } from "./FeatureCard.variants"
Expand All @@ -25,15 +25,6 @@ export type FeatureCardProps = HTMLAttributes<FeatureCardElement> &
closer?: boolean
}

type FeatureCardCloserProps = ButtonHTMLAttributes<HTMLButtonElement> &
VariantProps<typeof featureCardCloserVariants> & {
/**
* If set to `true`, the button will be rendered as a child within the component.
* This child component must be a valid React component.
*/
asChild?: boolean
}

const FeatureCardRoot = forwardRef<FeatureCardElement, FeatureCardProps>((props, ref) => {
const { className, asChild, theme: propTheme, variant, ...rest } = props

Expand All @@ -44,18 +35,31 @@ const FeatureCardRoot = forwardRef<FeatureCardElement, FeatureCardProps>((props,
const Component = useAsChild ? Slot : "div"

return (
<Component className={featureCardVariants({ theme, variant, className })} ref={ref} {...rest} />
<Component
className={cx(featureCardVariants({ theme, variant, className }))}
ref={ref}
{...rest}
/>
)
})

type FeatureCardCloserProps = ButtonHTMLAttributes<HTMLButtonElement> &
VariantProps<typeof featureCardCloserVariants> & {
/**
* If set to `true`, the button will be rendered as a child within the component.
* This child component must be a valid React component.
*/
asChild?: boolean
}

const FeatureCardCloser = forwardRef<HTMLButtonElement, FeatureCardCloserProps>((props, ref) => {
const { children, className, asChild, ...rest } = props

const useAsChild = asChild && isValidElement(children)
const Component = useAsChild ? Slot : "button"

return (
<Component ref={ref} className={featureCardCloserVariants({ className })} {...rest}>
<Component ref={ref} className={cx(featureCardCloserVariants({ className }))} {...rest}>
{useAsChild ? children : <IconX />}
</Component>
)
Expand Down
34 changes: 34 additions & 0 deletions src/ui/Sidebar/Sidebar.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import type { Meta, StoryObj } from "@storybook/react"

import { FeatureCard } from "~/ui/FeatureCard"
import { default as FeatureCardDefault } from "~/ui/FeatureCard/FeatureCard.stories"

import { Sidebar } from "./Sidebar"

type Story = StoryObj<typeof Sidebar>

// Meta
export default {
title: "UI/Sidebar",
component: Sidebar,
args: {
...Sidebar.defaultProps,
children: (
<>
Witam
<Sidebar.Separator />
<div className="flex-1" />
<FeatureCard theme="gray" variant="outline" closer>
{FeatureCardDefault.args.children}
</FeatureCard>
<Sidebar.Separator />
Żegnam
</>
),
},
} satisfies Meta

// Stories
export const Default = {
args: {},
} satisfies Story
30 changes: 30 additions & 0 deletions src/ui/Sidebar/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { forwardRef } from "react"
import type { HTMLAttributes } from "react"

import { cx, type VariantProps } from "~/shared/cva"

import { sidebarSeparatorVariants, sidebarVariants } from "./Sidebar.variants"

export type SidebarElement = HTMLDivElement

export type SidebarProps = HTMLAttributes<SidebarElement> & VariantProps<typeof sidebarVariants>

const SidebarBase = forwardRef<SidebarElement, SidebarProps>((props, ref) => {
const { className, ...rest } = props

return <div className={cx(sidebarVariants({ className }))} ref={ref} {...rest} />
})

const SidebarSeparator = forwardRef<HTMLHRElement, HTMLAttributes<HTMLHRElement>>((props, ref) => {
const { className, ...rest } = props

return <hr className={cx(sidebarSeparatorVariants({ className }))} ref={ref} {...rest} />
})

export const Sidebar = Object.assign(SidebarBase, {
Separator: SidebarSeparator,
})

Sidebar.defaultProps = {}

Sidebar.displayName = "Sidebar"
33 changes: 33 additions & 0 deletions src/ui/Sidebar/Sidebar.variants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { cva } from "~/shared/cva"

export const sidebarVariants = cva({
base: "sticky top-0 z-40 flex h-screen w-72 shrink-0 flex-col gap-y-5 overflow-y-scroll border-r p-5",

variants: {
theme: {
blue: "",
orange: "",
red: "",
yellow: "",
green: "",
purple: "",
pink: "",
teal: "",
gray: "",
},
variant: {
solid: "",
soft: "",
outline: "border-gray-200",
},
},

defaultVariants: {
theme: "gray",
variant: "soft",
},
})

export const sidebarSeparatorVariants = cva({
base: "-mx-5",
})
2 changes: 2 additions & 0 deletions src/ui/Sidebar/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export { Sidebar } from "./Sidebar"
export type { SidebarProps, SidebarElement } from "./Sidebar"

0 comments on commit f1bcf97

Please sign in to comment.