Buttons: primary, subtle and one danger; the restarts ask first (#316)
Cancel is the quiet button next to a filled one, in every dialog; Decline on an invitation is quiet too. There is one filled red danger button, with the outline version in theme.css gone. Restart Tor and Restart daemon ask again in place. Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
This commit is contained in:
@@ -569,6 +569,18 @@ const SCENES = [
|
||||
},
|
||||
clip: { x: 0, y: 380, width: 280, height: 260 }
|
||||
},
|
||||
{
|
||||
// Restarting Tor asks first (#316).
|
||||
name: 'settings-tor-confirm',
|
||||
setup: async (p) => {
|
||||
await p.evaluate(`window.__mohoShots.store.setActivePanel('settings')`)
|
||||
await sleep(300)
|
||||
await p.evaluate(click('.settings-rail-item', 'Tor'))
|
||||
await sleep(300)
|
||||
await p.evaluate(click('button', 'Restart Tor from scratch'))
|
||||
await sleep(300)
|
||||
}
|
||||
},
|
||||
// Motion, recorded rather than photographed.
|
||||
{
|
||||
name: 'motion-hover-rows',
|
||||
|
||||
@@ -2488,11 +2488,12 @@ img.composer-emoji {
|
||||
outline-offset: -10px;
|
||||
}
|
||||
|
||||
/* The one button in the app that destroys something. Not --error, which is a
|
||||
pale text colour and reads as decorative when used as a fill. */
|
||||
.button.danger {
|
||||
background: var(--danger);
|
||||
color: var(--on-accent);
|
||||
/* Asking again, in place of the button that was pressed. */
|
||||
.confirm-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-wrap: wrap;
|
||||
gap: var(--spacing-s);
|
||||
}
|
||||
|
||||
/* --- mentions ---------------------------------------------------------- */
|
||||
|
||||
@@ -488,7 +488,7 @@ function AccountRow({ account }: { account: Account }): JSX.Element {
|
||||
>
|
||||
<Icon name="delete" size={16} /> Remove
|
||||
</button>
|
||||
<button type="button" className="button" autoFocus onClick={() => setConfirmingRemove(false)}>
|
||||
<button type="button" className="button subtle" autoFocus onClick={() => setConfirmingRemove(false)}>
|
||||
Keep it
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
/**
|
||||
* A button for something that interrupts - restarting Tor, restarting the
|
||||
* daemon - that asks once more before doing it, in place.
|
||||
*
|
||||
* Not a dialog: the question is about the thing in front of you and answers
|
||||
* itself in a click, and it takes itself back after a few seconds so a
|
||||
* forgotten question is not left lying about as a loaded button.
|
||||
*/
|
||||
export function ConfirmButton({
|
||||
label,
|
||||
question,
|
||||
confirmLabel,
|
||||
onConfirm,
|
||||
danger
|
||||
}: {
|
||||
label: string
|
||||
/** What is being asked, in a few words: "Restart Tor and lose its circuits?" */
|
||||
question: string
|
||||
confirmLabel: string
|
||||
onConfirm: () => void
|
||||
danger?: boolean
|
||||
}): JSX.Element {
|
||||
const [asking, setAsking] = useState(false)
|
||||
|
||||
useEffect(() => {
|
||||
if (!asking) return
|
||||
const t = setTimeout(() => setAsking(false), 6000)
|
||||
return () => clearTimeout(t)
|
||||
}, [asking])
|
||||
|
||||
if (!asking) {
|
||||
return (
|
||||
<button type="button" className="button subtle" onClick={() => setAsking(true)}>
|
||||
{label}
|
||||
</button>
|
||||
)
|
||||
}
|
||||
return (
|
||||
<div className="confirm-button" role="alertdialog" aria-label={question}>
|
||||
<span className="small">{question}</span>
|
||||
<button
|
||||
type="button"
|
||||
className={danger ? 'button danger' : 'button'}
|
||||
onClick={() => {
|
||||
setAsking(false)
|
||||
onConfirm()
|
||||
}}
|
||||
>
|
||||
{confirmLabel}
|
||||
</button>
|
||||
<button type="button" className="button subtle" autoFocus onClick={() => setAsking(false)}>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -162,7 +162,7 @@ export function ExportDialog({
|
||||
)}
|
||||
|
||||
<div className="reason-prompt-actions">
|
||||
<button type="button" className="button" onClick={onCancel}>
|
||||
<button type="button" className="button subtle" onClick={onCancel}>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
|
||||
@@ -44,7 +44,7 @@ export function InvitePanel({ groupId }: { groupId: string }): JSX.Element | nul
|
||||
<button type="button" className="button primary" onClick={() => answer(true)}>
|
||||
Accept
|
||||
</button>
|
||||
<button type="button" className="button danger" onClick={() => answer(false)}>
|
||||
<button type="button" className="button subtle" onClick={() => answer(false)}>
|
||||
Decline
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -50,7 +50,7 @@ export function LeaveConfirm(props: {
|
||||
</div>
|
||||
<p className="small">{detail}</p>
|
||||
<div className="leave-confirm-actions">
|
||||
<button type="button" className="button" onClick={onCancel} autoFocus>
|
||||
<button type="button" className="button subtle" onClick={onCancel} autoFocus>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
|
||||
@@ -74,7 +74,7 @@ export function ReasonPrompt({
|
||||
}}
|
||||
/>
|
||||
<div className="reason-prompt-actions">
|
||||
<button type="button" className="button" onClick={onCancel}>
|
||||
<button type="button" className="button subtle" onClick={onCancel}>
|
||||
Cancel
|
||||
</button>
|
||||
<button
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import { ConfirmButton } from '../ConfirmButton'
|
||||
import {
|
||||
ChoiceSetting,
|
||||
DirectorySetting,
|
||||
@@ -941,15 +942,14 @@ function TorSettings(): JSX.Element {
|
||||
>
|
||||
Regenerate circuit
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className="button subtle"
|
||||
onClick={() =>
|
||||
<ConfirmButton
|
||||
label="Restart Tor from scratch"
|
||||
question="Drop every Tor connection and start again?"
|
||||
confirmLabel="Restart Tor"
|
||||
onConfirm={() =>
|
||||
call('restartTorFromScratch', {}, 'Restarting Tor from scratch - this can take a minute…')
|
||||
}
|
||||
>
|
||||
Restart Tor from scratch
|
||||
</button>
|
||||
/>
|
||||
</div>
|
||||
</SettingsSection>
|
||||
</>
|
||||
@@ -1173,16 +1173,15 @@ function AboutSettings(): JSX.Element {
|
||||
{linkUp ? 'connected' : 'not connected'}
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
type="button"
|
||||
className="button subtle"
|
||||
onClick={() => {
|
||||
<ConfirmButton
|
||||
label="Restart daemon"
|
||||
question="Disconnect everything and restart nobilis?"
|
||||
confirmLabel="Restart"
|
||||
onConfirm={() => {
|
||||
void window.moho.restartDaemon()
|
||||
store.toast('info', 'Restarting nobilis\u2026')
|
||||
}}
|
||||
>
|
||||
Restart daemon
|
||||
</button>
|
||||
/>
|
||||
{status && !status.available && (
|
||||
<p className="small" style={{ color: 'var(--warning)' }}>
|
||||
The nobilis binary wasn't found. Run <code>cargo build --release</code>, or start
|
||||
|
||||
@@ -376,9 +376,10 @@ a:hover {
|
||||
}
|
||||
|
||||
.button.danger {
|
||||
background: transparent;
|
||||
color: var(--error);
|
||||
border: 1px solid var(--outline-medium);
|
||||
/* The one button that destroys something: filled red, white text. Not
|
||||
--error, a pale pink for text that went wrong, which cannot be a fill. */
|
||||
background: var(--danger);
|
||||
color: var(--on-accent);
|
||||
}
|
||||
|
||||
.muted {
|
||||
|
||||
Reference in New Issue
Block a user