@passui/react 0.1.44 → 0.1.46

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.
Files changed (140) hide show
  1. package/README.md +57 -46
  2. package/dist/types/src/components/accordion/accordion.d.ts +1 -1
  3. package/dist/types/src/components/breadcrumb/breadcrumb.d.ts +1 -1
  4. package/dist/types/src/components/inline-disclosure/inline-disclosure.d.ts +1 -1
  5. package/dist/types/src/components/popover/anchored-surface.d.ts +5 -1
  6. package/dist/types/src/components/popover/index.d.ts +41 -0
  7. package/dist/types/src/components/popover/popover-content.d.ts +32 -0
  8. package/dist/types/src/components/popover/popover-root.d.ts +22 -0
  9. package/dist/types/src/components/popover/popover-trigger.d.ts +23 -0
  10. package/dist/types/src/components/stepper/rolling-digit.d.ts +1 -1
  11. package/dist/types/src/components/table/table.d.ts +1 -1
  12. package/dist/types/src/components/view-controller/view-controller.d.ts +2 -2
  13. package/dist/types/src/index.d.ts +1 -1
  14. package/dist/types/src/machines/popover.machine.d.ts +30 -0
  15. package/package.json +307 -307
  16. package/src/appearance/index.ts +2 -2
  17. package/src/appearance/platform.tsx +76 -60
  18. package/src/appearance/theme.tsx +409 -377
  19. package/src/components/accordion/accordion.tsx +58 -49
  20. package/src/components/ambient/ambient.tsx +25 -25
  21. package/src/components/ambient/index.ts +1 -1
  22. package/src/components/aspect-ratio/aspect-ratio.tsx +21 -16
  23. package/src/components/breadcrumb/breadcrumb.tsx +63 -57
  24. package/src/components/button/button-styles.ts +39 -32
  25. package/src/components/button/button.tsx +91 -84
  26. package/src/components/button/icon-button.tsx +27 -25
  27. package/src/components/button/pending-spinner.tsx +8 -8
  28. package/src/components/button/use-pending-indicator.ts +11 -11
  29. package/src/components/chip/chip.tsx +35 -30
  30. package/src/components/code-block/code-block.tsx +40 -39
  31. package/src/components/combo-box/combo-box.tsx +5 -5
  32. package/src/components/command/command.tsx +124 -94
  33. package/src/components/compact-date-picker/calendar-month.ts +75 -53
  34. package/src/components/compact-date-picker/compact-date-picker.tsx +308 -289
  35. package/src/components/compact-time-picker/compact-time-picker.tsx +288 -281
  36. package/src/components/compact-time-picker/time-value.ts +32 -29
  37. package/src/components/content-unavailable-view/content-unavailable-view.tsx +64 -48
  38. package/src/components/content-view/content-view.tsx +168 -159
  39. package/src/components/content-view/index.ts +1 -1
  40. package/src/components/context-menu/conceal-menu-source.ts +25 -25
  41. package/src/components/context-menu/context-menu-host.tsx +439 -398
  42. package/src/components/context-menu/context-menu-store.ts +125 -123
  43. package/src/components/context-menu/menu-navigation.ts +25 -18
  44. package/src/components/context-menu/menu-position.ts +33 -29
  45. package/src/components/context-menu/menu-reveal.ts +32 -32
  46. package/src/components/context-menu/use-context-menu.ts +63 -56
  47. package/src/components/conversation/conversation.tsx +265 -263
  48. package/src/components/conversation/index.ts +1 -1
  49. package/src/components/date-picker/date-picker.tsx +95 -94
  50. package/src/components/date-picker/date-value.ts +20 -10
  51. package/src/components/dialog/dialog-host.tsx +105 -103
  52. package/src/components/dialog/dialog-store.ts +37 -36
  53. package/src/components/dialog/dialog.tsx +192 -179
  54. package/src/components/dialog/index.ts +1 -1
  55. package/src/components/disclosure-group/disclosure-group.tsx +93 -86
  56. package/src/components/divider/divider.tsx +24 -22
  57. package/src/components/inline-disclosure/inline-disclosure.tsx +40 -36
  58. package/src/components/keyboard-shortcut/keyboard-shortcut.tsx +23 -19
  59. package/src/components/labeled-content/labeled-content.tsx +68 -68
  60. package/src/components/locale-switcher/index.ts +1 -1
  61. package/src/components/locale-switcher/locale-switcher.tsx +279 -251
  62. package/src/components/menu/menu.tsx +75 -58
  63. package/src/components/morph/index.ts +2 -2
  64. package/src/components/morph/morph.tsx +227 -201
  65. package/src/components/morph/use-morph-disclosure.ts +19 -19
  66. package/src/components/one-time-code/one-time-code.tsx +216 -200
  67. package/src/components/picker/picker-trigger.ts +16 -13
  68. package/src/components/picker/picker.tsx +371 -345
  69. package/src/components/popover/anchored-surface.tsx +253 -229
  70. package/src/components/popover/index.ts +50 -0
  71. package/src/components/popover/popover-content.tsx +334 -0
  72. package/src/components/popover/popover-fit.ts +58 -53
  73. package/src/components/popover/popover-root.tsx +97 -0
  74. package/src/components/popover/popover-trigger.tsx +71 -0
  75. package/src/components/profile-image/profile-image.tsx +80 -64
  76. package/src/components/progress-view/progress-view.tsx +61 -59
  77. package/src/components/progress-view/use-liquid-progress.ts +38 -38
  78. package/src/components/radio-group/radio-group.tsx +71 -68
  79. package/src/components/search-field/expanding-search-field.tsx +191 -177
  80. package/src/components/search-field/search-field.tsx +59 -50
  81. package/src/components/search-list/search-list.tsx +246 -236
  82. package/src/components/section/section.tsx +58 -58
  83. package/src/components/secure-field/secure-field.tsx +3 -3
  84. package/src/components/segmented-control/segmented-control.tsx +136 -136
  85. package/src/components/sheet/modal-environment.ts +71 -64
  86. package/src/components/sheet/sheet-portal.tsx +58 -53
  87. package/src/components/sheet/sheet.tsx +146 -141
  88. package/src/components/sheet/use-sheet-focus.ts +97 -82
  89. package/src/components/sidebar/sidebar.tsx +78 -78
  90. package/src/components/skeleton/skeleton.tsx +30 -21
  91. package/src/components/slider/slider.tsx +113 -104
  92. package/src/components/slosh-slider/liquid-step.ts +32 -31
  93. package/src/components/slosh-slider/slosh-slider.tsx +265 -228
  94. package/src/components/stat-tile/index.ts +1 -1
  95. package/src/components/stat-tile/stat-tile.tsx +79 -68
  96. package/src/components/status-indicator/status-indicator.tsx +40 -37
  97. package/src/components/stepper/rolling-digit.tsx +82 -68
  98. package/src/components/stepper/stepper.tsx +122 -113
  99. package/src/components/swatch-picker/swatch-picker.tsx +120 -120
  100. package/src/components/tab-bar/tab-bar.tsx +149 -148
  101. package/src/components/tab-view/tab-view.tsx +140 -137
  102. package/src/components/table/table.tsx +117 -98
  103. package/src/components/text-editor/text-editor.tsx +34 -29
  104. package/src/components/text-field/text-field.tsx +182 -180
  105. package/src/components/toast/toast-store.ts +127 -115
  106. package/src/components/toast/toaster.tsx +361 -347
  107. package/src/components/toggle/toggle.tsx +297 -282
  108. package/src/components/tooltip/tooltip-host.tsx +157 -150
  109. package/src/components/view-controller/index.ts +1 -1
  110. package/src/components/view-controller/view-controller.tsx +64 -53
  111. package/src/components/wake-slider/wake-slider.tsx +220 -205
  112. package/src/hooks/scroll/minimize-decision.ts +11 -7
  113. package/src/hooks/use-anchored-disclosure.ts +19 -19
  114. package/src/hooks/use-anchored-placement.ts +29 -25
  115. package/src/hooks/use-dismiss.ts +33 -29
  116. package/src/hooks/use-floating-dismiss.ts +24 -22
  117. package/src/hooks/use-media-query.ts +67 -60
  118. package/src/hooks/use-minimize-on-scroll.ts +69 -60
  119. package/src/hooks/use-visual-viewport.ts +63 -63
  120. package/src/hooks/viewport/types.ts +16 -16
  121. package/src/hooks/viewport/viewport-metrics.ts +16 -10
  122. package/src/icons/icons.tsx +440 -328
  123. package/src/index.ts +91 -91
  124. package/src/lib/anchored-placement.ts +70 -65
  125. package/src/lib/class-names.ts +14 -13
  126. package/src/lib/clipboard.ts +8 -7
  127. package/src/lib/date.ts +61 -60
  128. package/src/lib/floating-layers.ts +39 -24
  129. package/src/lib/haptics.ts +10 -10
  130. package/src/lib/language.ts +9 -9
  131. package/src/lib/range-value.ts +27 -21
  132. package/src/lib/screen-edges.ts +33 -30
  133. package/src/lib/shapes.ts +38 -34
  134. package/src/machines/popover.machine.ts +51 -0
  135. package/src/motion/transitions.ts +46 -43
  136. package/src/styles/code-block.css +69 -43
  137. package/src/styles/motion-controls.css +393 -191
  138. package/src/tokens.ts +1 -1
  139. package/dist/types/src/components/popover/popover.d.ts +0 -21
  140. package/src/components/popover/popover.tsx +0 -322
