the universal sandbox runtime for agents and humans. pocketenv.io
sandbox openclaw agent claude-code vercel-sandbox deno-sandbox cloudflare-sandbox atproto sprites daytona
7
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add NewProject modal and integrate into UI

Create NewProject modal component and export it for use. Hook the
modal into Navbar and Home, adding overlay.js import, ARIA attributes,
and toggle state. Add modal styling to index.css, remove DarkThemeDemo,
and fix Sidebar tabIndex and active item color.

+181 -251
-238
apps/web/src/components/DarkThemeDemo.tsx
··· 1 - import { useTheme } from "../hooks/useTheme"; 2 - 3 - export function DarkThemeDemo() { 4 - const { theme, isDark } = useTheme(); 5 - 6 - return ( 7 - <div className="space-y-8 p-6"> 8 - {/* Header */} 9 - <div className="mb-8"> 10 - <h1 className="text-4xl font-bold text-base-content mb-2"> 11 - FlyonUI Dark Theme Demo 12 - </h1> 13 - <p className="text-base-content/70"> 14 - Current theme: <span className="font-semibold">{theme}</span> 15 - </p> 16 - </div> 17 - 18 - {/* Buttons Section */} 19 - <section className="space-y-4"> 20 - <h2 className="text-2xl font-semibold text-base-content">Buttons</h2> 21 - <div className="flex flex-wrap gap-3"> 22 - <button className="btn btn-primary">Primary</button> 23 - <button className="btn btn-secondary">Secondary</button> 24 - <button className="btn btn-accent">Accent</button> 25 - <button className="btn btn-success">Success</button> 26 - <button className="btn btn-warning">Warning</button> 27 - <button className="btn btn-error">Error</button> 28 - <button className="btn btn-ghost">Ghost</button> 29 - <button className="btn btn-outline">Outline</button> 30 - </div> 31 - </section> 32 - 33 - {/* Cards Section */} 34 - <section className="space-y-4"> 35 - <h2 className="text-2xl font-semibold text-base-content">Cards</h2> 36 - <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"> 37 - <div className="card bg-base-100 border border-base-content/10 shadow-xl"> 38 - <div className="card-body"> 39 - <h3 className="card-title text-base-content">Card Title</h3> 40 - <p className="text-base-content/70"> 41 - This card uses the uniform #06051d dark background. 42 - </p> 43 - <div className="card-actions justify-end"> 44 - <button className="btn btn-primary btn-sm">Action</button> 45 - </div> 46 - </div> 47 - </div> 48 - 49 - <div className="card bg-base-100 border border-base-content/10 shadow-xl"> 50 - <div className="card-body"> 51 - <h3 className="card-title text-base-content">Featured Card</h3> 52 - <p className="text-base-content/70"> 53 - Deep dark #06051d background throughout the app. 54 - </p> 55 - <div className="card-actions justify-end"> 56 - <button className="btn btn-secondary btn-sm">Learn More</button> 57 - </div> 58 - </div> 59 - </div> 60 - 61 - <div className="card bg-primary text-primary-content shadow-xl"> 62 - <div className="card-body"> 63 - <h3 className="card-title">Primary Card</h3> 64 - <p>A card with primary color background.</p> 65 - <div className="card-actions justify-end"> 66 - <button className="btn bg-base-100 text-base-content btn-sm"> 67 - View 68 - </button> 69 - </div> 70 - </div> 71 - </div> 72 - </div> 73 - </section> 74 - 75 - {/* Alerts Section */} 76 - <section className="space-y-4"> 77 - <h2 className="text-2xl font-semibold text-base-content">Alerts</h2> 78 - <div className="space-y-3"> 79 - <div className="alert alert-info"> 80 - <span className="icon-[tabler--info-circle] size-5"></span> 81 - <span>This is an info alert message</span> 82 - </div> 83 - <div className="alert alert-success"> 84 - <span className="icon-[tabler--circle-check] size-5"></span> 85 - <span>Success! Your changes have been saved</span> 86 - </div> 87 - <div className="alert alert-warning"> 88 - <span className="icon-[tabler--alert-triangle] size-5"></span> 89 - <span>Warning: Please review your settings</span> 90 - </div> 91 - <div className="alert alert-error"> 92 - <span className="icon-[tabler--x-circle] size-5"></span> 93 - <span>Error: Something went wrong</span> 94 - </div> 95 - </div> 96 - </section> 97 - 98 - {/* Badges Section */} 99 - <section className="space-y-4"> 100 - <h2 className="text-2xl font-semibold text-base-content">Badges</h2> 101 - <div className="flex flex-wrap gap-3"> 102 - <span className="badge badge-primary">Primary</span> 103 - <span className="badge badge-secondary">Secondary</span> 104 - <span className="badge badge-accent">Accent</span> 105 - <span className="badge badge-success">Success</span> 106 - <span className="badge badge-warning">Warning</span> 107 - <span className="badge badge-error">Error</span> 108 - <span className="badge badge-ghost">Ghost</span> 109 - <span className="badge badge-outline">Outline</span> 110 - </div> 111 - </section> 112 - 113 - {/* Form Elements Section */} 114 - <section className="space-y-4"> 115 - <h2 className="text-2xl font-semibold text-base-content"> 116 - Form Elements 117 - </h2> 118 - <div className="max-w-md space-y-4"> 119 - <div className="form-control"> 120 - <label className="label"> 121 - <span className="label-text">Input Field</span> 122 - </label> 123 - <input 124 - type="text" 125 - placeholder="Type here..." 126 - className="input input-bordered w-full" 127 - /> 128 - </div> 129 - 130 - <div className="form-control"> 131 - <label className="label"> 132 - <span className="label-text">Select Option</span> 133 - </label> 134 - <select className="select select-bordered w-full"> 135 - <option>Option 1</option> 136 - <option>Option 2</option> 137 - <option>Option 3</option> 138 - </select> 139 - </div> 140 - 141 - <div className="form-control"> 142 - <label className="label"> 143 - <span className="label-text">Textarea</span> 144 - </label> 145 - <textarea 146 - className="textarea textarea-bordered" 147 - placeholder="Enter your message..." 148 - rows={3} 149 - ></textarea> 150 - </div> 151 - 152 - <div className="form-control"> 153 - <label className="label cursor-pointer"> 154 - <span className="label-text">Checkbox</span> 155 - <input type="checkbox" className="checkbox checkbox-primary" /> 156 - </label> 157 - </div> 158 - 159 - <div className="form-control"> 160 - <label className="label cursor-pointer"> 161 - <span className="label-text">Toggle</span> 162 - <input type="checkbox" className="toggle toggle-primary" /> 163 - </label> 164 - </div> 165 - </div> 166 - </section> 167 - 168 - {/* Progress & Loading Section */} 169 - <section className="space-y-4"> 170 - <h2 className="text-2xl font-semibold text-base-content"> 171 - Progress & Loading 172 - </h2> 173 - <div className="space-y-3"> 174 - <progress 175 - className="progress progress-primary w-full" 176 - value="25" 177 - max="100" 178 - ></progress> 179 - <progress 180 - className="progress progress-secondary w-full" 181 - value="50" 182 - max="100" 183 - ></progress> 184 - <progress 185 - className="progress progress-accent w-full" 186 - value="75" 187 - max="100" 188 - ></progress> 189 - </div> 190 - <div className="flex gap-4 items-center"> 191 - <span className="loading loading-spinner loading-sm"></span> 192 - <span className="loading loading-spinner loading-md"></span> 193 - <span className="loading loading-spinner loading-lg"></span> 194 - <span className="loading loading-dots loading-lg"></span> 195 - <span className="loading loading-ring loading-lg"></span> 196 - </div> 197 - </section> 198 - 199 - {/* Stats Section */} 200 - <section className="space-y-4"> 201 - <h2 className="text-2xl font-semibold text-base-content">Stats</h2> 202 - <div className="stats stats-vertical lg:stats-horizontal shadow bg-base-100 border border-base-content/10"> 203 - <div className="stat"> 204 - <div className="stat-title">Total Users</div> 205 - <div className="stat-value text-primary">25.6K</div> 206 - <div className="stat-desc">↗︎ 400 (22%)</div> 207 - </div> 208 - <div className="stat"> 209 - <div className="stat-title">Active Projects</div> 210 - <div className="stat-value text-secondary">2,420</div> 211 - <div className="stat-desc">↗︎ 90 (14%)</div> 212 - </div> 213 - <div className="stat"> 214 - <div className="stat-title">Revenue</div> 215 - <div className="stat-value text-accent">$89,400</div> 216 - <div className="stat-desc">↘︎ 12% compared to last month</div> 217 - </div> 218 - </div> 219 - </section> 220 - 221 - {/* Theme Status */} 222 - <section className="mt-12"> 223 - <div className="alert bg-base-100 border border-base-content/10"> 224 - <span className="icon-[tabler--palette] size-6"></span> 225 - <div> 226 - <h3 className="font-bold"> 227 - Uniform Dark Theme {isDark ? "Enabled" : "Disabled"} 228 - </h3> 229 - <div className="text-xs text-base-content/70"> 230 - All components use the same dark background (#06051d) for a 231 - consistent, uniform appearance. 232 - </div> 233 - </div> 234 - </div> 235 - </section> 236 - </div> 237 - ); 238 - }
+18 -1
apps/web/src/components/navbar/Navbar.tsx
··· 1 1 import { Link, useNavigate } from "@tanstack/react-router"; 2 2 import "flyonui/dist/dropdown.js"; 3 + import "flyonui/dist/overlay.js"; 3 4 import { useState, useEffect, useRef } from "react"; 5 + import NewProject from "../newproject"; 4 6 5 7 export type NavbarProps = { 6 8 title: string; ··· 8 10 9 11 function Navbar({ title }: NavbarProps) { 10 12 const [open, setOpen] = useState(false); 13 + const [modalOpen, setModalOpen] = useState(false); 11 14 const dropdownRef = useRef<HTMLDivElement>(null); 12 15 const navigate = useNavigate(); 13 16 14 17 const toggleDropdown = () => setOpen(!open); 18 + const toggleModal = () => { 19 + setModalOpen(!modalOpen); 20 + }; 15 21 16 22 const onSignOut = () => { 17 23 setOpen(false); ··· 46 52 </div> 47 53 <div className="navbar-end flex items-center gap-4"> 48 54 <div> 49 - <button className="btn btn-primary btn-block"> 55 + <button 56 + className="btn btn-primary btn-block" 57 + aria-haspopup="dialog" 58 + aria-expanded={modalOpen} 59 + onClick={toggleModal} 60 + > 50 61 <span className="icon-[tabler--plus] size-5"></span> 51 62 </button> 52 63 </div> ··· 148 159 </ul> 149 160 </div> 150 161 </div> 162 + <NewProject 163 + isOpen={modalOpen} 164 + onClose={() => { 165 + setModalOpen(false); 166 + }} 167 + /> 151 168 </nav> 152 169 ); 153 170 }
+99
apps/web/src/components/newproject/NewProject.tsx
··· 1 + import { useEffect, useRef } from "react"; 2 + 3 + export type NewProjectProps = { 4 + isOpen: boolean; 5 + onClose: () => void; 6 + }; 7 + 8 + function NewProject({ isOpen, onClose }: NewProjectProps) { 9 + const inputRef = useRef<HTMLInputElement>(null); 10 + 11 + useEffect(() => { 12 + if (isOpen) { 13 + console.log("Attempting to focus input:", inputRef.current); 14 + inputRef.current?.focus(); 15 + } 16 + }, [isOpen]); 17 + 18 + useEffect(() => { 19 + const handleEscapeKey = (event: KeyboardEvent) => { 20 + if (event.key === "Escape" && isOpen) { 21 + onClose(); 22 + } 23 + }; 24 + 25 + document.addEventListener("keydown", handleEscapeKey); 26 + return () => { 27 + document.removeEventListener("keydown", handleEscapeKey); 28 + }; 29 + }, [isOpen, onClose]); 30 + 31 + const handleBackdropClick = (e: React.MouseEvent<HTMLDivElement>) => { 32 + if (e.target === e.currentTarget) { 33 + onClose(); 34 + } 35 + }; 36 + 37 + return ( 38 + <> 39 + <div 40 + className={`overlay modal modal-middle overlay-open:opacity-100 overlay-open:duration-300 open ${isOpen ? "opened" : "hidden"}`} 41 + role="dialog" 42 + style={{ outline: "none" }} 43 + onClick={handleBackdropClick} 44 + > 45 + <div className="overlay-animation-target modal-dialog overlay-open:mt-4 overlay-open:duration-300 mt-12 transition-all ease-out"> 46 + <div className="modal-content"> 47 + <div className="modal-header"> 48 + <div className="form-control w-full"> 49 + <div className="input input-bordered w-full input-lg text-[15px] font-semibold bg-transparent focus-within:border-pink-500!"> 50 + <input 51 + ref={inputRef} 52 + placeholder="What would you like to try?" 53 + className="grow" 54 + /> 55 + </div> 56 + </div> 57 + </div> 58 + <div className="modal-body"> 59 + <div className="p-[12px]"> 60 + <div className="font-semibold">OpenClaw</div> 61 + </div> 62 + <div className="p-[12px]"> 63 + <div className="font-semibold">Claude Code</div> 64 + </div> 65 + <div className="p-[12px]"> 66 + <div className="font-semibold">OpenAI Codex CLI</div> 67 + </div> 68 + <div className="p-[12px]"> 69 + <div className="font-semibold">GitHub Copilot CLI</div> 70 + </div> 71 + <div className="p-[12px]"> 72 + <div className="font-semibold">Gemini CLI</div> 73 + </div> 74 + <div className="p-[12px]"> 75 + <div className="font-semibold">OpenCode</div> 76 + </div> 77 + 78 + <div className="p-[12px]"> 79 + <div className="font-semibold">Aider</div> 80 + </div> 81 + </div> 82 + </div> 83 + </div> 84 + </div> 85 + 86 + {isOpen && ( 87 + <div 88 + id="slide-down-animated-modal-backdrop" 89 + data-overlay-backdrop-template="" 90 + style={{ zIndex: 79 }} 91 + className="overlay-backdrop transition duration-300 fixed inset-0 bg-base-300/60 overflow-y-auto opacity-85" 92 + onClick={onClose} 93 + ></div> 94 + )} 95 + </> 96 + ); 97 + } 98 + 99 + export default NewProject;
+3
apps/web/src/components/newproject/index.tsx
··· 1 + import NewProject from "./NewProject"; 2 + 3 + export default NewProject;
+5 -5
apps/web/src/components/sidebar/Sidebar.tsx
··· 17 17 id="scoped-sidebar" 18 18 className="overlay [--auto-close:sm] sm:shadow-none overlay-open:translate-x-0 drawer drawer-start max-w-64 fixed z-50 sm:flex sm:translate-x-0 [--body-scroll:true] h-screen bg-base-100" 19 19 role="dialog" 20 - tabindex="-1" 20 + tabIndex="-1" 21 21 > 22 22 <div className="drawer-body px-2 pt-4 bg-base-100"> 23 23 <div className="mb-[20px]"> ··· 35 35 to="/projects" 36 36 className={ 37 37 isActive("/projects") 38 - ? "active bg-white/7 text-purple-400! font-semibold rounded-full" 38 + ? "active bg-white/7 text-[#ff41b5]! font-semibold rounded-full" 39 39 : "rounded-full" 40 40 } 41 41 > ··· 48 48 to="/snapshots" 49 49 className={ 50 50 isActive("/snapshots") 51 - ? "active bg-white/7 text-purple-400! font-semibold rounded-full" 51 + ? "active bg-white/7 text-[#ff41b5]! font-semibold rounded-full" 52 52 : "rounded-full" 53 53 } 54 54 > ··· 61 61 to="/volumes" 62 62 className={ 63 63 isActive("/volumes") 64 - ? "active bg-white/7 text-purple-400! font-semibold rounded-full" 64 + ? "active bg-white/7 text-[#ff41b5]! font-semibold rounded-full" 65 65 : "rounded-full" 66 66 } 67 67 > ··· 74 74 to="/secrets" 75 75 className={ 76 76 isActive("/secrets") 77 - ? "active bg-white/7 text-purple-400! font-semibold rounded-full" 77 + ? "active bg-white/7 text-[#ff41b5]! font-semibold rounded-full" 78 78 : "rounded-full" 79 79 } 80 80 >
+32
apps/web/src/index.css
··· 61 61 --bg-secondary: #06051d; 62 62 --text-primary: #e5e5e5; 63 63 --text-secondary: #a0a0a0; 64 + --modal-bg: #06051d; 64 65 } 65 66 66 67 body { ··· 134 135 border-color: rgba(99, 102, 241, 0.5); 135 136 background-color: #06051d !important; 136 137 } 138 + 139 + /* Modal backgrounds - applies to both light and dark mode */ 140 + .modal-content { 141 + background-color: #06051d !important; 142 + color: #e5e5e5; 143 + border: 1px solid rgba(229, 229, 229, 0.1) !important; 144 + border-radius: 0.5rem !important; 145 + overflow: hidden; 146 + } 147 + 148 + .modal-header, 149 + .modal-body, 150 + .modal-footer { 151 + background-color: #06051d !important; 152 + color: #e5e5e5; 153 + } 154 + 155 + /* Modal dialog container */ 156 + .modal-dialog { 157 + background-color: transparent; 158 + } 159 + 160 + /* Modal text colors */ 161 + .modal-title { 162 + color: #e5e5e5; 163 + } 164 + 165 + /* Modal buttons styling */ 166 + .modal-footer .btn { 167 + border-color: rgba(229, 229, 229, 0.2); 168 + }
+12 -4
apps/web/src/pages/home/Home.tsx
··· 1 - import { Link } from "@tanstack/react-router"; 2 1 import Navbar from "./Navbar"; 2 + import NewProject from "../../components/newproject"; 3 + import { useState } from "react"; 3 4 4 5 function Home() { 6 + const [modalOpen, setModalOpen] = useState(false); 5 7 const banner = ` 6 8 ____ __ __ 7 9 / __ \\____ _____/ /_____ / /____ ____ _ __ ··· 29 31 </div> 30 32 31 33 <div className="flex justify-center gap-[20px]"> 32 - <Link 34 + <button 33 35 className="btn bg-pink-500 border-none btn-xl font-bold" 34 - to="/signin" 36 + onClick={() => setModalOpen(true)} 35 37 > 36 38 Start For Free 37 - </Link> 39 + </button> 38 40 <a 39 41 href="https://docs.pocketenv.io" 40 42 target="_blank" ··· 46 48 </div> 47 49 </div> 48 50 </div> 51 + <NewProject 52 + isOpen={modalOpen} 53 + onClose={() => { 54 + setModalOpen(false); 55 + }} 56 + /> 49 57 </> 50 58 ); 51 59 }
+12 -3
apps/web/src/pages/home/Navbar/Navbar.tsx
··· 1 1 import { Link } from "@tanstack/react-router"; 2 2 import "flyonui/dist/dropdown.js"; 3 + import NewProject from "../../../components/newproject"; 4 + import { useState } from "react"; 3 5 4 6 function Navbar() { 7 + const [modalOpen, setModalOpen] = useState(false); 5 8 return ( 6 9 <nav className="navbar bg-base-100 h-20 max-w-[80%] m-auto mt-0"> 7 10 <div className="flex flex-1 items-center"> ··· 34 37 </a> 35 38 </div> 36 39 <div> 37 - <Link 38 - to="/signin" 40 + <button 41 + onClick={() => setModalOpen(true)} 39 42 className="btn btn-block bg-blue-600/20 border-none text-blue-500 font-extrabold" 40 43 > 41 44 Try Pocketenv 42 - </Link> 45 + </button> 43 46 </div> 44 47 </div> 48 + <NewProject 49 + isOpen={modalOpen} 50 + onClose={() => { 51 + setModalOpen(false); 52 + }} 53 + /> 45 54 </nav> 46 55 ); 47 56 }