@checkstack/ui 0.4.1 → 0.5.0
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/CHANGELOG.md +19 -0
- package/package.json +1 -1
- package/src/components/Card.tsx +19 -2
- package/src/components/DateRangeFilter.tsx +12 -7
- package/src/components/Page.tsx +17 -8
- package/src/components/PageLayout.tsx +24 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @checkstack/ui
|
|
2
2
|
|
|
3
|
+
## 0.5.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 223081d: Add icon support to PageLayout and improve mobile responsiveness
|
|
8
|
+
|
|
9
|
+
**PageLayout Icons:**
|
|
10
|
+
|
|
11
|
+
- Added required `icon` prop to `PageLayout` and `PageHeader` components that accepts a Lucide icon component reference
|
|
12
|
+
- Icons are rendered with consistent `h-6 w-6 text-primary` styling
|
|
13
|
+
- Updated all page components to include appropriate icons in their headers
|
|
14
|
+
|
|
15
|
+
**Mobile Layout Improvements:**
|
|
16
|
+
|
|
17
|
+
- Standardized responsive padding in main app shell (`p-3` on mobile, `p-6` on desktop)
|
|
18
|
+
- Added `CardHeaderRow` component for mobile-safe card headers with proper wrapping
|
|
19
|
+
- Improved `DateRangeFilter` responsive behavior with vertical stacking on mobile
|
|
20
|
+
- Migrated pages to use `PageLayout` for consistent responsive behavior
|
|
21
|
+
|
|
3
22
|
## 0.4.1
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
package/package.json
CHANGED
package/src/components/Card.tsx
CHANGED
|
@@ -8,7 +8,7 @@ export const Card = ({
|
|
|
8
8
|
<div
|
|
9
9
|
className={cn(
|
|
10
10
|
"rounded-lg border border-border bg-card text-card-foreground shadow-sm",
|
|
11
|
-
className
|
|
11
|
+
className,
|
|
12
12
|
)}
|
|
13
13
|
{...props}
|
|
14
14
|
/>
|
|
@@ -21,6 +21,23 @@ export const CardHeader = ({
|
|
|
21
21
|
<div className={cn("flex flex-col space-y-1.5 p-6", className)} {...props} />
|
|
22
22
|
);
|
|
23
23
|
|
|
24
|
+
/**
|
|
25
|
+
* A row layout for card headers with title and actions.
|
|
26
|
+
* Provides mobile-friendly defaults with flex-wrap and gap.
|
|
27
|
+
*/
|
|
28
|
+
export const CardHeaderRow = ({
|
|
29
|
+
className,
|
|
30
|
+
...props
|
|
31
|
+
}: React.HTMLAttributes<HTMLDivElement>) => (
|
|
32
|
+
<div
|
|
33
|
+
className={cn(
|
|
34
|
+
"flex flex-wrap items-center justify-between gap-3",
|
|
35
|
+
className,
|
|
36
|
+
)}
|
|
37
|
+
{...props}
|
|
38
|
+
/>
|
|
39
|
+
);
|
|
40
|
+
|
|
24
41
|
export const CardTitle = ({
|
|
25
42
|
className,
|
|
26
43
|
...props
|
|
@@ -28,7 +45,7 @@ export const CardTitle = ({
|
|
|
28
45
|
<h3
|
|
29
46
|
className={cn(
|
|
30
47
|
"text-2xl font-semibold leading-none tracking-tight",
|
|
31
|
-
className
|
|
48
|
+
className,
|
|
32
49
|
)}
|
|
33
50
|
{...props}
|
|
34
51
|
/>
|
|
@@ -22,11 +22,15 @@ export interface DateRangeFilterProps {
|
|
|
22
22
|
className?: string;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
-
const PRESETS: Array<{
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
25
|
+
const PRESETS: Array<{
|
|
26
|
+
id: DateRangePreset;
|
|
27
|
+
label: string;
|
|
28
|
+
shortLabel: string;
|
|
29
|
+
}> = [
|
|
30
|
+
{ id: DateRangePreset.Last24Hours, label: "Last 24h", shortLabel: "24h" },
|
|
31
|
+
{ id: DateRangePreset.Last7Days, label: "Last 7 days", shortLabel: "7d" },
|
|
32
|
+
{ id: DateRangePreset.Last30Days, label: "Last 30 days", shortLabel: "30d" },
|
|
33
|
+
{ id: DateRangePreset.Custom, label: "Custom", shortLabel: "Custom" },
|
|
30
34
|
];
|
|
31
35
|
|
|
32
36
|
export function getPresetRange(preset: DateRangePreset): DateRange {
|
|
@@ -88,7 +92,7 @@ export const DateRangeFilter: React.FC<DateRangeFilterProps> = ({
|
|
|
88
92
|
<span className="text-sm font-medium text-muted-foreground">
|
|
89
93
|
Time range:
|
|
90
94
|
</span>
|
|
91
|
-
<div className="flex gap-1">
|
|
95
|
+
<div className="flex gap-1 flex-wrap">
|
|
92
96
|
{PRESETS.map((preset) => (
|
|
93
97
|
<Button
|
|
94
98
|
key={preset.id}
|
|
@@ -102,7 +106,8 @@ export const DateRangeFilter: React.FC<DateRangeFilterProps> = ({
|
|
|
102
106
|
size="sm"
|
|
103
107
|
onClick={() => handlePresetClick(preset.id)}
|
|
104
108
|
>
|
|
105
|
-
{preset.
|
|
109
|
+
<span className="sm:hidden">{preset.shortLabel}</span>
|
|
110
|
+
<span className="hidden sm:inline">{preset.label}</span>
|
|
106
111
|
</Button>
|
|
107
112
|
))}
|
|
108
113
|
</div>
|
package/src/components/Page.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import type { LucideIcon } from "lucide-react";
|
|
2
3
|
import { cn } from "../utils";
|
|
3
4
|
|
|
4
5
|
interface PageProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
@@ -14,33 +15,37 @@ export const Page = React.forwardRef<HTMLDivElement, PageProps>(
|
|
|
14
15
|
>
|
|
15
16
|
{children}
|
|
16
17
|
</div>
|
|
17
|
-
)
|
|
18
|
+
),
|
|
18
19
|
);
|
|
19
20
|
Page.displayName = "Page";
|
|
20
21
|
|
|
21
22
|
interface PageHeaderProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
22
23
|
title: string;
|
|
23
24
|
subtitle?: string;
|
|
25
|
+
icon: LucideIcon;
|
|
24
26
|
actions?: React.ReactNode;
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
export const PageHeader = React.forwardRef<HTMLDivElement, PageHeaderProps>(
|
|
28
|
-
({ className, title, subtitle, actions, ...props }, ref) => (
|
|
30
|
+
({ className, title, subtitle, icon: Icon, actions, ...props }, ref) => (
|
|
29
31
|
<div
|
|
30
32
|
ref={ref}
|
|
31
33
|
className={cn(
|
|
32
|
-
"flex flex-col md:flex-row items-center justify-between
|
|
33
|
-
className
|
|
34
|
+
"flex flex-col md:flex-row items-center justify-between py-3 pb-2 md:py-6 md:pb-2",
|
|
35
|
+
className,
|
|
34
36
|
)}
|
|
35
37
|
{...props}
|
|
36
38
|
>
|
|
37
39
|
<div className="space-y-1">
|
|
38
|
-
<
|
|
40
|
+
<div className="flex items-center gap-3">
|
|
41
|
+
<Icon className="h-6 w-6 text-primary" />
|
|
42
|
+
<h2 className="text-2xl font-bold tracking-tight">{title}</h2>
|
|
43
|
+
</div>
|
|
39
44
|
{subtitle && <p className="text-muted-foreground">{subtitle}</p>}
|
|
40
45
|
</div>
|
|
41
46
|
{actions && <div className="flex items-center space-x-2">{actions}</div>}
|
|
42
47
|
</div>
|
|
43
|
-
)
|
|
48
|
+
),
|
|
44
49
|
);
|
|
45
50
|
PageHeader.displayName = "PageHeader";
|
|
46
51
|
|
|
@@ -50,9 +55,13 @@ interface PageContentProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
|
50
55
|
|
|
51
56
|
export const PageContent = React.forwardRef<HTMLDivElement, PageContentProps>(
|
|
52
57
|
({ className, children, ...props }, ref) => (
|
|
53
|
-
<div
|
|
58
|
+
<div
|
|
59
|
+
ref={ref}
|
|
60
|
+
className={cn("flex-1 py-3 pt-2 md:py-6 md:pt-2", className)}
|
|
61
|
+
{...props}
|
|
62
|
+
>
|
|
54
63
|
{children}
|
|
55
64
|
</div>
|
|
56
|
-
)
|
|
65
|
+
),
|
|
57
66
|
);
|
|
58
67
|
PageContent.displayName = "PageContent";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
+
import type { LucideIcon } from "lucide-react";
|
|
2
3
|
import {
|
|
3
4
|
Page,
|
|
4
5
|
PageHeader,
|
|
@@ -10,6 +11,7 @@ import {
|
|
|
10
11
|
interface PageLayoutProps {
|
|
11
12
|
title: string;
|
|
12
13
|
subtitle?: string;
|
|
14
|
+
icon: LucideIcon;
|
|
13
15
|
actions?: React.ReactNode;
|
|
14
16
|
loading?: boolean;
|
|
15
17
|
allowed?: boolean;
|
|
@@ -31,6 +33,7 @@ interface PageLayoutProps {
|
|
|
31
33
|
export const PageLayout: React.FC<PageLayoutProps> = ({
|
|
32
34
|
title,
|
|
33
35
|
subtitle,
|
|
36
|
+
icon,
|
|
34
37
|
actions,
|
|
35
38
|
loading,
|
|
36
39
|
allowed,
|
|
@@ -46,7 +49,12 @@ export const PageLayout: React.FC<PageLayoutProps> = ({
|
|
|
46
49
|
if (isLoading) {
|
|
47
50
|
return (
|
|
48
51
|
<Page>
|
|
49
|
-
<PageHeader
|
|
52
|
+
<PageHeader
|
|
53
|
+
title={title}
|
|
54
|
+
subtitle={subtitle}
|
|
55
|
+
icon={icon}
|
|
56
|
+
actions={actions}
|
|
57
|
+
/>
|
|
50
58
|
<PageContent>
|
|
51
59
|
<div className="flex justify-center py-12">
|
|
52
60
|
<LoadingSpinner />
|
|
@@ -60,7 +68,12 @@ export const PageLayout: React.FC<PageLayoutProps> = ({
|
|
|
60
68
|
if (allowed === false) {
|
|
61
69
|
return (
|
|
62
70
|
<Page>
|
|
63
|
-
<PageHeader
|
|
71
|
+
<PageHeader
|
|
72
|
+
title={title}
|
|
73
|
+
subtitle={subtitle}
|
|
74
|
+
icon={icon}
|
|
75
|
+
actions={actions}
|
|
76
|
+
/>
|
|
64
77
|
<PageContent>
|
|
65
78
|
<AccessDenied />
|
|
66
79
|
</PageContent>
|
|
@@ -70,10 +83,17 @@ export const PageLayout: React.FC<PageLayoutProps> = ({
|
|
|
70
83
|
|
|
71
84
|
return (
|
|
72
85
|
<Page>
|
|
73
|
-
<PageHeader
|
|
86
|
+
<PageHeader
|
|
87
|
+
title={title}
|
|
88
|
+
subtitle={subtitle}
|
|
89
|
+
icon={icon}
|
|
90
|
+
actions={actions}
|
|
91
|
+
/>
|
|
74
92
|
<PageContent>
|
|
75
93
|
<div
|
|
76
|
-
className={
|
|
94
|
+
className={
|
|
95
|
+
maxWidth === "full" ? "space-y-6" : `max-w-${maxWidth} space-y-6`
|
|
96
|
+
}
|
|
77
97
|
>
|
|
78
98
|
{children}
|
|
79
99
|
</div>
|