alert dialog component

This commit is contained in:
muzam1l
2022-05-02 21:05:18 +05:30
parent e88720327e
commit 5e997044ed
7 changed files with 124 additions and 46 deletions

View File

@@ -0,0 +1,72 @@
import { FC, ReactNode } from "react";
import { proxy, useSnapshot } from "valtio";
import Button from "../Button";
import Flex from "../Flex";
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogTitle,
} from "./primitive";
export interface AlertState {
isOpen: boolean;
title?: string;
body?: ReactNode;
cancelText?: string;
confirmNode?: ReactNode;
onConfirm?: () => any;
onCancel?: () => any;
}
export const alertState = proxy<AlertState>({
isOpen: false,
});
const Alert: FC = () => {
const {
title = "Are you sure?",
isOpen,
body,
cancelText,
confirmNode = "Ok",
onCancel,
onConfirm,
} = useSnapshot(alertState);
return (
<AlertDialog
open={isOpen}
onOpenChange={value => (alertState.isOpen = value)}
>
<AlertDialogContent>
<AlertDialogTitle>{title}</AlertDialogTitle>
<AlertDialogDescription>{body}</AlertDialogDescription>
<Flex css={{ justifyContent: "flex-end", gap: "$3" }}>
{cancelText && (
<AlertDialogCancel asChild>
<Button css={{ minWidth: "$16" }} outline onClick={onCancel}>
{cancelText}
</Button>
</AlertDialogCancel>
)}
<AlertDialogAction asChild>
<Button
css={{ minWidth: "$16" }}
variant="primary"
onClick={async () => {
await onConfirm?.();
alertState.isOpen = false;
}}
>
{confirmNode}
</Button>
</AlertDialogAction>
</Flex>
</AlertDialogContent>
</AlertDialog>
);
};
export default Alert;

View File

