diff --git a/desktop/src-tauri/capabilities/default.json b/desktop/src-tauri/capabilities/default.json index bfd29a66..9186b49c 100644 --- a/desktop/src-tauri/capabilities/default.json +++ b/desktop/src-tauri/capabilities/default.json @@ -2,9 +2,7 @@ "$schema": "../gen/schemas/desktop-schema.json", "identifier": "default", "description": "Capability for the main window", - "windows": [ - "main" - ], + "windows": ["main"], "permissions": [ "core:default", "shell:default", @@ -19,4 +17,4 @@ }, "log:default" ] -} \ No newline at end of file +} diff --git a/desktop/src-tauri/tauri.conf.json b/desktop/src-tauri/tauri.conf.json index 3c234045..77ad2d19 100644 --- a/desktop/src-tauri/tauri.conf.json +++ b/desktop/src-tauri/tauri.conf.json @@ -14,7 +14,6 @@ { "title": "flow desktop", "hiddenTitle": true, - "titleBarStyle": "Transparent", "width": 1000, "height": 800 } diff --git a/desktop/src/App.css b/desktop/src/App.css index ffd14dd0..d5aa76ae 100644 --- a/desktop/src/App.css +++ b/desktop/src/App.css @@ -1,19 +1,9 @@ -.logo.vite:hover { - filter: drop-shadow(0 0 2em #747bff); -} - -.logo.react:hover { - filter: drop-shadow(0 0 2em #61dafb); -} :root { font-family: Inter, Avenir, Helvetica, Arial, sans-serif; font-size: 16px; line-height: 24px; font-weight: 400; - color: #0f0f0f; - background-color: #f6f6f6; - font-synthesis: none; text-rendering: optimizeLegibility; -webkit-font-smoothing: antialiased; @@ -40,97 +30,3 @@ body { width: 100vw; overflow: hidden; } - -.container { - margin: 0; - padding-top: 10vh; - display: flex; - flex-direction: column; - justify-content: center; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; - transition: 0.75s; -} - -.logo.tauri:hover { - filter: drop-shadow(0 0 2em #24c8db); -} - -.row { - display: flex; - justify-content: center; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -h1 { - text-align: center; -} - -input, -button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; - font-weight: 500; - font-family: inherit; - color: #0f0f0f; - background-color: #ffffff; - transition: border-color 0.25s; - box-shadow: 0 2px 2px rgba(0, 0, 0, 0.2); -} - -button { - cursor: pointer; -} - -button:hover { - border-color: #396cd8; -} -button:active { - border-color: #396cd8; - background-color: #e8e8e8; -} - -input, -button { - outline: none; -} - -#greet-input { - margin-right: 5px; -} - -@media (prefers-color-scheme: dark) { - :root { - color: #f6f6f6; - background-color: #2f2f2f; - } - - a:hover { - color: #24c8db; - } - - input, - button { - color: #ffffff; - background-color: #0f0f0f98; - } - button:active { - background-color: #0f0f0f69; - } -} diff --git a/desktop/src/App.tsx b/desktop/src/App.tsx index 7ec3905d..ae73fd80 100644 --- a/desktop/src/App.tsx +++ b/desktop/src/App.tsx @@ -5,8 +5,8 @@ import { AppProvider } from "./hooks/useAppContext.tsx"; import { NotifierProvider } from "./hooks/useNotifier"; import { AppShell } from "./layout"; import { PageWrapper } from "./components/PageWrapper.tsx"; -import { Settings, Welcome, Data } from "./pages"; -import { WorkspaceRoute } from "./pages/Workspace/WorkspaceRoute.tsx"; +import {Settings, Welcome, Data, Workspaces} from "./pages"; +import { Workspace } from "./pages/Workspace/Workspace.tsx"; import { ExecutableRoute } from "./pages/Executable/ExecutableRoute.tsx"; import { Text } from "@mantine/core"; @@ -31,9 +31,13 @@ function App() { + { + const loadTheme = async () => { + const variant = theme ? themeMapper[theme] ?? "default" : "default"; + if (variant === "dark") { + await import("prismjs/themes/prism-dark.css"); + } else { + await import("prismjs/themes/prism.css"); + } + }; + void loadTheme(); + }, [theme]); + useEffect(() => { if (codeRef.current) { Prism.highlightElement(codeRef.current); @@ -63,7 +74,6 @@ export function CodeHighlighter({ ref={containerRef} pos="relative" style={{ - borderRadius: config.styling.borderRadius, overflow: "hidden", }} > @@ -88,7 +98,7 @@ export function CodeHighlighter({ margin: 0, padding: config.styling.padding, background: config.styling.backgroundColor, - borderRadius: config.styling.borderRadius, + border: "none", overflow: "auto", fontSize: config.styling.fontSize, lineHeight: config.styling.lineHeight, diff --git a/desktop/src/components/CodeHighlighter/config.ts b/desktop/src/components/CodeHighlighter/config.ts index a634e617..08a37905 100644 --- a/desktop/src/components/CodeHighlighter/config.ts +++ b/desktop/src/components/CodeHighlighter/config.ts @@ -4,15 +4,11 @@ import { ThemeName } from "../../theme/types"; export interface CodeHighlighterConfig { - // Whether to show copy button by default defaultCopyButton: boolean; - // Default theme for syntax highlighting defaultTheme: string; - // Custom styling options styling: { - borderRadius: string; padding: string; fontSize: string; lineHeight: string; @@ -41,11 +37,10 @@ export const defaultConfig: CodeHighlighterConfig = { defaultTheme: "default", styling: { - borderRadius: "var(--mantine-radius-sm)", padding: "var(--mantine-spacing-md)", fontSize: "var(--mantine-font-size-sm)", lineHeight: "1.5", - backgroundColor: "var(--mantine-color-dark-7)", + backgroundColor: "var(--mantine-color-gray-7)", copyButtonStyle: { background: "rgba(255, 255, 255, 0.1)", border: "1px solid rgba(255, 255, 255, 0.2)", @@ -62,7 +57,7 @@ export const darkThemeConfig: CodeHighlighterConfig = { defaultTheme: "dark", styling: { ...defaultConfig.styling, - backgroundColor: "var(--mantine-color-dark-8)", + backgroundColor: "var(--mantine-color-appshell-0)", copyButtonStyle: { ...defaultConfig.styling.copyButtonStyle, background: "rgba(255, 255, 255, 0.15)", @@ -101,5 +96,4 @@ export function getConfigForTheme(theme?: ThemeName): CodeHighlighterConfig { } } -// Export the current configuration (you can change this to switch themes) export const currentConfig = defaultConfig; diff --git a/desktop/src/components/Hero/Hero.module.css b/desktop/src/components/Hero/Hero.module.css new file mode 100644 index 00000000..4231a95e --- /dev/null +++ b/desktop/src/components/Hero/Hero.module.css @@ -0,0 +1,145 @@ +.root { + --hero-bg-primary: var(--mantine-color-appshell-0); + --hero-bg-secondary: var(--mantine-color-primary-0); + --hero-text-primary: var(--mantine-color-secondary-0); + --hero-text-secondary: var(--mantine-color-tertiary-0); + --hero-border: var(--mantine-color-border-0); + --hero-pattern-color: var(--mantine-color-emphasis-1); + + position: relative; + color: var(--hero-text-primary); + background: linear-gradient( + 150deg, + var(--hero-bg-primary) 0%, + var(--hero-bg-secondary) 100% + ); + border-bottom: 1px solid var(--hero-border); + overflow: hidden; + margin-bottom: var(--mantine-spacing-lg); +} + +.pattern { + position: absolute; + inset: 0; + opacity: 0.12; + pointer-events: none; +} + +.pattern-subtle { + background: + radial-gradient( + circle at 30% 20%, + var(--hero-pattern-color) 2px, + transparent 2px + ), + radial-gradient( + circle at 70% 80%, + var(--hero-pattern-color) 1.5px, + transparent 1.5px + ); + background-size: + 50px 50px, + 70px 70px; +} + +.pattern-lines { + background-image: + linear-gradient(90deg, var(--hero-pattern-color) 1px, transparent 1px), + linear-gradient(0deg, var(--hero-pattern-color) 1px, transparent 1px); + background-size: 40px 40px; +} + +.variant-center .inner { + text-align: center; +} + +.variant-left .inner { + text-align: left; +} + +.variant-split .inner { + text-align: left; +} + +.variant-split .header { + text-align: left; +} + +.contentContainer { + position: relative; + z-index: 1; +} + +.inner { + width: 100%; + max-width: 80rem; + margin-inline: auto; + padding: 2.5rem 2rem; + min-height: 120px; + display: flex; + align-items: center; +} + +.stackedContent { + width: 100%; +} + +.splitLayout { + width: 100%; + flex-wrap: nowrap; + align-items: center; +} + +.splitContent { + flex: 1; + min-width: 0; +} + +.splitActions { + flex-shrink: 0; + margin-left: auto; + align-self: center; +} + +.header { + margin-bottom: 0.5rem; +} + +.header :global(.mantine-Title-root) { + font-weight: 600; + line-height: 1.2; + margin-bottom: 0.5rem; +} + +.header :global(.mantine-Text-root) { + color: var(--hero-text-secondary); + font-size: var(--mantine-font-size-sm); + line-height: 1.4; +} + +.content { + margin: 1rem 0; +} + +.actions { + align-items: center; + flex-wrap: wrap; +} + +.actions-left { + justify-content: flex-start; +} + +.actions-center { + justify-content: center; +} + +.actions-right { + justify-content: flex-end; +} + +.root :global(.Mantine-Badge-root) { + --badge-bg: var(--mantine-color-gray-1) !important; + --badge-color: var(--mantine-color-gray-8) !important; + --badge-bd: transparent !important; +} diff --git a/desktop/src/components/Hero/Hero.tsx b/desktop/src/components/Hero/Hero.tsx new file mode 100644 index 00000000..e47b182d --- /dev/null +++ b/desktop/src/components/Hero/Hero.tsx @@ -0,0 +1,137 @@ +import { Box, Container, Group, Stack } from "@mantine/core"; +import React from "react"; +import classes from "./Hero.module.css"; + +export type HeroVariant = "center" | "split" | "left"; +export type PatternType = "lines" | "subtle" | "none"; + +export interface HeroProps { + children: React.ReactNode; + variant?: HeroVariant; + pattern?: PatternType; + className?: string; + containerSize?: string | number; +} + +export interface HeroHeaderProps { + children: React.ReactNode; + className?: string; +} + +export interface HeroContentProps { + children: React.ReactNode; + className?: string; +} + +export interface HeroActionsProps { + children: React.ReactNode; + className?: string; + align?: "left" | "center" | "right"; +} + +export function HeroHeader({ children, className }: HeroHeaderProps) { + return ( + {children} + ); +} + +export function HeroContent({ children, className }: HeroContentProps) { + return ( + {children} + ); +} + +export function HeroActions({ + children, + className, + align = "right", +}: HeroActionsProps) { + return ( + + {children} + + ); +} + +export function Hero({ + children, + variant = "center", + pattern = "subtle", + className, + containerSize = "xl", +}: HeroProps) { + const renderPattern = () => { + if (pattern === "none") return null; + return ( +