Skip to content

Commit f3d9c7d

Browse files
committed
Add dialog button tooltips
1 parent 2655ab9 commit f3d9c7d

File tree

2 files changed

+103
-37
lines changed

2 files changed

+103
-37
lines changed

src/app/components/previews/DialogPreview.tsx

Lines changed: 69 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Identifier, ItemStack } from 'deepslate'
2-
import type { ComponentChild } from 'preact'
3-
import { useEffect, useRef } from 'preact/hooks'
2+
import type { ComponentChild, ComponentChildren } from 'preact'
3+
import { useEffect, useRef, useState } from 'preact/hooks'
44
import { safeJsonParse } from '../../Utils.js'
55
import { ItemDisplay } from '../ItemDisplay.jsx'
66
import { TextComponent } from '../TextComponent.jsx'
@@ -46,7 +46,9 @@ function DialogTitle({ title }: { title: any }) {
4646
// TODO: add warning button tooltip
4747
return <div style={`height: ${px(33)}; display: flex; gap: ${px(10)}; justify-content: center; align-items: center`}>
4848
<TextComponent component={title} />
49-
<div class="dialog-warning-button" style={`width: ${px(20)}; height: ${px(20)};`}></div>
49+
<WithTooltip tooltip="This is a custom screen. Click here to learn more.">
50+
<div class="dialog-warning-button" style={`width: ${px(20)}; height: ${px(20)};`}></div>
51+
</WithTooltip>
5052
</div>
5153
}
5254

