@djangocfg/layouts 1.2.18 → 1.2.19

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@djangocfg/layouts",
3
- "version": "1.2.18",
3
+ "version": "1.2.19",
4
4
  "description": "Layout system and components for Unrealon applications",
5
5
  "author": {
6
6
  "name": "DjangoCFG",
@@ -53,9 +53,9 @@
53
53
  "check": "tsc --noEmit"
54
54
  },
55
55
  "peerDependencies": {
56
- "@djangocfg/api": "^1.2.18",
57
- "@djangocfg/og-image": "^1.2.18",
58
- "@djangocfg/ui": "^1.2.18",
56
+ "@djangocfg/api": "^1.2.19",
57
+ "@djangocfg/og-image": "^1.2.19",
58
+ "@djangocfg/ui": "^1.2.19",
59
59
  "@hookform/resolvers": "^5.2.0",
60
60
  "consola": "^3.4.2",
61
61
  "lucide-react": "^0.468.0",
@@ -76,7 +76,7 @@
76
76
  "vidstack": "0.6.15"
77
77
  },
78
78
  "devDependencies": {
79
- "@djangocfg/typescript-config": "^1.2.18",
79
+ "@djangocfg/typescript-config": "^1.2.19",
80
80
  "@types/node": "^24.7.2",
81
81
  "@types/react": "19.2.2",
82
82
  "@types/react-dom": "19.2.1",
@@ -16,36 +16,36 @@ export interface PackageInfo {
16
16
  /**
17
17
  * Package versions registry
18
18
  * Auto-synced from package.json files
19
- * Last updated: 2025-11-01T07:48:08.580Z
19
+ * Last updated: 2025-11-02T05:58:03.758Z
20
20
  */
21
21
  const PACKAGE_VERSIONS: PackageInfo[] = [
22
22
  {
23
23
  "name": "@djangocfg/ui",
24
- "version": "1.2.18"
24
+ "version": "1.2.19"
25
25
  },
26
26
  {
27
27
  "name": "@djangocfg/api",
28
- "version": "1.2.18"
28
+ "version": "1.2.19"
29
29
  },
30
30
  {
31
31
  "name": "@djangocfg/layouts",
32
- "version": "1.2.18"
32
+ "version": "1.2.19"
33
33
  },
34
34
  {
35
35
  "name": "@djangocfg/markdown",
36
- "version": "1.2.18"
36
+ "version": "1.2.19"
37
37
  },
38
38
  {
39
39
  "name": "@djangocfg/og-image",
40
- "version": "1.2.18"
40
+ "version": "1.2.19"
41
41
  },
42
42
  {
43
43
  "name": "@djangocfg/eslint-config",
44
- "version": "1.2.18"
44
+ "version": "1.2.19"
45
45
  },
46
46
  {
47
47
  "name": "@djangocfg/typescript-config",
48
- "version": "1.2.18"
48
+ "version": "1.2.19"
49
49
  }
50
50
  ];
51
51
 
@@ -1,60 +1,53 @@
1
1
  /**
2
2
  * Header Component
3
- * Adaptive header that renders mobile or desktop version
3
+ * Simple unified header for UI documentation
4
4
  */
5
5
 
6
6
  'use client';
7
7
 
8
8
  import React from 'react';
9
- import { useIsMobile } from '@djangocfg/ui';
10
- import { HeaderMobile } from './HeaderMobile';
11
- import { HeaderDesktop } from './HeaderDesktop';
9
+ import { CopyAIButton } from './CopyAIButton';
12
10
 
13
11
  export interface HeaderProps {
14
- /** Page title (desktop only) */
12
+ /** Page title */
15
13
  title?: string;
16
- /** Project name (mobile only) */
14
+ /** Project name */
17
15
  projectName?: string;
18
- /** Logo component (mobile only) */
16
+ /** Logo component */
19
17
  logo?: React.ReactNode;
20
- /** Is sidebar open (mobile only) */
21
- isSidebarOpen?: boolean;
22
- /** Toggle sidebar callback (mobile only) */
23
- onToggleSidebar?: () => void;
24
18
  /** Copy for AI callback - must return string */
25
19
  onCopyForAI?: () => string;
26
20
  }
27
21
 
28
22
  /**
29
23
  * Header Component
30
- * Automatically renders mobile or desktop version based on screen size
24
+ * Displays title and Copy for AI button
31
25
  */
32
26
  export function Header({
33
27
  title = 'UI Component Library',
34
28
  projectName = 'Django CFG',
35
29
  logo,
36
- isSidebarOpen = false,
37
- onToggleSidebar,
38
30
  onCopyForAI,
39
31
  }: HeaderProps) {
40
- const isMobile = useIsMobile();
41
-
42
- if (isMobile) {
43
- return (
44
- <HeaderMobile
45
- projectName={projectName}
46
- logo={logo}
47
- isSidebarOpen={isSidebarOpen}
48
- onToggleSidebar={onToggleSidebar}
49
- onCopyForAI={onCopyForAI}
50
- />
51
- );
52
- }
53
-
54
32
  return (
55
- <HeaderDesktop
56
- title={title}
57
- onCopyForAI={onCopyForAI}
58
- />
33
+ <header className="w-full border-b bg-background">
34
+ <div className="container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
35
+ <div className="flex items-center justify-between h-16">
36
+ {/* Left: Logo and Title */}
37
+ <div className="flex items-center gap-3">
38
+ {logo && <div className="flex-shrink-0">{logo}</div>}
39
+ <div className="flex flex-col">
40
+ <h1 className="text-lg font-semibold tracking-tight">{title}</h1>
41
+ <p className="text-xs text-muted-foreground hidden sm:block">{projectName}</p>
42
+ </div>
43
+ </div>
44
+
45
+ {/* Right: Copy for AI Button */}
46
+ {onCopyForAI && (
47
+ <CopyAIButton onCopyForAI={onCopyForAI} />
48
+ )}
49
+ </div>
50
+ </div>
51
+ </header>
59
52
  );
60
53
  }
@@ -147,12 +147,13 @@ export const NAVIGATION_COMPONENTS: ComponentConfig[] = [
147
147
  {
148
148
  name: 'Tabs',
149
149
  category: 'navigation',
150
- description: 'Tab navigation for switching between different views',
150
+ description: 'Tab navigation for switching between different views. Supports mobile sheet mode, sticky positioning, and auto-responsive behavior.',
151
151
  importPath: `import { Tabs, TabsContent, TabsList, TabsTrigger } from '@djangocfg/ui';`,
152
- example: `<Tabs defaultValue="account" className="w-[400px]">
153
- <TabsList className="grid w-full grid-cols-2">
154
- <TabsTrigger value="account">Account</TabsTrigger>
155
- <TabsTrigger value="password">Password</TabsTrigger>
152
+ example: `// Basic tabs with equal-width tabs
153
+ <Tabs defaultValue="account" className="w-[400px]">
154
+ <TabsList fullWidth>
155
+ <TabsTrigger value="account" flexEqual>Account</TabsTrigger>
156
+ <TabsTrigger value="password" flexEqual>Password</TabsTrigger>
156
157
  </TabsList>
157
158
  <TabsContent value="account">
158
159
  <div className="p-4 border rounded-md">
@@ -164,12 +165,32 @@ export const NAVIGATION_COMPONENTS: ComponentConfig[] = [
164
165
  <p className="text-sm">Change your password here.</p>
165
166
  </div>
166
167
  </TabsContent>
168
+ </Tabs>
169
+
170
+ // Mobile-responsive tabs with sticky positioning
171
+ <Tabs
172
+ defaultValue="account"
173
+ mobileSheet
174
+ mobileTitleText="Settings"
175
+ mobileSheetTitle="Navigation"
176
+ sticky
177
+ >
178
+ <TabsList fullWidth>
179
+ <TabsTrigger value="account" flexEqual>Account</TabsTrigger>
180
+ <TabsTrigger value="password" flexEqual>Password</TabsTrigger>
181
+ </TabsList>
182
+ <TabsContent value="account">
183
+ Account content
184
+ </TabsContent>
185
+ <TabsContent value="password">
186
+ Password content
187
+ </TabsContent>
167
188
  </Tabs>`,
168
189
  preview: (
169
190
  <Tabs defaultValue="account" className="w-[400px]">
170
- <TabsList className="grid w-full grid-cols-2">
171
- <TabsTrigger value="account">Account</TabsTrigger>
172
- <TabsTrigger value="password">Password</TabsTrigger>
191
+ <TabsList fullWidth>
192
+ <TabsTrigger value="account" flexEqual>Account</TabsTrigger>
193
+ <TabsTrigger value="password" flexEqual>Password</TabsTrigger>
173
194
  </TabsList>
174
195
  <TabsContent value="account">
175
196
  <div className="p-4 border rounded-md">
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * Showcase Context
3
- * Manages navigation state for ComponentShowcaseLayout
3
+ * Manages navigation state for UILayout
4
4
  */
5
5
 
6
6
  'use client';
@@ -10,9 +10,6 @@ import React, { createContext, useContext, useState, ReactNode } from 'react';
10
10
  interface ShowcaseContextValue {
11
11
  currentCategory: string;
12
12
  setCurrentCategory: (category: string) => void;
13
- isSidebarOpen: boolean;
14
- toggleSidebar: () => void;
15
- closeSidebar: () => void;
16
13
  }
17
14
 
18
15
  const ShowcaseContext = createContext<ShowcaseContextValue | undefined>(undefined);
@@ -24,19 +21,12 @@ interface ShowcaseProviderProps {
24
21
 
25
22
  export function ShowcaseProvider({ children, defaultCategory = 'overview' }: ShowcaseProviderProps) {
26
23
  const [currentCategory, setCurrentCategory] = useState(defaultCategory);
27
- const [isSidebarOpen, setIsSidebarOpen] = useState(false);
28
-
29
- const toggleSidebar = () => setIsSidebarOpen(prev => !prev);
30
- const closeSidebar = () => setIsSidebarOpen(false);
31
24
 
32
25
  return (
33
26
  <ShowcaseContext.Provider
34
27
  value={{
35
28
  currentCategory,
36
29
  setCurrentCategory,
37
- isSidebarOpen,
38
- toggleSidebar,
39
- closeSidebar,
40
30
  }}
41
31
  >
42
32
  {children}
@@ -17,7 +17,7 @@ import { TailwindGuideRenderer } from '../components/TailwindGuideRenderer';
17
17
  function UIGuideContent() {
18
18
  const { currentCategory, setCurrentCategory } = useShowcase();
19
19
 
20
- // For overview, show only landing page without layout
20
+ // For overview, show landing page without layout
21
21
  if (currentCategory === 'overview') {
22
22
  return <UIGuideLanding />;
23
23
  }
@@ -44,7 +44,7 @@ function UIGuideContent() {
44
44
  {currentCategory === 'tailwind4' && <TailwindGuideRenderer />}
45
45
 
46
46
  {/* All other categories use CategoryRenderer */}
47
- {currentCategory !== 'tailwind4' && currentCategory !== 'overview' && (
47
+ {currentCategory !== 'tailwind4' && (
48
48
  <CategoryRenderer categoryId={currentCategory} />
49
49
  )}
50
50
  </div>
@@ -6,11 +6,9 @@
6
6
  'use client';
7
7
 
8
8
  import React from 'react';
9
- import { Sidebar } from '../components/layout/Sidebar';
9
+ import { Tabs, TabsList, TabsTrigger } from '@djangocfg/ui';
10
10
  import { Header } from '../components/layout/Header';
11
- import { MobileOverlay } from '../components/layout/MobileOverlay';
12
11
  import { generateAIContext } from '../config';
13
- import { useShowcase } from '../context';
14
12
  import type { UILayoutProps } from '../types';
15
13
 
16
14
 
@@ -20,7 +18,7 @@ import type { UILayoutProps } from '../types';
20
18
  * Features:
21
19
  * - Config-driven: All component data comes from centralized config
22
20
  * - "Copy for AI": One-click export of all documentation
23
- * - Responsive: Mobile-first design with sidebar
21
+ * - Responsive: Auto-converts to mobile sheet menu on mobile
24
22
  * - Type-safe: Full TypeScript support
25
23
  *
26
24
  * @example
@@ -45,59 +43,58 @@ export function UILayout({
45
43
  logo,
46
44
  projectName = "Django CFG UI",
47
45
  }: UILayoutProps) {
48
- const { isSidebarOpen, toggleSidebar, closeSidebar } = useShowcase();
49
-
50
- const handleCategoryChange = (categoryId: string) => {
51
- onCategoryChange?.(categoryId);
52
- closeSidebar();
53
- };
54
-
55
46
  const handleCopyForAI = () => {
56
47
  return generateAIContext();
57
48
  };
58
49
 
59
50
  return (
60
- <div className="flex bg-background">
61
- {/* Mobile Overlay - outside flex container for proper z-index stacking */}
62
- <MobileOverlay
63
- isOpen={isSidebarOpen}
64
- onClose={closeSidebar}
51
+ <div className="flex flex-col min-h-screen bg-background">
52
+ {/* Header with Copy for AI button */}
53
+ <Header
54
+ title={title}
55
+ projectName={projectName}
56
+ logo={logo}
57
+ onCopyForAI={handleCopyForAI}
65
58
  />
66
59
 
67
- {/* Sidebar with Sticky - parent must be scrollable for react-sticky-box */}
68
- <div className="h-full sticky top-0">
69
- <Sidebar
70
- categories={categories}
71
- currentCategory={currentCategory}
72
- onCategoryChange={handleCategoryChange}
73
- isOpen={isSidebarOpen}
74
- projectName={projectName}
75
- logo={logo}
76
- />
60
+ {/* Category Navigation Tabs */}
61
+ <div className="container mx-auto max-w-7xl px-4 sm:px-6 lg:px-8 py-3">
62
+ <Tabs
63
+ value={currentCategory}
64
+ onValueChange={onCategoryChange}
65
+ mobileSheet
66
+ mobileTitleText="UI Library"
67
+ mobileSheetTitle="Categories"
68
+ sticky
69
+ >
70
+ <TabsList fullWidth className="h-auto flex-wrap">
71
+ {categories.map((category) => (
72
+ <TabsTrigger
73
+ key={category.id}
74
+ value={category.id}
75
+ flexEqual
76
+ className="gap-2 whitespace-nowrap"
77
+ >
78
+ {category.icon}
79
+ <span>{category.label}</span>
80
+ {category.count !== undefined && (
81
+ <span className="ml-1 text-xs opacity-60">({category.count})</span>
82
+ )}
83
+ </TabsTrigger>
84
+ ))}
85
+ </TabsList>
86
+ </Tabs>
77
87
  </div>
78
88
 
79
89
  {/* Main Content */}
80
- <main className="flex-1 flex flex-col min-w-0">
81
- {/* Header with Copy for AI button */}
82
- <Header
83
- title={title}
84
- projectName={projectName}
85
- logo={logo}
86
- isSidebarOpen={isSidebarOpen}
87
- onToggleSidebar={toggleSidebar}
88
- onCopyForAI={handleCopyForAI}
89
- />
90
-
91
- {/* Content Area */}
92
- <div className="flex-1">
93
- <div className="container max-w-7xl mx-auto p-6">
94
- {description && (
95
- <p className="text-sm text-muted-foreground mb-6">
96
- {description}
97
- </p>
98
- )}
99
- {children}
100
- </div>
90
+ <main className="flex-1">
91
+ <div className="container max-w-7xl mx-auto p-6">
92
+ {description && (
93
+ <p className="text-sm text-muted-foreground mb-6">
94
+ {description}
95
+ </p>
96
+ )}
97
+ {children}
101
98
  </div>
102
99
  </main>
103
100
  </div>
@@ -3,7 +3,7 @@
3
3
  * Custom hooks for UILayout functionality
4
4
  */
5
5
 
6
- export { useSidebarState } from './useSidebarState';
7
6
  export { useAIExport } from './useAIExport';
8
7
  export { useCategoryNavigation } from './useCategoryNavigation';
9
8
  export { useComponentSearch } from './useComponentSearch';
9
+ export { useSidebarState } from './useSidebarState';
@@ -33,13 +33,11 @@ export interface UILayoutProps {
33
33
  * Defines layout dimensions and behavior
34
34
  */
35
35
  export interface LayoutConfig {
36
- /** Sidebar width in pixels */
37
- sidebarWidth?: number;
38
36
  /** Header height in pixels */
39
37
  headerHeight?: number;
40
38
  /** Container max width */
41
39
  containerMaxWidth?: string;
42
- /** Enable sticky sidebar */
40
+ /** Enable sticky header */
43
41
  stickyHeader?: boolean;
44
42
  }
45
43