@diwauhris/ui 1.6.0 → 1.7.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/lib/assets/ui.css
CHANGED
|
@@ -3310,6 +3310,10 @@
|
|
|
3310
3310
|
line-height: 1;
|
|
3311
3311
|
}
|
|
3312
3312
|
|
|
3313
|
+
.text-\[100px\] {
|
|
3314
|
+
font-size: 100px;
|
|
3315
|
+
}
|
|
3316
|
+
|
|
3313
3317
|
.text-\[10px\] {
|
|
3314
3318
|
font-size: 10px;
|
|
3315
3319
|
}
|
|
@@ -3350,6 +3354,10 @@
|
|
|
3350
3354
|
font-size: 7px;
|
|
3351
3355
|
}
|
|
3352
3356
|
|
|
3357
|
+
.text-\[80px\] {
|
|
3358
|
+
font-size: 80px;
|
|
3359
|
+
}
|
|
3360
|
+
|
|
3353
3361
|
.text-\[8px\] {
|
|
3354
3362
|
font-size: 8px;
|
|
3355
3363
|
}
|
|
@@ -3853,6 +3861,14 @@
|
|
|
3853
3861
|
opacity: 0.8;
|
|
3854
3862
|
}
|
|
3855
3863
|
|
|
3864
|
+
.opacity-\[0\.07\] {
|
|
3865
|
+
opacity: 0.07;
|
|
3866
|
+
}
|
|
3867
|
+
|
|
3868
|
+
.opacity-\[0\.12\] {
|
|
3869
|
+
opacity: 0.12;
|
|
3870
|
+
}
|
|
3871
|
+
|
|
3856
3872
|
.shadow {
|
|
3857
3873
|
--tw-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
|
|
3858
3874
|
--tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color);
|
|
@@ -5052,6 +5068,9 @@ body {
|
|
|
5052
5068
|
padding-left: 2rem;
|
|
5053
5069
|
padding-right: 2rem;
|
|
5054
5070
|
}
|
|
5071
|
+
.sm\:text-\[120px\] {
|
|
5072
|
+
font-size: 120px;
|
|
5073
|
+
}
|
|
5055
5074
|
}
|
|
5056
5075
|
@media (min-width: 768px) {
|
|
5057
5076
|
.md\:relative {
|
|
@@ -5180,3 +5199,9 @@ body {
|
|
|
5180
5199
|
grid-template-columns: 340px minmax(0,1fr);
|
|
5181
5200
|
}
|
|
5182
5201
|
}
|
|
5202
|
+
.\[\&\>svg\]\:h-24>svg {
|
|
5203
|
+
height: 6rem;
|
|
5204
|
+
}
|
|
5205
|
+
.\[\&\>svg\]\:w-24>svg {
|
|
5206
|
+
width: 6rem;
|
|
5207
|
+
}
|
package/lib/index.cjs
CHANGED
|
@@ -3846,6 +3846,100 @@ function EmptyState({ title, hint, icon, action, className = "" }) {
|
|
|
3846
3846
|
});
|
|
3847
3847
|
}
|
|
3848
3848
|
//#endregion
|
|
3849
|
+
//#region src/ui-library/gallery/status-page/StatusPage.tsx
|
|
3850
|
+
/**
|
|
3851
|
+
* Named presets for the three common status states.
|
|
3852
|
+
* Each preset supplies code, eyebrow, title, and description.
|
|
3853
|
+
* Consumer always provides actions — presets never include navigation.
|
|
3854
|
+
*
|
|
3855
|
+
* Usage:
|
|
3856
|
+
* <StatusPage
|
|
3857
|
+
* {...STATUS_PAGE_PRESETS.notFound}
|
|
3858
|
+
* primaryAction={{ label: 'Go to Dashboard', onClick: () => navigate('/dashboard') }}
|
|
3859
|
+
* secondaryAction={{ label: 'Go Back', onClick: () => navigate(-1) }}
|
|
3860
|
+
* />
|
|
3861
|
+
*/
|
|
3862
|
+
var STATUS_PAGE_PRESETS = {
|
|
3863
|
+
notFound: {
|
|
3864
|
+
code: "404",
|
|
3865
|
+
eyebrow: "404 — Not Found",
|
|
3866
|
+
title: "Page Not Found",
|
|
3867
|
+
description: "The page you're looking for doesn't exist or may have been moved."
|
|
3868
|
+
},
|
|
3869
|
+
forbidden: {
|
|
3870
|
+
code: "403",
|
|
3871
|
+
eyebrow: "403 — Access Restricted",
|
|
3872
|
+
title: "Access Restricted",
|
|
3873
|
+
description: "You don't have permission to view this page. Contact your system administrator if you need access."
|
|
3874
|
+
},
|
|
3875
|
+
serverError: {
|
|
3876
|
+
code: "500",
|
|
3877
|
+
eyebrow: "500 — Server Error",
|
|
3878
|
+
title: "Something Went Wrong",
|
|
3879
|
+
description: "We encountered an unexpected problem. Please try again or return to the dashboard."
|
|
3880
|
+
}
|
|
3881
|
+
};
|
|
3882
|
+
var BASE_ANCHOR = "inline-flex items-center justify-center transition-all duration-150 ease-out active:scale-[.98] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-1 select-none h-10 gap-2 rounded-md px-4 text-sm";
|
|
3883
|
+
var ANCHOR_PRIMARY = `${BASE_ANCHOR} font-bold bg-brand-blue text-white shadow-lg shadow-brand-blue/25 hover:bg-brand-navy hover:shadow-xl hover:shadow-brand-blue/30 focus-visible:ring-brand-blue/30`;
|
|
3884
|
+
var ANCHOR_OUTLINE = `${BASE_ANCHOR} font-semibold border border-slate-300 bg-white text-slate-700 shadow-sm hover:border-brand-blue/40 hover:bg-blue-50/40 hover:text-brand-blue focus-visible:ring-brand-blue/20`;
|
|
3885
|
+
function ActionButton({ action, variant }) {
|
|
3886
|
+
if (action.href) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
|
|
3887
|
+
href: action.href,
|
|
3888
|
+
className: variant === "primary" ? ANCHOR_PRIMARY : ANCHOR_OUTLINE,
|
|
3889
|
+
children: action.label
|
|
3890
|
+
});
|
|
3891
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
|
|
3892
|
+
variant,
|
|
3893
|
+
onClick: action.onClick,
|
|
3894
|
+
children: action.label
|
|
3895
|
+
});
|
|
3896
|
+
}
|
|
3897
|
+
function StatusPage({ eyebrow, title, description, code, icon, primaryAction, secondaryAction, className = "" }) {
|
|
3898
|
+
const hasActions = primaryAction || secondaryAction;
|
|
3899
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3900
|
+
className: `relative flex min-h-screen items-center justify-center bg-surface-page px-6 py-16 overflow-hidden ${className}`,
|
|
3901
|
+
children: [code ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3902
|
+
"aria-hidden": "true",
|
|
3903
|
+
className: "pointer-events-none absolute select-none font-heading font-bold text-brand-navy opacity-[0.07] text-[80px] sm:text-[120px] leading-none",
|
|
3904
|
+
children: code
|
|
3905
|
+
}) : icon ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3906
|
+
"aria-hidden": "true",
|
|
3907
|
+
className: "pointer-events-none absolute select-none text-brand-navy opacity-[0.12]",
|
|
3908
|
+
style: { fontSize: 0 },
|
|
3909
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
3910
|
+
className: "block [&>svg]:h-24 [&>svg]:w-24",
|
|
3911
|
+
children: icon
|
|
3912
|
+
})
|
|
3913
|
+
}) : null, /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3914
|
+
className: "relative z-10 max-w-sm w-full os-slide-up",
|
|
3915
|
+
children: [
|
|
3916
|
+
eyebrow && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3917
|
+
className: "mb-3 text-[11px] font-bold uppercase tracking-[0.18em] text-brand-sky",
|
|
3918
|
+
children: eyebrow
|
|
3919
|
+
}),
|
|
3920
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", {
|
|
3921
|
+
className: "font-heading text-3xl font-bold text-brand-navy leading-tight",
|
|
3922
|
+
children: title
|
|
3923
|
+
}),
|
|
3924
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
3925
|
+
className: "mt-3 text-sm font-medium text-slate-500 leading-relaxed",
|
|
3926
|
+
children: description
|
|
3927
|
+
}),
|
|
3928
|
+
hasActions && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
3929
|
+
className: "mt-8 flex flex-wrap items-center gap-3",
|
|
3930
|
+
children: [primaryAction && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ActionButton, {
|
|
3931
|
+
action: primaryAction,
|
|
3932
|
+
variant: "primary"
|
|
3933
|
+
}), secondaryAction && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ActionButton, {
|
|
3934
|
+
action: secondaryAction,
|
|
3935
|
+
variant: "outline"
|
|
3936
|
+
})]
|
|
3937
|
+
})
|
|
3938
|
+
]
|
|
3939
|
+
})]
|
|
3940
|
+
});
|
|
3941
|
+
}
|
|
3942
|
+
//#endregion
|
|
3849
3943
|
//#region src/ui-library/gallery/employee-card/EmployeeCard.tsx
|
|
3850
3944
|
function EmployeeCard({ name, role, avatarSrc, status, meta, actions, className = "" }) {
|
|
3851
3945
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("article", {
|
|
@@ -7682,6 +7776,7 @@ exports.Progress = Progress;
|
|
|
7682
7776
|
exports.RadioGroup = RadioGroup;
|
|
7683
7777
|
exports.RadioItem = RadioItem;
|
|
7684
7778
|
exports.ReportTemplate = ReportTemplate;
|
|
7779
|
+
exports.STATUS_PAGE_PRESETS = STATUS_PAGE_PRESETS;
|
|
7685
7780
|
exports.Section = Section;
|
|
7686
7781
|
exports.SegmentedControl = SegmentedControl;
|
|
7687
7782
|
exports.Select = Select;
|
|
@@ -7698,6 +7793,7 @@ exports.Spinner = Spinner;
|
|
|
7698
7793
|
exports.Statistic = Statistic;
|
|
7699
7794
|
exports.StatusBadge = StatusBadge;
|
|
7700
7795
|
exports.StatusDot = StatusDot;
|
|
7796
|
+
exports.StatusPage = StatusPage;
|
|
7701
7797
|
exports.Stepper = Stepper;
|
|
7702
7798
|
exports.Switch = Switch;
|
|
7703
7799
|
exports.Tab = Tab;
|
package/lib/index.mjs
CHANGED
|
@@ -3821,6 +3821,100 @@ function EmptyState({ title, hint, icon, action, className = "" }) {
|
|
|
3821
3821
|
});
|
|
3822
3822
|
}
|
|
3823
3823
|
//#endregion
|
|
3824
|
+
//#region src/ui-library/gallery/status-page/StatusPage.tsx
|
|
3825
|
+
/**
|
|
3826
|
+
* Named presets for the three common status states.
|
|
3827
|
+
* Each preset supplies code, eyebrow, title, and description.
|
|
3828
|
+
* Consumer always provides actions — presets never include navigation.
|
|
3829
|
+
*
|
|
3830
|
+
* Usage:
|
|
3831
|
+
* <StatusPage
|
|
3832
|
+
* {...STATUS_PAGE_PRESETS.notFound}
|
|
3833
|
+
* primaryAction={{ label: 'Go to Dashboard', onClick: () => navigate('/dashboard') }}
|
|
3834
|
+
* secondaryAction={{ label: 'Go Back', onClick: () => navigate(-1) }}
|
|
3835
|
+
* />
|
|
3836
|
+
*/
|
|
3837
|
+
var STATUS_PAGE_PRESETS = {
|
|
3838
|
+
notFound: {
|
|
3839
|
+
code: "404",
|
|
3840
|
+
eyebrow: "404 — Not Found",
|
|
3841
|
+
title: "Page Not Found",
|
|
3842
|
+
description: "The page you're looking for doesn't exist or may have been moved."
|
|
3843
|
+
},
|
|
3844
|
+
forbidden: {
|
|
3845
|
+
code: "403",
|
|
3846
|
+
eyebrow: "403 — Access Restricted",
|
|
3847
|
+
title: "Access Restricted",
|
|
3848
|
+
description: "You don't have permission to view this page. Contact your system administrator if you need access."
|
|
3849
|
+
},
|
|
3850
|
+
serverError: {
|
|
3851
|
+
code: "500",
|
|
3852
|
+
eyebrow: "500 — Server Error",
|
|
3853
|
+
title: "Something Went Wrong",
|
|
3854
|
+
description: "We encountered an unexpected problem. Please try again or return to the dashboard."
|
|
3855
|
+
}
|
|
3856
|
+
};
|
|
3857
|
+
var BASE_ANCHOR = "inline-flex items-center justify-center transition-all duration-150 ease-out active:scale-[.98] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-1 select-none h-10 gap-2 rounded-md px-4 text-sm";
|
|
3858
|
+
var ANCHOR_PRIMARY = `${BASE_ANCHOR} font-bold bg-brand-blue text-white shadow-lg shadow-brand-blue/25 hover:bg-brand-navy hover:shadow-xl hover:shadow-brand-blue/30 focus-visible:ring-brand-blue/30`;
|
|
3859
|
+
var ANCHOR_OUTLINE = `${BASE_ANCHOR} font-semibold border border-slate-300 bg-white text-slate-700 shadow-sm hover:border-brand-blue/40 hover:bg-blue-50/40 hover:text-brand-blue focus-visible:ring-brand-blue/20`;
|
|
3860
|
+
function ActionButton({ action, variant }) {
|
|
3861
|
+
if (action.href) return /* @__PURE__ */ jsx("a", {
|
|
3862
|
+
href: action.href,
|
|
3863
|
+
className: variant === "primary" ? ANCHOR_PRIMARY : ANCHOR_OUTLINE,
|
|
3864
|
+
children: action.label
|
|
3865
|
+
});
|
|
3866
|
+
return /* @__PURE__ */ jsx(Button, {
|
|
3867
|
+
variant,
|
|
3868
|
+
onClick: action.onClick,
|
|
3869
|
+
children: action.label
|
|
3870
|
+
});
|
|
3871
|
+
}
|
|
3872
|
+
function StatusPage({ eyebrow, title, description, code, icon, primaryAction, secondaryAction, className = "" }) {
|
|
3873
|
+
const hasActions = primaryAction || secondaryAction;
|
|
3874
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
3875
|
+
className: `relative flex min-h-screen items-center justify-center bg-surface-page px-6 py-16 overflow-hidden ${className}`,
|
|
3876
|
+
children: [code ? /* @__PURE__ */ jsx("span", {
|
|
3877
|
+
"aria-hidden": "true",
|
|
3878
|
+
className: "pointer-events-none absolute select-none font-heading font-bold text-brand-navy opacity-[0.07] text-[80px] sm:text-[120px] leading-none",
|
|
3879
|
+
children: code
|
|
3880
|
+
}) : icon ? /* @__PURE__ */ jsx("span", {
|
|
3881
|
+
"aria-hidden": "true",
|
|
3882
|
+
className: "pointer-events-none absolute select-none text-brand-navy opacity-[0.12]",
|
|
3883
|
+
style: { fontSize: 0 },
|
|
3884
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
3885
|
+
className: "block [&>svg]:h-24 [&>svg]:w-24",
|
|
3886
|
+
children: icon
|
|
3887
|
+
})
|
|
3888
|
+
}) : null, /* @__PURE__ */ jsxs("div", {
|
|
3889
|
+
className: "relative z-10 max-w-sm w-full os-slide-up",
|
|
3890
|
+
children: [
|
|
3891
|
+
eyebrow && /* @__PURE__ */ jsx("p", {
|
|
3892
|
+
className: "mb-3 text-[11px] font-bold uppercase tracking-[0.18em] text-brand-sky",
|
|
3893
|
+
children: eyebrow
|
|
3894
|
+
}),
|
|
3895
|
+
/* @__PURE__ */ jsx("h1", {
|
|
3896
|
+
className: "font-heading text-3xl font-bold text-brand-navy leading-tight",
|
|
3897
|
+
children: title
|
|
3898
|
+
}),
|
|
3899
|
+
/* @__PURE__ */ jsx("p", {
|
|
3900
|
+
className: "mt-3 text-sm font-medium text-slate-500 leading-relaxed",
|
|
3901
|
+
children: description
|
|
3902
|
+
}),
|
|
3903
|
+
hasActions && /* @__PURE__ */ jsxs("div", {
|
|
3904
|
+
className: "mt-8 flex flex-wrap items-center gap-3",
|
|
3905
|
+
children: [primaryAction && /* @__PURE__ */ jsx(ActionButton, {
|
|
3906
|
+
action: primaryAction,
|
|
3907
|
+
variant: "primary"
|
|
3908
|
+
}), secondaryAction && /* @__PURE__ */ jsx(ActionButton, {
|
|
3909
|
+
action: secondaryAction,
|
|
3910
|
+
variant: "outline"
|
|
3911
|
+
})]
|
|
3912
|
+
})
|
|
3913
|
+
]
|
|
3914
|
+
})]
|
|
3915
|
+
});
|
|
3916
|
+
}
|
|
3917
|
+
//#endregion
|
|
3824
3918
|
//#region src/ui-library/gallery/employee-card/EmployeeCard.tsx
|
|
3825
3919
|
function EmployeeCard({ name, role, avatarSrc, status, meta, actions, className = "" }) {
|
|
3826
3920
|
return /* @__PURE__ */ jsxs("article", {
|
|
@@ -7592,4 +7686,4 @@ var shadow = {
|
|
|
7592
7686
|
overlay: "shadow-xl"
|
|
7593
7687
|
};
|
|
7594
7688
|
//#endregion
|
|
7595
|
-
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, ActivityFeed, Alert, ApprovalTimeline, AreaChart, Avatar, Badge, BarChart, BarList, Breadcrumb, Button, CHART_PALETTE, Calendar, Card, CardContent, CardFooter, CardHeader, Checkbox, Combobox, CommandPalette, ConfirmAction, ConfirmDialog, DatePicker, DescriptionItem, DescriptionList, Dialog, DialogBody, DialogFooter, Divider, Drawer, Dropdown, EmployeeCard, EmptyState, ErrorBanner, Field, FieldContext, FieldInput, FileUpload, FilterChip, Heatmap, IconButton, Input, IsoCubeBlock, Kanban, LineChart, Menu, Modal, OrgChart, OrgUnitTree, OtpInput, PafTemplate, PageHeader, Pagination, PayslipTemplate, PermissionMatrix, Popover, PopoverContent, PopoverTrigger, Progress, RadioGroup, RadioItem, ReportTemplate, Section, SegmentedControl, Select, SidebarGroup, SidebarItem, SidebarNav, SidebarSection, Skeleton, SkeletonAvatar, SkeletonCard, SkeletonTableRow, SkeletonText, Spinner, Statistic, StatusBadge, StatusDot, Stepper, Switch, Tab, TabList, TabPanel, TabPanels, Tabs, Textarea, TimekeepingTemplate, Timeline, TimelineEmptyState, TimelineFooter, TimelineItem, TimelineValueCard, Toaster, Toolbar, Tooltip, TreeView, ValidationSummary, colors_exports as colors, dimension_exports as dimension, radius_exports as radius, shadow_exports as shadow, statusMenuItems, toast, typography_exports as typography, useFieldContext };
|
|
7689
|
+
export { Accordion, AccordionContent, AccordionItem, AccordionTrigger, ActivityFeed, Alert, ApprovalTimeline, AreaChart, Avatar, Badge, BarChart, BarList, Breadcrumb, Button, CHART_PALETTE, Calendar, Card, CardContent, CardFooter, CardHeader, Checkbox, Combobox, CommandPalette, ConfirmAction, ConfirmDialog, DatePicker, DescriptionItem, DescriptionList, Dialog, DialogBody, DialogFooter, Divider, Drawer, Dropdown, EmployeeCard, EmptyState, ErrorBanner, Field, FieldContext, FieldInput, FileUpload, FilterChip, Heatmap, IconButton, Input, IsoCubeBlock, Kanban, LineChart, Menu, Modal, OrgChart, OrgUnitTree, OtpInput, PafTemplate, PageHeader, Pagination, PayslipTemplate, PermissionMatrix, Popover, PopoverContent, PopoverTrigger, Progress, RadioGroup, RadioItem, ReportTemplate, STATUS_PAGE_PRESETS, Section, SegmentedControl, Select, SidebarGroup, SidebarItem, SidebarNav, SidebarSection, Skeleton, SkeletonAvatar, SkeletonCard, SkeletonTableRow, SkeletonText, Spinner, Statistic, StatusBadge, StatusDot, StatusPage, Stepper, Switch, Tab, TabList, TabPanel, TabPanels, Tabs, Textarea, TimekeepingTemplate, Timeline, TimelineEmptyState, TimelineFooter, TimelineItem, TimelineValueCard, Toaster, Toolbar, Tooltip, TreeView, ValidationSummary, colors_exports as colors, dimension_exports as dimension, radius_exports as radius, shadow_exports as shadow, statusMenuItems, toast, typography_exports as typography, useFieldContext };
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* StatusPage — Design System Component
|
|
3
|
+
*
|
|
4
|
+
* Full-page status screen for 404, 403, 500, and custom states.
|
|
5
|
+
*
|
|
6
|
+
* Signature element: the status code itself rendered as a large Barlow
|
|
7
|
+
* watermark behind the heading — brand typography as the primary visual,
|
|
8
|
+
* no icon-in-a-circle required.
|
|
9
|
+
*
|
|
10
|
+
* Layout: full-page centered on bg-surface-page, no card wrapper.
|
|
11
|
+
* Motion: content block enters with .os-slide-up (respects prefers-reduced-motion).
|
|
12
|
+
* Watermark stays static — animating it would be distracting.
|
|
13
|
+
*
|
|
14
|
+
* No routing logic in this component. Action buttons accept onClick/href;
|
|
15
|
+
* the consumer wires navigation (e.g. useNavigate from react-router-dom).
|
|
16
|
+
*
|
|
17
|
+
* Usage:
|
|
18
|
+
* <StatusPage
|
|
19
|
+
* {...STATUS_PAGE_PRESETS.notFound}
|
|
20
|
+
* primaryAction={{ label: 'Go to Dashboard', onClick: () => navigate('/dashboard') }}
|
|
21
|
+
* secondaryAction={{ label: 'Go Back', onClick: () => navigate(-1) }}
|
|
22
|
+
* />
|
|
23
|
+
*
|
|
24
|
+
* Accessibility:
|
|
25
|
+
* - Heading is <h1> — appropriate for a full-page status screen.
|
|
26
|
+
* - Watermark is aria-hidden="true" — decorative; the heading communicates the state.
|
|
27
|
+
* - Action buttons have descriptive labels via the `label` prop.
|
|
28
|
+
* - The watermark is opacity-[0.07] and has no contrast requirement (aria-hidden).
|
|
29
|
+
*/
|
|
30
|
+
import type { ReactNode } from 'react';
|
|
31
|
+
export interface StatusPageAction {
|
|
32
|
+
/** Button label */
|
|
33
|
+
label: string;
|
|
34
|
+
/**
|
|
35
|
+
* Click handler — consumer wires navigation.
|
|
36
|
+
* Example: () => navigate('/dashboard')
|
|
37
|
+
*/
|
|
38
|
+
onClick?: () => void;
|
|
39
|
+
/**
|
|
40
|
+
* Renders an <a> tag instead of <button> when provided.
|
|
41
|
+
* Use for external links (e.g. a status-page URL) or non-SPA navigation.
|
|
42
|
+
*/
|
|
43
|
+
href?: string;
|
|
44
|
+
}
|
|
45
|
+
export interface StatusPageProps {
|
|
46
|
+
/**
|
|
47
|
+
* Short eyebrow label shown above the heading.
|
|
48
|
+
* Rendered in the brand-sky uppercase tracking style.
|
|
49
|
+
* Example: "404 — Not Found"
|
|
50
|
+
* Omit to skip the eyebrow row.
|
|
51
|
+
*/
|
|
52
|
+
eyebrow?: string;
|
|
53
|
+
/** Main heading. Rendered as <h1>. Required. */
|
|
54
|
+
title: string;
|
|
55
|
+
/** Body description below the heading. Rendered as <p>. Required. */
|
|
56
|
+
description: string;
|
|
57
|
+
/**
|
|
58
|
+
* Status code string used as the large typographic watermark
|
|
59
|
+
* rendered behind the heading (e.g. "404", "403", "500").
|
|
60
|
+
* When omitted and `icon` is provided, the icon renders as the
|
|
61
|
+
* background mark instead.
|
|
62
|
+
*/
|
|
63
|
+
code?: string;
|
|
64
|
+
/**
|
|
65
|
+
* Lucide icon used as the background mark when `code` is not set.
|
|
66
|
+
* Ignored when `code` is provided.
|
|
67
|
+
* Pass with aria-hidden="true"; rendered at large size automatically.
|
|
68
|
+
*/
|
|
69
|
+
icon?: ReactNode;
|
|
70
|
+
/** Primary action — rendered as Button variant="primary". */
|
|
71
|
+
primaryAction?: StatusPageAction;
|
|
72
|
+
/**
|
|
73
|
+
* Secondary action — rendered as Button variant="outline".
|
|
74
|
+
* Omit for single-action states.
|
|
75
|
+
*/
|
|
76
|
+
secondaryAction?: StatusPageAction;
|
|
77
|
+
/** Additional class on the root wrapper. */
|
|
78
|
+
className?: string;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Named presets for the three common status states.
|
|
82
|
+
* Each preset supplies code, eyebrow, title, and description.
|
|
83
|
+
* Consumer always provides actions — presets never include navigation.
|
|
84
|
+
*
|
|
85
|
+
* Usage:
|
|
86
|
+
* <StatusPage
|
|
87
|
+
* {...STATUS_PAGE_PRESETS.notFound}
|
|
88
|
+
* primaryAction={{ label: 'Go to Dashboard', onClick: () => navigate('/dashboard') }}
|
|
89
|
+
* secondaryAction={{ label: 'Go Back', onClick: () => navigate(-1) }}
|
|
90
|
+
* />
|
|
91
|
+
*/
|
|
92
|
+
export declare const STATUS_PAGE_PRESETS: {
|
|
93
|
+
readonly notFound: {
|
|
94
|
+
readonly code: "404";
|
|
95
|
+
readonly eyebrow: "404 — Not Found";
|
|
96
|
+
readonly title: "Page Not Found";
|
|
97
|
+
readonly description: "The page you're looking for doesn't exist or may have been moved.";
|
|
98
|
+
};
|
|
99
|
+
readonly forbidden: {
|
|
100
|
+
readonly code: "403";
|
|
101
|
+
readonly eyebrow: "403 — Access Restricted";
|
|
102
|
+
readonly title: "Access Restricted";
|
|
103
|
+
readonly description: "You don't have permission to view this page. Contact your system administrator if you need access.";
|
|
104
|
+
};
|
|
105
|
+
readonly serverError: {
|
|
106
|
+
readonly code: "500";
|
|
107
|
+
readonly eyebrow: "500 — Server Error";
|
|
108
|
+
readonly title: "Something Went Wrong";
|
|
109
|
+
readonly description: "We encountered an unexpected problem. Please try again or return to the dashboard.";
|
|
110
|
+
};
|
|
111
|
+
};
|
|
112
|
+
export declare function StatusPage({ eyebrow, title, description, code, icon, primaryAction, secondaryAction, className, }: StatusPageProps): import("react").JSX.Element;
|
|
@@ -106,6 +106,8 @@ export { Timeline, TimelineItem, TimelineValueCard, TimelineFooter, TimelineEmpt
|
|
|
106
106
|
export type { TimelineProps, TimelineItemProps, TimelineValueCardProps, TimelineFooterProps, TimelineEmptyStateProps } from './gallery/timeline/Timeline';
|
|
107
107
|
export { EmptyState } from './gallery/empty-state/EmptyState';
|
|
108
108
|
export type { EmptyStateProps } from './gallery/empty-state/EmptyState';
|
|
109
|
+
export { StatusPage, STATUS_PAGE_PRESETS } from './gallery/status-page/StatusPage';
|
|
110
|
+
export type { StatusPageProps, StatusPageAction } from './gallery/status-page/StatusPage';
|
|
109
111
|
export { EmployeeCard } from './gallery/employee-card/EmployeeCard';
|
|
110
112
|
export type { EmployeeCardProps, EmployeeCardMeta } from './gallery/employee-card/EmployeeCard';
|
|
111
113
|
export { TreeView } from './gallery/tree-view/TreeView';
|