feat(ui): redesign grouped application shell
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import React, { createContext, useCallback, useContext, useId, useMemo, useState } from "react";
|
||||
import React, { createContext, useCallback, useContext, useEffect, useId, useMemo, useRef, useState } from "react";
|
||||
import { Button, Dialog, DialogActions, DialogContent, DialogTitle, TextField, Typography } from "@mui/material";
|
||||
import { useOptionalI18n } from "./i18n/I18nProvider";
|
||||
|
||||
@@ -24,6 +24,7 @@ const PromptContext = createContext<PromptContextValue | null>(null);
|
||||
export function PromptProvider({ children }: { children: React.ReactNode }) {
|
||||
const i18n = useOptionalI18n();
|
||||
const messageId = useId();
|
||||
const inputRef = useRef<HTMLInputElement>(null);
|
||||
const [state, setState] = useState<PromptState>({
|
||||
open: false,
|
||||
title: "Enter value",
|
||||
@@ -34,6 +35,12 @@ export function PromptProvider({ children }: { children: React.ReactNode }) {
|
||||
});
|
||||
const [value, setValue] = useState("");
|
||||
|
||||
useEffect(() => {
|
||||
if (!state.open) return;
|
||||
const frame = requestAnimationFrame(() => inputRef.current?.focus());
|
||||
return () => cancelAnimationFrame(frame);
|
||||
}, [state.open]);
|
||||
|
||||
const closeWith = useCallback((next: string | null) => {
|
||||
setState((prev) => {
|
||||
prev.resolver?.(next);
|
||||
@@ -66,7 +73,7 @@ export function PromptProvider({ children }: { children: React.ReactNode }) {
|
||||
<DialogTitle sx={{ pb: 1, fontWeight: 800 }}>{state.title}</DialogTitle>
|
||||
<DialogContent>
|
||||
<Typography id={messageId} sx={{ color: "text.secondary", mb: 1.5 }}>{state.message}</Typography>
|
||||
<TextField autoFocus fullWidth value={value} onChange={(e) => setValue(e.target.value)} inputProps={{ maxLength: 180, "aria-labelledby": messageId }} helperText={`${value.length}/180`} />
|
||||
<TextField inputRef={inputRef} autoFocus fullWidth value={value} onChange={(e) => setValue(e.target.value)} inputProps={{ maxLength: 180, "aria-labelledby": messageId }} helperText={`${value.length}/180`} />
|
||||
</DialogContent>
|
||||
<DialogActions sx={{ px: 3, pb: 2.5, gap: 1 }}>
|
||||
<Button onClick={() => closeWith(null)}>{state.cancelLabel}</Button>
|
||||
|
||||
Reference in New Issue
Block a user