@fragments-sdk/ui 0.8.1 → 0.8.2

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.
Files changed (57) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +2 -0
  3. package/fragments.json +1 -1
  4. package/package.json +21 -2
  5. package/src/assets/fragments-logo.tsx +37 -0
  6. package/src/assets/fragments_logo.svg +1 -0
  7. package/src/assets/fragments_logo_text.svg +1 -0
  8. package/src/blocks/AccountSettings.block.ts +1 -1
  9. package/src/blocks/ActivityFeed.block.ts +7 -7
  10. package/src/blocks/ChatInterface.block.ts +36 -80
  11. package/src/blocks/DashboardLayout.block.ts +85 -66
  12. package/src/blocks/DashboardPage.block.ts +297 -0
  13. package/src/blocks/EmptyState.block.ts +5 -3
  14. package/src/blocks/FeatureGrid.block.ts +1 -1
  15. package/src/blocks/LoginForm.block.ts +21 -26
  16. package/src/blocks/PricingComparison.block.ts +1 -1
  17. package/src/blocks/ShoppingCart.block.ts +2 -2
  18. package/src/components/Input/Input.test.tsx +35 -0
  19. package/src/components/Input/index.tsx +47 -2
  20. package/src/components/Menu/Menu.module.scss +2 -0
  21. package/src/components/Table/Table.fragment.tsx +1 -1
  22. package/src/components/ToggleGroup/ToggleGroup.fragment.tsx +32 -0
  23. package/src/index.ts +3 -0
  24. package/src/tokens/_derive.scss +32 -8
  25. package/src/blocks/AIChat.block.ts +0 -266
  26. package/src/blocks/AppShell.block.ts +0 -175
  27. package/src/blocks/CTABanner.block.ts +0 -24
  28. package/src/blocks/CardGrid.block.ts +0 -22
  29. package/src/blocks/CodeExamples.block.ts +0 -66
  30. package/src/blocks/ConfirmDialog.block.ts +0 -19
  31. package/src/blocks/ConversationWithHistory.block.ts +0 -45
  32. package/src/blocks/DashboardNav.block.ts +0 -183
  33. package/src/blocks/ForgotPassword.block.ts +0 -26
  34. package/src/blocks/FormLayout.block.ts +0 -31
  35. package/src/blocks/InsetDashboardLayout.block.ts +0 -79
  36. package/src/blocks/MetricDashboard.block.ts +0 -38
  37. package/src/blocks/NewsletterSignup.block.ts +0 -26
  38. package/src/blocks/NotificationList.block.ts +0 -39
  39. package/src/blocks/NotificationPreferences.block.ts +0 -40
  40. package/src/blocks/OrderSummary.block.ts +0 -52
  41. package/src/blocks/ProfileEditForm.block.ts +0 -51
  42. package/src/blocks/SearchResults.block.ts +0 -39
  43. package/src/blocks/SettingsPage.block.ts +0 -58
  44. package/src/blocks/StreamingMessage.block.ts +0 -24
  45. package/src/blocks/TestimonialCard.block.ts +0 -27
  46. package/src/blocks/UserProfileCard.block.ts +0 -29
  47. package/src/recipes/AIChat.recipe.ts +0 -266
  48. package/src/recipes/AppShell.recipe.ts +0 -175
  49. package/src/recipes/CardGrid.recipe.ts +0 -22
  50. package/src/recipes/ChatInterface.recipe.ts +0 -87
  51. package/src/recipes/CodeExamples.recipe.ts +0 -66
  52. package/src/recipes/ConfirmDialog.recipe.ts +0 -19
  53. package/src/recipes/DashboardLayout.recipe.ts +0 -73
  54. package/src/recipes/DashboardNav.recipe.ts +0 -183
  55. package/src/recipes/FormLayout.recipe.ts +0 -31
  56. package/src/recipes/LoginForm.recipe.ts +0 -33
  57. package/src/recipes/SettingsPage.recipe.ts +0 -58
