@neoptocom/neopto-ui 1.4.3 → 1.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1391,6 +1391,60 @@ MessageBubble.displayName = "MessageBubble";
1391
1391
  function Separator({ className = "" }) {
1392
1392
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `w-full my-1.5 h-px bg-[var(--border)] ${className}` });
1393
1393
  }
1394
+ var Breadcrumb = ({
1395
+ items,
1396
+ showHomeIcon = false,
1397
+ className = ""
1398
+ }) => {
1399
+ if (!items || items.length === 0) {
1400
+ return null;
1401
+ }
1402
+ return /* @__PURE__ */ jsxRuntime.jsx("nav", { "aria-label": "Breadcrumb", className, children: /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "flex items-center flex-wrap", children: items.map((item, index) => {
1403
+ const isLast = index === items.length - 1;
1404
+ const isFirst = index === 0;
1405
+ return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-center", children: [
1406
+ item.href && !isLast ? /* @__PURE__ */ jsxRuntime.jsxs(
1407
+ "a",
1408
+ {
1409
+ href: item.href,
1410
+ onClick: (e) => {
1411
+ if (item.onClick) {
1412
+ e.preventDefault();
1413
+ item.onClick();
1414
+ }
1415
+ },
1416
+ className: "group flex items-center gap-1 cursor-pointer text-[var(--muted-fg)]",
1417
+ children: [
1418
+ isFirst && showHomeIcon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "home", size: "sm" }),
1419
+ item.icon && !showHomeIcon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: item.icon, size: "sm" }),
1420
+ /* @__PURE__ */ jsxRuntime.jsx(Typo, { variant: "label-md", bold: "semibold", className: "group-hover:underline", children: item.label })
1421
+ ]
1422
+ }
1423
+ ) : /* @__PURE__ */ jsxRuntime.jsxs(
1424
+ "span",
1425
+ {
1426
+ className: `group flex items-center gap-1 ${isLast ? "text-[var(--info)]" : "text-[var(--muted-fg)]"} ${item.onClick && !isLast ? "cursor-pointer" : ""}`,
1427
+ onClick: item.onClick,
1428
+ role: item.onClick && !isLast ? "button" : void 0,
1429
+ tabIndex: item.onClick && !isLast ? 0 : void 0,
1430
+ onKeyDown: item.onClick && !isLast ? (e) => {
1431
+ if (e.key === "Enter" || e.key === " ") {
1432
+ e.preventDefault();
1433
+ item.onClick?.();
1434
+ }
1435
+ } : void 0,
1436
+ "aria-current": isLast ? "page" : void 0,
1437
+ children: [
1438
+ isFirst && showHomeIcon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "home", size: "sm" }),
1439
+ item.icon && !showHomeIcon && /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: item.icon, size: "sm" }),
1440
+ /* @__PURE__ */ jsxRuntime.jsx(Typo, { variant: "label-md", bold: isLast ? "bold" : "semibold", className: item.onClick && !isLast ? "group-hover:underline" : "", children: item.label })
1441
+ ]
1442
+ }
1443
+ ),
1444
+ !isLast && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[var(--muted-fg)]", children: /* @__PURE__ */ jsxRuntime.jsx(Icon, { name: "chevron_right", size: "md" }) })
1445
+ ] }, index);
1446
+ }) }) });
1447
+ };
1394
1448
 
1395
1449
  exports.AgentButton = AgentButton_default;
1396
1450
  exports.AnimatedBgCircle = AnimatedBgCircle_default;
@@ -1400,6 +1454,7 @@ exports.Autocomplete = Autocomplete;
1400
1454
  exports.Avatar = Avatar;
1401
1455
  exports.AvatarGroup = AvatarGroup;
1402
1456
  exports.BackgroundBlur = BackgroundBlur;
1457
+ exports.Breadcrumb = Breadcrumb;
1403
1458
  exports.Button = Button;
1404
1459
  exports.Card = Card;
1405
1460
  exports.Chip = Chip;
package/dist/index.d.cts CHANGED
@@ -1,5 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
+ import React__default from 'react';
3
4
 
4
5
  declare const bgLight: string;
5
6
  declare const bgDark: string;
@@ -333,4 +334,38 @@ type SeparatorProps = {
333
334
  };
