@papernote/ui 1.8.0 → 1.8.1

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": "@papernote/ui",
3
- "version": "1.8.0",
3
+ "version": "1.8.1",
4
4
  "type": "module",
5
5
  "description": "A modern React component library with a paper notebook aesthetic - minimal, professional, and expressive",
6
6
  "main": "dist/index.js",
@@ -1,8 +1,12 @@
1
1
  import { ReactNode } from 'react';
2
2
  import Page from './Page';
3
+ import { PageHeaderAction } from './PageHeader';
4
+ import Button from './Button';
5
+ import Stack from './Stack';
6
+ import Text from './Text';
3
7
 
4
8
  export interface PageLayoutProps {
5
- /** Page title displayed at the top */
9
+ /** Page title displayed at the top (also used for document title) */
6
10
  title: string;
7
11
  /** Optional subtitle/description text below the title */
8
12
  description?: string;
@@ -16,6 +20,10 @@ export interface PageLayoutProps {
16
20
  maxWidth?: '4xl' | '5xl' | '6xl' | '7xl' | 'full';
17
21
  /** Fix all margins/padding instead of responsive (default: false) */
18
22
  fixed?: boolean;
23
+ /** Page-level action buttons rendered inline with title */
24
+ actions?: PageHeaderAction[];
25
+ /** Custom content to render on the right (instead of actions) */
26
+ rightContent?: ReactNode;
19
27
  }
20
28
 
21
29
  /**
@@ -46,6 +54,21 @@ export interface PageLayoutProps {
46
54
  * </PageLayout>
47
55
  * ```
48
56
  *
57
+ * @example With actions
58
+ * ```tsx
59
+ * <PageLayout
60
+ * title="Products"
61
+ * description="Manage your product catalog"
62
+ * headerContent={<Breadcrumbs items={[{ label: 'Home', href: '/' }, { label: 'Products' }]} />}
63
+ * actions={[
64
+ * { id: 'export', label: 'Export', icon: <Download />, onClick: handleExport, variant: 'ghost' },
65
+ * { id: 'add', label: 'Add Product', icon: <Plus />, onClick: handleAdd, variant: 'primary' },
66
+ * ]}
67
+ * >
68
+ * <DataTable data={products} columns={columns} />
69
+ * </PageLayout>
70
+ * ```
71
+ *
49
72
  * @example With Layout for sidebar and gutter
50
73
  * ```tsx
51
74
  * <Layout sidebar={<Sidebar items={items} />}>
@@ -62,7 +85,9 @@ export function PageLayout({
62
85
  className = '',
63
86
  headerContent,
64
87
  maxWidth = '7xl',
65
- fixed = false
88
+ fixed = false,
89
+ actions,
90
+ rightContent,
66
91
  }: PageLayoutProps) {
67
92
  // Responsive padding classes - fixed left/top, responsive right/bottom
68
93
  const paddingClasses = fixed
@@ -85,10 +110,32 @@ export function PageLayout({
85
110
  <div className={`${paddingClasses} ${maxWidthClasses[maxWidth]} mx-auto ${className}`}>
86
111
  {/* Header */}
87
112
  <div className="mb-8">
88
- <h1 className="text-3xl font-bold text-ink-900 mb-2">{title}</h1>
89
- {description && (
90
- <p className="text-ink-600">{description}</p>
91
- )}
113
+ <Stack direction="horizontal" justify="between" align="start" gap="md">
114
+ <div className="min-w-0 flex-1">
115
+ <Text as="h1" size="2xl" weight="bold" className="text-3xl mb-2">{title}</Text>
116
+ {description && (
117
+ <Text color="muted">{description}</Text>
118
+ )}
119
+ </div>
120
+ {(actions || rightContent) && (
121
+ <Stack direction="horizontal" gap="sm" className="flex-shrink-0">
122
+ {rightContent}
123
+ {actions?.map((action) => (
124
+ <Button
125
+ key={action.id}
126
+ variant={action.variant || 'secondary'}
127
+ icon={action.icon}
128
+ onClick={action.onClick}
129
+ disabled={action.disabled}
130
+ loading={action.loading}
131
+ className={action.hideOnMobile ? 'hidden sm:inline-flex' : ''}
132
+ >
133
+ {action.label}
134
+ </Button>
135
+ ))}
136
+ </Stack>
137
+ )}
138
+ </Stack>
92
139
  </div>
93
140
 
94
141
  {children}