minka-ds 0.1.4 → 0.1.5

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": "minka-ds",
3
- "version": "0.1.4",
3
+ "version": "0.1.5",
4
4
  "description": "Minka product design system — tokenized component library",
5
5
  "license": "MIT",
6
6
  "files": [
@@ -23,6 +23,7 @@
23
23
  "lucide-react": "^1.14.0",
24
24
  "radix-ui": "^1.4.3",
25
25
  "react-day-picker": "^10.0.0",
26
+ "sonner": "^2.0.7",
26
27
  "tailwind-merge": "^3.5.0",
27
28
  "tw-animate-css": "^1.4.0"
28
29
  }
@@ -10,12 +10,13 @@ import { cn } from "../../lib/utils"
10
10
  interface TextStackProps {
11
11
  primary: React.ReactNode
12
12
  secondary?: React.ReactNode
13
+ inline?: boolean
13
14
  className?: string
14
15
  }
15
16
 
16
- function TextStack({ primary, secondary, className }: TextStackProps) {
17
+ function TextStack({ primary, secondary, inline, className }: TextStackProps) {
17
18
  return (
18
- <div className={cn("flex flex-col gap-0.5", className)}>
19
+ <div className={cn(inline ? "flex flex-row items-baseline gap-1.5" : "flex flex-col gap-0.5", className)}>
19
20
  <span className="text-caption-light text-[var(--color-text-default)]">{primary}</span>
20
21
  {secondary && (
21
22
  <span className="text-caption-sm-light text-[var(--color-text-muted)]">{secondary}</span>
@@ -108,16 +108,19 @@ interface DataTableProps<TData, TValue> {
108
108
  data: TData[]
109
109
  batchSize?: number
110
110
  onRowClick?: (row: TData) => void
111
+ variant?: "default" | "compact"
111
112
  className?: string
112
113
  }
113
114
 
114
115
  function DataTable<TData, TValue>({
115
116
  columns,
116
117
  data,
117
- batchSize = 20,
118
+ batchSize = 40,
118
119
  onRowClick,
120
+ variant = "default",
119
121
  className,
120
122
  }: DataTableProps<TData, TValue>) {
123
+ const compact = variant === "compact"
121
124
  const [sorting, setSorting] = React.useState<SortingState>([])
122
125
  const [columnVisibility, setColumnVisibility] = React.useState<VisibilityState>({})
123
126
  const [displayCount, setDisplayCount] = React.useState(batchSize)
@@ -154,15 +157,21 @@ function DataTable<TData, TValue>({
154
157
  className="flex-1 min-h-0 overflow-auto rounded-[var(--radius-card)] border border-[var(--color-border-default)] bg-[var(--color-bg-raised)] [&_[data-slot=table-container]]:overflow-visible"
155
158
  >
156
159
 
157
- <Table className="[&_th:first-child]:pl-4 [&_td:first-child]:pl-4">
158
- <TableHeader className="sticky top-0 [z-index:var(--z-sticky)] bg-[var(--color-bg-base)]">
160
+ <Table className={cn(
161
+ "[&_th:first-child]:pl-4 [&_td:first-child]:pl-4",
162
+ compact && "[&_th]:h-7 [&_th]:text-caption [&_th]:text-[var(--color-text-default)] [&_td]:h-11 [&_td]:py-1.5 [&_td]:text-body-sm"
163
+ )}>
164
+ <TableHeader className={cn(
165
+ "sticky top-0 [z-index:var(--z-sticky)]",
166
+ "bg-[var(--color-bg-base)]"
167
+ )}>
159
168
  {table.getHeaderGroups().map((headerGroup) => (
160
169
  <TableRow key={headerGroup.id}>
161
170
  {headerGroup.headers.map((header, index) => (
162
171
  <TableHead key={header.id}>
163
172
  {index === headerGroup.headers.length - 1 ? (
164
173
  <div className="flex items-center justify-between gap-2">
165
- {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
174
+ <span>{header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}</span>
166
175
  <DataTableColumnToggle table={table} />
167
176
  </div>
168
177
  ) : (
@@ -42,7 +42,7 @@ function DropdownMenuContent({
42
42
  data-slot="dropdown-menu-content"
43
43
  sideOffset={sideOffset}
44
44
  className={cn(
45
- "[z-index:var(--z-dropdown)] max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto [border-radius:var(--radius-popover)] border border-[var(--color-border-default)] bg-[var(--color-bg-overlay)] p-1 text-body-sm text-[var(--color-text-default)] shadow-[var(--shadow-popover)] data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
45
+ "[z-index:var(--z-floating)] max-h-(--radix-dropdown-menu-content-available-height) min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto [border-radius:var(--radius-popover)] border border-[var(--color-border-default)] bg-[var(--color-bg-overlay)] p-1 text-body-sm text-[var(--color-text-default)] shadow-[var(--shadow-popover)] data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
46
46
  className
47
47
  )}
48
48
  {...props}
@@ -230,7 +230,7 @@ function DropdownMenuSubContent({
230
230
  <DropdownMenuPrimitive.SubContent
231
231
  data-slot="dropdown-menu-sub-content"
232
232
  className={cn(
233
- "[z-index:var(--z-dropdown)] min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden [border-radius:var(--radius-popover)] border border-[var(--color-border-default)] bg-[var(--color-bg-overlay)] p-1 text-[var(--color-text-default)] shadow-[var(--shadow-popover)] data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
233
+ "[z-index:var(--z-floating)] min-w-[8rem] origin-(--radix-dropdown-menu-content-transform-origin) overflow-hidden [border-radius:var(--radius-popover)] border border-[var(--color-border-default)] bg-[var(--color-bg-overlay)] p-1 text-[var(--color-text-default)] shadow-[var(--shadow-popover)] data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
234
234
  className
235
235
  )}
236
236
  {...props}
@@ -101,13 +101,14 @@ function SearchBar({
101
101
  onFocus={onFocus}
102
102
  autoComplete="off"
103
103
  />
104
- {(!!value || (hasFilterCategories && !hasActiveFilters)) && (
104
+ {(!!value || (hasFilterCategories && !hasActiveFilters) || (!value && !!kbdHint)) && (
105
105
  <InputGroupAddon align="inline-end">
106
106
  {value && (
107
107
  <InputGroupButton size="sm" variant="ghost" onClick={() => onChange("")} className="text-[var(--color-text-muted)] hover:text-[var(--color-text-default)]">
108
108
  <XIcon className="size-4" />
109
109
  </InputGroupButton>
110
110
  )}
111
+ {!value && kbdHint && !hasFilterCategories && <Kbd>{kbdHint}</Kbd>}
111
112
  {hasFilterCategories && !hasActiveFilters && (
112
113
  <>
113
114
  {!value && kbdHint && <Kbd>{kbdHint}</Kbd>}
@@ -69,7 +69,7 @@ function SelectContent({
69
69
  <SelectPrimitive.Content
70
70
  data-slot="select-content"
71
71
  className={cn(
72
- "relative z-[var(--z-dropdown)] max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto [border-radius:var(--radius-popover)] border border-[var(--color-border-default)] bg-[var(--color-bg-overlay)] text-[var(--color-text-default)] shadow-[var(--shadow-popover)]",
72
+ "relative z-[var(--z-floating)] max-h-(--radix-select-content-available-height) min-w-[8rem] origin-(--radix-select-content-transform-origin) overflow-x-hidden overflow-y-auto [border-radius:var(--radius-popover)] border border-[var(--color-border-default)] bg-[var(--color-bg-overlay)] text-[var(--color-text-default)] shadow-[var(--shadow-popover)]",
73
73
  "data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
74
74
  "data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95",
75
75
  "data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95",
@@ -0,0 +1,64 @@
1
+ "use client"
2
+
3
+ import { Toaster as Sonner, toast } from "sonner"
4
+
5
+ type ToasterProps = React.ComponentProps<typeof Sonner>
6
+
7
+ function Toaster({ ...props }: ToasterProps) {
8
+ return (
9
+ <Sonner
10
+ className="toaster group"
11
+ style={
12
+ {
13
+ "--normal-bg": "var(--primitive-neutral-950)",
14
+ "--normal-text": "var(--primitive-neutral-50)",
15
+ "--normal-border": "var(--primitive-neutral-900)",
16
+
17
+ "--success-bg": "var(--primitive-neutral-950)",
18
+ "--success-text": "var(--primitive-green-400)",
19
+ "--success-border": "var(--primitive-neutral-900)",
20
+
21
+ "--error-bg": "var(--primitive-neutral-950)",
22
+ "--error-text": "var(--primitive-red-400)",
23
+ "--error-border": "var(--primitive-neutral-900)",
24
+
25
+ "--warning-bg": "var(--primitive-neutral-950)",
26
+ "--warning-text": "var(--primitive-yellow-300)",
27
+ "--warning-border": "var(--primitive-neutral-900)",
28
+
29
+ "--info-bg": "var(--primitive-neutral-950)",
30
+ "--info-text": "var(--primitive-blue-400)",
31
+ "--info-border": "var(--primitive-neutral-900)",
32
+
33
+ "--border-radius": "var(--radius-card)",
34
+ "--font": "inherit",
35
+ } as React.CSSProperties
36
+ }
37
+ toastOptions={{
38
+ classNames: {
39
+ toast: "!items-start",
40
+ icon: "mt-0.5",
41
+ title: "text-label !text-[var(--primitive-neutral-50)]",
42
+ description: "text-body-sm !text-[var(--primitive-neutral-300)]",
43
+ success: "[&_[data-icon]]:text-[var(--primitive-green-400)]",
44
+ error: "[&_[data-icon]]:text-[var(--primitive-red-400)]",
45
+ warning: "[&_[data-icon]]:text-[var(--primitive-yellow-300)]",
46
+ info: "[&_[data-icon]]:text-[var(--primitive-neutral-50)]",
47
+ },
48
+ actionButtonStyle: {
49
+ height: "2rem",
50
+ padding: "0 0.75rem",
51
+ borderRadius: "var(--radius-button)",
52
+ border: "1px solid var(--primitive-neutral-700)",
53
+ background: "var(--primitive-neutral-800)",
54
+ color: "var(--primitive-neutral-50)",
55
+ fontSize: "0.875rem",
56
+ fontWeight: "600",
57
+ },
58
+ }}
59
+ {...props}
60
+ />
61
+ )
62
+ }
63
+
64
+ export { Toaster, toast }
@@ -30,7 +30,7 @@ const tabsListVariants = cva(
30
30
  {
31
31
  variants: {
32
32
  variant: {
33
- default: "[border-radius:var(--radius-card)] bg-[var(--color-bg-disabled)]",
33
+ default: "[border-radius:var(--radius-card)] border border-[var(--color-border-default)] bg-[var(--color-bg-raised)] shadow-xs",
34
34
  line: "gap-1 rounded-none bg-transparent",
35
35
  },
36
36
  },
@@ -71,7 +71,7 @@ function TabsTrigger({
71
71
  "focus-visible:border-[var(--color-border-focus)] focus-visible:ring-[3px] focus-visible:ring-[var(--color-border-focus)]/50",
72
72
  "disabled:pointer-events-none disabled:text-[var(--color-text-disabled)]",
73
73
  // default variant — active tab gets raised surface
74
- "group-data-[variant=default]/tabs-list:data-[state=active]:bg-[var(--color-bg-raised)] group-data-[variant=default]/tabs-list:data-[state=active]:text-[var(--color-text-default)] group-data-[variant=default]/tabs-list:data-[state=active]:shadow-[var(--shadow-card)]",
74
+ "group-data-[variant=default]/tabs-list:data-[state=active]:bg-[var(--color-bg-inverted)] group-data-[variant=default]/tabs-list:data-[state=active]:text-[var(--color-bg-raised)] group-data-[variant=default]/tabs-list:data-[state=active]:shadow-[var(--shadow-card)]",
75
75
  // line variant — active tab is transparent, underline indicator
76
76
  "group-data-[variant=line]/tabs-list:bg-transparent group-data-[variant=line]/tabs-list:data-[state=active]:bg-transparent group-data-[variant=line]/tabs-list:data-[state=active]:text-[var(--color-text-default)] group-data-[variant=line]/tabs-list:data-[state=active]:shadow-none",
77
77
  // underline indicator for line variant
@@ -54,4 +54,30 @@ function TooltipContent({
54
54
  )
55
55
  }
56
56
 
57
- export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }
57
+ function TooltipLabel({
58
+ className,
59
+ ...props
60
+ }: React.ComponentProps<"p">) {
61
+ return (
62
+ <p
63
+ data-slot="tooltip-label"
64
+ className={cn("text-caption text-[var(--color-text-inverse)]", className)}
65
+ {...props}
66
+ />
67
+ )
68
+ }
69
+
70
+ function TooltipDescription({
71
+ className,
72
+ ...props
73
+ }: React.ComponentProps<"p">) {
74
+ return (
75
+ <p
76
+ data-slot="tooltip-description"
77
+ className={cn("text-caption text-[var(--color-text-inverse-muted)]", className)}
78
+ {...props}
79
+ />
80
+ )
81
+ }
82
+
83
+ export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider, TooltipLabel, TooltipDescription }
package/src/index.ts CHANGED
@@ -27,6 +27,7 @@ export * from "./components/ui/kbd"
27
27
  export * from "./components/ui/label"
28
28
  export * from "./components/ui/pagination"
29
29
  export * from "./components/ui/select"
30
+ export * from "./components/ui/sonner"
30
31
  export * from "./components/ui/separator"
31
32
  export * from "./components/ui/sheet"
32
33
  export * from "./components/ui/sidebar"
@@ -0,0 +1,13 @@
1
+ /*
2
+ * Gradient tokens — semantic gradient expressions.
3
+ * Import after primitives.css. References semantic tokens (e.g. --color-bg-canvas)
4
+ * which are resolved at paint time, so import order with app globals doesn't matter.
5
+ */
6
+
7
+ :root {
8
+ --gradient-page: linear-gradient(180deg, var(--color-bg-base) 0%, var(--color-bg-base) 20%, var(--primitive-neutral-0) 100%);
9
+ }
10
+
11
+ .dark {
12
+ --gradient-page: linear-gradient(180deg, var(--color-bg-base) 0%, var(--color-bg-base) 20%, var(--primitive-neutral-800) 100%);
13
+ }
@@ -222,7 +222,8 @@
222
222
  --primitive-z-raised: 10;
223
223
  --primitive-z-dropdown: 20;
224
224
  --primitive-z-overlay: 100;
225
- --primitive-z-modal: 200;
226
- --primitive-z-toast: 300;
225
+ --primitive-z-modal: 200;
226
+ --primitive-z-floating: 210;
227
+ --primitive-z-toast: 300;
227
228
  --primitive-z-tooltip: 400;
228
229
  }