diff --git a/app/bun.lockb b/app/bun.lockb index 7a9f4fd50..be38fde5b 100755 Binary files a/app/bun.lockb and b/app/bun.lockb differ diff --git a/app/common/hotkeys.ts b/app/common/hotkeys.ts index 15a3f69f5..b6275dff2 100644 --- a/app/common/hotkeys.ts +++ b/app/common/hotkeys.ts @@ -22,10 +22,22 @@ export class Hotkey { } get readableCommand() { + const isMac = process.platform === 'darwin'; return this.command - .replace('meta', '⌘') + .replace('mod', isMac ? '⌘' : 'Ctrl') .split('+') - .map((value) => capitalizeFirstLetter(value)) + .map((value) => { + if (value === 'shift') { + return '⇧'; + } + if (value === 'alt') { + return isMac ? '⌥' : 'Alt'; + } + if (value === 'ctrl') { + return isMac ? '⌃' : 'Ctrl'; + } + return capitalizeFirstLetter(value); + }) .join(' '); } } diff --git a/app/common/ide.ts b/app/common/ide.ts index 151363198..c429c361c 100644 --- a/app/common/ide.ts +++ b/app/common/ide.ts @@ -1,16 +1,23 @@ +import CursorIcon from '../src/assets/cursor.svg'; +import VsCodeIcon from '../src/assets/vscode.svg'; +import ZedIcon from '../src/assets/zed.svg'; + export enum IdeType { VS_CODE = 'VSCode', CURSOR = 'Cursor', + ZED = 'Zed', } export class IDE { - static readonly VS_CODE = new IDE('VSCode', IdeType.VS_CODE, 'vscode'); - static readonly CURSOR = new IDE('Cursor', IdeType.CURSOR, 'cursor'); + static readonly VS_CODE = new IDE('VSCode', IdeType.VS_CODE, 'vscode', VsCodeIcon); + static readonly CURSOR = new IDE('Cursor', IdeType.CURSOR, 'cursor', CursorIcon); + static readonly ZED = new IDE('Zed', IdeType.ZED, 'zed', ZedIcon); private constructor( public readonly displayName: string, public readonly type: IdeType, public readonly command: string, + public readonly icon: string, ) {} toString() { @@ -23,12 +30,14 @@ export class IDE { return IDE.VS_CODE; case IdeType.CURSOR: return IDE.CURSOR; + case IdeType.ZED: + return IDE.ZED; default: throw new Error(`Unknown IDE type: ${type}`); } } static getAll(): IDE[] { - return [this.VS_CODE, this.CURSOR]; + return [this.VS_CODE, this.CURSOR, this.ZED]; } } diff --git a/app/package.json b/app/package.json index 76594d491..c157e80f5 100644 --- a/app/package.json +++ b/app/package.json @@ -57,6 +57,7 @@ "@supabase/supabase-js": "^2.44.4", "class-variance-authority": "^0.7.0", "clsx": "^2.1.1", + "cmdk": "1.0.0", "css-to-tailwind-translator": "^1.2.8", "culori": "^4.0.1", "electron-log": "^5.2.0", diff --git a/app/src/assets/zed.svg b/app/src/assets/zed.svg new file mode 100644 index 000000000..781931cfd --- /dev/null +++ b/app/src/assets/zed.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/app/src/components/ui/command.tsx b/app/src/components/ui/command.tsx new file mode 100644 index 000000000..83d8b8515 --- /dev/null +++ b/app/src/components/ui/command.tsx @@ -0,0 +1,143 @@ +import * as React from 'react'; +import { type DialogProps } from '@radix-ui/react-dialog'; +import { MagnifyingGlassIcon } from '@radix-ui/react-icons'; +import { Command as CommandPrimitive } from 'cmdk'; + +import { cn } from '@/lib/utils'; +import { Dialog, DialogContent } from '@/components/ui/dialog'; + +const Command = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +Command.displayName = CommandPrimitive.displayName; + +interface CommandDialogProps extends DialogProps {} + +const CommandDialog = ({ children, ...props }: CommandDialogProps) => { + return ( + + + + {children} + + + + ); +}; + +const CommandInput = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( +
+ + +
+)); + +CommandInput.displayName = CommandPrimitive.Input.displayName; + +const CommandList = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); + +CommandList.displayName = CommandPrimitive.List.displayName; + +const CommandEmpty = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>((props, ref) => ( + +)); + +CommandEmpty.displayName = CommandPrimitive.Empty.displayName; + +const CommandGroup = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); + +CommandGroup.displayName = CommandPrimitive.Group.displayName; + +const CommandSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +CommandSeparator.displayName = CommandPrimitive.Separator.displayName; + +const CommandItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); + +CommandItem.displayName = CommandPrimitive.Item.displayName; + +const CommandShortcut = ({ className, ...props }: React.HTMLAttributes) => { + return ( + + ); +}; +CommandShortcut.displayName = 'CommandShortcut'; + +export { + Command, + CommandDialog, + CommandInput, + CommandList, + CommandEmpty, + CommandGroup, + CommandItem, + CommandShortcut, + CommandSeparator, +}; diff --git a/app/src/components/ui/hotkeys-label.tsx b/app/src/components/ui/hotkeys-label.tsx index 969025093..c15d8273c 100644 --- a/app/src/components/ui/hotkeys-label.tsx +++ b/app/src/components/ui/hotkeys-label.tsx @@ -3,9 +3,15 @@ import { Kbd } from './kbd'; export function HotKeyLabel({ hotkey }: { hotkey: Hotkey }) { return ( - + {hotkey.description} - {hotkey.readableCommand} + + + + ); } diff --git a/app/src/lib/editor/styles/index.ts b/app/src/lib/editor/styles/index.ts index f92d89e04..fd56b78dd 100644 --- a/app/src/lib/editor/styles/index.ts +++ b/app/src/lib/editor/styles/index.ts @@ -282,7 +282,7 @@ export const ELEMENT_STYLES: ElementStyle[] = [ new ElementStyleImpl( 'backgroundColor', '', - 'Fill', + 'Background', ElementStyleType.Color, ElementStyleGroup.Style, ), diff --git a/app/src/lib/editor/styles/models.ts b/app/src/lib/editor/styles/models.ts index b90370a55..f525ebba3 100644 --- a/app/src/lib/editor/styles/models.ts +++ b/app/src/lib/editor/styles/models.ts @@ -23,7 +23,7 @@ export enum ElementStyleType { export enum ElementStyleGroup { Size = 'Size', Position = 'Position & Dimensions', - Layout = 'Layout', + Layout = 'Flexbox & Layout', Style = 'Styles', Text = 'Text', Effects = 'Effects', diff --git a/app/src/routes/editor/LayersPanel/Tree/TreeNode.tsx b/app/src/routes/editor/LayersPanel/Tree/TreeNode.tsx index 53ba3e098..d10c030fa 100644 --- a/app/src/routes/editor/LayersPanel/Tree/TreeNode.tsx +++ b/app/src/routes/editor/LayersPanel/Tree/TreeNode.tsx @@ -171,7 +171,7 @@ const TreeNode = observer( > {instance?.component ? instance.component - : node.data.tagName.toLowerCase()}{' '} + : node.data.tagName.toLowerCase()} {node.data.textContent} diff --git a/app/src/routes/editor/RightClickMenu/index.tsx b/app/src/routes/editor/RightClickMenu/index.tsx index 0309f991c..c1162c903 100644 --- a/app/src/routes/editor/RightClickMenu/index.tsx +++ b/app/src/routes/editor/RightClickMenu/index.tsx @@ -6,6 +6,13 @@ import { ContextMenuTrigger, } from '@/components/ui/context-menu'; import { Kbd } from '@/components/ui/kbd'; +import { + CodeIcon, + Component1Icon, + ComponentInstanceIcon, + ExternalLinkIcon, + ReloadIcon, +} from '@radix-ui/react-icons'; import { observer } from 'mobx-react-lite'; import { useEffect, useState } from 'react'; import { Hotkey } from '/common/hotkeys'; @@ -21,7 +28,9 @@ interface MenuItem { action: () => void; hotkey?: Hotkey; children?: MenuItem[]; + icon: React.ReactNode; } + export const RightClickMenu = observer(({ children }: RightClickMenuProps) => { const editorEngine = useEditorEngine(); const [menuItems, setMenuItems] = useState([]); @@ -32,12 +41,14 @@ export const RightClickMenu = observer(({ children }: RightClickMenuProps) => { action: () => { editorEngine.inspect(); }, + icon: , }, { label: 'Refresh layers', action: () => { editorEngine.refreshLayers(); }, + icon: , }, ]; @@ -58,10 +69,16 @@ export const RightClickMenu = observer(({ children }: RightClickMenuProps) => { instance && { label: 'View instance code', action: () => viewSource(instance), + icon: , }, root && { label: `View ${instance ? 'component' : 'element'} code`, action: () => viewSource(root), + icon: instance ? ( + + ) : ( + + ), }, ...DEFAULT_MENU_ITEMS, ].filter(Boolean) as MenuItem[]; @@ -79,7 +96,8 @@ export const RightClickMenu = observer(({ children }: RightClickMenuProps) => { {menuItems.map((item) => ( - + + {item.icon} {item.label} {item.hotkey && {item.hotkey.readableCommand}} diff --git a/app/src/routes/editor/TopBar/OpenCode/index.tsx b/app/src/routes/editor/TopBar/OpenCode/index.tsx index 0866792ff..6a99579a5 100644 --- a/app/src/routes/editor/TopBar/OpenCode/index.tsx +++ b/app/src/routes/editor/TopBar/OpenCode/index.tsx @@ -1,5 +1,3 @@ -import CursorIcon from '@/assets/cursor.svg'; -import VsCodeIcon from '@/assets/vscode.svg'; import { useEditorEngine } from '@/components/Context'; import { DropdownMenu, @@ -72,10 +70,7 @@ const OpenCode = observer(() => { onClick={() => viewSource(instance || root)} > - {`${ide} + {`${ide} {`Open in ${ide}`} @@ -130,10 +125,7 @@ const OpenCode = observer(() => { }} > - {`${item} + {`${item} {item.displayName} {ide === item && } diff --git a/app/src/routes/editor/TopBar/ProjectSelect/index.tsx b/app/src/routes/editor/TopBar/ProjectSelect/index.tsx index 06f74c27a..f550a72e4 100644 --- a/app/src/routes/editor/TopBar/ProjectSelect/index.tsx +++ b/app/src/routes/editor/TopBar/ProjectSelect/index.tsx @@ -30,7 +30,7 @@ const ProjectBreadcrumb = observer(() => { } return ( -
+
- + Return to project selection -

{'/'}

+

{'/'}

{projectsManager.project?.name}

diff --git a/app/src/routes/editor/TopBar/PublishModal/index.tsx b/app/src/routes/editor/TopBar/PublishModal/index.tsx index 144fddb83..b77b7d120 100644 --- a/app/src/routes/editor/TopBar/PublishModal/index.tsx +++ b/app/src/routes/editor/TopBar/PublishModal/index.tsx @@ -123,7 +123,7 @@ const PublishModal = observer(() => { className="truncate justify-start" onClick={() => viewSource(item.path)} > - {item.path} {' '} + {item.path}
{'Let’s name your project'} - {'You can always change this later'} + + { + "This is your Onlook project name. Don't worry, This will not rename your actual folder." + } +
diff --git a/app/src/routes/projects/ProjectsTab/Select/ProjectSettingsButton.tsx b/app/src/routes/projects/ProjectsTab/Select/ProjectSettingsButton.tsx index fee461d19..295da81b4 100644 --- a/app/src/routes/projects/ProjectsTab/Select/ProjectSettingsButton.tsx +++ b/app/src/routes/projects/ProjectsTab/Select/ProjectSettingsButton.tsx @@ -46,7 +46,7 @@ export default function ProjectSettingsButton({ project }: { project: Project }) Open Project Folder diff --git a/app/src/routes/projects/SettingsTab/index.tsx b/app/src/routes/projects/SettingsTab/index.tsx index 314590198..efa050a5d 100644 --- a/app/src/routes/projects/SettingsTab/index.tsx +++ b/app/src/routes/projects/SettingsTab/index.tsx @@ -1,5 +1,3 @@ -import CursorIcon from '@/assets/cursor.svg'; -import VsCodeIcon from '@/assets/vscode.svg'; import { Button } from '@/components/ui/button'; import { DropdownMenu, @@ -55,10 +53,7 @@ export default function SettingsTab() { - Sign out + + + Sign out +
diff --git a/app/src/routes/signin/index.tsx b/app/src/routes/signin/index.tsx index 5c5ed0f25..c2fa799fd 100644 --- a/app/src/routes/signin/index.tsx +++ b/app/src/routes/signin/index.tsx @@ -88,19 +88,19 @@ const SignIn = observer(() => {

- By signing up, you agree to our{' '} + {'By signing up, you agree to our '} {' '} - and{' '} + {'Privacy Policy'} + + {' and '}