@dilipod/ui 0.3.2 → 0.3.4

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": "@dilipod/ui",
3
- "version": "0.3.2",
3
+ "version": "0.3.4",
4
4
  "description": "Dilipod Design System - Shared UI components and styles",
5
5
  "author": "Dilipod <hello@dilipod.com>",
6
6
  "license": "MIT",
@@ -0,0 +1,118 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+ import { Card, CardContent } from './card'
5
+ import { IconBox } from './icon-box'
6
+ import { Button } from './button'
7
+ import { cn } from '../lib/utils'
8
+
9
+ export interface ErrorStateProps extends React.HTMLAttributes<HTMLDivElement> {
10
+ /** Title text */
11
+ title?: string
12
+ /** Description text */
13
+ description?: string
14
+ /** Whether to show the retry button */
15
+ showRetry?: boolean
16
+ /** Whether to show the home/dashboard link */
17
+ showHomeLink?: boolean
18
+ /** Custom retry button text */
19
+ retryText?: string
20
+ /** Custom home link text */
21
+ homeLinkText?: string
22
+ /** Callback when retry is clicked */
23
+ onRetry?: () => void
24
+ /** Callback when home link is clicked */
25
+ onHomeClick?: () => void
26
+ /** Custom icon to display */
27
+ icon?: React.ReactNode
28
+ /** Custom action buttons */
29
+ actions?: React.ReactNode
30
+ }
31
+
32
+ const ErrorState = React.forwardRef<HTMLDivElement, ErrorStateProps>(
33
+ (
34
+ {
35
+ title = 'Something went wrong',
36
+ description = 'We encountered an error loading this page. Please try again.',
37
+ showRetry = true,
38
+ showHomeLink = true,
39
+ retryText = 'Try again',
40
+ homeLinkText = 'Go to dashboard',
41
+ onRetry,
42
+ onHomeClick,
43
+ icon,
44
+ actions,
45
+ className,
46
+ ...props
47
+ },
48
+ ref
49
+ ) => {
50
+ // Default icon - Warning icon
51
+ const defaultIcon = (
52
+ <svg
53
+ xmlns="http://www.w3.org/2000/svg"
54
+ width="24"
55
+ height="24"
56
+ fill="currentColor"
57
+ viewBox="0 0 256 256"
58
+ className="text-red-500"
59
+ >
60
+ <path d="M236.8,188.09,149.35,36.22h0a24.76,24.76,0,0,0-42.7,0L19.2,188.09a23.51,23.51,0,0,0,0,23.72A24.35,24.35,0,0,0,40.55,224h174.9a24.35,24.35,0,0,0,21.33-12.19A23.51,23.51,0,0,0,236.8,188.09ZM120,104a8,8,0,0,1,16,0v40a8,8,0,0,1-16,0Zm8,88a12,12,0,1,1,12-12A12,12,0,0,1,128,192Z" />
61
+ </svg>
62
+ )
63
+
64
+ // Default refresh icon for retry button
65
+ const refreshIcon = (
66
+ <svg
67
+ xmlns="http://www.w3.org/2000/svg"
68
+ width="16"
69
+ height="16"
70
+ fill="currentColor"
71
+ viewBox="0 0 256 256"
72
+ className="mr-2"
73
+ >
74
+ <path d="M240,56v48a8,8,0,0,1-8,8H184a8,8,0,0,1,0-16H211.4L184.81,71.64A80,80,0,1,0,207.6,176.16a8,8,0,1,1,13.54,8.49A96,96,0,1,1,227.59,64l.3-.31L208,44.31V56a8,8,0,0,0,8,8h16A8,8,0,0,0,240,56Z" />
75
+ </svg>
76
+ )
77
+
78
+ const hasDefaultActions = (showRetry && onRetry) || (showHomeLink && onHomeClick)
79
+
80
+ return (
81
+ <div
82
+ ref={ref}
83
+ className={cn('flex items-center justify-center min-h-[60vh]', className)}
84
+ {...props}
85
+ >
86
+ <Card className="max-w-md w-full">
87
+ <CardContent className="p-8 text-center">
88
+ <IconBox size="lg" className="mx-auto mb-4 bg-red-50">
89
+ {icon || defaultIcon}
90
+ </IconBox>
91
+ <h2 className="text-lg font-semibold text-[var(--black)] mb-2">
92
+ {title}
93
+ </h2>
94
+ <p className="text-sm text-muted-foreground mb-6">{description}</p>
95
+ {actions ? (
96
+ <div className="flex gap-3 justify-center">{actions}</div>
97
+ ) : hasDefaultActions ? (
98
+ <div className="flex gap-3 justify-center">
99
+ {showRetry && onRetry && (
100
+ <Button variant="outline" onClick={onRetry}>
101
+ {refreshIcon}
102
+ {retryText}
103
+ </Button>
104
+ )}
105
+ {showHomeLink && onHomeClick && (
106
+ <Button onClick={onHomeClick}>{homeLinkText}</Button>
107
+ )}
108
+ </div>
109
+ ) : null}
110
+ </CardContent>
111
+ </Card>
112
+ </div>
113
+ )
114
+ }
115
+ )
116
+ ErrorState.displayName = 'ErrorState'
117
+
118
+ export { ErrorState }
@@ -0,0 +1,135 @@
1
+ 'use client'
2
+
3
+ import * as React from 'react'
4
+ import { cn } from '../lib/utils'
5
+
6
+ export interface MetricLabelProps extends React.HTMLAttributes<HTMLParagraphElement> {
7
+ /** The label text */
8
+ children: React.ReactNode
9
+ }
10
+
11
+ /**
12
+ * MetricLabel - A utility component for consistent metric labeling
13
+ *
14
+ * Uses the standardized pattern: text-xs uppercase tracking-wide text-muted-foreground
15
+ * Typically used above metric values in dashboards and cards.
16
+ *
17
+ * @example
18
+ * <MetricLabel>Monthly Revenue</MetricLabel>
19
+ * <p className="text-2xl font-bold">€5,000</p>
20
+ */
21
+ const MetricLabel = React.forwardRef<HTMLParagraphElement, MetricLabelProps>(
22
+ ({ className, children, ...props }, ref) => {
23
+ return (
24
+ <p
25
+ ref={ref}
26
+ className={cn(
27
+ 'text-xs text-muted-foreground uppercase tracking-wide',
28
+ className
29
+ )}
30
+ {...props}
31
+ >
32
+ {children}
33
+ </p>
34
+ )
35
+ }
36
+ )
37
+ MetricLabel.displayName = 'MetricLabel'
38
+
39
+ export interface MetricValueProps extends React.HTMLAttributes<HTMLParagraphElement> {
40
+ /** The value to display */
41
+ children: React.ReactNode
42
+ /** Size variant */
43
+ size?: 'default' | 'lg' | 'sm'
44
+ /** Highlight the value (uses brand cyan) */
45
+ highlight?: boolean
46
+ }
47
+
48
+ /**
49
+ * MetricValue - A utility component for consistent metric value display
50
+ *
51
+ * Pairs with MetricLabel for a complete metric display pattern.
52
+ *
53
+ * @example
54
+ * <MetricLabel>Monthly Revenue</MetricLabel>
55
+ * <MetricValue highlight>€5,000</MetricValue>
56
+ */
57
+ const MetricValue = React.forwardRef<HTMLParagraphElement, MetricValueProps>(
58
+ ({ className, children, size = 'default', highlight = false, ...props }, ref) => {
59
+ return (
60
+ <p
61
+ ref={ref}
62
+ className={cn(
63
+ 'font-bold mt-1',
64
+ size === 'lg' && 'text-3xl',
65
+ size === 'default' && 'text-2xl',
66
+ size === 'sm' && 'text-xl',
67
+ highlight && 'text-[#00e5cc]',
68
+ className
69
+ )}
70
+ {...props}
71
+ >
72
+ {children}
73
+ </p>
74
+ )
75
+ }
76
+ )
77
+ MetricValue.displayName = 'MetricValue'
78
+
79
+ export interface MetricSubtextProps extends React.HTMLAttributes<HTMLParagraphElement> {
80
+ /** The subtext content */
81
+ children: React.ReactNode
82
+ }
83
+
84
+ /**
85
+ * MetricSubtext - A utility component for metric subtitles/descriptions
86
+ *
87
+ * @example
88
+ * <MetricLabel>Monthly Revenue</MetricLabel>
89
+ * <MetricValue>€5,000</MetricValue>
90
+ * <MetricSubtext>ARR: €60,000</MetricSubtext>
91
+ */
92
+ const MetricSubtext = React.forwardRef<HTMLParagraphElement, MetricSubtextProps>(
93
+ ({ className, children, ...props }, ref) => {
94
+ return (
95
+ <p
96
+ ref={ref}
97
+ className={cn(
98
+ 'text-xs text-muted-foreground mt-1',
99
+ className
100
+ )}
101
+ {...props}
102
+ >
103
+ {children}
104
+ </p>
105
+ )
106
+ }
107
+ )
108
+ MetricSubtext.displayName = 'MetricSubtext'
109
+
110
+ /**
111
+ * Metric - A compound component combining Label, Value, and optional Subtext
112
+ *
113
+ * @example
114
+ * <Metric>
115
+ * <MetricLabel>Monthly Revenue</MetricLabel>
116
+ * <MetricValue highlight>€5,000</MetricValue>
117
+ * <MetricSubtext>ARR: €60,000</MetricSubtext>
118
+ * </Metric>
119
+ */
120
+ const Metric = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
121
+ ({ className, children, ...props }, ref) => {
122
+ return (
123
+ <div
124
+ ref={ref}
125
+ className={cn(className)}
126
+ {...props}
127
+ >
128
+ {children}
129
+ </div>
130
+ )
131
+ }
132
+ )
133
+ Metric.displayName = 'Metric'
134
+
135
+ export { MetricLabel, MetricValue, MetricSubtext, Metric }
@@ -74,7 +74,9 @@ const TabsTriggerUnderline = React.forwardRef<
74
74
  <TabsPrimitive.Trigger