334
335
  declare function Separator({ className }: SeparatorProps): react_jsx_runtime.JSX.Element;
335
336
 
336
- export { AgentButton, type AgentButtonProps, AnimatedBgCircle, AnimatedBgRectangle, AppBackground, type AppBackgroundProps, Autocomplete, type AutocompleteOption, type AutocompleteProps, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, BackgroundBlur, type BackgroundBlurProps, Button, type ButtonProps, Card, type CardProps, Chip, type ChipProps, Counter, type CounterProps, Icon, IconButton, type IconButtonProps, type IconProps, Input, type InputProps, MessageBubble, type MessageBubbleProps, Modal, type ModalProps, Search, type SearchOption, type SearchProps, Separator, type SeparatorProps, Skeleton, type SkeletonProps, Textarea, type TextareaProps, Typo, type TypoProps, type TypoVariant, type TypoWeight, index as assets };
337
+ interface BreadcrumbItem {
338
+ /** Label to display */
339
+ label: string;
340
+ /** Optional href for navigation */
341
+ href?: string;
342
+ /** Optional icon name (Material Symbols) */
343
+ icon?: string;
344
+ /** Optional click handler */
345
+ onClick?: () => void;
346
+ }
347
+ interface BreadcrumbProps {
348
+ /** Array of breadcrumb items */
349
+ items: BreadcrumbItem[];
350
+ /** Whether to show home icon on first item */
351
+ showHomeIcon?: boolean;
352
+ /** Additional CSS classes */
353
+ className?: string;
354
+ }
355
+ /**
356
+ * Breadcrumb navigation component
357
+ *
358
+ * @example
359
+ * ```tsx
360
+ * <Breadcrumb
361
+ * items={[
362
+ * { label: "Home", href: "/" },
363
+ * { label: "Products", href: "/products" },
364
+ * { label: "Category" }
365
+ * ]}
366
+ * />
367
+ * ```
368
+ */
369
+ declare const Breadcrumb: React__default.FC<BreadcrumbProps>;
370
+
371
+ export { AgentButton, type AgentButtonProps, AnimatedBgCircle, AnimatedBgRectangle, AppBackground, type AppBackgroundProps, Autocomplete, type AutocompleteOption, type AutocompleteProps, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, BackgroundBlur, type BackgroundBlurProps, Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, Button, type ButtonProps, Card, type CardProps, Chip, type ChipProps, Counter, type CounterProps, Icon, IconButton, type IconButtonProps, type IconProps, Input, type InputProps, MessageBubble, type MessageBubbleProps, Modal, type ModalProps, Search, type SearchOption, type SearchProps, Separator, type SeparatorProps, Skeleton, type SkeletonProps, Textarea, type TextareaProps, Typo, type TypoProps, type TypoVariant, type TypoWeight, index as assets };
package/dist/index.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import * as React from 'react';
3
+ import React__default from 'react';
3
4
 
4
5
  declare const bgLight: string;
5
6
  declare const bgDark: string;
@@ -333,4 +334,38 @@ type SeparatorProps = {
333
334
  };
334
335
  declare function Separator({ className }: SeparatorProps): react_jsx_runtime.JSX.Element;
335
336
 