@@ -1,175 +0,0 @@
1
- import { defineRecipe } from '@fragments/core';
2
-
3
- export default defineRecipe({
4
- name: 'App Shell',
5
- description: 'Full application layout with sidebar, header, and main content. Supports two layout modes: stacked (header full-width) and sidebar-inset (sidebar full-height).',
6
- category: 'layout',
7
- components: ['AppShell', 'Header', 'Sidebar', 'Theme'],
8
- tags: ['layout', 'app-shell', 'sidebar', 'navigation', 'dashboard'],
9
- code: `
10
- // App Shell - Stacked Layout (header spans full width)
11
- // Best for apps where the brand should be prominent in the header
12
-
13
- import { AppShell, Header, Input, Sidebar, ThemeToggle } from '@fragments-sdk/ui';
14
-
15
- function StackedLayout({ children }) {
16
- return (
17
- <AppShell layout="stacked">
18
- <AppShell.Header>
19
- <Header>
20
- <Header.SkipLink />
21
- <Header.Trigger />
22
- <Header.Brand href="/">MyApp</Header.Brand>
23
- <Header.Nav>
24
- <Header.NavItem href="/" active>Dashboard</Header.NavItem>
25
- <Header.NavItem href="/settings">Settings</Header.NavItem>
26
- </Header.Nav>
27
- <Header.Spacer />
28
- <Header.Actions>
29
- <ThemeToggle />
30
- </Header.Actions>
31
- </Header>
32
- </AppShell.Header>
33
-
34
- <AppShell.Sidebar width="240px" collapsible="offcanvas">
35
- <Sidebar.Nav>
36
- <Sidebar.Section label="Menu">
37
- <Sidebar.Item icon={<HomeIcon />} href="/" active>
38
- Home
39
- </Sidebar.Item>
40
- <Sidebar.Item icon={<ChartIcon />} href="/analytics">
41
- Analytics
42
- </Sidebar.Item>
43
- <Sidebar.Item icon={<GearIcon />} href="/settings">
44
- Settings
45
- </Sidebar.Item>
46
- </Sidebar.Section>
47
- </Sidebar.Nav>
48
- </AppShell.Sidebar>
49
-
50
- <AppShell.Main padding="lg">
51
- {children}
52
- </AppShell.Main>
53
- </AppShell>
54
- );
55
- }
56
-
57
- // App Shell - Sidebar Inset Layout (sidebar is full height)
58
- // Best for documentation sites or when sidebar branding is preferred
59
-
60
- function SidebarInsetLayout({ children }) {
61
- return (
62
- <AppShell layout="sidebar-inset">
63
- <AppShell.Header>
64
- <Header>
65
- <Header.SkipLink />
66
- <Header.Trigger />
67
- <Header.Search>
68
- <Input placeholder="Search..." />
69
- </Header.Search>
70
- <Header.Spacer />
71
- <Header.Actions>
72
- <ThemeToggle />
73
- </Header.Actions>
74
- </Header>
75
- </AppShell.Header>
76
-
77
- <AppShell.Sidebar width="260px" collapsible="offcanvas">
78
- <Sidebar.Header>
79
- <a href="/">MyApp</a>
80
- </Sidebar.Header>
81
- <Sidebar.Nav>
82
- <Sidebar.Section label="Getting Started">
83
- <Sidebar.Item href="/docs" active>Introduction</Sidebar.Item>
84
- <Sidebar.Item href="/docs/install">Installation</Sidebar.Item>
85
- </Sidebar.Section>
86
- <Sidebar.Section label="Components">
87
- <Sidebar.Item href="/components">Overview</Sidebar.Item>
88
- <Sidebar.Item href="/components/button">Button</Sidebar.Item>
89
- </Sidebar.Section>
90
- </Sidebar.Nav>
91
- <Sidebar.Footer>v1.0.0</Sidebar.Footer>
92
- </AppShell.Sidebar>
93
-
94
- <AppShell.Main padding="lg">
95
- {children}
96
- </AppShell.Main>
97
- </AppShell>
98
- );
99
- }
100
-
101
- // App Shell with Collapsible Icon Sidebar
102
- // Sidebar collapses to icons only - great for dashboards
103
-
104
- function CollapsibleLayout({ children }) {
105
- return (
106
- <AppShell layout="sidebar-inset">
107
- <AppShell.Header>
108
- <Header>
109
- <Header.Trigger />
110
- <Header.Spacer />
111
- <Header.Actions>
112
- <ThemeToggle />
113
- </Header.Actions>
114
- </Header>
115
- </AppShell.Header>
116
-
117
- <AppShell.Sidebar collapsible="icon" width="240px" collapsedWidth="64px">
118
- <Sidebar.Header collapsedContent={<Logo />}>
119
- <Logo /> <span>MyApp</span>
120
- </Sidebar.Header>
121
- <Sidebar.Nav>
122
- <Sidebar.Section>
123
- <Sidebar.Item icon={<HomeIcon />} active>Dashboard</Sidebar.Item>
124
- <Sidebar.Item icon={<ChartIcon />}>Analytics</Sidebar.Item>
125
- <Sidebar.Item icon={<GearIcon />}>Settings</Sidebar.Item>
126
- </Sidebar.Section>
127
- </Sidebar.Nav>
128
- <Sidebar.Footer>
129
- <Sidebar.CollapseToggle />
130
- </Sidebar.Footer>
131
- </AppShell.Sidebar>
132
-
133
- <AppShell.Main padding="lg">
134
- {children}
135
- </AppShell.Main>
136
- </AppShell>
137
- );
138
- }
139
-
140
- // App Shell with Aside Panel
141
- // Optional right panel for additional context
142
-
143
- function LayoutWithAside({ children, aside }) {
144
- return (
145
- <AppShell layout="stacked">
146
- <AppShell.Header>
147
- <Header>
148
- <Header.Brand>MyApp</Header.Brand>
149
- <Header.Spacer />
150
- <Header.Actions>
151
- <ThemeToggle />
152
- </Header.Actions>
153
- </Header>
154
- </AppShell.Header>
155
-
156
- <AppShell.Sidebar width="200px" collapsible="offcanvas">
157
- <Sidebar.Nav>
158
- <Sidebar.Section>
159
- <Sidebar.Item icon={<HomeIcon />} active>Home</Sidebar.Item>
160
- </Sidebar.Section>
161
- </Sidebar.Nav>
162
- </AppShell.Sidebar>
163
-
164
- <AppShell.Main padding="lg">
165
- {children}
166
- </AppShell.Main>
167
-
168
- <AppShell.Aside width="280px">
169
- {aside}
170
- </AppShell.Aside>
171
- </AppShell>
172
- );
173
- }
174
- `.trim(),
175
- });
@@ -1,22 +0,0 @@
1
- import { defineRecipe } from '@fragments/core';
2
-
3
- export default defineRecipe({
4
- name: 'Card Grid',
5
- description: 'Responsive grid of cards that reflows based on available space',
6
- category: 'layout',
7
- components: ['Grid', 'Card'],
8
- tags: ['grid', 'cards', 'responsive', 'dashboard', 'tiles'],
9
- code: `
10
- <Grid columns="auto" minChildWidth="16rem" gap="md">
11
- {items.map(item => (
12
- <Card key={item.id}>
13
- <Card.Header>
14
- <Card.Title>{item.title}</Card.Title>
15
- <Card.Description>{item.description}</Card.Description>
16
- </Card.Header>
17
- <Card.Body>{item.content}</Card.Body>
18
- </Card>
19
- ))}
20
- </Grid>
21
- `.trim(),
22
- });
@@ -1,87 +0,0 @@
1
- import { defineRecipe } from '@fragments/core';
2
-
3
- export default defineRecipe({
4
- name: 'Chat Interface',
5
- description: 'AI chat interface with message history and prompt input',
6
- category: 'layout',
7
- components: ['Prompt', 'Card', 'Avatar', 'Stack'],
8
- tags: ['chat', 'ai', 'assistant', 'conversation'],
9
- code: `
10
- import { useState } from 'react';
11
- import { Prompt, Card, Avatar, Stack } from '@fragments-sdk/ui';
12
-
13
- interface Message {
14
- id: string;
15
- role: 'user' | 'assistant';
16
- content: string;
17
- }
18
-
19
- function ChatInterface() {
20
- const [messages, setMessages] = useState<Message[]>([]);
21
- const [isLoading, setIsLoading] = useState(false);
22
-
23
- const handleSubmit = async (value: string) => {
24
- // Add user message
25
- const userMessage: Message = {
26
- id: crypto.randomUUID(),
27
- role: 'user',
28
- content: value,
29
- };
30
- setMessages((prev) => [...prev, userMessage]);
31
- setIsLoading(true);
32
-
33
- try {
34
- // Simulate API call
35
- await new Promise((resolve) => setTimeout(resolve, 1000));
36
-
37
- // Add assistant response
38
- const assistantMessage: Message = {
39
- id: crypto.randomUUID(),
40
- role: 'assistant',
41
- content: 'This is a simulated response. Replace with your AI API call.',
42
- };
43
- setMessages((prev) => [...prev, assistantMessage]);
44
- } finally {
45
- setIsLoading(false);
46
- }
47
- };
48
-
49
- return (
50
- <Stack gap="4" style={{ height: '100vh', padding: '1rem' }}>
51
- {/* Messages */}
52
- <Stack gap="3" style={{ flex: 1, overflow: 'auto' }}>
53
- {messages.map((msg) => (
54
- <Card key={msg.id} padding="md">
55
- <Card.Body>
56
- <Stack direction="row" gap="3" align="start">
57
- <Avatar size="sm">
58
- {msg.role === 'user' ? 'U' : 'AI'}
59
- </Avatar>
60
- <div style={{ flex: 1 }}>{msg.content}</div>
61
- </Stack>
62
- </Card.Body>
63
- </Card>
64
- ))}
65
- </Stack>
66
-
67
- {/* Prompt */}
68
- <Prompt onSubmit={handleSubmit} loading={isLoading}>
69
- <Prompt.Textarea placeholder="Ask anything..." />
70
- <Prompt.Toolbar>
71
- <Prompt.Actions>
72
- <Prompt.ActionButton aria-label="Attach file">
73
- +
74
- </Prompt.ActionButton>
75
- <Prompt.ModeButton>Auto</Prompt.ModeButton>
76
- </Prompt.Actions>
77
- <Prompt.Info>
78
- <Prompt.Usage>52% used</Prompt.Usage>
79
- <Prompt.Submit />
80
- </Prompt.Info>
81
- </Prompt.Toolbar>
82
- </Prompt>
83
- </Stack>
84
- );
85
- }
86
- `.trim(),
87
- });
@@ -1,66 +0,0 @@
1
- import { defineRecipe } from '@fragments/core';
2
-
3
- export default defineRecipe({
4
- name: 'Code Examples',
5
- description: 'Patterns for displaying code in documentation with syntax highlighting',
6
- category: 'documentation',
7
- components: ['CodeBlock', 'Tabs', 'Card'],
8
- tags: ['code', 'documentation', 'syntax', 'examples'],
9
- code: `
10
- // Installation commands with package manager tabs
11
- <Tabs defaultValue="npm">
12
- <Tabs.List>
13
- <Tabs.Tab value="npm">npm</Tabs.Tab>
14
- <Tabs.Tab value="pnpm">pnpm</Tabs.Tab>
15
- <Tabs.Tab value="yarn">yarn</Tabs.Tab>
16
- </Tabs.List>
17
- <Tabs.Panel value="npm">
18
- <CodeBlock code="npm install @fragments-sdk/ui" language="bash" />
19
- </Tabs.Panel>
20
- <Tabs.Panel value="pnpm">
21
- <CodeBlock code="pnpm add @fragments-sdk/ui" language="bash" />
22
- </Tabs.Panel>
23
- <Tabs.Panel value="yarn">
24
- <CodeBlock code="yarn add @fragments-sdk/ui" language="bash" />
25
- </Tabs.Panel>
26
- </Tabs>
27
-
28
- // Usage example with preview
29
- <Card>
30
- <Card.Header>
31
- <Card.Title>Button Example</Card.Title>
32
- </Card.Header>
33
- <Card.Body>
34
- <div className="preview">
35
- <Button variant="primary">Click me</Button>
36
- </div>
37
- <CodeBlock
38
- code={\`<Button variant="primary">Click me</Button>\`}
39
- language="tsx"
40
- />
41
- </Card.Body>
42
- </Card>
43
-
44
- // Multi-file example with titles
45
- <CodeBlock
46
- title="Button.tsx"
47
- code={buttonCode}
48
- language="tsx"
49
- showLineNumbers
50
- />
51
- <CodeBlock
52
- title="Button.module.scss"
53
- code={stylesCode}
54
- language="scss"
55
- showLineNumbers
56
- />
57
-
58
- // Highlighted important lines
59
- <CodeBlock
60
- code={exampleCode}
61
- language="tsx"
62
- showLineNumbers
63
- highlightLines={[3, "7-10"]}
64
- />
65
- `.trim(),
66
- });
@@ -1,19 +0,0 @@
1
- import { defineRecipe } from '@fragments/core';
2
-
3
- export default defineRecipe({
4
- name: 'Confirm Dialog',
5
- description: 'Confirmation dialog with destructive action warning',
6
- category: 'overlays',
7
- components: ['Dialog', 'Button'],
8
- tags: ['confirm', 'dialog', 'modal', 'destructive'],
9
- code: `
10
- <Dialog open={isOpen} onClose={onClose}>
11
- <Dialog.Title>{title}</Dialog.Title>
12
- <Dialog.Description>{description}</Dialog.Description>
13
- <Dialog.Actions>
14
- <Button variant="secondary" onClick={onClose}>Cancel</Button>
15
- <Button variant="danger" onClick={onConfirm}>Confirm</Button>
16
- </Dialog.Actions>
17
- </Dialog>
18
- `.trim(),
19
- });
@@ -1,73 +0,0 @@
1
- import { defineRecipe } from '@fragments/core';
2
-
3
- export default defineRecipe({
4
- name: 'Dashboard Layout',
5
- description: 'Dashboard grid with a featured full-width card and smaller metric cards below',
6
- category: 'layout',
7
- components: ['Grid', 'Card', 'Badge', 'Separator'],
8
- tags: ['dashboard', 'layout', 'metrics', 'widgets', 'overview'],
9
- code: `
10
- <Grid columns={4} gap="lg">
11
- <Grid.Item colSpan="full">
12
- <Card>
13
- <Card.Header>
14
- <Card.Title>Overview</Card.Title>
15
- <Card.Description>Key metrics for this period</Card.Description>
16
- </Card.Header>
17
- <Card.Body>{summaryContent}</Card.Body>
18
- </Card>
19
- </Grid.Item>
20
- <Card variant="outlined">
21
- <Card.Header>
22
- <Card.Title>Users</Card.Title>
23
- </Card.Header>
24
- <Card.Body>
25
- <Badge variant="success">{stats.users}</Badge>
26
- </Card.Body>
27
- </Card>
28
- <Card variant="outlined">
29
- <Card.Header>
30
- <Card.Title>Revenue</Card.Title>
31
- </Card.Header>
32
- <Card.Body>
33
- <Badge variant="info">{stats.revenue}</Badge>
34
- </Card.Body>
35
- </Card>
36
- <Card variant="outlined">
37
- <Card.Header>
38
- <Card.Title>Orders</Card.Title>
39
- </Card.Header>
40
- <Card.Body>
41
- <Badge variant="warning">{stats.orders}</Badge>
42
- </Card.Body>
43
- </Card>
44
- <Card variant="outlined">
45
- <Card.Header>
46
- <Card.Title>Errors</Card.Title>
47
- </Card.Header>
48
- <Card.Body>
49
- <Badge variant="danger">{stats.errors}</Badge>
50
- </Card.Body>
51
- </Card>
52
- <Grid.Item colSpan="full">
53
- <Separator spacing="md" />
54
- </Grid.Item>
55
- <Grid.Item colSpan={2}>
56
- <Card>
57
- <Card.Header>
58
- <Card.Title>Recent Activity</Card.Title>
59
- </Card.Header>
60
- <Card.Body>{activityList}</Card.Body>
61
- </Card>
62
- </Grid.Item>
63
- <Grid.Item colSpan={2}>
64
- <Card>
65
- <Card.Header>
66
- <Card.Title>Notifications</Card.Title>
67
- </Card.Header>
68
- <Card.Body>{notificationList}</Card.Body>
69
- </Card>
70
- </Grid.Item>
71
- </Grid>
72
- `.trim(),
73
- });
@@ -1,183 +0,0 @@
1
- import { defineRecipe } from '@fragments/core';
2
-
3
- export default defineRecipe({
4
- name: 'Dashboard Navigation',
5
- description: 'Sidebar navigation pattern for dashboard applications with user profile, sections, and nested menus',
6
- category: 'navigation',
7
- components: ['Sidebar', 'Avatar'],
8
- tags: ['navigation', 'sidebar', 'dashboard', 'admin', 'menu'],
9
- code: `
10
- // Dashboard Navigation with User Profile
11
- // A complete sidebar navigation for admin/dashboard interfaces
12
-
13
- function DashboardNav({ user, currentPath }) {
14
- const [collapsed, setCollapsed] = React.useState(false);
15
- const [projectsExpanded, setProjectsExpanded] = React.useState(false);
16
-
17
- return (
18
- <Sidebar
19
- collapsed={collapsed}
20
- onCollapsedChange={setCollapsed}
21
- >
22
- {/* Brand header */}
23
- <Sidebar.Header>
24
- <svg width="32" height="32" viewBox="0 0 256 256" fill="var(--fui-color-accent)">
25
- <path d="M208,32H48A16,16,0,0,0,32,48V208a16,16,0,0,0,16,16H208a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32Zm0,176H48V48H208V208Z" />
26
- </svg>
27
- {!collapsed && (
28
- <span style={{ fontWeight: 600, fontSize: '16px' }}>Dashboard</span>
29
- )}
30
- <Sidebar.CollapseToggle />
31
- </Sidebar.Header>
32
-
33
- {/* Main navigation */}
34
- <Sidebar.Nav aria-label="Dashboard navigation">
35
- {/* Primary section */}
36
- <Sidebar.Section>
37
- <Sidebar.Item
38
- icon={<HomeIcon />}
39
- href="/dashboard"
40
- active={currentPath === '/dashboard'}
41
- >
42
- Overview
43
- </Sidebar.Item>
44
- <Sidebar.Item
45
- icon={<ChartIcon />}
46
- href="/analytics"
47
- active={currentPath === '/analytics'}
48
- badge="New"
49
- >
50
- Analytics
51
- </Sidebar.Item>
52
- <Sidebar.Item
53
- icon={<InboxIcon />}
54
- href="/inbox"
55
- active={currentPath === '/inbox'}
56
- badge="5"
57
- >
58
- Inbox
59
- </Sidebar.Item>
60
- </Sidebar.Section>
61
-
62
- {/* Projects section with nested items */}
63
- <Sidebar.Section label="Workspace">
64
- <Sidebar.Item
65
- icon={<FolderIcon />}
66
- hasSubmenu
67
- expanded={projectsExpanded}
68
- onExpandedChange={setProjectsExpanded}
69
- >
70
- Projects
71
- </Sidebar.Item>
72
- <Sidebar.Submenu>
73
- <Sidebar.SubItem
74
- href="/projects/website"
75
- active={currentPath === '/projects/website'}
76
- >
77
- Website Redesign
78
- </Sidebar.SubItem>
79
- <Sidebar.SubItem
80
- href="/projects/mobile"
81
- active={currentPath === '/projects/mobile'}
82
- >
83
- Mobile App
84
- </Sidebar.SubItem>
85
- <Sidebar.SubItem
86
- href="/projects/api"
87
- active={currentPath === '/projects/api'}
88
- >
89
- API Integration
90
- </Sidebar.SubItem>
91
- </Sidebar.Submenu>
92
- <Sidebar.Item
93
- icon={<UsersIcon />}
94
- href="/team"
95
- active={currentPath === '/team'}
96
- >
97
- Team Members
98
- </Sidebar.Item>
99
- <Sidebar.Item
100
- icon={<CalendarIcon />}
101
- href="/calendar"
102
- active={currentPath === '/calendar'}
103
- >
104
- Calendar
105
- </Sidebar.Item>
106
- </Sidebar.Section>
107
-
108
- {/* Settings section */}
109
- <Sidebar.Section label="Account">
110
- <Sidebar.Item
111
- icon={<GearIcon />}
112
- href="/settings"
113
- active={currentPath === '/settings'}
114
- >
115
- Settings
116
- </Sidebar.Item>
117
- <Sidebar.Item
118
- icon={<HelpIcon />}
119
- href="/help"
120
- active={currentPath === '/help'}
121
- >
122
- Help & Support
123
- </Sidebar.Item>
124
- </Sidebar.Section>
125
- </Sidebar.Nav>
126
-
127
- {/* Footer with user profile */}
128
- <Sidebar.Footer>
129
- <div style={{
130
- display: 'flex',
131
- alignItems: 'center',
132
- gap: '12px',
133
- padding: collapsed ? '0' : '8px',
134
- borderRadius: '8px',
135
- cursor: 'pointer',
136
- }}>
137
- <Avatar
138
- src={user.avatar}
139
- name={user.name}
140
- size="sm"
141
- />
142
- {!collapsed && (
143
- <div style={{ flex: 1, minWidth: 0 }}>
144
- <div style={{
145
- fontWeight: 500,
146
- fontSize: '14px',
147
- whiteSpace: 'nowrap',
148
- overflow: 'hidden',
149
- textOverflow: 'ellipsis',
150
- }}>
151
- {user.name}
152
- </div>
153
- <div style={{
154
- fontSize: '12px',
155
- color: 'var(--fui-text-secondary)',
156
- whiteSpace: 'nowrap',
157
- overflow: 'hidden',
158
- textOverflow: 'ellipsis',
159
- }}>
160
- {user.email}
161
- </div>
162
- </div>
163
- )}
164
- </div>
165
- </Sidebar.Footer>
166
- </Sidebar>
167
- );
168
- }
169
-
170
- // Usage example:
171
- // <DashboardNav
172
- // user={{ name: 'Jane Doe', email: 'jane@example.com', avatar: '/avatar.jpg' }}
173
- // currentPath="/dashboard"
174
- // />
175
-
176
- // Icon components (use your preferred icon library)
177
- const HomeIcon = () => (
178
- <svg width="20" height="20" viewBox="0 0 256 256" fill="currentColor">
179
- <path d="M219.31,108.68l-80-80a16,16,0,0,0-22.62,0l-80,80A15.87,15.87,0,0,0,32,120v96a8,8,0,0,0,8,8H96a8,8,0,0,0,8-8V160h48v56a8,8,0,0,0,8,8h56a8,8,0,0,0,8-8V120A15.87,15.87,0,0,0,219.31,108.68Z" />
180
- </svg>
181
- );
182
- `.trim(),
183
- });
@@ -1,31 +0,0 @@
1
- import { defineRecipe } from '@fragments/core';
2
-
3
- export default defineRecipe({
4
- name: 'Form Layout',
5
- description: 'Two-column form with full-width fields where needed, using Grid for alignment',
6
- category: 'forms',
7
- components: ['Grid', 'Input', 'Textarea', 'Select', 'Button'],
8
- tags: ['form', 'layout', 'grid', 'inputs', 'settings'],
9
- code: `
10
- <Grid columns={2} gap="md">
11
- <Input label="First Name" placeholder="Jane" />
12
- <Input label="Last Name" placeholder="Doe" />
13
- <Grid.Item colSpan="full">
14
- <Input label="Email" type="email" placeholder="jane@example.com" />
15
- </Grid.Item>
16
- <Grid.Item colSpan="full">
17
- <Select label="Role">
18
- <Select.Item value="admin">Admin</Select.Item>
19
- <Select.Item value="editor">Editor</Select.Item>
20
- <Select.Item value="viewer">Viewer</Select.Item>
21
- </Select>
22
- </Grid.Item>
23
- <Grid.Item colSpan="full">
24
- <Textarea label="Bio" placeholder="Tell us about yourself" />
25
- </Grid.Item>
26
- <Grid.Item colSpan="full">
27
- <Button type="submit" variant="primary">Save</Button>
28
- </Grid.Item>
29
- </Grid>
30
- `.trim(),
31
- });