75
75
  ref={ref}
76
76
  className={cn(
77
- 'inline-flex items-center justify-center whitespace-nowrap px-4 py-2 text-sm font-medium text-muted-foreground transition-colors hover:text-foreground border-b-2 border-transparent -mb-px data-[state=active]:text-foreground data-[state=active]:border-[var(--cyan)] disabled:pointer-events-none disabled:opacity-50',
77
+ 'inline-flex items-center justify-center whitespace-nowrap px-4 py-2.5 text-sm font-medium text-muted-foreground transition-all hover:text-foreground border-b-2 border-transparent -mb-px',
78
+ 'data-[state=active]:text-[var(--cyan)] data-[state=active]:border-[var(--cyan)] data-[state=active]:font-semibold',
79
+ 'disabled:pointer-events-none disabled:opacity-50',
78
80
  className
79
81
  )}
80
82
  {...props}
package/src/index.ts CHANGED
@@ -46,6 +46,9 @@ export type { StatProps } from './components/stat'
46
46
  export { MetricCard, metricCardVariants } from './components/metric-card'
47
47
  export type { MetricCardProps } from './components/metric-card'
48
48
 
49
+ export { MetricLabel, MetricValue, MetricSubtext, Metric } from './components/metric-label'
50
+ export type { MetricLabelProps, MetricValueProps, MetricSubtextProps } from './components/metric-label'
51
+
49
52
  export { UsageBar, usageBarVariants } from './components/usage-bar'
50
53
  export type { UsageBarProps } from './components/usage-bar'
51
54
 
@@ -121,13 +124,10 @@ export {
121
124
  DropdownMenuRadioGroup,
122
125
  } from './components/dropdown-menu'
123
126
 
124
- export {
125
- Sidebar,
126
- SidebarNavItem,
127
- } from './components/sidebar'
127
+ export { Sidebar } from './components/sidebar'
128
128
  export type {
129
129
  SidebarProps,
130
- SidebarNavItem as SidebarNavItemType,
130
+ SidebarNavItem,
131
131
  SidebarNavItemProps,
132
132
  } from './components/sidebar'
133
133
 
@@ -137,6 +137,9 @@ export type { AlertProps } from './components/alert'
137
137
  export { EmptyState } from './components/empty-state'
138
138
  export type { EmptyStateProps } from './components/empty-state'
139
139
 
140
+ export { ErrorState } from './components/error-state'
141
+ export type { ErrorStateProps } from './components/error-state'
142
+
140
143
  export { CodeBlock } from './components/code-block'
141
144
  export type { CodeBlockProps } from './components/code-block'
142
145