336
- export { AgentButton, type AgentButtonProps, AnimatedBgCircle, AnimatedBgRectangle, AppBackground, type AppBackgroundProps, Autocomplete, type AutocompleteOption, type AutocompleteProps, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, BackgroundBlur, type BackgroundBlurProps, Button, type ButtonProps, Card, type CardProps, Chip, type ChipProps, Counter, type CounterProps, Icon, IconButton, type IconButtonProps, type IconProps, Input, type InputProps, MessageBubble, type MessageBubbleProps, Modal, type ModalProps, Search, type SearchOption, type SearchProps, Separator, type SeparatorProps, Skeleton, type SkeletonProps, Textarea, type TextareaProps, Typo, type TypoProps, type TypoVariant, type TypoWeight, index as assets };
337
+ interface BreadcrumbItem {
338
+ /** Label to display */
339
+ label: string;
340
+ /** Optional href for navigation */
341
+ href?: string;
342
+ /** Optional icon name (Material Symbols) */
343
+ icon?: string;
344
+ /** Optional click handler */
345
+ onClick?: () => void;
346
+ }
347
+ interface BreadcrumbProps {
348
+ /** Array of breadcrumb items */
349
+ items: BreadcrumbItem[];
350
+ /** Whether to show home icon on first item */
351
+ showHomeIcon?: boolean;
352
+ /** Additional CSS classes */
353
+ className?: string;
354
+ }
355
+ /**
356
+ * Breadcrumb navigation component
357
+ *
358
+ * @example
359
+ * ```tsx
360
+ * <Breadcrumb
361
+ * items={[
362
+ * { label: "Home", href: "/" },
363
+ * { label: "Products", href: "/products" },
364
+ * { label: "Category" }
365
+ * ]}
366
+ * />
367
+ * ```
368
+ */
369
+ declare const Breadcrumb: React__default.FC<BreadcrumbProps>;
370
+
371
+ export { AgentButton, type AgentButtonProps, AnimatedBgCircle, AnimatedBgRectangle, AppBackground, type AppBackgroundProps, Autocomplete, type AutocompleteOption, type AutocompleteProps, Avatar, AvatarGroup, type AvatarGroupProps, type AvatarProps, BackgroundBlur, type BackgroundBlurProps, Breadcrumb, type BreadcrumbItem, type BreadcrumbProps, Button, type ButtonProps, Card, type CardProps, Chip, type ChipProps, Counter, type CounterProps, Icon, IconButton, type IconButtonProps, type IconProps, Input, type InputProps, MessageBubble, type MessageBubbleProps, Modal, type ModalProps, Search, type SearchOption, type SearchProps, Separator, type SeparatorProps, Skeleton, type SkeletonProps, Textarea, type TextareaProps, Typo, type TypoProps, type TypoVariant, type TypoWeight, index as assets };
package/dist/index.js CHANGED
@@ -1370,5 +1370,59 @@ MessageBubble.displayName = "MessageBubble";
1370
1370
  function Separator({ className = "" }) {
1371
1371
  return /* @__PURE__ */ jsx("div", { className: `w-full my-1.5 h-px bg-[var(--border)] ${className}` });
1372
1372
  }
1373
+ var Breadcrumb = ({
1374
+ items,
1375
+ showHomeIcon = false,
1376
+ className = ""
1377
+ }) => {
1378
+ if (!items || items.length === 0) {
1379
+ return null;
1380
+ }
1381
+ return /* @__PURE__ */ jsx("nav", { "aria-label": "Breadcrumb", className, children: /* @__PURE__ */ jsx("ol", { className: "flex items-center flex-wrap", children: items.map((item, index) => {
1382
+ const isLast = index === items.length - 1;
1383
+ const isFirst = index === 0;
1384
+ return /* @__PURE__ */ jsxs("li", { className: "flex items-center", children: [
1385
+ item.href && !isLast ? /* @__PURE__ */ jsxs(
1386
+ "a",
1387
+ {
1388
+ href: item.href,
1389
+ onClick: (e) => {
1390
+ if (item.onClick) {
1391
+ e.preventDefault();
1392
+ item.onClick();
1393
+ }
1394
+ },
1395
+ className: "group flex items-center gap-1 cursor-pointer text-[var(--muted-fg)]",
1396
+ children: [
1397
+ isFirst && showHomeIcon && /* @__PURE__ */ jsx(Icon, { name: "home", size: "sm" }),
1398
+ item.icon && !showHomeIcon && /* @__PURE__ */ jsx(Icon, { name: item.icon, size: "sm" }),
1399
+ /* @__PURE__ */ jsx(Typo, { variant: "label-md", bold: "semibold", className: "group-hover:underline", children: item.label })
1400
+ ]
1401
+ }
1402
+ ) : /* @__PURE__ */ jsxs(
1403
+ "span",
1404
+ {
1405
+ className: `group flex items-center gap-1 ${isLast ? "text-[var(--info)]" : "text-[var(--muted-fg)]"} ${item.onClick && !isLast ? "cursor-pointer" : ""}`,
1406
+ onClick: item.onClick,
1407
+ role: item.onClick && !isLast ? "button" : void 0,
1408
+ tabIndex: item.onClick && !isLast ? 0 : void 0,
1409
+ onKeyDown: item.onClick && !isLast ? (e) => {
1410
+ if (e.key === "Enter" || e.key === " ") {
1411
+ e.preventDefault();
1412
+ item.onClick?.();
1413
+ }
1414
+ } : void 0,
1415
+ "aria-current": isLast ? "page" : void 0,
1416
+ children: [
1417
+ isFirst && showHomeIcon && /* @__PURE__ */ jsx(Icon, { name: "home", size: "sm" }),
1418
+ item.icon && !showHomeIcon && /* @__PURE__ */ jsx(Icon, { name: item.icon, size: "sm" }),
1419
+ /* @__PURE__ */ jsx(Typo, { variant: "label-md", bold: isLast ? "bold" : "semibold", className: item.onClick && !isLast ? "group-hover:underline" : "", children: item.label })
1420
+ ]
1421
+ }
1422
+ ),
1423
+ !isLast && /* @__PURE__ */ jsx("span", { className: "text-[var(--muted-fg)]", children: /* @__PURE__ */ jsx(Icon, { name: "chevron_right", size: "md" }) })
1424
+ ] }, index);
1425
+ }) }) });
1426
+ };
1373
1427
 
