1
- import { Fragment , useEffect , useState } from "react" ;
1
+ import { GlobeAltIcon , GlobeAmericasIcon } from "@heroicons/react/20/solid" ;
2
+ import { Laptop } from "lucide-react" ;
3
+ import { Fragment , type ReactNode , useEffect , useState } from "react" ;
2
4
import { useLocales } from "./LocaleProvider" ;
5
+ import { Paragraph } from "./Paragraph" ;
6
+ import { SimpleTooltip } from "./Tooltip" ;
3
7
4
8
type DateTimeProps = {
5
9
date : Date | string ;
@@ -18,8 +22,9 @@ export const DateTime = ({
18
22
showTimezone = false ,
19
23
} : DateTimeProps ) => {
20
24
const locales = useLocales ( ) ;
21
-
22
25
const realDate = typeof date === "string" ? new Date ( date ) : date ;
26
+ const resolvedOptions = Intl . DateTimeFormat ( ) . resolvedOptions ( ) ;
27
+ const localTimeZone = resolvedOptions . timeZone ;
23
28
24
29
const initialFormattedDateTime = formatDateTime (
25
30
realDate ,
@@ -32,8 +37,6 @@ export const DateTime = ({
32
37
const [ formattedDateTime , setFormattedDateTime ] = useState < string > ( initialFormattedDateTime ) ;
33
38
34
39
useEffect ( ( ) => {
35
- const resolvedOptions = Intl . DateTimeFormat ( ) . resolvedOptions ( ) ;
36
-
37
40
setFormattedDateTime (
38
41
formatDateTime (
39
42
realDate ,
@@ -45,11 +48,55 @@ export const DateTime = ({
45
48
) ;
46
49
} , [ locales , includeSeconds , realDate ] ) ;
47
50
51
+ const tooltipContent = (
52
+ < div className = "flex flex-col gap-1" >
53
+ { ! timeZone || timeZone === "UTC" ? (
54
+ < div className = "flex flex-col gap-3" >
55
+ < DateTimeTooltipContent
56
+ title = "UTC"
57
+ dateTime = { formatDateTime ( realDate , "UTC" , locales , true , true ) }
58
+ icon = { < GlobeAltIcon className = "size-4 text-blue-500" /> }
59
+ />
60
+ < DateTimeTooltipContent
61
+ title = "Local"
62
+ dateTime = { formatDateTime ( realDate , localTimeZone , locales , true , true ) }
63
+ icon = { < Laptop className = "size-4 text-green-500" /> }
64
+ />
65
+ </ div >
66
+ ) : (
67
+ < div className = "flex flex-col gap-3" >
68
+ < DateTimeTooltipContent
69
+ title = { timeZone }
70
+ dateTime = { formatDateTime ( realDate , timeZone , locales , true , true ) }
71
+ icon = { < GlobeAmericasIcon className = "size-4 text-purple-500" /> }
72
+ />
73
+ < DateTimeTooltipContent
74
+ title = "UTC"
75
+ dateTime = { formatDateTime ( realDate , "UTC" , locales , true , true ) }
76
+ icon = { < GlobeAltIcon className = "size-4 text-blue-500" /> }
77
+ />
78
+ < DateTimeTooltipContent
79
+ title = "Local"
80
+ dateTime = { formatDateTime ( realDate , localTimeZone , locales , true , true ) }
81
+ icon = { < Laptop className = "size-4 text-green-500" /> }
82
+ />
83
+ </ div >
84
+ ) }
85
+ </ div >
86
+ ) ;
87
+
48
88
return (
49
- < Fragment >
50
- { formattedDateTime . replace ( / \s / g, String . fromCharCode ( 32 ) ) }
51
- { showTimezone ? ` (${ timeZone ?? "UTC" } )` : null }
52
- </ Fragment >
89
+ < SimpleTooltip
90
+ button = {
91
+ < Fragment >
92
+ { formattedDateTime . replace ( / \s / g, String . fromCharCode ( 32 ) ) }
93
+ { showTimezone ? ` (${ timeZone ?? "UTC" } )` : null }
94
+ </ Fragment >
95
+ }
96
+ content = { tooltipContent }
97
+ side = "right"
98
+ // disableHoverableContent
99
+ />
53
100
) ;
54
101
} ;
55
102
@@ -226,3 +273,23 @@ function formatDateTimeShort(date: Date, timeZone: string, locales: string[]): s
226
273
227
274
return formattedDateTime ;
228
275
}
276
+
277
+ type DateTimeTooltipContentProps = {
278
+ title : string ;
279
+ dateTime : string ;
280
+ icon : ReactNode ;
281
+ } ;
282
+
283
+ function DateTimeTooltipContent ( { title, dateTime, icon } : DateTimeTooltipContentProps ) {
284
+ return (
285
+ < div className = "flex flex-col gap-1" >
286
+ < div className = "flex items-center gap-1 text-sm" >
287
+ { icon }
288
+ < span className = "font-medium" > { title } </ span >
289
+ </ div >
290
+ < Paragraph variant = "extra-small" className = "text-text-dimmed" >
291
+ { dateTime }
292
+ </ Paragraph >
293
+ </ div >
294
+ ) ;
295
+ }
0 commit comments