1
- import { DocumentBlockHint } from '@gitbook/api' ;
2
- import { Icon , IconName } from '@gitbook/icons' ;
1
+ import type { DocumentBlockHeading , DocumentBlockHint } from '@gitbook/api' ;
2
+ import { Icon , type IconName } from '@gitbook/icons' ;
3
3
import React from 'react' ;
4
4
5
- import { ClassValue , tcls } from '@/lib/tailwind' ;
5
+ import { type ClassValue , tcls } from '@/lib/tailwind' ;
6
6
7
- import { BlockProps } from './Block' ;
7
+ import { Block , type BlockProps } from './Block' ;
8
8
import { Blocks } from './Blocks' ;
9
9
import { getBlockTextStyle } from './spacing' ;
10
10
@@ -13,119 +13,143 @@ export function Hint(props: BlockProps<DocumentBlockHint>) {
13
13
const hintStyle = HINT_STYLES [ block . data . style ] ?? HINT_STYLES . info ;
14
14
const firstLine = getBlockTextStyle ( block . nodes [ 0 ] ) ;
15
15
16
+ const firstNode = block . nodes [ 0 ] ;
17
+ const hasHeading = [ 'heading-1' , 'heading-2' , 'heading-3' ] . includes ( block . nodes [ 0 ] . type ) ;
18
+
16
19
return (
17
20
< div
18
21
className = { tcls (
19
22
'hint' ,
20
- 'p-4' ,
21
23
'transition-colors' ,
22
24
'rounded-md' ,
25
+ hasHeading ? 'rounded-l' : null ,
23
26
'straight-corners:rounded-none' ,
24
- hintStyle . style ,
27
+ 'overflow-hidden' ,
28
+ hasHeading ? [ 'border-l-2' , hintStyle . containerWithHeader ] : hintStyle . container ,
29
+
30
+ 'text-sm' ,
31
+
32
+ 'grid' ,
33
+ 'grid-cols-[auto_1fr]' ,
34
+ hasHeading ? 'grid-rows-[auto_auto]' : '' ,
35
+
25
36
style ,
26
37
) }
27
38
>
28
- < div className = { tcls ( 'flex' , 'flex-row' ) } >
39
+ < div
40
+ className = { tcls (
41
+ 'py-3' ,
42
+ 'pl-3' ,
43
+ hasHeading ? hintStyle . header : null ,
44
+ hintStyle . iconColor ,
45
+ ) }
46
+ >
29
47
< Icon
30
48
icon = { hintStyle . icon }
31
- className = { tcls (
32
- 'size-5' ,
33
- 'mr-4' ,
34
- 'mt-0.5' ,
35
- firstLine . lineHeight ,
36
- hintStyle . iconColor ,
37
- ) }
49
+ className = { tcls ( 'size-[1.2em]' , 'mt-0.5' , firstLine . lineHeight ) }
38
50
/>
39
- < Blocks
40
- { ...contextProps }
41
- ancestorBlocks = { [ ...ancestorBlocks , block ] }
42
- nodes = { block . nodes }
43
- blockStyle = { tcls (
44
- hintStyle . bodyColor ,
45
- // render hash icon on the other side of the heading
46
- 'flip-heading-hash' ,
51
+ </ div >
52
+ { hasHeading ? (
53
+ < Block
54
+ style = { tcls (
55
+ 'text-[1em] *:mt-0 p-3 flip-heading-hash' ,
56
+ hasHeading ? hintStyle . header : null ,
47
57
) }
48
- style = { [ 'flex-1' , 'space-y-4' , '[&_.hint]:border' , '[&_pre]:border' ] }
58
+ ancestorBlocks = { [ ...ancestorBlocks , block ] }
59
+ { ...contextProps }
60
+ block = { firstNode }
49
61
/>
50
- </ div >
62
+ ) : null }
63
+ < Blocks
64
+ { ...contextProps }
65
+ ancestorBlocks = { [ ...ancestorBlocks , block ] }
66
+ nodes = { hasHeading ? block . nodes . slice ( 1 ) : block . nodes }
67
+ blockStyle = { tcls (
68
+ hintStyle . body ,
69
+ // render hash icon on the other side of the heading
70
+ 'flip-heading-hash' ,
71
+ ) }
72
+ style = { [
73
+ 'p-3' ,
74
+ 'empty:p-0' ,
75
+ '-row-end-1' ,
76
+ '-col-end-1' ,
77
+ 'space-y-4' ,
78
+ '[&_.hint]:border' ,
79
+ '[&_pre]:border' ,
80
+ '[&_pre]:border-neutral' ,
81
+ ] }
82
+ />
51
83
</ div >
52
84
) ;
53
85
}
54
86
55
87
const HINT_STYLES : {
56
88
[ style in DocumentBlockHint [ 'data' ] [ 'style' ] ] : {
57
89
icon : IconName ;
58
- iconColor : ClassValue ;
59
- bodyColor : ClassValue ;
60
- style : ClassValue ;
90
+ iconColor ?: ClassValue ;
91
+ body ?: ClassValue ;
92
+ header ?: ClassValue ;
93
+ container ?: ClassValue ;
94
+ containerWithHeader ?: ClassValue ;
61
95
} ;
62
96
} = {
63
97
info : {
64
98
icon : 'circle-info' ,
65
- iconColor : [ 'text-primary' ] ,
66
- bodyColor : [ '[&_a]:text-primary' , '[&_a:hover]:text-primary-strong' ] ,
67
- style : [
68
- 'bg-tint' ,
69
- 'print-mode:!bg-tint' ,
70
- 'theme-muted:bg-tint-base' ,
71
- 'theme-bold-tint:bg-tint-base' ,
72
- 'theme-gradient:bg-tint-12/1' ,
73
- 'border-tint' ,
74
- '[&_.can-override-bg]:bg-tint-active' ,
75
- '[&_.can-override-text]:text-tint-strong' ,
99
+ iconColor : 'text-info-subtle contrast-more:text-info' ,
100
+ header : 'bg-info-active' ,
101
+ body : [
102
+ 'text-neutral-strong' ,
103
+ '[&_.can-override-bg]:bg-neutral-active' ,
104
+ '[&_.can-override-text]:text-neutral-strong' ,
76
105
] ,
106
+ container :
107
+ 'bg-neutral theme-muted:bg-neutral-base theme-bold-tint:bg-neutral-base theme-gradient:bg-neutral-12/1 border-neutral' ,
108
+ containerWithHeader : 'border-info-solid bg-neutral-subtle theme-gradient:bg-neutral-12/1' ,
77
109
} ,
78
110
warning : {
79
111
icon : 'circle-exclamation' ,
80
- iconColor : [ 'text-amber-500' , 'dark:text-orange-400' ] , // Darker shades of orange-* mismatch with lighter shades, so in light mode we use amber text on top of orange bg.
81
- bodyColor : [
82
- 'text-orange-950' ,
83
- 'dark:text-orange-50' ,
84
- '[&_a]:text-orange-800' ,
85
- '[&_a:hover]:text-orange-900' ,
86
- 'dark:[&_a]:text-orange-400' ,
87
- 'dark:[&_a:hover]:text-orange-300' ,
88
- '[&_.can-override-bg]:bg-orange-500/3' ,
89
- '[&_.can-override-text]:text-orange-800' ,
90
- 'dark:[&_.can-override-text]:text-orange-400' ,
91
- 'decoration-orange-800/6' ,
92
- 'dark:decoration-orange-400/6' ,
112
+ iconColor : 'text-warning-subtle contrast-more:text-warning' ,
113
+ header : 'bg-warning-active' ,
114
+ body : [
115
+ 'text-neutral-strong' ,
116
+ '[&_a]:text-warning' ,
117
+ '[&_a:hover]:text-warning-strong' ,
118
+ '[&_.can-override-bg]:bg-warning-active' ,
119
+ '[&_.can-override-text]:text-warning-strong' ,
120
+ 'decoration-warning/6' ,
93
121
] ,
94
- style : [ 'bg-orange-500/2' , 'border-orange-500/4' ] ,
122
+ container : 'bg-warning border-warning' ,
123
+ containerWithHeader : 'border-warning-solid bg-warning-subtle' ,
95
124
} ,
96
125
danger : {
97
126
icon : 'triangle-exclamation' ,
98
- iconColor : [ 'text-red-500' , 'dark:text-red-400' ] ,
99
- bodyColor : [
100
- 'text-red-950' ,
101
- 'dark:text-red-50' ,
102
- '[&_a]:text-red-800' ,
103
- '[&_a:hover]:text-red-900' ,
104
- 'dark:[&_a]:text-red-400' ,
105
- 'dark:[&_a:hover]:text-red-300' ,
106
- '[&_.can-override-bg]:bg-red-500/3' ,
107
- '[&_.can-override-text]:text-red-400' ,
108
- 'decoration-red-800/6' ,
109
- 'dark:decoration-red-400/6' ,
127
+ iconColor : 'text-danger-subtle contrast-more:text-danger' ,
128
+ header : 'bg-danger-active' ,
129
+ body : [
130
+ 'text-neutral-strong' ,
131
+ '[&_a]:text-danger' ,
132
+ '[&_a:hover]:text-danger-strong' ,
133
+ '[&_.can-override-bg]:bg-danger-active' ,
134
+ '[&_.can-override-text]:text-danger-strong' ,
135
+ 'decoration-danger/6' ,
110
136
] ,
111
- style : [ 'bg-red-500/2' , 'border-red-500/4' ] ,
137
+ container : 'bg-danger border-danger' ,
138
+ containerWithHeader : 'border-danger-solid bg-danger-subtle' ,
112
139
} ,
113
140
success : {
114
141
icon : 'circle-check' ,
115
- iconColor : [ 'text-green-500' , 'dark:text-green-400' ] ,
116
- bodyColor : [
117
- 'text-green-950' ,
118
- 'dark:text-green-50' ,
119
- '[&_a]:text-green-800' ,
120
- '[&_a:hover]:text-green-900' ,
121
- 'dark:[&_a]:text-green-400' ,
122
- 'dark:[&_a:hover]:text-green-300' ,
123
- '[&_.can-override-bg]:bg-green-500/3' ,
124
- '[&_.can-override-text]:text-green-800' ,
125
- 'dark:[&_.can-override-text]:text-green-400' ,
126
- 'decoration-green-800/6' ,
127
- 'dark:decoration-green-400/6' ,
142
+ iconColor : 'text-success-subtle contrast-more:text-success' ,
143
+ header : 'bg-success-active' ,
144
+ body : [
145
+ 'text-neutral-strong' ,
146
+ '[&_a]:text-success' ,
147
+ '[&_a:hover]:text-success-strong' ,
148
+ '[&_.can-override-bg]:bg-success-active' ,
149
+ '[&_.can-override-text]:text-success-strong' ,
150
+ 'decoration-success/6' ,
128
151
] ,
129
- style : [ 'bg-green-500/2' , 'border-green-500/4' ] ,
152
+ container : 'bg-success border-success' ,
153
+ containerWithHeader : 'border-success-solid bg-success-subtle' ,
130
154
} ,
131
155
} ;
0 commit comments