From 81901ec717e9a4aa0579e7ef75be03e5ee465888 Mon Sep 17 00:00:00 2001 From: Daniel Gonzalez Albo Date: Wed, 24 Sep 2025 09:44:19 +0200 Subject: [PATCH] update: add a welcome dialog to the app --- webapp/app.ironcalc.com/frontend/src/App.tsx | 5 + .../WelcomeDialog/WelcomeDialog.tsx | 211 ++++++++++++++++++ .../WelcomeDialog/ironcalc_icon_white.svg | 7 + 3 files changed, 223 insertions(+) create mode 100644 webapp/app.ironcalc.com/frontend/src/components/WelcomeDialog/WelcomeDialog.tsx create mode 100644 webapp/app.ironcalc.com/frontend/src/components/WelcomeDialog/ironcalc_icon_white.svg diff --git a/webapp/app.ironcalc.com/frontend/src/App.tsx b/webapp/app.ironcalc.com/frontend/src/App.tsx index d2c72fc..f3ef15c 100644 --- a/webapp/app.ironcalc.com/frontend/src/App.tsx +++ b/webapp/app.ironcalc.com/frontend/src/App.tsx @@ -2,6 +2,7 @@ import "./App.css"; import styled from "@emotion/styled"; import { useEffect, useState } from "react"; import { FileBar } from "./components/FileBar"; +import WelcomeDialog from "./components/WelcomeDialog/WelcomeDialog"; import { get_documentation_model, get_model, @@ -21,6 +22,7 @@ import { IronCalc, IronCalcIcon, Model, init } from "@ironcalc/workbook"; function App() { const [model, setModel] = useState(null); + const [showWelcomeDialog, setShowWelcomeDialog] = useState(true); useEffect(() => { async function start() { @@ -109,6 +111,9 @@ function App() { }} /> + {showWelcomeDialog && ( + setShowWelcomeDialog(false)} /> + )} ); } diff --git a/webapp/app.ironcalc.com/frontend/src/components/WelcomeDialog/WelcomeDialog.tsx b/webapp/app.ironcalc.com/frontend/src/components/WelcomeDialog/WelcomeDialog.tsx new file mode 100644 index 0000000..cfb2343 --- /dev/null +++ b/webapp/app.ironcalc.com/frontend/src/components/WelcomeDialog/WelcomeDialog.tsx @@ -0,0 +1,211 @@ +import { Dialog, styled } from "@mui/material"; +import { House, Table, TicketsPlane, X } from "lucide-react"; +import { useState } from "react"; +import TemplatesListItem from "./TemplatesListItem"; +import IronCalcIcon from "./ironcalc_icon_white.svg"; + +function WelcomeDialog(properties: { + onClose: () => void; +}) { + const [selectedTemplate, setSelectedTemplate] = useState( + "blank", + ); + + const handleClose = () => { + properties.onClose(); + }; + + const handleTemplateSelect = (templateId: string) => { + setSelectedTemplate(templateId); + }; + + return ( + {}}> + + + + + + Welcome to IronCalc + + Start with a blank workbook or a ready-made template. + + + event.key === "Enter" && properties.onClose()} + > + + + + + New + + } + iconColor="#F2994A" + active={selectedTemplate === "blank"} + onClick={() => handleTemplateSelect("blank")} + /> + + Templates + + } + iconColor="#2F80ED" + active={selectedTemplate === "mortgage"} + onClick={() => handleTemplateSelect("mortgage")} + /> + } + iconColor="#EB5757" + active={selectedTemplate === "travel"} + onClick={() => handleTemplateSelect("travel")} + /> + + + + Create workbook + + + ); +} + +const DialogWrapper = styled(Dialog)` + font-family: Inter; + .MuiDialog-paper { + width: 440px; + border-radius: 12px; + margin: 16px; + border: 1px solid #e0e0e0;; + } + .MuiBackdrop-root { + background-color: rgba(0, 0, 0, 0.4); + } +`; + +const DialogHeader = styled("div")` + display: flex; + flex-direction: row; + align-items: flex-start; + border-bottom: 1px solid #e0e0e0; + padding: 16px; + font-family: Inter; +`; + +const DialogHeaderTitleWrapper = styled("span")` + display: flex; + flex-direction: column; + align-items: flex-start; + font-size: 14px; + font-weight: 500; + padding: 4px 0px; + gap: 4px; + width: 100%; +`; + +const DialogHeaderTitle = styled("span")` + font-weight: 700; +`; + +const DialogHeaderTitleSubtitle = styled("span")` + font-size: 12px; + color: #757575; +`; + +const DialogHeaderLogoWrapper = styled("div")` + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + max-width: 20px; + max-height: 20px; + background-color: #F2994A; + padding: 10px; + margin-bottom: 12px; + border-radius: 6px; + box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); + transform: rotate(-8deg); + user-select: none; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; +`; + +const DialogHeaderLogo = styled("img")` + width: 18px; + height: auto; +`; + +const Cross = styled("div")` + &:hover { + background-color: #f5f5f5; + } + display: flex; + border-radius: 4px; + min-height: 24px; + min-width: 24px; + cursor: pointer; + align-items: center; + justify-content: center; + svg { + width: 16px; + height: 16px; + stroke-width: 1.5; + } +`; + +const DialogContent = styled("div")` + display: flex; + flex-direction: column; + gap: 12px; + padding: 16px; + max-height: 300px; + overflow: hidden; + overflow-y: auto; +`; + +const ListTitle = styled("div")` + font-size: 12px; + font-weight: 600; + color: #424242; +`; + +const TemplatesListWrapper = styled("div")` + display: flex; + flex-direction: column; + gap: 10px; +`; + +const DialogFooter = styled("div")` + border-top: 1px solid #e0e0e0; + padding: 16px; +`; + +const DialogFooterButton = styled("button")` + background-color: #F2994A; + border: none; + color: #FFF; + padding: 12px; + border-radius: 4px; + cursor: pointer; + width: 100%; + font-size: 12px; + font-family: Inter; + &:hover { + background-color: #D68742; + } + &:active { + background-color: #D68742; + } +`; + +export default WelcomeDialog; diff --git a/webapp/app.ironcalc.com/frontend/src/components/WelcomeDialog/ironcalc_icon_white.svg b/webapp/app.ironcalc.com/frontend/src/components/WelcomeDialog/ironcalc_icon_white.svg new file mode 100644 index 0000000..57e2d2c --- /dev/null +++ b/webapp/app.ironcalc.com/frontend/src/components/WelcomeDialog/ironcalc_icon_white.svg @@ -0,0 +1,7 @@ + + + + + + +