@mdguggenbichler/slugbase-core 0.0.36 → 0.0.37

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.
@@ -62,9 +62,9 @@ export function StatCard({
62
62
  const progressPercent = limit > 0 ? Math.min(100, (used / limit) * 100) : 0;
63
63
 
64
64
  const content = (
65
- <>
66
- <div className="flex items-center justify-between">
67
- <div className="min-w-0 flex-1">
65
+ <div className="flex items-stretch justify-between gap-3 flex-1 min-h-0">
66
+ <div className="min-w-0 flex-1 flex flex-col">
67
+ <div className="min-w-0">
68
68
  <p className={cn('text-muted-foreground', dense ? 'text-xs' : 'text-sm')}>
69
69
  {label}
70
70
  </p>
@@ -79,42 +79,46 @@ export function StatCard({
79
79
  {labelOverride ?? label} {used} / {limit}
80
80
  </p>
81
81
  )}
82
- {showProgressBar && (
83
- <div className="mt-2 w-full overflow-hidden rounded-full bg-primary/20">
84
- <div
85
- className={cn(
86
- 'h-2 transition-all',
87
- progressVariant === 'warning' && 'bg-amber-500',
88
- progressVariant === 'danger' && 'bg-destructive',
89
- (progressVariant === 'normal' || !progressVariant) && 'bg-primary'
90
- )}
91
- style={{ width: `${progressPercent}%` }}
92
- />
93
- </div>
94
- )}
95
- {cta && (
96
- <button
97
- type="button"
98
- onClick={(e) => {
99
- e.preventDefault();
100
- e.stopPropagation();
101
- cta.onClick();
102
- }}
103
- className="mt-2 text-xs font-medium text-primary hover:underline focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 rounded"
104
- >
105
- {cta.label}
106
- </button>
107
- )}
108
- </div>
109
- <div className={cn('shrink-0 rounded-lg', iconContainerClassName ?? 'bg-muted', dense ? 'p-2' : 'p-3')}>
110
- <Icon className={cn(iconColorClassName ?? 'text-muted-foreground', dense ? 'h-5 w-5' : 'h-6 w-6')} />
111
82
  </div>
83
+ {(showProgressBar || cta) && (
84
+ <div className="mt-auto pt-2">
85
+ {showProgressBar && (
86
+ <div className="w-full overflow-hidden rounded-full bg-primary/20">
87
+ <div
88
+ className={cn(
89
+ 'h-2 transition-all',
90
+ progressVariant === 'warning' && 'bg-amber-500',
91
+ progressVariant === 'danger' && 'bg-destructive',
92
+ (progressVariant === 'normal' || !progressVariant) && 'bg-primary'
93
+ )}
94
+ style={{ width: `${progressPercent}%` }}
95
+ />
96
+ </div>
97
+ )}
98
+ {cta && (
99
+ <button
100
+ type="button"
101
+ onClick={(e) => {
102
+ e.preventDefault();
103
+ e.stopPropagation();
104
+ cta.onClick();
105
+ }}
106
+ className={cn('text-xs font-medium text-primary hover:underline focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 rounded', showProgressBar ? 'mt-2' : 'mt-0')}
107
+ >
108
+ {cta.label}
109
+ </button>
110
+ )}
111
+ </div>
112
+ )}
113
+ </div>
114
+ <div className={cn('shrink-0 rounded-lg self-center', iconContainerClassName ?? 'bg-muted', dense ? 'p-2' : 'p-3')}>
115
+ <Icon className={cn(iconColorClassName ?? 'text-muted-foreground', dense ? 'h-5 w-5' : 'h-6 w-6')} />
112
116
  </div>
113
- </>
117
+ </div>
114
118
  );
115
119
 
116
120
  const cardClassName = cn(
117
- 'transition-colors',
121
+ 'transition-colors h-full flex flex-col',
118
122
  href && 'cursor-pointer hover:border-primary/70 hover:bg-muted/50 focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2 rounded-xl',
119
123
  className
120
124
  );
@@ -123,9 +127,9 @@ export function StatCard({
123
127
 
124
128
  if (href) {
125
129
  return (
126
- <Link to={href} className="block focus:outline-none">
130
+ <Link to={href} className="block h-full focus:outline-none">
127
131
  <Card className={cardClassName}>
128
- <CardContent className={contentPadding}>
132
+ <CardContent className={cn(contentPadding, 'flex-1 flex flex-col min-h-0')}>
129
133
  {content}
130
134
  </CardContent>
131
135
  </Card>
@@ -135,7 +139,7 @@ export function StatCard({
135
139
 
136
140
  return (
137
141
  <Card className={cardClassName}>
138
- <CardContent className={contentPadding}>
142
+ <CardContent className={cn(contentPadding, 'flex-1 flex flex-col min-h-0')}>
139
143
  {content}
140
144
  </CardContent>
141
145
  </Card>
@@ -24,7 +24,7 @@ export interface StatsCardsRowProps {
24
24
  */
25
25
  export function StatsCardsRow({ bookmarks, folders, tags, dense }: StatsCardsRowProps) {
26
26
  return (
27
- <div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
27
+ <div className="grid grid-cols-1 sm:grid-cols-3 gap-4 items-stretch">
28
28
  <StatCard
29
29
  label={bookmarks.label}
30
30
  value={bookmarks.value}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mdguggenbichler/slugbase-core",
3
- "version": "0.0.36",
3
+ "version": "0.0.37",
4
4
  "description": "SlugBase core: backend and frontend entrypoints for self-hosted and cloud apps",
5
5
  "type": "module",
6
6
  "exports": {