1374
- export { AgentButton_default as AgentButton, AnimatedBgCircle_default as AnimatedBgCircle, AnimatedBgRectangle_default as AnimatedBgRectangle, AppBackground, Autocomplete, Avatar, AvatarGroup, BackgroundBlur, Button, Card, Chip, Counter, Icon, IconButton, Input, MessageBubble, Modal, Search, Separator, Skeleton, Textarea, Typo, assets_exports as assets };
1428
+ export { AgentButton_default as AgentButton, AnimatedBgCircle_default as AnimatedBgCircle, AnimatedBgRectangle_default as AnimatedBgRectangle, AppBackground, Autocomplete, Avatar, AvatarGroup, BackgroundBlur, Breadcrumb, Button, Card, Chip, Counter, Icon, IconButton, Input, MessageBubble, Modal, Search, Separator, Skeleton, Textarea, Typo, assets_exports as assets };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neoptocom/neopto-ui",
3
- "version": "1.4.3",
3
+ "version": "1.4.4",
4
4
  "private": false,
5
5
  "description": "A modern React component library built with Tailwind CSS v4 and TypeScript. Features dark mode, design tokens, and comprehensive Storybook documentation. Requires Tailwind v4+.",
6
6
  "keywords": [
@@ -0,0 +1,110 @@
1
+ import React from "react";
2
+ import Icon from "./Icon";
3
+ import Typo from "./Typo";
4
+
5
+ export interface BreadcrumbItem {
6
+ /** Label to display */
7
+ label: string;
8
+ /** Optional href for navigation */
9
+ href?: string;
10
+ /** Optional icon name (Material Symbols) */
11
+ icon?: string;
12
+ /** Optional click handler */
13
+ onClick?: () => void;
14
+ }
15
+
16
+ export interface BreadcrumbProps {
17
+ /** Array of breadcrumb items */
18
+ items: BreadcrumbItem[];
19
+ /** Whether to show home icon on first item */
20
+ showHomeIcon?: boolean;
21
+ /** Additional CSS classes */
22
+ className?: string;
23
+ }
24
+
25
+ /**
26
+ * Breadcrumb navigation component
27
+ *
28
+ * @example
29
+ * ```tsx
30
+ * <Breadcrumb
31
+ * items={[
32
+ * { label: "Home", href: "/" },
33
+ * { label: "Products", href: "/products" },
34
+ * { label: "Category" }
35
+ * ]}
36
+ * />
37
+ * ```
38
+ */
39
+ export const Breadcrumb: React.FC<BreadcrumbProps> = ({
40
+ items,
41
+ showHomeIcon = false,
42
+ className = "",
43
+ }) => {
44
+ if (!items || items.length === 0) {
45
+ return null;
46
+ }
47
+
48
+ return (
49
+ <nav aria-label="Breadcrumb" className={className}>
50
+ <ol className="flex items-center flex-wrap">
51
+ {items.map((item, index) => {
52
+ const isLast = index === items.length - 1;
53
+ const isFirst = index === 0;
54
+
55
+ return (
56
+ <li key={index} className="flex items-center">
57
+ {/* Breadcrumb Item */}
58
+ {item.href && !isLast ? (
59
+ <a
60
+ href={item.href}
61
+ onClick={(e) => {
62
+ if (item.onClick) {
63
+ e.preventDefault();
64
+ item.onClick();
65
+ }
66
+ }}
67
+ className="group flex items-center gap-1 cursor-pointer text-[var(--muted-fg)]"
68
+ >
69
+ {isFirst && showHomeIcon && <Icon name="home" size="sm" />}
70
+ {item.icon && !showHomeIcon && <Icon name={item.icon} size="sm" />}
71
+ <Typo variant="label-md" bold="semibold" className="group-hover:underline">{item.label}</Typo>
72
+ </a>
73
+ ) : (
74
+ <span
75
+ className={`group flex items-center gap-1 ${isLast ? "text-[var(--info)]" : "text-[var(--muted-fg)]"} ${item.onClick && !isLast ? "cursor-pointer" : ""}`}
76
+ onClick={item.onClick}
77
+ role={item.onClick && !isLast ? "button" : undefined}
78
+ tabIndex={item.onClick && !isLast ? 0 : undefined}
79
+ onKeyDown={
80
+ item.onClick && !isLast
81
+ ? (e) => {
82
+ if (e.key === "Enter" || e.key === " ") {
83
+ e.preventDefault();
84
+ item.onClick?.();
85
+ }
86
+ }
87
+ : undefined
88
+ }
89
+ aria-current={isLast ? "page" : undefined}
90
+ >
91
+ {isFirst && showHomeIcon && <Icon name="home" size="sm" />}
92
+ {item.icon && !showHomeIcon && <Icon name={item.icon} size="sm" />}
93
+ <Typo variant="label-md" bold={isLast ? "bold" : "semibold"} className={item.onClick && !isLast ? "group-hover:underline" : ""}>{item.label}</Typo>
94
+ </span>
95
+ )}
96
+
97
+ {/* Separator */}
98
+ {!isLast && (
99
+ <span className="text-[var(--muted-fg)]">
100
+ <Icon name="chevron_right" size="md" />
101
+ </span>
102
+ )}
103
+ </li>
104
+ );
105
+ })}
106
+ </ol>
107
+ </nav>
108
+ );
109
+ };
110
+
package/src/index.ts CHANGED
@@ -22,6 +22,7 @@ export { default as Counter } from "./components/Counter";
22
22
  export * from "./components/Chat";
23
23
  export * from "./components/MessageBubble";
24
24
  export * from "./components/Separator";
25
+ export { Breadcrumb } from "./components/Breadcrumb";
25
26
 
26
27
  // Types
27
28
  export type { AppBackgroundProps } from "./components/AppBackground";
@@ -43,4 +44,5 @@ export type { ChipProps } from "./components/Chip";
43
44
  export type { CounterProps } from "./components/Counter";
44
45
  export type { AgentButtonProps } from "./components/Chat";
45
46
  export type { MessageBubbleProps } from "./components/MessageBubble";
46
- export type { SeparatorProps } from "./components/Separator";
47
+ export type { SeparatorProps } from "./components/Separator";
48
+ export type { BreadcrumbProps, BreadcrumbItem } from "./components/Breadcrumb";
@@ -0,0 +1,270 @@
1
+ import type { Meta, StoryObj } from "@storybook/react";
2
+ import { useState } from "react";
3
+ import { Breadcrumb } from "../components/Breadcrumb";
4
+
5
+ const meta: Meta<typeof Breadcrumb> = {
6
+ title: "Components/Breadcrumb",
7
+ component: Breadcrumb,
8
+ parameters: {
9
+ layout: "centered",
10
+ },
11
+ tags: ["autodocs"],
12
+ argTypes: {
13
+ items: {
14
+ description: "Array of breadcrumb items to display",
15
+ control: { type: "object" },
16
+ },
17
+ showHomeIcon: {
18
+ description: "Show home icon on first item",
19
+ control: { type: "boolean" },
20
+ },
21
+ className: {
22
+ description: "Additional CSS classes",
23
+ control: { type: "text" },
24
+ },
25
+ },
26
+ };
27
+
28
+ export default meta;
29
+ type Story = StoryObj<typeof Breadcrumb>;
30
+
31
+ // Basic Examples
32
+ export const Default: Story = {
33
+ args: {
34
+ items: [
35
+ { label: "Home", href: "/" },
36
+ { label: "Products", href: "/products" },
37
+ { label: "Electronics", href: "/products/electronics" },
38
+ { label: "Laptops" },
39
+ ],
40
+ },
41
+ };
42
+
43
+ export const WithHomeIcon: Story = {
44
+ args: {
45
+ items: [
46
+ { label: "Home", href: "/" },
47
+ { label: "Products", href: "/products" },
48
+ { label: "Electronics" },
49
+ ],
50
+ showHomeIcon: true,
51
+ },
52
+ };
53
+
54
+ export const TwoLevels: Story = {
55
+ args: {
56
+ items: [
57
+ { label: "Home", href: "/" },
58
+ { label: "Current Page" },
59
+ ],
60
+ },
61
+ };
62
+
63
+ export const SingleItem: Story = {
64
+ args: {
65
+ items: [{ label: "Home" }],
66
+ },
67
+ };
68
+
69
+
70
+ // With Icons
71
+ export const WithIcons: Story = {
72
+ args: {
73
+ items: [
74
+ { label: "Home", href: "/", icon: "home" },
75
+ { label: "Settings", href: "/settings", icon: "settings" },
76
+ { label: "Profile", icon: "person" },
77
+ ],
78
+ },
79
+ };
80
+
81
+ export const MixedIcons: Story = {
82
+ args: {
83
+ items: [
84
+ { label: "Dashboard", href: "/", icon: "dashboard" },
85
+ { label: "Projects", href: "/projects", icon: "folder" },
86
+ { label: "Documents", href: "/documents", icon: "description" },
87
+ { label: "Report.pdf" },
88
+ ],
89
+ },
90
+ };
91
+
92
+ // With Click Handlers
93
+ export const WithClickHandlers: Story = {
94
+ args: {
95
+ items: [
96
+ {
97
+ label: "Home",
98
+ onClick: () => alert("Navigating to Home"),
99
+ },
100
+ {
101
+ label: "Products",
102
+ onClick: () => alert("Navigating to Products"),
103
+ },
104
+ {
105
+ label: "Category",
106
+ onClick: () => alert("Navigating to Category"),
107
+ },
108
+ { label: "Item" },
109
+ ],
110
+ },
111
+ };
112
+
113
+ // Interactive Component Navigation (no URL changes)
114
+ export const ComponentNavigation = () => {
115
+ const sections = [
116
+ { id: "account", label: "Account", icon: "person" },
117
+ { id: "security", label: "Security", icon: "lock" },
118
+ { id: "notifications", label: "Notifications", icon: "notifications" },
119
+ { id: "billing", label: "Billing", icon: "payment" },
120
+ ];
121
+
122
+ const [activeSection, setActiveSection] = useState("account");
123
+
124
+ const sectionContent: Record<string, { title: string; description: string }> = {
125
+ account: {
126
+ title: "Account Settings",
127
+ description: "Manage your account information, profile details, and preferences.",
128
+ },
129
+ security: {
130
+ title: "Security Settings",
131
+ description: "Configure password, two-factor authentication, and security preferences.",
132
+ },
133
+ notifications: {
134
+ title: "Notification Preferences",
135
+ description: "Control how and when you receive notifications from our platform.",
136
+ },
137
+ billing: {
138
+ title: "Billing & Subscription",
139
+ description: "View invoices, update payment methods, and manage your subscription.",
140
+ },
141
+ };
142
+
143
+ const breadcrumbItems = [
144
+ {
145
+ label: "Settings",
146
+ icon: "settings",
147
+ onClick: () => setActiveSection("account"),
148
+ },
149
+ ...sections
150
+ .slice(0, sections.findIndex((s) => s.id === activeSection) + 1)
151
+ .map((section, index, arr) => ({
152
+ label: section.label,
153
+ icon: section.icon,
154
+ onClick: index < arr.length - 1 ? () => setActiveSection(section.id) : undefined,
155
+ })),
156
+ ];
157
+
158
+ return (
159
+ <div className="w-full max-w-4xl p-6 space-y-6">
160
+ {/* Breadcrumb Navigation */}
161
+ <Breadcrumb items={breadcrumbItems} />
162
+
163
+ {/* Content Area */}
164
+ <div className="border rounded-lg p-6 space-y-4">
165
+ <h2 className="text-2xl font-semibold">{sectionContent[activeSection].title}</h2>
166
+ <p className="text-gray-600">{sectionContent[activeSection].description}</p>
167
+
168
+ {/* Navigation Buttons */}
169
+ <div className="flex gap-2 pt-4">
170
+ {sections.map((section) => (
171
+ <button
172
+ key={section.id}
173
+ onClick={() => setActiveSection(section.id)}
174
+ className={`px-4 py-2 rounded transition ${
175
+ activeSection === section.id
176
+ ? "bg-blue-500 text-white"
177
+ : "bg-gray-100 hover:bg-gray-200"
178
+ }`}
179
+ >
180
+ {section.label}
181
+ </button>
182
+ ))}
183
+ </div>
184
+ </div>
185
+
186
+ {/* Usage Example Code */}
187
+ <div className="bg-gray-50 p-4 rounded text-sm">
188
+ <p className="font-mono text-xs text-gray-600">
189
+ Current section: <strong>{activeSection}</strong>
190
+ </p>
191
+ <p className="text-xs text-gray-500 mt-2">
192
+ Click any breadcrumb item or button to navigate between sections without changing the URL.
193
+ </p>
194
+ </div>
195
+ </div>
196
+ );
197
+ };
198
+
199
+ // Long Breadcrumb
200
+ export const LongBreadcrumb: Story = {
201
+ args: {
202
+ items: [
203
+ { label: "Home", href: "/" },
204
+ { label: "Products", href: "/products" },
205
+ { label: "Electronics", href: "/products/electronics" },
206
+ { label: "Computers", href: "/products/electronics/computers" },
207
+ { label: "Laptops", href: "/products/electronics/computers/laptops" },
208
+ { label: "Gaming Laptops", href: "/products/electronics/computers/laptops/gaming" },
209
+ { label: "ASUS ROG" },
210
+ ],
211
+ },
212
+ };
213
+
214
+ // Navigation Patterns
215
+ export const FileSystem: Story = {
216
+ args: {
217
+ items: [
218
+ { label: "Root", href: "/", icon: "folder" },
219
+ { label: "Documents", href: "/documents", icon: "folder" },
220
+ { label: "Projects", href: "/documents/projects", icon: "folder" },
221
+ { label: "2024", href: "/documents/projects/2024", icon: "folder" },
222
+ { label: "report.pdf", icon: "description" },
223
+ ],
224
+ },
225
+ };
226
+
227
+ export const AdminPanel: Story = {
228
+ args: {
229
+ items: [
230
+ { label: "Dashboard", href: "/", icon: "dashboard" },
231
+ { label: "Users", href: "/users", icon: "group" },
232
+ { label: "Edit User", icon: "edit" },
233
+ ],
234
+ },
235
+ };
236
+
237
+ export const ECommerce: Story = {
238
+ args: {
239
+ items: [
240
+ { label: "Home", href: "/" },
241
+ { label: "Electronics", href: "/electronics" },
242
+ { label: "Smartphones", href: "/electronics/smartphones" },
243
+ { label: "iPhone 15 Pro" },
244
+ ],
245
+ showHomeIcon: true,
246
+ },
247
+ };
248
+
249
+ // Edge Cases
250
+ export const VeryLongLabels: Story = {
251
+ args: {
252
+ items: [
253
+ { label: "Home", href: "/" },
254
+ { label: "This is a very long breadcrumb label that might wrap", href: "/long" },
255
+ { label: "Another extremely long label for testing purposes" },
256
+ ],
257
+ },
258
+ };
259
+
260
+ export const WithCustomClassName: Story = {
261
+ args: {
262
+ items: [
263
+ { label: "Home", href: "/" },
264
+ { label: "Products", href: "/products" },
265
+ { label: "Category" },
266
+ ],
267
+ className: "text-blue-600",
268
+ },
269
+ };
270
+