minka-ds 0.1.3 → 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 +2 -1
- package/src/components/ui/alert.tsx +64 -0
- package/src/components/ui/cell.tsx +3 -2
- package/src/components/ui/data-table.tsx +13 -4
- package/src/components/ui/dropdown-menu.tsx +2 -2
- package/src/components/ui/search-bar.tsx +2 -1
- package/src/components/ui/select.tsx +1 -1
- package/src/components/ui/sonner.tsx +64 -0
- package/src/components/ui/tabs.tsx +2 -2
- package/src/components/ui/tooltip.tsx +27 -1
- package/src/index.ts +2 -0
- package/tokens/gradients.css +13 -0
- package/tokens/primitives.css +3 -2
- package/tokens/text-utilities.css +140 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "minka-ds",
|
|
3
|
-
"version": "0.1.
|
|
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
|
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
3
|
+
|
|
4
|
+
import { cn } from "../../lib/utils"
|
|
5
|
+
|
|
6
|
+
const alertVariants = cva(
|
|
7
|
+
"relative w-full [border-radius:var(--radius-card)] border px-4 py-3 text-body-sm grid grid-cols-[0_1fr] has-[>svg]:grid-cols-[1rem_1fr] gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:shrink-0",
|
|
8
|
+
{
|
|
9
|
+
variants: {
|
|
10
|
+
variant: {
|
|
11
|
+
default:
|
|
12
|
+
"bg-[var(--color-bg-raised)] border-[var(--color-border-default)] text-[var(--color-text-default)] [&>svg]:text-[var(--color-text-muted)]",
|
|
13
|
+
info:
|
|
14
|
+
"bg-[var(--color-bg-info)] border-[var(--color-border-info)] text-[var(--color-text-default)] [&>svg]:text-[var(--color-feedback-info)]",
|
|
15
|
+
success:
|
|
16
|
+
"bg-[var(--color-bg-success)] border-[var(--color-border-success)] text-[var(--color-text-default)] [&>svg]:text-[var(--color-feedback-success)]",
|
|
17
|
+
warning:
|
|
18
|
+
"bg-[var(--color-bg-warning)] border-[var(--color-border-warning)] text-[var(--color-text-default)] [&>svg]:text-[var(--color-text-default)]",
|
|
19
|
+
error:
|
|
20
|
+
"bg-[var(--color-bg-error)] border-[var(--color-border-error)] text-[var(--color-text-default)] [&>svg]:text-[var(--color-feedback-error)]",
|
|
21
|
+
},
|
|
22
|
+
},
|
|
23
|
+
defaultVariants: {
|
|
24
|
+
variant: "default",
|
|
25
|
+
},
|
|
26
|
+
}
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
function Alert({
|
|
30
|
+
className,
|
|
31
|
+
variant,
|
|
32
|
+
...props
|
|
33
|
+
}: React.ComponentProps<"div"> & VariantProps<typeof alertVariants>) {
|
|
34
|
+
return (
|
|
35
|
+
<div
|
|
36
|
+
data-slot="alert"
|
|
37
|
+
role="alert"
|
|
38
|
+
className={cn(alertVariants({ variant }), className)}
|
|
39
|
+
{...props}
|
|
40
|
+
/>
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function AlertTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
45
|
+
return (
|
|
46
|
+
<div
|
|
47
|
+
data-slot="alert-title"
|
|
48
|
+
className={cn("col-start-2 text-label", className)}
|
|
49
|
+
{...props}
|
|
50
|
+
/>
|
|
51
|
+
)
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function AlertDescription({ className, ...props }: React.ComponentProps<"div">) {
|
|
55
|
+
return (
|
|
56
|
+
<div
|
|
57
|
+
data-slot="alert-description"
|
|
58
|
+
className={cn("col-start-2 text-caption-light text-[var(--color-text-default)] [&_p]:leading-relaxed", className)}
|
|
59
|
+
{...props}
|
|
60
|
+
/>
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export { Alert, AlertTitle, AlertDescription }
|
|
@@ -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 =
|
|
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=
|
|
158
|
-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
-
|
|
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
|
@@ -5,6 +5,7 @@ export { cn } from "./lib/utils"
|
|
|
5
5
|
export { usePlatform } from "./hooks/use-platform"
|
|
6
6
|
|
|
7
7
|
// Components
|
|
8
|
+
export * from "./components/ui/alert"
|
|
8
9
|
export * from "./components/ui/badge"
|
|
9
10
|
export * from "./components/ui/breadcrumb"
|
|
10
11
|
export * from "./components/ui/calendar"
|
|
@@ -26,6 +27,7 @@ export * from "./components/ui/kbd"
|
|
|
26
27
|
export * from "./components/ui/label"
|
|
27
28
|
export * from "./components/ui/pagination"
|
|
28
29
|
export * from "./components/ui/select"
|
|
30
|
+
export * from "./components/ui/sonner"
|
|
29
31
|
export * from "./components/ui/separator"
|
|
30
32
|
export * from "./components/ui/sheet"
|
|
31
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
|
+
}
|
package/tokens/primitives.css
CHANGED
|
@@ -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:
|
|
226
|
-
--primitive-z-
|
|
225
|
+
--primitive-z-modal: 200;
|
|
226
|
+
--primitive-z-floating: 210;
|
|
227
|
+
--primitive-z-toast: 300;
|
|
227
228
|
--primitive-z-tooltip: 400;
|
|
228
229
|
}
|
|
@@ -3,6 +3,11 @@
|
|
|
3
3
|
utilities are available alongside the base text styles defined in globals.css.
|
|
4
4
|
|
|
5
5
|
Does NOT set font-family — that's the consuming app's responsibility.
|
|
6
|
+
|
|
7
|
+
Serif variants come in two tiers:
|
|
8
|
+
base — mirrors the sans scale exactly (same pixel size)
|
|
9
|
+
-lg — one primitive step up, to compensate for serif's optical smallness
|
|
10
|
+
Weight is fixed at 400 — display serifs typically have no bold cut.
|
|
6
11
|
────────────────────────────────────────────────────────────────────────── */
|
|
7
12
|
@layer utilities {
|
|
8
13
|
.text-body-lg-light {
|
|
@@ -41,4 +46,139 @@
|
|
|
41
46
|
line-height: var(--primitive-line-height-normal);
|
|
42
47
|
letter-spacing: var(--primitive-letter-spacing-normal);
|
|
43
48
|
}
|
|
49
|
+
|
|
50
|
+
/* ── Serif variants ──────────────────────────────────────────────────────
|
|
51
|
+
base: same size as the sans equivalent
|
|
52
|
+
-lg: one primitive step up for optical compensation */
|
|
53
|
+
|
|
54
|
+
/* Headings — base */
|
|
55
|
+
.text-heading-1-serif {
|
|
56
|
+
font-size: var(--primitive-font-size-4xl); /* 36px */
|
|
57
|
+
font-weight: var(--primitive-font-weight-400);
|
|
58
|
+
line-height: var(--primitive-line-height-tight);
|
|
59
|
+
letter-spacing: var(--primitive-letter-spacing-normal);
|
|
60
|
+
font-family: var(--font-serif);
|
|
61
|
+
}
|
|
62
|
+
.text-heading-2-serif {
|
|
63
|
+
font-size: var(--primitive-font-size-3xl); /* 30px */
|
|
64
|
+
font-weight: var(--primitive-font-weight-400);
|
|
65
|
+
line-height: var(--primitive-line-height-snug);
|
|
66
|
+
letter-spacing: var(--primitive-letter-spacing-normal);
|
|
67
|
+
font-family: var(--font-serif);
|
|
68
|
+
}
|
|
69
|
+
.text-heading-3-serif {
|
|
70
|
+
font-size: var(--primitive-font-size-2xl); /* 24px */
|
|
71
|
+
font-weight: var(--primitive-font-weight-400);
|
|
72
|
+
line-height: var(--primitive-line-height-snug);
|
|
73
|
+
letter-spacing: var(--primitive-letter-spacing-normal);
|
|
74
|
+
font-family: var(--font-serif);
|
|
75
|
+
}
|
|
76
|
+
.text-heading-4-serif {
|
|
77
|
+
font-size: var(--primitive-font-size-xl); /* 20px */
|
|
78
|
+
font-weight: var(--primitive-font-weight-400);
|
|
79
|
+
line-height: var(--primitive-line-height-snug);
|
|
80
|
+
letter-spacing: var(--primitive-letter-spacing-normal);
|
|
81
|
+
font-family: var(--font-serif);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/* Headings — lg */
|
|
85
|
+
.text-heading-1-lg-serif {
|
|
86
|
+
font-size: var(--primitive-font-size-5xl); /* 48px */
|
|
87
|
+
font-weight: var(--primitive-font-weight-400);
|
|
88
|
+
line-height: var(--primitive-line-height-tight);
|
|
89
|
+
letter-spacing: var(--primitive-letter-spacing-normal);
|
|
90
|
+
font-family: var(--font-serif);
|
|
91
|
+
}
|
|
92
|
+
.text-heading-2-lg-serif {
|
|
93
|
+
font-size: var(--primitive-font-size-4xl); /* 36px */
|
|
94
|
+
font-weight: var(--primitive-font-weight-400);
|
|
95
|
+
line-height: var(--primitive-line-height-snug);
|
|
96
|
+
letter-spacing: var(--primitive-letter-spacing-normal);
|
|
97
|
+
font-family: var(--font-serif);
|
|
98
|
+
}
|
|
99
|
+
.text-heading-3-lg-serif {
|
|
100
|
+
font-size: var(--primitive-font-size-3xl); /* 30px */
|
|
101
|
+
font-weight: var(--primitive-font-weight-400);
|
|
102
|
+
line-height: var(--primitive-line-height-snug);
|
|
103
|
+
letter-spacing: var(--primitive-letter-spacing-normal);
|
|
104
|
+
font-family: var(--font-serif);
|
|
105
|
+
}
|
|
106
|
+
.text-heading-4-lg-serif {
|
|
107
|
+
font-size: var(--primitive-font-size-2xl); /* 24px */
|
|
108
|
+
font-weight: var(--primitive-font-weight-400);
|
|
109
|
+
line-height: var(--primitive-line-height-snug);
|
|
110
|
+
letter-spacing: var(--primitive-letter-spacing-normal);
|
|
111
|
+
font-family: var(--font-serif);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* Body — base */
|
|
115
|
+
.text-body-lg-serif {
|
|
116
|
+
font-size: var(--primitive-font-size-lg); /* 18px */
|
|
117
|
+
font-weight: var(--primitive-font-weight-400);
|
|
118
|
+
line-height: var(--primitive-line-height-normal);
|
|
119
|
+
letter-spacing: var(--primitive-letter-spacing-normal);
|
|
120
|
+
font-family: var(--font-serif);
|
|
121
|
+
}
|
|
122
|
+
.text-body-serif {
|
|
123
|
+
font-size: var(--primitive-font-size-base); /* 16px */
|
|
124
|
+
font-weight: var(--primitive-font-weight-400);
|
|
125
|
+
line-height: var(--primitive-line-height-normal);
|
|
126
|
+
letter-spacing: var(--primitive-letter-spacing-normal);
|
|
127
|
+
font-family: var(--font-serif);
|
|
128
|
+
}
|
|
129
|
+
.text-body-sm-serif {
|
|
130
|
+
font-size: var(--primitive-font-size-sm); /* 14px */
|
|
131
|
+
font-weight: var(--primitive-font-weight-400);
|
|
132
|
+
line-height: var(--primitive-line-height-normal);
|
|
133
|
+
letter-spacing: var(--primitive-letter-spacing-normal);
|
|
134
|
+
font-family: var(--font-serif);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
/* Body — lg */
|
|
138
|
+
.text-body-xl-serif {
|
|
139
|
+
font-size: var(--primitive-font-size-xl); /* 20px — body-lg stepped up */
|
|
140
|
+
font-weight: var(--primitive-font-weight-400);
|
|
141
|
+
line-height: var(--primitive-line-height-normal);
|
|
142
|
+
letter-spacing: var(--primitive-letter-spacing-normal);
|
|
143
|
+
font-family: var(--font-serif);
|
|
144
|
+
}
|
|
145
|
+
.text-body-sm-lg-serif {
|
|
146
|
+
font-size: var(--primitive-font-size-base); /* 16px — body-sm stepped up */
|
|
147
|
+
font-weight: var(--primitive-font-weight-400);
|
|
148
|
+
line-height: var(--primitive-line-height-normal);
|
|
149
|
+
letter-spacing: var(--primitive-letter-spacing-normal);
|
|
150
|
+
font-family: var(--font-serif);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/* Caption — base */
|
|
154
|
+
.text-caption-serif {
|
|
155
|
+
font-size: var(--primitive-font-size-xs); /* 12px */
|
|
156
|
+
font-weight: var(--primitive-font-weight-400);
|
|
157
|
+
line-height: var(--primitive-line-height-normal);
|
|
158
|
+
letter-spacing: var(--primitive-letter-spacing-normal);
|
|
159
|
+
font-family: var(--font-serif);
|
|
160
|
+
}
|
|
161
|
+
.text-caption-sm-serif {
|
|
162
|
+
font-size: var(--primitive-font-size-2xs); /* 10px */
|
|
163
|
+
font-weight: var(--primitive-font-weight-400);
|
|
164
|
+
line-height: var(--primitive-line-height-normal);
|
|
165
|
+
letter-spacing: var(--primitive-letter-spacing-normal);
|
|
166
|
+
font-family: var(--font-serif);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/* Caption — lg */
|
|
170
|
+
.text-caption-lg-serif {
|
|
171
|
+
font-size: var(--primitive-font-size-sm); /* 14px — caption stepped up */
|
|
172
|
+
font-weight: var(--primitive-font-weight-400);
|
|
173
|
+
line-height: var(--primitive-line-height-normal);
|
|
174
|
+
letter-spacing: var(--primitive-letter-spacing-normal);
|
|
175
|
+
font-family: var(--font-serif);
|
|
176
|
+
}
|
|
177
|
+
.text-caption-sm-lg-serif {
|
|
178
|
+
font-size: var(--primitive-font-size-xs); /* 12px — caption-sm stepped up */
|
|
179
|
+
font-weight: var(--primitive-font-weight-400);
|
|
180
|
+
line-height: var(--primitive-line-height-normal);
|
|
181
|
+
letter-spacing: var(--primitive-letter-spacing-normal);
|
|
182
|
+
font-family: var(--font-serif);
|
|
183
|
+
}
|
|
44
184
|
}
|