diff --git a/.changeset/tangy-groups-listen.md b/.changeset/tangy-groups-listen.md new file mode 100644 index 0000000..2c1cbf6 --- /dev/null +++ b/.changeset/tangy-groups-listen.md @@ -0,0 +1,5 @@ +--- +'commerce-toolkit': minor +--- + +Added Breadcrumbs component diff --git a/.cursor/commands/tailwind-downgrade.md b/.cursor/commands/tailwind-downgrade.md index 7abd7f3..652db86 100644 --- a/.cursor/commands/tailwind-downgrade.md +++ b/.cursor/commands/tailwind-downgrade.md @@ -27,13 +27,13 @@ Below is an example: - `
` → `
` -Sometimes you may come across examples that use a fallback value for CSS variables. When that's the case, you'll need to change "()" with "[]" and also wrap ANY CSS variable fallback with the hsl color function (this applies to all color variables like `--background`, `--foreground`, `--contrast-*`, etc.). +Sometimes you may come across examples that use a fallback value for CSS variables. When that's the case, you'll need to change "()" with "[]". Below are examples: -- `bg-(--dropdown-menu-background,var(--background))` → `bg-[var(--dropdown-menu-background,hsl(var(--background)))]` -- `border-(--dropdown-menu-border,var(--contrast-100))` → `border-[var(--dropdown-menu-border,hsl(var(--contrast-100)))]` -- `text-(--custom-text,var(--foreground))` → `text-[var(--custom-text,hsl(var(--foreground)))]` +- `bg-(--dropdown-menu-background,var(--background))` → `bg-[var(--dropdown-menu-background,var(--background))]` +- `border-(--dropdown-menu-border,var(--contrast-100))` → `border-[var(--dropdown-menu-border,var(--contrast-100))]` +- `text-(--custom-text,var(--foreground))` → `text-[var(--custom-text,var(--foreground))]` ## Highlight and Shadow variants @@ -50,5 +50,5 @@ The following CSS variables are included in the Tailwind 4 version: However, in Tailwind 3 we do not have these CSS variables defined. Therefore, when you come across a class name that uses one of these CSS variables it needs to be converted for Tailwind 3 like this: -- `bg-(--alert-success-background,var(--success-highlight))` → `bg-[var(--alert-success-background,color-mix(in_oklab,_hsl(var(--success)),_white_75%))]` -- `text-(--form-status-light-text-success,var(--success-shadow))` → `text-[var(--form-status-light-text-success,color-mix(in_oklab,hsl(var(--success)),black_75%))]` +- `bg-(--alert-success-background,var(--success-highlight))` → `bg-[var(--alert-success-background,color-mix(in_oklab,var(--success),white_75%))]` +- `text-(--form-status-light-text-success,var(--success-shadow))` → `text-[var(--form-status-light-text-success,color-mix(in_oklab,var(--success),black_75%))]` diff --git a/package.json b/package.json index 32273e5..cd01fd3 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,16 @@ "default": "./dist/banner.cjs" } }, + "./breadcrumbs": { + "import": { + "types": "./dist/components/breadcrumbs/primitives.d.ts", + "default": "./dist/breadcrumbs.js" + }, + "require": { + "types": "./dist/components/breadcrumbs/primitives.d.ts", + "default": "./dist/breadcrumbs.cjs" + } + }, "./button-radio-group": { "import": { "types": "./dist/components/button-radio-group/primitives.d.ts", diff --git a/src/components/accordion/archive/archive-accordion.tsx b/src/components/accordion/archive/archive-accordion.tsx deleted file mode 100644 index e8070af..0000000 --- a/src/components/accordion/archive/archive-accordion.tsx +++ /dev/null @@ -1,147 +0,0 @@ -'use client'; - -import * as AccordionPrimitive from '@radix-ui/react-accordion'; -import { clsx } from 'clsx'; -import { ComponentPropsWithoutRef, useEffect, useState } from 'react'; - -export interface AccordionProps extends ComponentPropsWithoutRef { - colorScheme?: 'light' | 'dark'; -} - -/** - * This component supports various CSS variables for theming. Here's a comprehensive list, along - * with their default values: - * - * ```css - * :root { - * --accordion-focus: var(--primary); - * --acordion-light-offset: var(--background); - * --accordion-light-title-text: var(--contrast-400); - * --accordion-light-title-text-hover: var(--foreground); - * --accordion-light-title-icon: var(--contrast-500); - * --accordion-light-title-icon-hover: var(--foreground); - * --accordion-light-content-text: var(--foreground); - * --acordion-dark-offset: var(--foreground); - * --accordion-dark-title-text: var(--contrast-200); - * --accordion-dark-title-text-hover: var(--background); - * --accordion-dark-title-icon: var(--contrast-200); - * --accordion-dark-title-icon-hover: var(--background); - * --accordion-dark-content-text: var(--background); - * --accordion-title-font-family: var(--font-family-mono); - * --accordion-content-font-family: var(--font-family-body); - * } - * ``` - */ -function AccordionItem({ - title, - children, - colorScheme = 'light', - className, - ...props -}: AccordionProps) { - const [isMounted, setIsMounted] = useState(false); - - useEffect(() => { - setIsMounted(true); - }, []); - - return ( - - - -
- {title} -
- -
-
- -
- {children} -
-
-
- ); -} - -function AnimatedChevron({ - className, - ...props -}: React.JSX.IntrinsicAttributes & React.SVGProps) { - return ( - line]:origin-center [&>line]:transition [&>line]:duration-300 [&>line]:ease-out', - className, - )} - viewBox="0 0 10 10" - width={16} - > - {/* Left Line of Chevron */} - - {/* Right Line of Chevron */} - - - ); -} - -const Accordion = AccordionPrimitive.Root; - -export { Accordion, AccordionItem }; diff --git a/src/components/breadcrumbs/breadcrumbs.tsx b/src/components/breadcrumbs/breadcrumbs.tsx new file mode 100644 index 0000000..6f87c46 --- /dev/null +++ b/src/components/breadcrumbs/breadcrumbs.tsx @@ -0,0 +1,69 @@ +import type { ReactNode } from 'react'; + +import { AnimatedUnderline } from '@/components/animated-underline'; +import * as BreadcrumbsPrimitive from '@/components/breadcrumbs'; +import { cn } from '@/lib'; + +interface Breadcrumb { + label: string; + href: string; + asChild?: boolean; + children?: ReactNode; +} + +export interface BreadcrumbsProps { + breadcrumbs: Breadcrumb[]; + className?: string; + ariaLabel?: string; + icon?: { + asChild?: boolean; + children?: ReactNode; + }; +} + +/** + * This component supports various CSS variables for theming. Here's a comprehensive list, along + * with their default values: + * + * ```css + * :root { + * --breadcrumbs-font-family: var(--font-family-body); + * --breadcrumbs-primary-text: var(--foreground); + * --breadcrumbs-secondary-text: var(--contrast-500); + * --breadcrumbs-icon: var(--contrast-500); + * } + * ``` + */ +export function Breadcrumbs({ + breadcrumbs, + className, + ariaLabel = 'Breadcrumb', + icon, +}: BreadcrumbsProps) { + return ( + + + {breadcrumbs.map(({ label, href, asChild, children }, index) => { + if (index < breadcrumbs.length - 1) { + return ( + + + {asChild === true ? children : {label}} + + + {icon?.children} + + + ); + } + + return ( + + {label} + + ); + })} + + + ); +} diff --git a/src/components/breadcrumbs/index.ts b/src/components/breadcrumbs/index.ts new file mode 100644 index 0000000..b76ad83 --- /dev/null +++ b/src/components/breadcrumbs/index.ts @@ -0,0 +1,2 @@ +export { Breadcrumbs, type BreadcrumbsProps } from '@/components/breadcrumbs/breadcrumbs'; +export * from '@/components/breadcrumbs/primitives'; diff --git a/src/components/breadcrumbs/primitives.ts b/src/components/breadcrumbs/primitives.ts new file mode 100644 index 0000000..46624a3 --- /dev/null +++ b/src/components/breadcrumbs/primitives.ts @@ -0,0 +1,24 @@ +export { + BreadcrumbsRoot as Root, + type BreadcrumbsRootProps as RootProps, +} from '@/components/breadcrumbs/primitives/breadcrumbs-root'; +export { + BreadcrumbsList as List, + type BreadcrumbsListProps as ListProps, +} from '@/components/breadcrumbs/primitives/breadcrumbs-list'; +export { + BreadcrumbsItem as Item, + type BreadcrumbsItemProps as ItemProps, +} from '@/components/breadcrumbs/primitives/breadcrumbs-item'; +export { + BreadcrumbsLink as Link, + type BreadcrumbsLinkProps as LinkProps, +} from '@/components/breadcrumbs/primitives/breadcrumbs-link'; +export { + BreadcrumbsIcon as Icon, + type BreadcrumbsIconProps as IconProps, +} from '@/components/breadcrumbs/primitives/breadcrumbs-icon'; +export { + BreadcrumbsCurrent as Current, + type BreadcrumbsCurrentProps as CurrentProps, +} from '@/components/breadcrumbs/primitives/breadcrumbs-current'; diff --git a/src/components/breadcrumbs/primitives/breadcrumbs-current.tsx b/src/components/breadcrumbs/primitives/breadcrumbs-current.tsx new file mode 100644 index 0000000..4a1d056 --- /dev/null +++ b/src/components/breadcrumbs/primitives/breadcrumbs-current.tsx @@ -0,0 +1,20 @@ +import type { ComponentProps } from 'react'; + +import { cn } from '@/lib'; + +export type BreadcrumbsCurrentProps = ComponentProps<'span'>; + +export function BreadcrumbsCurrent({ className, children, ...props }: BreadcrumbsCurrentProps) { + return ( + + {children} + + ); +} diff --git a/src/components/breadcrumbs/primitives/breadcrumbs-icon.tsx b/src/components/breadcrumbs/primitives/breadcrumbs-icon.tsx new file mode 100644 index 0000000..c490519 --- /dev/null +++ b/src/components/breadcrumbs/primitives/breadcrumbs-icon.tsx @@ -0,0 +1,37 @@ +'use client'; + +import { Slot } from '@radix-ui/react-slot'; +import { ChevronRight } from 'lucide-react'; +import type { ReactNode } from 'react'; + +import { cn } from '@/lib'; + +export interface BreadcrumbsIconProps { + asChild?: boolean; + className?: string; + children?: ReactNode; +} + +export function BreadcrumbsIcon({ asChild = false, className, children }: BreadcrumbsIconProps) { + if (asChild) { + return ( + + ); + } + + return ( +