forked from wrenn/wrenn
Minor frontend enhancements
This commit is contained in:
@ -311,8 +311,8 @@
|
||||
<h1 class="font-serif text-page tracking-[-0.02em] text-[var(--color-text-bright)]">
|
||||
Capsules
|
||||
</h1>
|
||||
<p class="mt-2 text-ui text-[var(--color-text-tertiary)]">
|
||||
Isolated VMs you can start, pause, and snapshot on demand.
|
||||
<p class="mt-2 text-ui text-[var(--color-text-secondary)]">
|
||||
Isolated VMs. Start cold in under a second — pause, snapshot, or destroy at will.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@ -329,7 +329,7 @@
|
||||
<span class="relative inline-flex h-[7px] w-[7px] rounded-full bg-[var(--color-accent)]"></span>
|
||||
</span>
|
||||
<span class="font-mono text-body font-semibold text-[var(--color-accent-bright)]">{runningCount}</span>
|
||||
<span class="text-ui text-[var(--color-text-secondary)]">concurrent capsules</span>
|
||||
<span class="text-ui text-[var(--color-text-secondary)]">running now</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -482,18 +482,21 @@
|
||||
</div>
|
||||
{:else if filteredCapsules.length === 0}
|
||||
<div class="flex flex-col items-center justify-center py-[72px]">
|
||||
<div class="mb-5 flex h-14 w-14 items-center justify-center rounded-[var(--radius-card)] border border-[var(--color-border-mid)] bg-[var(--color-bg-3)]">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="var(--color-text-secondary)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect x="2" y="3" width="20" height="14" rx="2" />
|
||||
<line x1="8" y1="21" x2="16" y2="21" />
|
||||
<line x1="12" y1="17" x2="12" y2="21" />
|
||||
</svg>
|
||||
<div class="relative mb-5">
|
||||
<div class="absolute inset-0 -m-4 rounded-full" style="background: radial-gradient(circle, rgba(94,140,88,0.08) 0%, transparent 70%)"></div>
|
||||
<div class="relative flex h-14 w-14 items-center justify-center rounded-[var(--radius-card)] border border-[var(--color-accent)]/20 bg-[var(--color-bg-3)]" style="animation: iconFloat 4s ease-in-out infinite">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="var(--color-accent-mid)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<rect x="2" y="3" width="20" height="14" rx="2" />
|
||||
<line x1="8" y1="21" x2="16" y2="21" />
|
||||
<line x1="12" y1="17" x2="12" y2="21" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<p class="font-serif text-heading tracking-[-0.02em] text-[var(--color-text-bright)]">
|
||||
No capsules yet
|
||||
</p>
|
||||
<p class="mt-1.5 text-ui text-[var(--color-text-tertiary)]">
|
||||
Launch a capsule to start running isolated code.
|
||||
Each capsule is an isolated VM. Launch one to get started.
|
||||
</p>
|
||||
<button
|
||||
onclick={() => { showCreateDialog = true; createError = null; }}
|
||||
@ -694,7 +697,7 @@
|
||||
|
||||
<div class="relative w-full max-w-[420px] rounded-[var(--radius-card)] border border-[var(--color-border-mid)] bg-[var(--color-bg-2)] p-6" style="animation: fadeUp 0.2s ease both">
|
||||
<h2 class="font-serif text-heading tracking-[-0.02em] text-[var(--color-text-bright)]">Launch Capsule</h2>
|
||||
<p class="mt-1 text-ui text-[var(--color-text-tertiary)]">Configure and launch a new isolated capsule.</p>
|
||||
<p class="mt-1 text-ui text-[var(--color-text-tertiary)]">Configure resources and launch. The VM will be ready in under a second.</p>
|
||||
|
||||
{#if createError}
|
||||
<div class="mt-4 rounded-[var(--radius-input)] border border-[var(--color-red)]/30 bg-[var(--color-red)]/5 px-3 py-2 text-meta text-[var(--color-red)]">
|
||||
@ -741,7 +744,7 @@
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="mb-1.5 block text-label font-semibold uppercase tracking-[0.05em] text-[var(--color-text-tertiary)]" for="create-timeout">Auto-pause timeout (seconds, 0 = never)</label>
|
||||
<label class="mb-1.5 block text-label font-semibold uppercase tracking-[0.05em] text-[var(--color-text-tertiary)]" for="create-timeout">Idle timeout (seconds — 0 = never pause)</label>
|
||||
<input
|
||||
id="create-timeout"
|
||||
type="number"
|
||||
@ -792,7 +795,7 @@
|
||||
<div class="relative w-full max-w-[380px] rounded-[var(--radius-card)] border border-[var(--color-border-mid)] bg-[var(--color-bg-2)] p-6" style="animation: fadeUp 0.2s ease both">
|
||||
<h2 class="font-serif text-heading tracking-[-0.02em] text-[var(--color-text-bright)]">Destroy Capsule</h2>
|
||||
<p class="mt-2 text-ui text-[var(--color-text-tertiary)]">
|
||||
Destroy <span class="font-mono text-[var(--color-text-secondary)]">{destroyTarget.id}</span>? The capsule will be terminated and all data inside it lost.
|
||||
Terminate <span class="font-mono text-[var(--color-text-secondary)]">{destroyTarget.id}</span> and destroy all data inside it. This cannot be undone.
|
||||
</p>
|
||||
|
||||
{#if destroyError}
|
||||
|
||||
@ -120,8 +120,8 @@
|
||||
<h1 class="font-serif text-page tracking-[-0.02em] text-[var(--color-text-bright)]">
|
||||
API Keys
|
||||
</h1>
|
||||
<p class="mt-2 text-ui text-[var(--color-text-tertiary)]">
|
||||
Keys authenticate SDK and direct API requests. Treat them like passwords.
|
||||
<p class="mt-2 text-ui text-[var(--color-text-secondary)]">
|
||||
Bearer tokens for the Wrenn API and SDKs. Each key grants full access — guard it like a password.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@ -164,13 +164,16 @@
|
||||
</div>
|
||||
{:else if keys.length === 0}
|
||||
<div class="flex flex-col items-center justify-center py-[72px]">
|
||||
<div class="mb-5 flex h-14 w-14 items-center justify-center rounded-[var(--radius-card)] border border-[var(--color-border-mid)] bg-[var(--color-bg-3)]" style="animation: iconFloat 4s ease-in-out infinite">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="var(--color-text-secondary)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4" />
|
||||
</svg>
|
||||
<div class="relative mb-5">
|
||||
<div class="absolute inset-0 -m-4 rounded-full" style="background: radial-gradient(circle, rgba(94,140,88,0.08) 0%, transparent 70%)"></div>
|
||||
<div class="relative flex h-14 w-14 items-center justify-center rounded-[var(--radius-card)] border border-[var(--color-accent)]/20 bg-[var(--color-bg-3)]" style="animation: iconFloat 4s ease-in-out infinite">
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="var(--color-accent-mid)" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
|
||||
<path d="M21 2l-2 2m-7.61 7.61a5.5 5.5 0 1 1-7.778 7.778 5.5 5.5 0 0 1 7.777-7.777zm0 0L15.5 7.5m0 0l3 3L22 7l-3-3m-3.5 3.5L19 4" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<p class="font-serif text-heading tracking-[-0.02em] text-[var(--color-text-bright)]">No API keys yet</p>
|
||||
<p class="mt-1.5 text-ui text-[var(--color-text-tertiary)]">Create your first key to start making API requests.</p>
|
||||
<p class="mt-1.5 text-ui text-[var(--color-text-tertiary)]">Nothing can call the API without a key. Create one to authenticate your SDK or HTTP requests.</p>
|
||||
<button
|
||||
onclick={() => { showCreate = true; createError = null; createName = ''; }}
|
||||
class="mt-6 flex items-center gap-2 rounded-[var(--radius-button)] bg-[var(--color-accent)] px-5 py-2.5 text-ui font-semibold text-white transition-all duration-150 hover:brightness-115 hover:-translate-y-px active:translate-y-0"
|
||||
@ -201,7 +204,7 @@
|
||||
<!-- Name + prefix -->
|
||||
<div class="min-w-0 flex flex-col gap-1 px-5 py-4">
|
||||
<span class="truncate text-ui font-medium text-[var(--color-text-bright)]">{key.name || '—'}</span>
|
||||
<span class="inline-flex w-fit items-center rounded-sm border border-[var(--color-border-mid)] bg-[var(--color-bg-4)] px-1.5 py-0.5 font-mono text-badge text-[var(--color-text-muted)]">{key.key_prefix}…</span>
|
||||
<span class="inline-flex w-fit items-center rounded-sm border border-[var(--color-border-mid)] bg-[var(--color-bg-4)] px-1.5 py-0.5 font-mono text-badge text-[var(--color-accent-mid)]">{key.key_prefix}…</span>
|
||||
</div>
|
||||
|
||||
<!-- Created by -->
|
||||
@ -261,7 +264,7 @@
|
||||
|
||||
<div class="relative w-full max-w-[420px] rounded-[var(--radius-card)] border border-[var(--color-border-mid)] bg-[var(--color-bg-2)] p-6" style="animation: fadeUp 0.2s ease both">
|
||||
<h2 class="font-serif text-heading tracking-[-0.02em] text-[var(--color-text-bright)]">New API Key</h2>
|
||||
<p class="mt-1 text-ui text-[var(--color-text-tertiary)]">Give your key a name to identify it later.</p>
|
||||
<p class="mt-1 text-ui text-[var(--color-text-tertiary)]">Name it after its environment or purpose — production, staging, CI. You can't rename it later.</p>
|
||||
|
||||
{#if createError}
|
||||
<div class="mt-4 rounded-[var(--radius-input)] border border-[var(--color-red)]/30 bg-[var(--color-red)]/5 px-3 py-2 text-meta text-[var(--color-red)]">
|
||||
@ -375,7 +378,7 @@
|
||||
<line x1="12" y1="9" x2="12" y2="13" /><line x1="12" y1="17" x2="12.01" y2="17" />
|
||||
</svg>
|
||||
<p class="text-meta leading-relaxed text-[var(--color-amber)]">
|
||||
Treat this like a password — store it in a secrets manager, not a document or chat message.
|
||||
This is shown once. Store it in your secrets manager — not a note, not a chat message, not a commit.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
@ -404,8 +407,8 @@
|
||||
<div class="relative w-full max-w-[380px] rounded-[var(--radius-card)] border border-[var(--color-border-mid)] bg-[var(--color-bg-2)] p-6" style="animation: fadeUp 0.2s ease both">
|
||||
<h2 class="font-serif text-heading tracking-[-0.02em] text-[var(--color-text-bright)]">Revoke Key</h2>
|
||||
<p class="mt-2 text-ui text-[var(--color-text-tertiary)]">
|
||||
Revoke <span class="font-medium text-[var(--color-text-secondary)]">{revokeTarget.name || revokeTarget.id}</span>?
|
||||
Any request using it will stop working immediately.
|
||||
Permanently revoke <span class="font-medium text-[var(--color-text-secondary)]">{revokeTarget.name || revokeTarget.id}</span>.
|
||||
Any request using this key will fail immediately.
|
||||
</p>
|
||||
<span class="mt-2 inline-flex items-center rounded-sm border border-[var(--color-border-mid)] bg-[var(--color-bg-4)] px-1.5 py-0.5 font-mono text-badge text-[var(--color-text-muted)]">{revokeTarget.key_prefix}…</span>
|
||||
|
||||
|
||||
@ -120,9 +120,9 @@
|
||||
}
|
||||
|
||||
function emptyDescription(f: TypeFilter): string {
|
||||
if (f === 'snapshot') return 'Capture a running capsule to create a snapshot.';
|
||||
if (f === 'base') return 'Images appear here once added to your account.';
|
||||
return 'Snapshots are created from the Capsules page. Pause or snapshot a running capsule to get started.';
|
||||
if (f === 'snapshot') return 'Pause a capsule from the Capsules page, then snapshot it to capture its state.';
|
||||
if (f === 'base') return 'Base images are added by the Wrenn team. Contact support to request a custom image.';
|
||||
return 'To create a snapshot, go to Capsules, pause a running capsule, then choose Snapshot.';
|
||||
}
|
||||
|
||||
onMount(fetchSnapshots);
|
||||
@ -161,8 +161,8 @@
|
||||
<h1 class="font-serif text-page tracking-[-0.02em] text-[var(--color-text-bright)]">
|
||||
Templates
|
||||
</h1>
|
||||
<p class="mt-2 text-ui text-[var(--color-text-tertiary)]">
|
||||
Saved capsule states and base images. Launch a new capsule from any template.
|
||||
<p class="mt-2 text-ui text-[var(--color-text-secondary)]">
|
||||
Snapshots capture a live capsule state. Base images are the rootfs every capsule starts from. Launch a full VM from any template.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@ -490,8 +490,8 @@
|
||||
>
|
||||
<h2 class="font-serif text-heading tracking-[-0.02em] text-[var(--color-text-bright)]">Delete Snapshot</h2>
|
||||
<p class="mt-2 text-ui text-[var(--color-text-tertiary)]">
|
||||
Delete <span class="font-mono font-medium text-[var(--color-text-secondary)]">{deleteTarget.name}</span>?
|
||||
This action cannot be undone.
|
||||
Permanently delete <span class="font-mono font-medium text-[var(--color-text-secondary)]">{deleteTarget.name}</span>.
|
||||
Any capsule using this template will not be affected, but you won't be able to launch from it again.
|
||||
</p>
|
||||
|
||||
{#if deleteTarget.type === 'snapshot'}
|
||||
@ -555,7 +555,7 @@
|
||||
>
|
||||
<h2 class="font-serif text-heading tracking-[-0.02em] text-[var(--color-text-bright)]">Launch Capsule</h2>
|
||||
<p class="mt-1 text-ui text-[var(--color-text-tertiary)]">
|
||||
Start a new capsule from this template.
|
||||
Configure resources and launch. The VM will clone from this template and be ready in seconds.
|
||||
</p>
|
||||
|
||||
{#if launchError}
|
||||
|
||||
@ -334,8 +334,8 @@
|
||||
<h1 class="font-serif text-page tracking-[-0.02em] text-[var(--color-text-bright)]">
|
||||
Team
|
||||
</h1>
|
||||
<p class="mt-2 text-ui text-[var(--color-text-tertiary)]">
|
||||
Manage your team, its members, and account settings.
|
||||
<p class="mt-2 text-ui text-[var(--color-text-secondary)]">
|
||||
Members, roles, and workspace configuration for your team.
|
||||
</p>
|
||||
<div class="mt-6 border-b border-[var(--color-border)]"></div>
|
||||
</div>
|
||||
@ -715,7 +715,7 @@
|
||||
>{member.name || member.email}</span
|
||||
>
|
||||
{#if member.user_id === auth.userId}
|
||||
<span class="shrink-0 rounded-[2px] bg-[var(--color-bg-4)] px-1.5 py-0.5 text-badge font-semibold uppercase tracking-[0.05em] text-[var(--color-text-muted)]">you</span>
|
||||
<span class="shrink-0 rounded-[2px] bg-[var(--color-accent-glow-mid)] px-1.5 py-0.5 text-badge font-semibold uppercase tracking-[0.05em] text-[var(--color-accent-mid)]">you</span>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
@ -745,7 +745,7 @@
|
||||
{member.role === 'owner'
|
||||
? 'bg-[var(--color-accent-glow-mid)] text-[var(--color-accent-mid)]'
|
||||
: member.role === 'admin'
|
||||
? 'bg-[var(--color-bg-5)] text-[var(--color-text-secondary)]'
|
||||
? 'bg-[var(--color-amber)]/8 text-[var(--color-amber)]'
|
||||
: 'bg-[var(--color-bg-4)] text-[var(--color-text-muted)]'}"
|
||||
>
|
||||
{roleLabel(member.role)}
|
||||
@ -840,7 +840,7 @@
|
||||
Delete this team
|
||||
</p>
|
||||
<p class="mt-0.5 text-meta text-[var(--color-text-tertiary)]">
|
||||
{#if isLastTeam}Create another team before deleting this one.{:else}Permanently deletes the team and destroys all running capsules. This cannot be undone.{/if}
|
||||
{#if isLastTeam}Create another team first — you can't delete your only team.{:else}Permanently deletes the team and destroys all running capsules. This cannot be undone.{/if}
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
@ -856,7 +856,7 @@
|
||||
Leave this team
|
||||
</p>
|
||||
<p class="mt-0.5 text-meta text-[var(--color-text-tertiary)]">
|
||||
{#if isLastTeam}Create another team before leaving this one.{:else}You will lose access to all capsules and resources belonging to this team.{/if}
|
||||
{#if isLastTeam}Create another team first — you can't leave your only team.{:else}You'll immediately lose access to all capsules and resources in this team.{/if}
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
@ -964,7 +964,7 @@
|
||||
Add Member
|
||||
</h2>
|
||||
<p class="mt-1 text-ui text-[var(--color-text-tertiary)]">
|
||||
Add an existing Wrenn user to your team by email.
|
||||
Search by email. The user must already have a Wrenn account.
|
||||
</p>
|
||||
|
||||
{#if addError}
|
||||
@ -1101,9 +1101,9 @@
|
||||
Remove Member
|
||||
</h2>
|
||||
<p class="mt-2 text-ui text-[var(--color-text-tertiary)]">
|
||||
Remove <span class="font-medium text-[var(--color-text-secondary)]"
|
||||
<span class="font-medium text-[var(--color-text-secondary)]"
|
||||
>{removeTarget.name || removeTarget.email}</span
|
||||
> from the team? They will lose access immediately.
|
||||
> will immediately lose access to all team capsules and resources.
|
||||
</p>
|
||||
|
||||
{#if removeError}
|
||||
@ -1187,7 +1187,7 @@
|
||||
Leave Team
|
||||
</h2>
|
||||
<p class="mt-2 text-ui text-[var(--color-text-tertiary)]">
|
||||
You will lose access to all capsules and resources in <span
|
||||
You'll immediately lose access to all capsules and resources in <span
|
||||
class="font-medium text-[var(--color-text-secondary)]">{team?.name}</span
|
||||
>.
|
||||
</p>
|
||||
|
||||
@ -145,7 +145,7 @@
|
||||
<h1
|
||||
class="font-serif text-[5rem] leading-[1.1] tracking-[-0.04em] text-[var(--color-text-bright)]"
|
||||
>
|
||||
Scale Up.<br />Spin Out.
|
||||
Scale Up.<br /><span class="text-[var(--color-accent-bright)]">Spin Out.</span>
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
@ -154,7 +154,7 @@
|
||||
class="relative z-10 mt-12 font-mono text-ui uppercase tracking-[0.08em] text-[var(--color-text-tertiary)]"
|
||||
style="animation: fadeUp 0.35s ease 0.2s both"
|
||||
>
|
||||
Run Anything. Worry about Nothing.
|
||||
Isolated VMs. Milliseconds to live.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user