@@ -1,7 +1,7 @@
import React from "react";
import { blackA } from "@radix-ui/colors";
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog";
import { styled, keyframes } from "../stitches.config";
import { styled, keyframes } from "../../stitches.config";
const overlayShow = keyframes({
"0%": { opacity: 0 },

View File

@@ -50,15 +50,8 @@ import Stack from "./Stack";
import { Input, Label } from "./Input";
import Text from "./Text";
import Tooltip from "./Tooltip";
import {
AlertDialog,
AlertDialogContent,
AlertDialogTitle,
AlertDialogDescription,
AlertDialogCancel,
AlertDialogAction,
} from "./AlertDialog";
import { styled } from "../stitches.config";
import { showAlert } from "../state/actions/showAlert";
const ErrorText = styled(Text, {
color: "$error",
@@ -68,7 +61,6 @@ const ErrorText = styled(Text, {
const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
const snap = useSnapshot(state);
const [createNewAlertOpen, setCreateNewAlertOpen] = useState(false);
const [editorSettingsOpen, setEditorSettingsOpen] = useState(false);
const [isNewfileDialogOpen, setIsNewfileDialogOpen] = useState(false);
const [newfileError, setNewfileError] = useState<string | null>(null);
@@ -87,13 +79,32 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
setNewfileError(null);
}, [filename, setNewfileError]);
const showNewGistAlert = () => {
showAlert("Are you sure?", {
body: (
<>
This action will create new <strong>public</strong> Github Gist from
your current saved files. You can delete gist anytime from your GitHub
Gists page.
</>
),
cancelText: "Cancel",
confirmNode: (
<>
<FilePlus size="15px" /> Create new Gist
</>
),
onConfirm: () => syncToGist(session, true),
});
};
const validateFilename = useCallback(
(filename: string): { error: string | null } => {
// check if filename already exists
if (!filename) {
return { error: "You need to add filename" };
}
if (snap.files.find((file) => file.name === filename)) {
if (snap.files.find(file => file.name === filename)) {
return { error: "Filename already exists." };
}
@@ -225,8 +236,8 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
<Label>Filename</Label>
<Input
value={filename}
onChange={(e) => setFilename(e.target.value)}
onKeyPress={(e) => {
onChange={e => setFilename(e.target.value)}
onKeyPress={e => {
if (e.key === "Enter") {
handleConfirm();
}
@@ -416,7 +427,7 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
if (snap.gistOwner === session?.user.username) {
syncToGist(session);
} else {
setCreateNewAlertOpen(true);
showNewGistAlert();
}
}}
>
@@ -466,7 +477,7 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
<DropdownMenuItem
disabled={status !== "authenticated"}
onClick={() => {
setCreateNewAlertOpen(true);
showNewGistAlert();
}}
>
<FilePlus size="16px" /> Create as a new Gist
@@ -486,34 +497,6 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
) : null}
</Container>
</Flex>
<AlertDialog
open={createNewAlertOpen}
onOpenChange={(value) => setCreateNewAlertOpen(value)}
>
<AlertDialogContent>
<AlertDialogTitle>Are you sure?</AlertDialogTitle>
<AlertDialogDescription>
This action will create new <strong>public</strong> Github Gist from
your current saved files. You can delete gist anytime from your
GitHub Gists page.
</AlertDialogDescription>
<Flex css={{ justifyContent: "flex-end", gap: "$3" }}>
<AlertDialogCancel asChild>
<Button outline>Cancel</Button>
</AlertDialogCancel>
<AlertDialogAction asChild>
<Button
variant="primary"
onClick={() => {
syncToGist(session, true);
}}
>
<FilePlus size="15px" /> Create new Gist
</Button>
</AlertDialogAction>
</Flex>
</AlertDialogContent>
</AlertDialog>
<Dialog open={editorSettingsOpen} onOpenChange={setEditorSettingsOpen}>
<DialogTrigger asChild>
@@ -529,8 +512,8 @@ const EditorNavigation = ({ showWat }: { showWat?: boolean }) => {
type="number"
min="1"
value={editorSettings.tabSize}
onChange={(e) =>
setEditorSettings((curr) => ({
onChange={e =>
setEditorSettings(curr => ({
...curr,
tabSize: Number(e.target.value),
}))

View File

@@ -7,7 +7,7 @@ export { default as Text } from "./Text";
export { default as Input, Label } from "./Input";
export { default as Select } from "./Select";
export * from "./Tabs";
export * from "./AlertDialog";
export * from "./AlertDialog/primitive";
export { default as Box } from "./Box";
export { default as Button } from "./Button";
export { default as Pre } from "./Pre";

View File

@@ -16,6 +16,7 @@ import state from "../state";
import TimeAgo from "javascript-time-ago";
import en from "javascript-time-ago/locale/en.json";
import { useSnapshot } from "valtio";
import Alert from '../components/AlertDialog';
TimeAgo.setDefaultLocale(en.locale);
TimeAgo.addLocale(en);
@@ -140,6 +141,7 @@ function MyApp({ Component, pageProps: { session, ...pageProps } }: AppProps) {
})(),
}}
/>
<Alert />
</ThemeProvider>
</SessionProvider>
</IdProvider>

View File

@@ -6,6 +6,8 @@ import Transaction from "../../components/Transaction";
import state from "../../state";
import { getSplit, saveSplit } from "../../state/actions/persistSplits";
import { transactionsState, modifyTransaction } from "../../state";
import { useEffect } from 'react';
import { showAlert } from '../../state/actions/showAlert';
const DebugStream = dynamic(() => import("../../components/DebugStream"), {
ssr: false,

View File

@@ -0,0 +1,19 @@
import { ref } from 'valtio';
import { AlertState, alertState } from "../../components/AlertDialog";
export const showAlert = (title: string, opts: Partial<AlertState> = {}) => {
const { body: _body, confirmNode: _confirmNode, ...rest } = opts
const body = (_body && typeof _body === 'object') ? ref(_body) : _body
const confirmNode = (_confirmNode && typeof _confirmNode === 'object') ? ref(_confirmNode) : _confirmNode
const nwState = {
isOpen: true,
title,
body,
confirmNode,
...rest
}
Object.entries(nwState).forEach(([key, value]) => {
(alertState as any)[key] = value
})
}