@@ -111,7 +113,7 @@ function DialogContent({ dialog }: { dialog: any }) {
111113
if (type === 'multi_action') {
112114
return <ColumnsGrid columns={dialog.columns ?? 2}>
113115
{dialog.actions?.map((a: any) =>
114-
<Button label={a.label} width={a.width ?? 150} />
116+
<Button label={a.label} width={a.width ?? 150} tooltip={a.tooltip} />
115117
) ?? []}
116118
</ColumnsGrid>
117119
}
@@ -121,7 +123,7 @@ function DialogContent({ dialog }: { dialog: any }) {
121123
{dialog.inputs?.map((i: any) => <InputControl input={i} />)}
122124
<ColumnsGrid columns={2}>
123125
{dialog.actions?.map((a: any) =>
124-
<Button label={a.label} width={a.width ?? 150} />
126+
<Button label={a.label} width={a.width ?? 150} tooltip={a.tooltip} />
125127
) ?? []}
126128
</ColumnsGrid>
127129
</>
@@ -150,8 +152,8 @@ function DialogFooter({ dialog }: { dialog: any }) {
150152

151153
if (type === 'confirmation') {
152154
return <div style={`display: flex; gap: ${px(8)}; justify-content: center;`}>
153-
<Button label={dialog.yes?.label} width={dialog.yes?.width ?? 150} />
154-
<Button label={dialog.no?.label} width={dialog.no?.width ?? 150} />
155+
<Button label={dialog.yes?.label} width={dialog.yes?.width ?? 150} tooltip={dialog.yes?.tooltip} />
156+
<Button label={dialog.no?.label} width={dialog.no?.width ?? 150} tooltip={dialog.no?.tooltip} />
155157
</div>
156158
}
157159

@@ -165,7 +167,7 @@ function DialogFooter({ dialog }: { dialog: any }) {
165167

166168
if (type === 'notice') {
167169
return <div style={`display: flex; gap: ${px(8)}; justify-content: center;`}>
168-
<Button label={dialog.action?.label ?? {translate: 'gui.ok'}} width={dialog.action?.width ?? 150} />
170+
<Button label={dialog.action?.label ?? {translate: 'gui.ok'}} width={dialog.action?.width ?? 150} tooltip={dialog.action?.tooltip} />
169171
</div>
170172
}
171173

@@ -175,40 +177,13 @@ function DialogFooter({ dialog }: { dialog: any }) {
175177

176178
if (type === 'simple_input_form') {
177179
return <div style={`display: flex; gap: ${px(8)}; justify-content: center;`}>
178-
<Button label={dialog.action?.label} width={dialog.action?.width ?? 150} />
180+
<Button label={dialog.action?.label} width={dialog.action?.width ?? 150} tooltip={dialog.action?.tooltip} />
179181
</div>
180182
}
181183

182184
return <></>
183185
}
184186

185-
interface ColumnsGridProps {
186-
columns: number
187-
children: ComponentChild[]
188-
}
189-
function ColumnsGrid({ columns, children }: ColumnsGridProps) {
190-
const totalCount = children.length
191-
const gridCount = Math.floor(totalCount / columns) * columns
192-
return <div style={`padding-top: ${px(4)}; display: grid; grid-template-columns: repeat(${columns}, minmax(0, 1fr)); gap: ${px(2)}; justify-content: center;`}>
193-
{children.slice(0, gridCount)}
194-
{totalCount > gridCount && <div style={`grid-column: span ${columns}; display: flex; gap: ${px(2)}; justify-content: center; padding-top: ${px(2)} /* MC-297977 */;`}>
195-
{children.slice(gridCount)}
196-
</div>}
197-
</div>
198-
}
199-
200-
interface ButtonProps {
201-
label: any
202-
width: number
203-
tooltip?: any
204-
}
205-
function Button({ label, width }: ButtonProps) {
206-
// TODO: add tooltip
207-
return <div class="dialog-button" style={`width: ${px(width)}; height: ${px(20)};`}>
208-
<TextComponent component={label} oneline />
209-
</div>
210-
}
211-
212187
function InputControl({ input }: { input: any }) {
213188
const type = input.type?.replace(/^minecraft:/, '')
214189

@@ -249,6 +224,64 @@ function InputControl({ input }: { input: any }) {
249224
return <></>
250225
}
251226

227+
interface ColumnsGridProps {
228+
columns: number
229+
children: ComponentChild[]
230+
}
231+
function ColumnsGrid({ columns, children }: ColumnsGridProps) {
232+
const totalCount = children.length
233+
const gridCount = Math.floor(totalCount / columns) * columns
234+
return <div style={`padding-top: ${px(4)}; display: grid; grid-template-columns: repeat(${columns}, minmax(0, 1fr)); gap: ${px(2)}; justify-content: center;`}>
235+
{children.slice(0, gridCount)}
236+
{totalCount > gridCount && <div style={`grid-column: span ${columns}; display: flex; gap: ${px(2)}; justify-content: center; padding-top: ${px(2)} /* MC-297977 */;`}>
237+
{children.slice(gridCount)}
238+
</div>}
239+
</div>
240+
}
241+
242+
interface ButtonProps {
243+
label: any
244+
width: number
245+
tooltip?: any
246+
}
247+
function Button({ label, width, tooltip }: ButtonProps) {
248+
return <WithTooltip tooltip={tooltip}>
249+
<div class="dialog-button" style={`width: ${px(width)}; height: ${px(20)};`}>
250+
<TextComponent component={label} oneline />
251+
</div>
252+
</WithTooltip>
253+
}
254+
255+
interface WithTooltipProps {
256+
tooltip?: any
257+
children: ComponentChildren
258+
}
259+
function WithTooltip({ tooltip, children }: WithTooltipProps) {
260+
if (!tooltip) {
261+
return <>{children}</>
262+
}
263+
264+
const el = useRef<HTMLDivElement>(null)
265+
const [tooltipOffset, setTooltipOffset] = useState<[number, number]>([0, 0])
266+
267+
useEffect(() => {
268+
const onMove = (e: MouseEvent) => {
269+
requestAnimationFrame(() => {
270+
setTooltipOffset([e.offsetX + 20, e.offsetY - 10])
271+
})
272+
}
273+
el.current?.addEventListener('mousemove', onMove)
274+
return () => el.current?.removeEventListener('mousemove', onMove)
275+
}, [])
276+
277+
return <div ref={el} class="tooltip-container">
278+
{children}
279+
{<div class="dialog-tooltip" style={`left: ${tooltipOffset[0]}px; top: ${tooltipOffset[1]}px;`}>
280+
<TextComponent component={tooltip} />
281+
</div>}
282+
</div>
283+
}
284+
252285
function px(n: number) {
253286
return `calc(var(--dialog-px) * ${n})`
254287
}

src/styles/global.css

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1895,7 +1895,8 @@ hr {
18951895
.dialog-edit-box,
18961896
.dialog-checkbox,
18971897
.dialog-slider-track,
1898-
.dialog-slider-handle {
1898+
.dialog-slider-handle,
1899+
.dialog-tooltip {
18991900
image-rendering: -moz-crisp-edges;
19001901
image-rendering: -webkit-crisp-edges;
19011902
image-rendering: crisp-edges;
@@ -1986,6 +1987,38 @@ hr {
19861987
padding-bottom: var(--dialog-px);
19871988
}
19881989

1990+
.tooltip-container {
1991+
position: relative;
1992+
}
1993+
1994+
.tooltip-container > * > * {
1995+
pointer-events: none;
1996+
}
1997+
1998+
.dialog-tooltip {
1999+
padding: var(--dialog-px);
2000+
border: solid calc(var(--dialog-px) * 2) #220044;
2001+
border-image-source: url(/images/tooltip.png);
2002+
border-image-slice: 2 fill;
2003+
border-image-outset: calc(var(--dialog-px) * 1);
2004+
width: max-content;
2005+
max-width: calc(var(--dialog-px) * 150);
2006+
display: none;
2007+
position: absolute;
2008+
pointer-events: none;
2009+
z-index: 5;
2010+
padding: calc(var(--dialog-px) * 2);
2011+
}
2012+
2013+
.tooltip-container:hover > .dialog-tooltip {
2014+
display: block;
2015+
}
2016+
2017+
.tooltip-container > .dialog-tooltip .text-component {
2018+
white-space: pre-wrap;
2019+
text-align: initial;
2020+
}
2021+
19892022
.project-files {
19902023
background-color: var(--background-2);
19912024
color: var(--text-2);

0 commit comments

Comments
 (0)