Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactors and proper light/dark mode support #173

Merged
merged 11 commits into from
Feb 5, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file removed .DS_Store
Binary file not shown.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,5 @@ vite.config.ts.timestamp-*
database-debug.log
firebase-debug.log
ui-debug.log

.DS_Store
224 changes: 107 additions & 117 deletions package-lock.json

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"lint": "prettier --check . && eslint .",
"test:e2e": "playwright test",
"test": "npm run test:e2e",
"postinstall": "patch-package"
"postinstall": "patch-package",
"emulators:stop": "lsof -t -i:8080 -i:9000 -i:9099 -i:9199 -i:9090 | xargs kill -9"
},
"devDependencies": {
"@eslint/compat": "^1.2.3",
Expand Down Expand Up @@ -61,7 +62,7 @@
"@replit/codemirror-vim": "^6.2.1",
"@tailwindcss/forms": "^0.5.9",
"@tailwindcss/typography": "^0.5.15",
"@tailwindcss/vite": "^4.0.0-beta.8",
"@tailwindcss/vite": "^4.0.3",
"@uiw/codemirror-theme-github": "^4.23.7",
"@uiw/codemirror-theme-vscode": "^4.23.7",
"codemirror": "^6.0.1",
Expand Down
41 changes: 23 additions & 18 deletions src/app.css
Original file line number Diff line number Diff line change
@@ -1,33 +1,38 @@
@import "tailwindcss";
@import 'tailwindcss';
@custom-variant dark (&:where([data-theme=dark], [data-theme=dark] *));

@plugin "@tailwindcss/forms";
@plugin "@tailwindcss/typography";

body {
/* Matches the color of monaco-editor */
background-color: #1e1e1e;
/* Matches the color of monaco-editor */
background-color: #1e1e1e;

@apply text-gray-100;
@apply text-gray-100;
}

/* Styles for remote cursors for monaco */
.yRemoteSelection {
/* background-color: rgb(250, 129, 0, 0.5); */
background-color: var(--yjs-selection-color-bg, rgb(250, 129, 0, 0.5));
/* background-color: rgb(250, 129, 0, 0.5); */
background-color: var(--yjs-selection-color-bg, rgb(250, 129, 0, 0.5));
}
.yRemoteSelectionHead {
position: absolute;
border-left: var(--yjs-selection-color, orange) solid 2px;
border-top: var(--yjs-selection-color, orange) solid 2px;
border-bottom: var(--yjs-selection-color, orange) solid 2px;
height: 100%;
box-sizing: border-box;
position: absolute;
border-left: var(--yjs-selection-color, orange) solid 2px;
border-top: var(--yjs-selection-color, orange) solid 2px;
border-bottom: var(--yjs-selection-color, orange) solid 2px;
height: 100%;
box-sizing: border-box;
}
.yRemoteSelectionHead::after {
position: absolute;
content: ' ';
border: 3px solid var(--yjs-selection-color, orange);
border-radius: 4px;
left: -4px;
top: -5px;
position: absolute;
content: ' ';
border: 3px solid var(--yjs-selection-color, orange);
border-radius: 4px;
left: -4px;
top: -5px;
}

button {
@apply cursor-pointer;
}
102 changes: 24 additions & 78 deletions src/lib/components/FileMenu.svelte
Original file line number Diff line number Diff line change
@@ -1,23 +1,21 @@
<script lang="ts">
import { createDropdownMenu, melt } from '@melt-ui/svelte';
import { Plus, Download, Files, Cog } from 'lucide-svelte';
const {
elements: { menu, item, trigger, arrow }
elements: { menu, item, trigger }
} = createDropdownMenu({
positioning: {
placement: 'bottom-start',
gutter: 0
}
});

const { onDownloadFile, onOpenSettings } = $props();

const menuItemClass =
'group flex items-center px-4 py-2 text-sm text-gray-200 data-[highlighted]:bg-neutral-700 data-[highlighted]:text-gray-100 w-full focus:outline-none cursor-pointer';
const { onDownloadFile, onOpenSettings, theme } = $props();
</script>

<button
use:melt={$trigger}
class="relative inline-flex cursor-pointer items-center px-4 py-2 text-sm font-medium text-gray-200 shadow-sm hover:bg-neutral-800 focus:bg-neutral-800 focus:outline-none"
class="relative inline-flex cursor-pointer items-center px-4 py-2 text-sm font-medium text-gray-800 shadow-sm hover:bg-neutral-100 focus:bg-neutral-100 focus:outline-none dark:text-gray-200 dark:hover:bg-neutral-800 dark:focus:bg-neutral-800"
>
File
<!-- Chevron Down Icon -->
Expand All @@ -35,78 +33,26 @@
/>
</svg>
</button>
<div class="ring-opacity-5 w-56 bg-neutral-800 py-1 shadow-lg focus:outline-none" use:melt={$menu}>
<a use:melt={$item} href="/new" target="_blank" class={menuItemClass}>
<!-- Plus Icon -->
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="mr-3 h-5 w-5 text-gray-400 group-hover:text-gray-300"
aria-hidden="true"
>
<path
d="M10.75 4.75a.75.75 0 0 0-1.5 0v4.5h-4.5a.75.75 0 0 0 0 1.5h4.5v4.5a.75.75 0 0 0 1.5 0v-4.5h4.5a.75.75 0 0 0 0-1.5h-4.5v-4.5Z"
/>
</svg>
New File
</a>
<button use:melt={$item} type="button" onclick={onDownloadFile} class={menuItemClass}>
<!-- Arrow Down Tray Icon -->
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="mr-3 h-5 w-5 text-gray-400 group-hover:text-gray-300"
aria-hidden="true"
>
<path
d="M10.75 2.75a.75.75 0 0 0-1.5 0v8.614L6.295 8.235a.75.75 0 1 0-1.09 1.03l4.25 4.5a.75.75 0 0 0 1.09 0l4.25-4.5a.75.75 0 0 0-1.09-1.03l-2.955 3.129V2.75Z"
/>
<path
d="M3.5 12.75a.75.75 0 0 0-1.5 0v2.5A2.75 2.75 0 0 0 4.75 18h10.5A2.75 2.75 0 0 0 18 15.25v-2.5a.75.75 0 0 0-1.5 0v2.5c0 .69-.56 1.25-1.25 1.25H4.75c-.69 0-1.25-.56-1.25-1.25v-2.5Z"
/>
</svg>
Download File
</button>

<a use:melt={$item} href={window.location.href + '/copy'} target="_blank" rel="noreferrer" class={menuItemClass}>
<!-- Document Duplicate Icon -->
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="mr-3 h-5 w-5 text-gray-400 group-hover:text-gray-300"
aria-hidden="true"
>
<path
d="M7 3.5A1.5 1.5 0 0 1 8.5 2h3.879a1.5 1.5 0 0 1 1.06.44l3.122 3.12A1.5 1.5 0 0 1 17 6.622V12.5a1.5 1.5 0 0 1-1.5 1.5h-1v-3.379a3 3 0 0 0-.879-2.121L10.5 5.379A3 3 0 0 0 8.379 4.5H7v-1Z"
/>
<path
d="M4.5 6A1.5 1.5 0 0 0 3 7.5v9A1.5 1.5 0 0 0 4.5 18h7a1.5 1.5 0 0 0 1.5-1.5v-5.879a1.5 1.5 0 0 0-.44-1.06L9.44 6.439A1.5 1.5 0 0 0 8.378 6H4.5Z"
/>
</svg>
Clone File
</a>

<button use:melt={$item} onclick={onOpenSettings} type="button" class={menuItemClass}>
<!-- Cog Icon -->
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="mr-3 h-5 w-5 text-gray-400 group-hover:text-gray-300"
aria-hidden="true"
<!-- menu options -->
<div
class="ring-opacity-5 w-56 bg-white py-1 shadow-lg focus:outline-none dark:bg-neutral-800"
data-theme={theme}
use:melt={$menu}
>
{#each [[Plus, 'New File', '/new', null], [Download, 'Download File', null, onDownloadFile], [Files, 'Clone File', `${window.location.href}/copy`, null], [Cog, 'Settings', null, onOpenSettings]] as [Icon, text, href, onclick] (text)}
<a
use:melt={$item}
{href}
{onclick}
target="_blank"
class="group flex w-full cursor-pointer items-center px-4 py-2
text-sm text-gray-800 focus:outline-none data-[highlighted]:bg-neutral-100 data-[highlighted]:text-gray-900
dark:bg-neutral-800 dark:text-gray-200 dark:data-[highlighted]:bg-neutral-700 dark:data-[highlighted]:text-gray-100"
>
<path
d="M13.024 9.25c.47 0 .827-.433.637-.863a4 4 0 0 0-4.094-2.364c-.468.05-.665.576-.43.984l1.08 1.868a.75.75 0 0 0 .649.375h2.158ZM7.84 7.758c-.236-.408-.79-.5-1.068-.12A3.982 3.982 0 0 0 6 10c0 .884.287 1.7.772 2.363.278.38.832.287 1.068-.12l1.078-1.868a.75.75 0 0 0 0-.75L7.839 7.758ZM9.138 12.993c-.235.408-.039.934.43.984a4 4 0 0 0 4.094-2.364c.19-.43-.168-.863-.638-.863h-2.158a.75.75 0 0 0-.65.375l-1.078 1.868Z"
/>
<path
fill-rule="evenodd"
d="m14.13 4.347.644-1.117a.75.75 0 0 0-1.299-.75l-.644 1.116a6.954 6.954 0 0 0-2.081-.556V1.75a.75.75 0 0 0-1.5 0v1.29a6.954 6.954 0 0 0-2.081.556L6.525 2.48a.75.75 0 1 0-1.3.75l.645 1.117A7.04 7.04 0 0 0 4.347 5.87L3.23 5.225a.75.75 0 1 0-.75 1.3l1.116.644A6.954 6.954 0 0 0 3.04 9.25H1.75a.75.75 0 0 0 0 1.5h1.29c.078.733.27 1.433.556 2.081l-1.116.645a.75.75 0 1 0 .75 1.298l1.117-.644a7.04 7.04 0 0 0 1.523 1.523l-.645 1.117a.75.75 0 1 0 1.3.75l.644-1.116a6.954 6.954 0 0 0 2.081.556v1.29a.75.75 0 0 0 1.5 0v-1.29a6.954 6.954 0 0 0 2.081-.556l.645 1.116a.75.75 0 0 0 1.299-.75l-.645-1.117a7.042 7.042 0 0 0 1.523-1.523l1.117.644a.75.75 0 0 0 .75-1.298l-1.116-.645a6.954 6.954 0 0 0 .556-2.081h1.29a.75.75 0 0 0 0-1.5h-1.29a6.954 6.954 0 0 0-.556-2.081l1.116-.644a.75.75 0 0 0-.75-1.3l-1.117.645a7.04 7.04 0 0 0-1.524-1.523ZM10 4.5a5.475 5.475 0 0 0-2.781.754A5.527 5.527 0 0 0 5.22 7.277 5.475 5.475 0 0 0 4.5 10a5.475 5.475 0 0 0 .752 2.777 5.527 5.527 0 0 0 2.028 2.004c.802.458 1.73.719 2.72.719a5.474 5.474 0 0 0 2.78-.753 5.527 5.527 0 0 0 2.001-2.027c.458-.802.719-1.73.719-2.72a5.475 5.475 0 0 0-.753-2.78 5.528 5.528 0 0 0-2.028-2.002A5.475 5.475 0 0 0 10 4.5Z"
clip-rule="evenodd"
<Icon
class="mr-3 h-5 w-5 text-gray-400 group-hover:text-gray-500 dark:group-hover:text-gray-300"
/>
</svg>
Settings
</button>
{text}
</a>
{/each}
</div>
24 changes: 15 additions & 9 deletions src/lib/components/IDELayout.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ This should be a "dumb", self-contained component that only contains UI logic.
mainPane,
inputPane,
outputPane,
layout
layout,
theme
}: {
navbar: any;
mainPane: any;
inputPane: any;
outputPane: any;
layout: 'mobile' | 'desktop';
theme: string;
} = $props();

let verticalGutter: HTMLElement;
Expand Down Expand Up @@ -50,12 +52,12 @@ This should be a "dumb", self-contained component that only contains UI logic.
let mobileActiveTab = $state<'main' | 'inputOutput'>('main');
</script>

<div class="h-full">
<div class="h-full overflow-x-hidden" data-theme={theme}>
<div class="flex h-full flex-col">
<div class="flex-shrink-0 bg-[#1E1E1E]">
<div class="flex-shrink-0 bg-white dark:bg-[#1E1E1E]">
{@render navbar()}
</div>
<div class="min-h-0 flex-1 border-t border-black">
<div class="min-h-0 flex-1 border-t border-neutral-100 dark:border-black">
<div class="split-grid h-full">
<!-- Without min-w-0, we won't be able to reize the pane to make monaco-editor smaller. -->
<div
Expand All @@ -71,7 +73,7 @@ This should be a "dumb", self-contained component that only contains UI logic.
class:hidden={layout === 'mobile'}
>
<div
class="pointer-events-none absolute right-[6px] left-[6px] h-full bg-black transition group-hover:bg-neutral-600 group-active:bg-neutral-600"
class="pointer-events-none absolute right-[6px] left-[6px] h-full bg-neutral-200 transition group-hover:bg-neutral-300 group-active:bg-neutral-300 dark:bg-black dark:group-hover:bg-neutral-600 dark:group-active:bg-neutral-600"
></div>
</div>
<div
Expand All @@ -89,7 +91,7 @@ This should be a "dumb", self-contained component that only contains UI logic.
class:col-span-full={layout === 'mobile'}
>
<div
class={`pointer-events-none absolute w-full bg-black transition group-hover:bg-neutral-600 group-focus:bg-neutral-600 group-active:bg-neutral-600 ${
class={`gutter pointer-events-none absolute w-full ${
layout === 'desktop'
? 'top-[6px] bottom-[6px]'
: 'inset-y-0 flex items-center justify-center bg-neutral-800'
Expand Down Expand Up @@ -127,13 +129,13 @@ This should be a "dumb", self-contained component that only contains UI logic.

<!-- Mobile bottom bar -->
{#if layout === 'mobile'}
<div class="grid grid-cols-2 bg-[#1E1E1E]">
<div class="grid grid-cols-2 bg-white dark:bg-[#1E1E1E]">
{#each ['main', 'inputOutput'] as const as tab}
<button
class="flex flex-col items-center py-1 transition focus:outline-none {mobileActiveTab ===
tab
? 'text-gray-200'
: 'text-gray-400'}"
? 'text-gray-800 dark:text-gray-200'
: 'text-gray-500 dark:text-gray-400'}"
onclick={() => (mobileActiveTab = tab)}
data-testid="mobile-bottom-nav-{tab}-button"
>
Expand All @@ -152,9 +154,13 @@ This should be a "dumb", self-contained component that only contains UI logic.
</div>

<style>
@reference "../../app.css";
.split-grid {
display: grid;
grid-template-columns: 1fr 3px 1fr;
grid-template-rows: 1fr 3px 1fr;
}
.gutter {
@apply bg-neutral-200 transition group-hover:bg-neutral-300 group-focus:bg-neutral-600 group-active:bg-neutral-300 dark:bg-black dark:group-hover:bg-neutral-600 dark:group-active:bg-neutral-600;
}
</style>
16 changes: 8 additions & 8 deletions src/lib/components/IDENavbar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
}
</script>

<div class="flex items-center overflow-x-auto">
<div class="flex items-center divide-x divide-neutral-700">
<div class="flex items-center overflow-x-auto text-gray-800 dark:text-gray-200">
<div class="flex items-center divide-x divide-neutral-200 dark:divide-neutral-700">
<a
href="/"
class="relative inline-flex items-center px-4 py-2 text-sm font-medium text-gray-200 shadow-sm hover:bg-neutral-800 focus:bg-neutral-800 focus:outline-none"
class="relative inline-flex items-center px-4 py-2 text-sm font-medium shadow-sm hover:bg-neutral-200 focus:bg-neutral-200 focus:outline-none dark:hover:bg-neutral-800 dark:focus:bg-neutral-800"
>
<!-- Home Icon -->
<svg
Expand All @@ -41,7 +41,7 @@
{@render fileMenu()}
<button
type="button"
class="relative inline-flex cursor-pointer items-center px-4 py-2 text-sm font-medium text-gray-200 shadow-sm hover:bg-neutral-800 focus:bg-neutral-800 focus:outline-none"
class="focus: relative inline-flex cursor-pointer items-center px-4 py-2 text-sm font-medium shadow-sm hover:bg-neutral-300 focus:outline-none dark:hover:bg-neutral-800 dark:focus:bg-neutral-800"
onclick={handleShare}
>
<!-- Share Icon -->
Expand All @@ -60,11 +60,11 @@
</button>
</div>
{@render runButton()}
<div class="flex items-center divide-x divide-neutral-700">
<div class="flex items-center divide-x divide-neutral-200 dark:divide-neutral-700">
<a
href="https://github.com/cpinitiative/ide/issues"
target="_blank"
class="flex-shrink-0 px-4 py-2 text-sm font-medium text-gray-400 hover:text-gray-200"
class="flex-shrink-0 px-4 py-2 text-sm font-medium hover:text-gray-900 dark:hover:text-gray-100"
rel="noreferrer"
>
Report an Issue
Expand All @@ -73,12 +73,12 @@
href="https://github.com/cpinitiative/ide"
target="_blank"
rel="noreferrer"
class="flex-shrink-0 px-4 py-2 text-sm font-medium text-gray-400 hover:text-gray-200"
class="flex-shrink-0 px-4 py-2 text-sm font-medium hover:text-gray-900 dark:hover:text-gray-100"
>
Star this on GitHub!
</a>
{#if showViewOnlyMessage}
<span class="px-4 py-2 text-sm font-medium text-gray-400"> View Only </span>
<span class="px-4 py-2 text-sm font-medium"> View Only </span>
{/if}
</div>
</div>
11 changes: 6 additions & 5 deletions src/lib/components/OutputStatusBar.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,20 @@
} else if (verdict === Verdict.RuntimeError) {
return 'Runtime Error';
} else {
return verdict;
}
return verdict;
}
}
</script>

<!-- Font family is copied from vscode to match the status bar font. -->
<div
class="pr-4 text-right text-xs text-gray-200 py-1"
class="bg-white py-1 pr-4 text-right text-xs text-gray-800 dark:bg-[#1e1e1e] dark:text-gray-200"
data-test-id="code-execution-output-status"
style="font-family: -apple-system,BlinkMacSystemFont,Segoe WPC,Segoe UI,system-ui,Ubuntu,Droid Sans,sans-serif"
style="font-family: -apple-system,BlinkMacSystemFont,Segoe WPC,Segoe UI,system-ui,Ubuntu,Droid Sans,sans-serif"
>
{#if result?.execute}
{formatVerdict(result.execute.verdict)}, {result.execute.wall_time}s, {result.execute.memory_usage}KB
{formatVerdict(result.execute.verdict)}, {result.execute.wall_time}s, {result.execute
.memory_usage}KB
{:else if result?.compile}
Compile Error
{:else}
Expand Down
Loading