@@ -1,29 +1,29 @@
1
- import { AnimatePresence, motion, useReducedMotion } from "motion/react"
2
- import { spring } from "../../motion/transitions"
3
- import { useEffect, useId, useState } from "react"
4
- import { cn } from "../../lib/class-names"
1
+ import { AnimatePresence, motion, useReducedMotion } from "motion/react";
2
+ import { spring } from "../../motion/transitions";
3
+ import { useEffect, useId, useState } from "react";
4
+ import { cn } from "../../lib/class-names";
5
5
 
6
- export type TooltipSize = "sm" | "md" | "lg"
6
+ export type TooltipSize = "sm" | "md" | "lg";
7
7
 
8
8
  const tooltipClasses: Record<TooltipSize, string> = {
9
- sm: "pointer-events-none fixed z-[80] max-w-[200px] rounded-md bg-inverse px-2 py-1 text-center text-caption2 leading-tight font-medium text-on-inverse shadow-lg",
10
- md: "pointer-events-none fixed z-[80] max-w-[240px] rounded-md bg-inverse px-2.5 py-1.5 text-center text-caption leading-tight font-medium text-on-inverse shadow-lg",
11
- lg: "pointer-events-none fixed z-[80] max-w-[280px] rounded-md bg-inverse px-3 py-2 text-center text-footnote leading-tight font-medium text-on-inverse shadow-lg",
12
- }
9
+ sm: "pointer-events-none fixed z-[80] max-w-[200px] rounded-md bg-inverse px-2 py-1 text-center text-caption2 leading-tight font-medium text-on-inverse shadow-lg",
10
+ md: "pointer-events-none fixed z-[80] max-w-[240px] rounded-md bg-inverse px-2.5 py-1.5 text-center text-caption leading-tight font-medium text-on-inverse shadow-lg",
11
+ lg: "pointer-events-none fixed z-[80] max-w-[280px] rounded-md bg-inverse px-3 py-2 text-center text-footnote leading-tight font-medium text-on-inverse shadow-lg",
12
+ };
13
13
 
