frappe-ui 1.0.0-beta.75 → 1.0.0-beta.76
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/experimental/CommandPalette/CommandPaletteFooter.vue +1 -1
- package/experimental/CommandPalette/CommandPaletteGroup.vue +1 -1
- package/experimental/CommandPalette/CommandPaletteInput.vue +1 -1
- package/experimental/CommandPalette/CommandPaletteItem.vue +1 -1
- package/package.json +1 -1
- package/src/components/Badge/Badge.vue +1 -1
- package/src/components/Breadcrumbs/Breadcrumbs.vue +6 -4
- package/src/components/Button/Button.vue +6 -1
- package/src/components/Combobox/Combobox.vue +1 -1
- package/src/components/Combobox/ComboboxResults.vue +2 -2
- package/src/components/DatePicker/CalendarPanel.vue +2 -2
- package/src/components/FormLabel/FormLabel.vue +5 -1
- package/src/components/InputLabeling/InputLabel.vue +1 -1
- package/src/components/ItemListRow/ItemListRow.vue +1 -1
- package/src/components/Menu/MenuItemContent.vue +1 -1
- package/src/components/Menu/utils.ts +2 -1
- package/src/components/MobileNav/MobileNavItem.vue +2 -2
- package/src/components/MultiSelect/MultiSelectResults.vue +1 -1
- package/src/components/Select/Select.vue +3 -3
- package/src/components/SettingsDialog/SettingsRow.vue +1 -1
- package/src/components/Sidebar/SidebarHeader.vue +6 -2
- package/src/components/Sidebar/SidebarItem.vue +6 -2
- package/src/components/Sidebar/SidebarLabel.vue +1 -1
- package/src/components/Sidebar/SidebarSection.vue +1 -1
- package/src/components/Switch/Switch.vue +4 -1
- package/src/components/TextInput/TextInput.vue +1 -1
- package/src/components/TimePicker/TimePicker.vue +1 -1
- package/src/components/Tree/TreeItem.vue +3 -1
- package/src/components/shared/tabs/Pill.vue +3 -1
- package/src/molecules/list/ListGroup.vue +1 -1
- package/src/molecules/list/ListHeader.vue +5 -1
- package/src/molecules/list/ListHeaderCell.vue +1 -1
- package/src/molecules/list/ListHeaderCellSort.vue +2 -2
- package/tailwind/plugin.js +7 -0
- package/tailwind/tokens/build.js +11 -2
- package/tailwind/tokens/typography.js +10 -10
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
3
|
data-slot="command-palette-footer"
|
|
4
|
-
class="flex shrink-0 items-center gap-4 border-t border-outline-gray-1 px-4.5 py-2 text-sm text-ink-gray-6 dark:border-outline-gray-2"
|
|
4
|
+
class="flex shrink-0 items-center gap-4 border-t border-outline-gray-1 px-4.5 py-2 text-sm leading-tighter text-ink-gray-6 dark:border-outline-gray-2"
|
|
5
5
|
>
|
|
6
6
|
<slot v-bind="slotProps" />
|
|
7
7
|
</div>
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
auto-focus
|
|
13
13
|
autocomplete="off"
|
|
14
14
|
:placeholder="placeholder"
|
|
15
|
-
class="w-full border-none bg-transparent py-3 px-0 text-base text-ink-gray-8 placeholder-ink-gray-4 focus:ring-0"
|
|
15
|
+
class="w-full border-none bg-transparent py-3 px-0 text-base leading-tighter text-ink-gray-8 placeholder-ink-gray-4 focus:ring-0"
|
|
16
16
|
v-bind="$attrs"
|
|
17
17
|
/>
|
|
18
18
|
<slot name="suffix" />
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
data-slot="command-palette-item"
|
|
14
14
|
:data-state="active ? 'active' : undefined"
|
|
15
15
|
:data-disabled="disabled ? '' : undefined"
|
|
16
|
-
class="mx-2.5 flex min-w-0 cursor-default items-center rounded-4 px-2 py-2 text-base-medium text-ink-gray-8 outline-none data-[state=active]:bg-surface-gray-2 data-[disabled]:cursor-not-allowed data-[disabled]:text-ink-gray-4"
|
|
16
|
+
class="mx-2.5 flex min-w-0 cursor-default items-center rounded-4 px-2 py-2 text-base-medium leading-tighter text-ink-gray-8 outline-none data-[state=active]:bg-surface-gray-2 data-[disabled]:cursor-not-allowed data-[disabled]:text-ink-gray-4"
|
|
17
17
|
v-bind="$attrs"
|
|
18
18
|
>
|
|
19
19
|
<slot name="prefix" v-bind="slotProps" />
|
package/package.json
CHANGED
|
@@ -13,13 +13,15 @@
|
|
|
13
13
|
</span>
|
|
14
14
|
</template>
|
|
15
15
|
|
|
16
|
-
<div
|
|
16
|
+
<div
|
|
17
|
+
class="flex min-w-0 items-center text-ellipsis whitespace-nowrap leading-tighter"
|
|
18
|
+
>
|
|
17
19
|
<template v-for="(item, i) in crumbs" :key="item.label">
|
|
18
20
|
<router-link
|
|
19
21
|
v-if="item.route"
|
|
20
22
|
:to="item.route"
|
|
21
23
|
@click="item.onClick?.($event)"
|
|
22
|
-
class="flex items-center rounded-4 px-0.5 py-1 text-lg-medium"
|
|
24
|
+
class="flex items-center rounded-4 px-0.5 py-1 text-lg-medium leading-tighter"
|
|
23
25
|
:class="[
|
|
24
26
|
i == crumbs.length - 1
|
|
25
27
|
? 'min-w-0 text-ink-gray-9'
|
|
@@ -39,7 +41,7 @@
|
|
|
39
41
|
v-else-if="item.href"
|
|
40
42
|
:href="item.href"
|
|
41
43
|
@click="onLinkClick(item, $event)"
|
|
42
|
-
class="flex items-center rounded-4 px-0.5 py-1 text-lg-medium"
|
|
44
|
+
class="flex items-center rounded-4 px-0.5 py-1 text-lg-medium leading-tighter"
|
|
43
45
|
:class="[
|
|
44
46
|
i == crumbs.length - 1
|
|
45
47
|
? 'min-w-0 text-ink-gray-9'
|
|
@@ -58,7 +60,7 @@
|
|
|
58
60
|
<button
|
|
59
61
|
v-else
|
|
60
62
|
@click="item.onClick?.($event)"
|
|
61
|
-
class="flex items-center rounded-4 px-0.5 py-1 text-lg-medium"
|
|
63
|
+
class="flex items-center rounded-4 px-0.5 py-1 text-lg-medium leading-tighter"
|
|
62
64
|
:class="[
|
|
63
65
|
i == crumbs.length - 1
|
|
64
66
|
? 'min-w-0 text-ink-gray-9'
|
|
@@ -321,7 +321,12 @@ export default defineComponent({
|
|
|
321
321
|
}
|
|
322
322
|
return h(
|
|
323
323
|
'span',
|
|
324
|
-
{
|
|
324
|
+
{
|
|
325
|
+
class: [
|
|
326
|
+
'truncate leading-tighter',
|
|
327
|
+
{ 'sr-only': isIconButton.value },
|
|
328
|
+
],
|
|
329
|
+
},
|
|
325
330
|
slots.default?.() ?? props.label,
|
|
326
331
|
)
|
|
327
332
|
}
|
|
@@ -140,7 +140,7 @@ function handleSelect(item: NormalizedItem, event: Event) {
|
|
|
140
140
|
<ComboboxLabel
|
|
141
141
|
v-if="group.group && !group.hideLabel"
|
|
142
142
|
data-slot="group-label"
|
|
143
|
-
class="flex h-7 items-center px-2 text-sm-medium text-ink-gray-4"
|
|
143
|
+
class="flex h-7 items-center px-2 text-sm-medium leading-tighter text-ink-gray-4"
|
|
144
144
|
>
|
|
145
145
|
<component
|
|
146
146
|
:is="ItemSlotRender"
|
|
@@ -245,7 +245,7 @@ function handleSelect(item: NormalizedItem, event: Event) {
|
|
|
245
245
|
/>
|
|
246
246
|
|
|
247
247
|
<div v-else class="min-w-0">
|
|
248
|
-
<div class="truncate">{{ item.label }}</div>
|
|
248
|
+
<div class="truncate leading-tighter">{{ item.label }}</div>
|
|
249
249
|
<div
|
|
250
250
|
v-if="item.description"
|
|
251
251
|
class="truncate text-p-sm text-ink-gray-5"
|
|
@@ -158,7 +158,7 @@
|
|
|
158
158
|
v-for="y in years"
|
|
159
159
|
type="button"
|
|
160
160
|
:key="y"
|
|
161
|
-
class="w-full text-ink-gray-8 h-7 shrink-0 rounded-4 py-1 text-sm text-center cursor-pointer transition-colors duration-100"
|
|
161
|
+
class="w-full text-ink-gray-8 h-7 shrink-0 rounded-4 py-1 text-sm leading-tighter text-center cursor-pointer transition-colors duration-100"
|
|
162
162
|
:class="
|
|
163
163
|
y === currentYear
|
|
164
164
|
? 'bg-surface-gray-2 hover:bg-surface-gray-3'
|
|
@@ -181,7 +181,7 @@
|
|
|
181
181
|
v-for="(m, i) in months"
|
|
182
182
|
type="button"
|
|
183
183
|
:key="m"
|
|
184
|
-
class="w-full text-ink-gray-8 shrink-0 h-7 rounded-4 py-1 text-sm text-center cursor-pointer transition-colors duration-100"
|
|
184
|
+
class="w-full text-ink-gray-8 shrink-0 h-7 rounded-4 py-1 text-sm leading-tighter text-center cursor-pointer transition-colors duration-100"
|
|
185
185
|
:class="
|
|
186
186
|
i === currentMonth
|
|
187
187
|
? 'bg-surface-gray-2 hover:bg-surface-gray-3'
|
|
@@ -41,7 +41,7 @@ const labelClasses = computed(() => {
|
|
|
41
41
|
// Disabled wins over `color` — a dimmed label is a state, not a choice, so
|
|
42
42
|
// callers shouldn't have to remember to swap the colour themselves.
|
|
43
43
|
return [
|
|
44
|
-
'block text-sm',
|
|
44
|
+
'block text-sm leading-tighter',
|
|
45
45
|
props.disabled
|
|
46
46
|
? 'text-ink-gray-4'
|
|
47
47
|
: props.color === 'gray-7'
|
|
@@ -167,7 +167,7 @@ function handleSwitchChange(value: boolean) {
|
|
|
167
167
|
:content="itemSlotsLabelContent"
|
|
168
168
|
/>
|
|
169
169
|
<div v-else class="min-w-0">
|
|
170
|
-
<div :class="['truncate', getMenuTextColor(item)]">
|
|
170
|
+
<div :class="['truncate leading-tighter', getMenuTextColor(item)]">
|
|
171
171
|
{{ item.label }}
|
|
172
172
|
</div>
|
|
173
173
|
<div v-if="item.description" class="truncate text-p-sm text-ink-gray-5">
|
|
@@ -18,7 +18,8 @@ export const menuClasses = {
|
|
|
18
18
|
content:
|
|
19
19
|
'menu-content z-[100] min-w-40 divide-y divide-outline-elevation-2 rounded-6 bg-surface-elevation-2 shadow-2xl ring-1 ring-black ring-opacity-5 focus:outline-none',
|
|
20
20
|
group: 'p-1.5',
|
|
21
|
-
groupLabel:
|
|
21
|
+
groupLabel:
|
|
22
|
+
'flex h-7 items-center px-2 text-sm font-medium leading-tighter text-ink-gray-4',
|
|
22
23
|
itemIcon: 'size-4 shrink-0',
|
|
23
24
|
itemIconPlaceholder: 'size-4 shrink-0',
|
|
24
25
|
chevronIcon: 'size-4 shrink-0',
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
/>
|
|
27
27
|
</slot>
|
|
28
28
|
<span
|
|
29
|
-
class="text-xs-medium"
|
|
29
|
+
class="text-xs-medium leading-tighter"
|
|
30
30
|
:class="resolvedActive ? 'text-ink-gray-8' : 'text-ink-gray-5'"
|
|
31
31
|
>
|
|
32
32
|
{{ label }}
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
/>
|
|
52
52
|
</slot>
|
|
53
53
|
<span
|
|
54
|
-
class="text-xs-medium"
|
|
54
|
+
class="text-xs-medium leading-tighter"
|
|
55
55
|
:class="resolvedActive ? 'text-ink-gray-8' : 'text-ink-gray-5'"
|
|
56
56
|
>
|
|
57
57
|
{{ label }}
|
|
@@ -109,7 +109,7 @@ function getItemTextValue(item: NormalizedOption) {
|
|
|
109
109
|
<ComboboxLabel
|
|
110
110
|
v-if="group.group && !group.hideLabel"
|
|
111
111
|
data-slot="group-label"
|
|
112
|
-
class="flex h-7 items-center px-2 text-sm-medium text-ink-gray-4"
|
|
112
|
+
class="flex h-7 items-center px-2 text-sm-medium leading-tighter text-ink-gray-4"
|
|
113
113
|
>
|
|
114
114
|
<component
|
|
115
115
|
:is="ItemSlotRender"
|
|
@@ -362,7 +362,7 @@ defineExpose(exposed)
|
|
|
362
362
|
>
|
|
363
363
|
<SelectValue
|
|
364
364
|
:placeholder="placeholder"
|
|
365
|
-
class="max-w-full truncate opacity-0"
|
|
365
|
+
class="max-w-full truncate leading-tighter opacity-0"
|
|
366
366
|
:class="{ 'text-ink-gray-4': showPlaceholderForSelected }"
|
|
367
367
|
>
|
|
368
368
|
<template v-if="selectedOption">
|
|
@@ -400,7 +400,7 @@ defineExpose(exposed)
|
|
|
400
400
|
<div class="grid min-w-0 text-left truncate">
|
|
401
401
|
<SelectValue
|
|
402
402
|
:placeholder="placeholder"
|
|
403
|
-
class="col-start-1 row-start-1 max-w-full truncate"
|
|
403
|
+
class="col-start-1 row-start-1 max-w-full truncate leading-tighter"
|
|
404
404
|
:class="{ 'text-ink-gray-4': showPlaceholderForSelected }"
|
|
405
405
|
>
|
|
406
406
|
<template v-if="selectedOption">
|
|
@@ -540,7 +540,7 @@ defineExpose(exposed)
|
|
|
540
540
|
name="item-label"
|
|
541
541
|
v-bind="getItemSlotProps(internalOption.option)"
|
|
542
542
|
>
|
|
543
|
-
<div class="truncate">
|
|
543
|
+
<div class="truncate leading-tighter">
|
|
544
544
|
{{ internalOption.option.label }}
|
|
545
545
|
</div>
|
|
546
546
|
<div
|
|
@@ -51,10 +51,14 @@
|
|
|
51
51
|
inherited size and text at another puts the baseline at a
|
|
52
52
|
different offset in an app whose layout sets a smaller base
|
|
53
53
|
size, and the header text sat a px lower there. -->
|
|
54
|
-
<div
|
|
54
|
+
<div
|
|
55
|
+
class="truncate text-base-medium leading-tighter text-ink-gray-8"
|
|
56
|
+
>
|
|
55
57
|
{{ props.title }}
|
|
56
58
|
</div>
|
|
57
|
-
<div
|
|
59
|
+
<div
|
|
60
|
+
class="mt-0.5 truncate text-sm leading-tighter text-ink-gray-6"
|
|
61
|
+
>
|
|
58
62
|
{{ props.subtitle }}
|
|
59
63
|
</div>
|
|
60
64
|
</div>
|
|
@@ -52,7 +52,9 @@
|
|
|
52
52
|
>
|
|
53
53
|
<span ref="labelEl" class="flex min-w-0 items-center">
|
|
54
54
|
<slot
|
|
55
|
-
><span class="truncate text-sm">{{
|
|
55
|
+
><span class="truncate text-sm leading-tighter">{{
|
|
56
|
+
label
|
|
57
|
+
}}</span></slot
|
|
56
58
|
>
|
|
57
59
|
</span>
|
|
58
60
|
</span>
|
|
@@ -91,7 +93,9 @@
|
|
|
91
93
|
>
|
|
92
94
|
<span ref="labelEl" class="flex min-w-0 items-center">
|
|
93
95
|
<slot
|
|
94
|
-
><span class="truncate text-sm">{{
|
|
96
|
+
><span class="truncate text-sm leading-tighter">{{
|
|
97
|
+
label
|
|
98
|
+
}}</span></slot
|
|
95
99
|
>
|
|
96
100
|
</span>
|
|
97
101
|
</span>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div data-slot="sidebar-label" class="relative flex h-7 items-center pl-2">
|
|
3
3
|
<h3
|
|
4
|
-
class="text-base text-ink-gray-5 transition-all duration-300 ease-in-out"
|
|
4
|
+
class="text-base leading-tighter text-ink-gray-5 transition-all duration-300 ease-in-out"
|
|
5
5
|
:class="
|
|
6
6
|
isCollapsed ? 'w-0 overflow-hidden opacity-0' : 'w-auto opacity-100'
|
|
7
7
|
"
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
<h3> inside it strips the heading from the accessibility tree.
|
|
17
17
|
-->
|
|
18
18
|
<h3
|
|
19
|
-
class="h-4 text-sm text-ink-gray-5 transition-all duration-300 ease-in-out"
|
|
19
|
+
class="h-4 text-sm leading-tighter text-ink-gray-5 transition-all duration-300 ease-in-out"
|
|
20
20
|
:class="
|
|
21
21
|
isSidebarCollapsed
|
|
22
22
|
? 'w-0 overflow-hidden opacity-0'
|
|
@@ -189,7 +189,10 @@ const controlPosition = computed(() => props.controlPosition ?? 'end')
|
|
|
189
189
|
const switchGroupClasses = computed(() => {
|
|
190
190
|
const hasLabel = props.label || slots.label
|
|
191
191
|
const hasDescription = props.description || slots.description
|
|
192
|
-
|
|
192
|
+
// A bare switch still gets `flex`: in a plain block the inline-flex control
|
|
193
|
+
// sits on a text line, and that line takes its height from the parent's
|
|
194
|
+
// line-height. In a 28px menu row that made the row 29px.
|
|
195
|
+
if (!hasLabel && !hasDescription) return 'flex'
|
|
193
196
|
|
|
194
197
|
// `flex-row-reverse` / `justify-*` are inline-axis aware, so this flips
|
|
195
198
|
// correctly under RTL without any physical left/right values.
|
|
@@ -82,7 +82,7 @@
|
|
|
82
82
|
:id="optionId(idx)"
|
|
83
83
|
type="button"
|
|
84
84
|
role="option"
|
|
85
|
-
class="group flex h-7 w-full items-center rounded-4 px-2 text-left tabular-nums"
|
|
85
|
+
class="group flex h-7 w-full items-center rounded-4 px-2 text-left leading-tighter tabular-nums"
|
|
86
86
|
:class="rowClass(opt, idx)"
|
|
87
87
|
:aria-selected="canonicalValue === opt.value || undefined"
|
|
88
88
|
@click="selectOption(opt.value)"
|
|
@@ -66,7 +66,9 @@
|
|
|
66
66
|
<slot name="item-prefix" v-bind="itemSlotProps" />
|
|
67
67
|
|
|
68
68
|
<slot name="item-label" v-bind="itemSlotProps">
|
|
69
|
-
<span class="truncate text-base text-ink-gray-8">{{
|
|
69
|
+
<span class="truncate text-base leading-tighter text-ink-gray-8">{{
|
|
70
|
+
label
|
|
71
|
+
}}</span>
|
|
70
72
|
</slot>
|
|
71
73
|
|
|
72
74
|
<span class="ml-auto flex items-center">
|
|
@@ -76,7 +76,9 @@ const rootClasses = computed(() => [
|
|
|
76
76
|
'inline-flex box-border shrink-0 select-none items-center justify-center whitespace-nowrap outline-none transition-[background-color,color,box-shadow] duration-150 ease-out motion-reduce:transition-none',
|
|
77
77
|
// Shipped v1 subtle typography (overrides Figma): 13px regular at both
|
|
78
78
|
// sizes, never medium.
|
|
79
|
-
props.variant === 'subtle'
|
|
79
|
+
props.variant === 'subtle'
|
|
80
|
+
? 'text-sm leading-[16.1px]'
|
|
81
|
+
: 'text-base leading-tighter',
|
|
80
82
|
props.active ? 'text-ink-gray-8' : 'text-ink-gray-5',
|
|
81
83
|
// Figma: md ghost/browser labels use text/base/medium (500, 0.015em);
|
|
82
84
|
// md underline and all sm labels stay regular. The selected state
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<div
|
|
8
8
|
v-if="label || $slots.label"
|
|
9
9
|
data-slot="list-group-header"
|
|
10
|
-
class="flex h-8 items-center text-sm-medium text-ink-gray-5"
|
|
10
|
+
class="flex h-8 items-center text-sm-medium leading-tighter text-ink-gray-5"
|
|
11
11
|
:class="sticky && 'sticky top-0 z-10 bg-surface-base'"
|
|
12
12
|
>
|
|
13
13
|
<slot name="label">{{ label }}</slot>
|
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
<template>
|
|
2
|
-
<div
|
|
2
|
+
<div
|
|
3
|
+
data-slot="list-header"
|
|
4
|
+
role="row"
|
|
5
|
+
class="h-8 text-sm leading-tighter text-ink-gray-5"
|
|
6
|
+
>
|
|
3
7
|
<slot />
|
|
4
8
|
<Transition
|
|
5
9
|
enter-active-class="transition-transform duration-75 ease-out"
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<span v-if="$slots.prefix" class="shrink-0">
|
|
8
8
|
<slot name="prefix" />
|
|
9
9
|
</span>
|
|
10
|
-
<span class="truncate"><slot /></span>
|
|
10
|
+
<span class="truncate leading-tighter"><slot /></span>
|
|
11
11
|
<span v-if="$slots.suffix" class="shrink-0">
|
|
12
12
|
<slot name="suffix" />
|
|
13
13
|
</span>
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
<button
|
|
17
17
|
ref="button"
|
|
18
18
|
type="button"
|
|
19
|
-
class="group inline-flex h-7 min-w-0 items-center gap-1 rounded-4 text-sm-medium text-ink-gray-5 transition-colors"
|
|
19
|
+
class="group inline-flex h-7 min-w-0 items-center gap-1 rounded-4 text-sm-medium leading-tighter text-ink-gray-5 transition-colors"
|
|
20
20
|
@click="emit('click', $event)"
|
|
21
21
|
>
|
|
22
22
|
<!-- End-aligned: the glyph leads so the label stays flush with the
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
<span v-if="$slots.prefix" class="shrink-0">
|
|
36
36
|
<slot name="prefix" :direction="direction ?? null" />
|
|
37
37
|
</span>
|
|
38
|
-
<span class="truncate"><slot /></span>
|
|
38
|
+
<span class="truncate leading-tighter"><slot /></span>
|
|
39
39
|
<!-- A built-in arrow derived from `direction` by default, so the common
|
|
40
40
|
case needs no glyph wiring; supply #sort-indicator to override. The cell
|
|
41
41
|
owns the reveal: an inactive column's glyph shows on hover. -->
|
package/tailwind/plugin.js
CHANGED
|
@@ -239,6 +239,13 @@ export default plugin(
|
|
|
239
239
|
fontSize: buildFontSize(),
|
|
240
240
|
screens: screenTokens,
|
|
241
241
|
extend: {
|
|
242
|
+
// `leading-tighter` pins text to 1.15. It is the opt-out for
|
|
243
|
+
// single-line chrome whose height must not move: buttons, badges,
|
|
244
|
+
// labels, table headers. It sits between Tailwind's `leading-none` (1)
|
|
245
|
+
// and `leading-tight` (1.25). Tailwind's `leading-tight` does not change.
|
|
246
|
+
lineHeight: {
|
|
247
|
+
tighter: '1.15',
|
|
248
|
+
},
|
|
242
249
|
textColor: {
|
|
243
250
|
ink: semanticColors.ink,
|
|
244
251
|
},
|
package/tailwind/tokens/build.js
CHANGED
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
* ships nothing, it changed six times in four months, and it does not say
|
|
12
12
|
* what frappe-ui actually uses. The committed record is the output above, and
|
|
13
13
|
* this file is where frappe-ui deliberately overrules the export —
|
|
14
|
-
* RADIUS_OVERRIDE, FONT_WEIGHT_MAP,
|
|
14
|
+
* RADIUS_OVERRIDE, FONT_WEIGHT_MAP, TEXT_LINE_HEIGHT_OVERRIDE, DROPPED_SIZES,
|
|
15
|
+
* DROPPED_CUSTOM_ELEVATIONS,
|
|
15
16
|
* the hex→oklch conversion and the shadow layer reversal. Those are code-side
|
|
16
17
|
* opinions, which is why they live in a tested Node script rather than in a
|
|
17
18
|
* Figma plugin that no CI can run.
|
|
@@ -379,6 +380,14 @@ const pctToRatio = (v) => String(round(parseFloat(v) / 100, 4)) // "115%" -> "1.
|
|
|
379
380
|
// letter-spacing % of font size === em. `paragraph/5xl` exports as "0.5px" by an
|
|
380
381
|
// exporter bug (should be "0.5%"); parseFloat keeps the number and we treat it
|
|
381
382
|
// as a percent regardless of unit, which yields the intended value either way.
|
|
383
|
+
// The UI text styles, sizes 2xs to 4xl, export at 115%, which cramps
|
|
384
|
+
// any text that wraps. frappe-ui ships them at 135%. Single-line chrome opts
|
|
385
|
+
// back to 1.15 with `leading-tighter` (tailwind/plugin.js). The paragraph and
|
|
386
|
+
// display styles export other values and are not touched. Keep the override
|
|
387
|
+
// until the Figma text styles move to 135%.
|
|
388
|
+
const TEXT_LINE_HEIGHT_OVERRIDE = { '115%': '135%' }
|
|
389
|
+
export const textLineHeight = (v) =>
|
|
390
|
+
pctToRatio(TEXT_LINE_HEIGHT_OVERRIDE[v] ?? v)
|
|
382
391
|
const lsToEm = (v) => `${round(parseFloat(v) / 100, 5)}em` // "2%" -> "0.02em"
|
|
383
392
|
|
|
384
393
|
function round(n, places) {
|
|
@@ -448,7 +457,7 @@ function buildTypography() {
|
|
|
448
457
|
fontSize[key] = [
|
|
449
458
|
v.fontSize,
|
|
450
459
|
{
|
|
451
|
-
lineHeight:
|
|
460
|
+
lineHeight: textLineHeight(v.lineHeight),
|
|
452
461
|
letterSpacing: lsToEm(v.letterSpacing),
|
|
453
462
|
fontWeight: FONT_WEIGHT_MAP.regular,
|
|
454
463
|
},
|
|
@@ -16,7 +16,7 @@ export default {
|
|
|
16
16
|
"2xs": [
|
|
17
17
|
"11px",
|
|
18
18
|
{
|
|
19
|
-
"lineHeight": "1.
|
|
19
|
+
"lineHeight": "1.35",
|
|
20
20
|
"letterSpacing": "0.01em",
|
|
21
21
|
"fontWeight": 420
|
|
22
22
|
}
|
|
@@ -24,7 +24,7 @@ export default {
|
|
|
24
24
|
"xs": [
|
|
25
25
|
"12px",
|
|
26
26
|
{
|
|
27
|
-
"lineHeight": "1.
|
|
27
|
+
"lineHeight": "1.35",
|
|
28
28
|
"letterSpacing": "0.02em",
|
|
29
29
|
"fontWeight": 420
|
|
30
30
|
}
|
|
@@ -32,7 +32,7 @@ export default {
|
|
|
32
32
|
"sm": [
|
|
33
33
|
"13px",
|
|
34
34
|
{
|
|
35
|
-
"lineHeight": "1.
|
|
35
|
+
"lineHeight": "1.35",
|
|
36
36
|
"letterSpacing": "0.02em",
|
|
37
37
|
"fontWeight": 420
|
|
38
38
|
}
|
|
@@ -40,7 +40,7 @@ export default {
|
|
|
40
40
|
"base": [
|
|
41
41
|
"14px",
|
|
42
42
|
{
|
|
43
|
-
"lineHeight": "1.
|
|
43
|
+
"lineHeight": "1.35",
|
|
44
44
|
"letterSpacing": "0.02em",
|
|
45
45
|
"fontWeight": 420
|
|
46
46
|
}
|
|
@@ -48,7 +48,7 @@ export default {
|
|
|
48
48
|
"md": [
|
|
49
49
|
"15px",
|
|
50
50
|
{
|
|
51
|
-
"lineHeight": "1.
|
|
51
|
+
"lineHeight": "1.35",
|
|
52
52
|
"letterSpacing": "0.02em",
|
|
53
53
|
"fontWeight": 420
|
|
54
54
|
}
|
|
@@ -56,7 +56,7 @@ export default {
|
|
|
56
56
|
"lg": [
|
|
57
57
|
"16px",
|
|
58
58
|
{
|
|
59
|
-
"lineHeight": "1.
|
|
59
|
+
"lineHeight": "1.35",
|
|
60
60
|
"letterSpacing": "0.02em",
|
|
61
61
|
"fontWeight": 420
|
|
62
62
|
}
|
|
@@ -64,7 +64,7 @@ export default {
|
|
|
64
64
|
"xl": [
|
|
65
65
|
"17px",
|
|
66
66
|
{
|
|
67
|
-
"lineHeight": "1.
|
|
67
|
+
"lineHeight": "1.35",
|
|
68
68
|
"letterSpacing": "0.02em",
|
|
69
69
|
"fontWeight": 420
|
|
70
70
|
}
|
|
@@ -72,7 +72,7 @@ export default {
|
|
|
72
72
|
"2xl": [
|
|
73
73
|
"18px",
|
|
74
74
|
{
|
|
75
|
-
"lineHeight": "1.
|
|
75
|
+
"lineHeight": "1.35",
|
|
76
76
|
"letterSpacing": "0.01em",
|
|
77
77
|
"fontWeight": 420
|
|
78
78
|
}
|
|
@@ -80,7 +80,7 @@ export default {
|
|
|
80
80
|
"3xl": [
|
|
81
81
|
"20px",
|
|
82
82
|
{
|
|
83
|
-
"lineHeight": "1.
|
|
83
|
+
"lineHeight": "1.35",
|
|
84
84
|
"letterSpacing": "0.005em",
|
|
85
85
|
"fontWeight": 420
|
|
86
86
|
}
|
|
@@ -88,7 +88,7 @@ export default {
|
|
|
88
88
|
"4xl": [
|
|
89
89
|
"24px",
|
|
90
90
|
{
|
|
91
|
-
"lineHeight": "1.
|
|
91
|
+
"lineHeight": "1.35",
|
|
92
92
|
"letterSpacing": "0.005em",
|
|
93
93
|
"fontWeight": 420
|
|
94
94
|
}
|