14
14
  interface Tip {
15
- text: string
16
- x: number
17
- y: number
18
- /** Shown above the element when there's no room below. */
19
- above: boolean
20
- size: TooltipSize
15
+ text: string;
16
+ x: number;
17
+ y: number;
18
+ /** Shown above the element when there's no room below. */
19
+ above: boolean;
20
+ size: TooltipSize;
21
21
  }
22
22
 
23
- const DELAY = 450
23
+ const DELAY = 450;
24
24
  /** Moving from one control to the next within this window shows at once. */
25
- const WARM_WINDOW = 600
26
- const MARGIN = 8
25
+ const WARM_WINDOW = 600;
26
+ const MARGIN = 8;
27
27
 
28
28
  /**
29
29
  * Tooltips for any element with `data-tooltip`, on devices that can hover.
@@ -31,141 +31,148 @@ const MARGIN = 8
31
31
  * instant while moving between controls, as on macOS.
32
32
  */
33
33
  export function TooltipHost() {
34
- const [tip, setTip] = useState<Tip | null>(null)
35
- const tooltipId = useId()
36
- const reducedMotion = useReducedMotion()
34
+ const [tip, setTip] = useState<Tip | null>(null);
35
+ const tooltipId = useId();
36
+ const reducedMotion = useReducedMotion();
37
37
 
38
- useEffect(() => {
39
- const canHover = window.matchMedia("(hover: hover) and (pointer: fine)").matches
40
- let timer: ReturnType<typeof setTimeout> | undefined
41
- let current: Element | null = null
42
- let lastShown = 0
43
- let described: Element | null = null
44
- let previousDescription: string | null = null
38
+ useEffect(() => {
39
+ const canHover = window.matchMedia(
40
+ "(hover: hover) and (pointer: fine)",
41
+ ).matches;
42
+ let timer: ReturnType<typeof setTimeout> | undefined;
43
+ let current: Element | null = null;
44
+ let lastShown = 0;
45
+ let described: Element | null = null;
46
+ let previousDescription: string | null = null;
45
47
 
46
- const restoreDescription = () => {
47
- if (!described) return
48
- if (previousDescription === null) described.removeAttribute("aria-describedby")
49
- else described.setAttribute("aria-describedby", previousDescription)
50
- described = null
51
- }
48
+ const restoreDescription = () => {
49
+ if (!described) return;
50
+ if (previousDescription === null)
51
+ described.removeAttribute("aria-describedby");
52
+ else described.setAttribute("aria-describedby", previousDescription);
53
+ described = null;
54
+ };
52
55
 
53
- const show = (element: Element) => {
54
- const text = element.getAttribute("data-tooltip")
55
- if (!text) return
56
- const rect = element.getBoundingClientRect()
57
- const above = rect.bottom + 40 > window.innerHeight
58
- const sizeAttr = element.getAttribute("data-tooltip-size")
59
- const size: TooltipSize = sizeAttr === "sm" || sizeAttr === "lg" ? sizeAttr : "md"
60
- setTip({
61
- text,
62
- x: rect.left + rect.width / 2,
63
- y: above ? rect.top - MARGIN : rect.bottom + MARGIN,
64
- above,
65
- size,
66
- })
67
- lastShown = Date.now()
68
- }
69
- const hide = () => {
70
- clearTimeout(timer)
71
- if (current) lastShown = Date.now()
72
- current = null
73
- restoreDescription()
74
- setTip(null)
75
- }
76
- const onOver = (event: PointerEvent) => {
77
- if (!canHover) return
78
- const element = (event.target as Element | null)?.closest?.("[data-tooltip]") ?? null
79
- if (element === current) return
80
- clearTimeout(timer)
81
- current = element
82
- if (!element) {
83
- setTip(null)
84
- return
85
- }
86
- const warm = Date.now() - lastShown < WARM_WINDOW
87
- if (warm) show(element)
88
- else {
89
- setTip(null)
90
- timer = setTimeout(() => current === element && show(element), DELAY)
91
- }
92
- }
93
- const onFocus = (event: FocusEvent) => {
94
- const element = (event.target as Element | null)?.closest?.("[data-tooltip]") ?? null
95
- if (!element) return
96
- hide()
97
- current = element
98
- described = element
99
- previousDescription = element.getAttribute("aria-describedby")
100
- element.setAttribute(
101
- "aria-describedby",
102
- [previousDescription, tooltipId].filter(Boolean).join(" ")
103
- )
104
- show(element)
105
- }
106
- const onBlur = (event: FocusEvent) => {
107
- if (described && !described.contains(event.relatedTarget as Node | null)) hide()
108
- }
56
+ const show = (element: Element) => {
57
+ const text = element.getAttribute("data-tooltip");
58
+ if (!text) return;
59
+ const rect = element.getBoundingClientRect();
60
+ const above = rect.bottom + 40 > window.innerHeight;
61
+ const sizeAttr = element.getAttribute("data-tooltip-size");
62
+ const size: TooltipSize =
63
+ sizeAttr === "sm" || sizeAttr === "lg" ? sizeAttr : "md";
64
+ setTip({
65
+ text,
66
+ x: rect.left + rect.width / 2,
67
+ y: above ? rect.top - MARGIN : rect.bottom + MARGIN,
68
+ above,
69
+ size,
70
+ });
71
+ lastShown = Date.now();
72
+ };
73
+ const hide = () => {
74
+ clearTimeout(timer);
75
+ if (current) lastShown = Date.now();
76
+ current = null;
77
+ restoreDescription();
78
+ setTip(null);
79
+ };
80
+ const onOver = (event: PointerEvent) => {
81
+ if (!canHover) return;
82
+ const element =
83
+ (event.target as Element | null)?.closest?.("[data-tooltip]") ?? null;
84
+ if (element === current) return;
85
+ clearTimeout(timer);
86
+ current = element;
87
+ if (!element) {
88
+ setTip(null);
89
+ return;
90
+ }
91
+ const warm = Date.now() - lastShown < WARM_WINDOW;
92
+ if (warm) show(element);
93
+ else {
94
+ setTip(null);
95
+ timer = setTimeout(() => current === element && show(element), DELAY);
96
+ }
97
+ };
98
+ const onFocus = (event: FocusEvent) => {
99
+ const element =
100
+ (event.target as Element | null)?.closest?.("[data-tooltip]") ?? null;
101
+ if (!element) return;
102
+ hide();
103
+ current = element;
104
+ described = element;
105
+ previousDescription = element.getAttribute("aria-describedby");
106
+ element.setAttribute(
107
+ "aria-describedby",
108
+ [previousDescription, tooltipId].filter(Boolean).join(" "),
109
+ );
110
+ show(element);
111
+ };
112
+ const onBlur = (event: FocusEvent) => {
113
+ if (described && !described.contains(event.relatedTarget as Node | null))
114
+ hide();
115
+ };
109
116
 
110
- window.document.addEventListener("pointerover", onOver)
111
- window.document.addEventListener("focusin", onFocus)
112
- window.document.addEventListener("focusout", onBlur)
113
- window.document.addEventListener("pointerdown", hide, true)
114
- window.document.addEventListener("keydown", hide, true)
115
- window.addEventListener("scroll", hide, true)
116
- window.addEventListener("blur", hide)
117
- return () => {
118
- clearTimeout(timer)
119
- restoreDescription()
120
- window.document.removeEventListener("pointerover", onOver)
121
- window.document.removeEventListener("focusin", onFocus)
122
- window.document.removeEventListener("focusout", onBlur)
123
- window.document.removeEventListener("pointerdown", hide, true)
124
- window.document.removeEventListener("keydown", hide, true)
125
- window.removeEventListener("scroll", hide, true)
126
- window.removeEventListener("blur", hide)
127
- }
128
- }, [tooltipId])
117
+ window.document.addEventListener("pointerover", onOver);
118
+ window.document.addEventListener("focusin", onFocus);
119
+ window.document.addEventListener("focusout", onBlur);
120
+ window.document.addEventListener("pointerdown", hide, true);
121
+ window.document.addEventListener("keydown", hide, true);
122
+ window.addEventListener("scroll", hide, true);
123
+ window.addEventListener("blur", hide);
124
+ return () => {
125
+ clearTimeout(timer);
126
+ restoreDescription();
127
+ window.document.removeEventListener("pointerover", onOver);
128
+ window.document.removeEventListener("focusin", onFocus);
129
+ window.document.removeEventListener("focusout", onBlur);
130
+ window.document.removeEventListener("pointerdown", hide, true);
131
+ window.document.removeEventListener("keydown", hide, true);
132
+ window.removeEventListener("scroll", hide, true);
133
+ window.removeEventListener("blur", hide);
134
+ };
135
+ }, [tooltipId]);
129
136
 
130
- return (
131
- <AnimatePresence>
132
- {tip && (
133
- <motion.div
134
- id={tooltipId}
135
- key={tip.text + tip.x}
136
- role="tooltip"
137
- className={cn(tooltipClasses[tip.size])}
138
- style={{
139
- left: Math.min(Math.max(tip.x, 128), window.innerWidth - 128),
140
- top: tip.y,
141
- translateX: "-50%",
142
- translateY: tip.above ? "-100%" : 0,
143
- }}
144
- initial={
145
- reducedMotion
146
- ? false
147
- : {
148
- opacity: 0,
149
- scale: 0.92,
150
- y: tip.above ? 4 : -4,
151
- }
152
- }
153
- animate={{ opacity: 1, scale: 1, y: 0 }}
154
- exit={
155
- reducedMotion
156
- ? { opacity: 0 }
157
- : {
158
- opacity: 0,
159
- scale: 0.96,
160
- y: tip.above ? 2 : -2,
161
- transition: spring.snappy,
162
- }
163
- }
164
- transition={reducedMotion ? { duration: 0 } : spring.snappy}
165
- >
166
- {tip.text}
167
- </motion.div>
168
- )}
169
- </AnimatePresence>
170
- )
137
+ return (
138
+ <AnimatePresence>
139
+ {tip && (
140
+ <motion.div
141
+ id={tooltipId}
142
+ key={tip.text + tip.x}
143
+ role="tooltip"
144
+ className={cn(tooltipClasses[tip.size])}
145
+ style={{
146
+ left: Math.min(Math.max(tip.x, 128), window.innerWidth - 128),
147
+ top: tip.y,
148
+ translateX: "-50%",
149
+ translateY: tip.above ? "-100%" : 0,
150
+ }}
151
+ initial={
152
+ reducedMotion
153
+ ? false
154
+ : {
155
+ opacity: 0,
156
+ scale: 0.92,
157
+ y: tip.above ? 4 : -4,
158
+ }
159
+ }
160
+ animate={{ opacity: 1, scale: 1, y: 0 }}
161
+ exit={
162
+ reducedMotion
163
+ ? { opacity: 0 }
164
+ : {
165
+ opacity: 0,
166
+ scale: 0.96,
167
+ y: tip.above ? 2 : -2,
168
+ transition: spring.snappy,
169
+ }
170
+ }
171
+ transition={reducedMotion ? { duration: 0 } : spring.snappy}
172
+ >
173
+ {tip.text}
174
+ </motion.div>
175
+ )}
176
+ </AnimatePresence>
177
+ );
171
178
  }
@@ -1 +1 @@
1
- export * from "./view-controller"
1
+ export * from "./view-controller";
@@ -1,64 +1,75 @@
1
- import type { PropsWithChildren, ReactNode } from "react"
2
- import { cn } from "../../lib/class-names"
1
+ import type { PropsWithChildren, ReactNode } from "react";
2
+ import { cn } from "../../lib/class-names";
3
3
 
4
4
  type ViewControllerProps = PropsWithChildren<{
5
- heading: ReactNode
6
- className?: string
7
- }>
5
+ heading: ReactNode;
6
+ className?: string;
7
+ }>;
8
8
 
9
9
  type HeadingProps = {
10
- title: ReactNode
11
- description?: ReactNode
12
- action?: ReactNode
13
- size?: keyof typeof titleSizes
14
- }
10
+ title: ReactNode;
11
+ description?: ReactNode;
12
+ action?: ReactNode;
13
+ size?: keyof typeof titleSizes;
14
+ };
15
15
 
16
16
  const titleSizes = {
17
- default: "text-large-title leading-large-title",
18
- // sign in style screens: centered, tighter, like a system sheet
19
- compact: "text-title leading-title font-semibold tracking-tight",
20
- } as const
17
+ default: "text-large-title leading-large-title",
18
+ // sign in style screens: centered, tighter, like a system sheet
19
+ compact: "text-title leading-title font-semibold tracking-tight",
20
+ } as const;
21
21
 
22
- export function ViewController({ heading, className, children }: ViewControllerProps) {
23
- return (
24
- <article
25
- className={cn(
26
- "container mx-auto flex flex-col",
27
- "w-full gap-0 py-12 md:max-w-3xl",
28
- className
29
- )}
30
- >
31
- {heading}
32
- <div className="mt-8 flex flex-col gap-6">{children}</div>
33
- </article>
34
- )
22
+ export function ViewController({
23
+ heading,
24
+ className,
25
+ children,
26
+ }: ViewControllerProps) {
27
+ return (
28
+ <article
29
+ className={cn(
30
+ "container mx-auto flex flex-col",
31
+ "w-full gap-0 py-12 md:max-w-3xl",
32
+ className,
33
+ )}
34
+ >
35
+ {heading}
36
+ <div className="mt-8 flex flex-col gap-6">{children}</div>
37
+ </article>
38
+ );
35
39
  }
36
40
 
37
- function Heading({ title, description, action, size = "default" }: HeadingProps) {
38
- const centered = size === "compact"
39
- return (
40
- <>
41
- <div
42
- className={cn(
43
- "flex flex-wrap items-center gap-3",
44
- centered && "justify-center text-center"
45
- )}
46
- >
47
- <h1 className={cn("min-w-0 wrap-anywhere", titleSizes[size])}>{title}</h1>
48
- {action}
49
- </div>
50
- {description && (
51
- <p
52
- className={cn(
53
- "mt-0 max-w-prose text-subheadline leading-relaxed text-label-secondary",
54
- centered && "text-center"
55
- )}
56
- >
57
- {description}
58
- </p>
59
- )}
60
- </>
61
- )
41
+ function Heading({
42
+ title,
43
+ description,
44
+ action,
45
+ size = "default",
46
+ }: HeadingProps) {
47
+ const centered = size === "compact";
48
+ return (
49
+ <>
50
+ <div
51
+ className={cn(
52
+ "flex flex-wrap items-center gap-3",
53
+ centered && "justify-center text-center",
54
+ )}
55
+ >
56
+ <h1 className={cn("min-w-0 wrap-anywhere", titleSizes[size])}>
57
+ {title}
58
+ </h1>
59
+ {action}
60
+ </div>
61
+ {description && (
62
+ <p
63
+ className={cn(
64
+ "text-subheadline text-label-secondary mt-0 max-w-prose leading-relaxed",
65
+ centered && "text-center",
66
+ )}
67
+ >
68
+ {description}
69
+ </p>
70
+ )}
71
+ </>
72
+ );
62
73
  }
63
74
 
64
- ViewController.Heading = Heading
75
+ ViewController.Heading = Heading;