Skip to content

Commit 5a5a50f

Browse files
committed
polish(web): phone notch removed, bud input glow, bud-style loading mark
- device-frame: drop the black notch pill from the phone bezel. - personalization inputs: add bud's exact focus effect — a group + inner bg-gradient-to-b from-[#f7f7f7] layer with group-focus-within:shadow-[inset_0_0_40px_0_oklch(0.93_0.06_70/0.4)] (the warm amber inset glow bud shows on input focus), on both the name field + memory textarea. - loading: booting-computer + the 'Opening Files' IdePlaceholder now render the Cheatcode mark with a gentle cc-breathe animation (scale+opacity) instead of animate-pulse / a lone dot — matches bud's booting logo feel.
1 parent fb88b7c commit 5a5a50f

5 files changed

Lines changed: 62 additions & 34 deletions

File tree

apps/web/src/app/globals.css

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,29 @@
3232

3333
@custom-variant dark (&:where(.dark, .dark *));
3434

35+
/* bud-style loading breathe for the Cheatcode mark (booting sandbox / opening files) */
36+
@keyframes cc-breathe {
37+
0%,
38+
100% {
39+
transform: scale(0.92);
40+
opacity: 0.35;
41+
}
42+
50% {
43+
transform: scale(1);
44+
opacity: 0.72;
45+
}
46+
}
47+
.cc-loading-mark {
48+
animation: cc-breathe 1.8s cubic-bezier(0.4, 0, 0.2, 1) infinite;
49+
will-change: transform, opacity;
50+
}
51+
@media (prefers-reduced-motion: reduce) {
52+
.cc-loading-mark {
53+
animation: none;
54+
opacity: 0.5;
55+
}
56+
}
57+
3558
.cheatcode-workspace-frame {
3659
padding-top: 8px;
3760
padding-right: 8px;

apps/web/src/components/preview/booting-computer.tsx

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,13 @@ export function BootingComputer({ label = "Booting computer" }: { label?: string
1313
className="grid h-full min-h-[420px] place-items-center rounded-[16px] border border-[#f1f1f1] bg-[#fafafa]"
1414
>
1515
<div className="flex flex-col items-center gap-4 text-center">
16-
<span className="opacity-40">
17-
<Image
18-
alt=""
19-
className="h-14 w-14 animate-pulse"
20-
height={56}
21-
src="/cheatcode-symbol.png"
22-
width={56}
23-
/>
24-
</span>
16+
<Image
17+
alt=""
18+
className="cc-loading-mark h-14 w-14"
19+
height={56}
20+
src="/cheatcode-symbol.png"
21+
width={56}
22+
/>
2523
<span className="text-[13px] text-thread-text-muted">{label}</span>
2624
</div>
2725
</div>

apps/web/src/components/preview/device-frame.tsx

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,6 @@ export function DeviceFrame({ children, device }: { children: ReactNode; device:
3232
// CSS (container-query units): width fills the panel height, clamped to its width.
3333
style={{ aspectRatio: "390 / 844", width: "min(100cqw, calc(100cqh * 390 / 844))" }}
3434
>
35-
<div
36-
aria-hidden
37-
className="pointer-events-none absolute top-[9px] left-1/2 z-10 h-[24px] w-[86px] -translate-x-1/2 rounded-full bg-[#1b1b1b]"
38-
/>
3935
{children}
4036
</div>
4137
) : (

apps/web/src/components/preview/sandbox-ide-tab.tsx

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import { useAuth } from "@clerk/nextjs";
44
import { useQuery } from "@tanstack/react-query";
5+
import Image from "next/image";
56
import { useEffect, useRef, useState } from "react";
67
import { BudTooltip } from "@/components/ui/bud-tooltip";
78
import { PanelLeftOpen } from "@/components/ui/icons";
@@ -130,9 +131,15 @@ export function SandboxIdeTab({
130131
function IdePlaceholder({ label }: { label: string }) {
131132
return (
132133
<div className="grid h-full min-h-[420px] place-items-center bg-[#fafafa]">
133-
<div className="text-center">
134-
<div className="mx-auto mb-4 h-2 w-2 rounded-full bg-thread-status-warning" />
135-
<div className="text-[12px] text-thread-text-muted">{label}</div>
134+
<div className="flex flex-col items-center gap-4 text-center">
135+
<Image
136+
alt=""
137+
className="cc-loading-mark h-12 w-12"
138+
height={48}
139+
src="/cheatcode-symbol.png"
140+
width={48}
141+
/>
142+
<div className="text-[13px] text-thread-text-muted">{label}</div>
136143
</div>
137144
</div>
138145
);

apps/web/src/components/settings/personalization-panel.tsx

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,16 @@ function PersonalizationForm({ profile }: { profile: UserProfile }) {
6161
<div className="w-full space-y-7">
6262
<section className="rounded-[24px] bg-[#f7f7f7] p-5">
6363
<FieldLabel helper="Cheatcode will answer to this name." label="Your Cheatcode's Name" />
64-
<div className="mt-5 rounded-[20px] bg-white p-px">
65-
<input
66-
className="h-12 w-full bg-transparent px-4 font-medium text-[#1b1b1b] text-[14px] outline-none placeholder:text-[#6f7782]"
67-
maxLength={80}
68-
onChange={(event) => update("name", event.target.value)}
69-
placeholder="Give your Cheatcode a name"
70-
value={form.name}
71-
/>
64+
<div className="group mt-5 rounded-[20px] bg-white p-px">
65+
<div className="rounded-[19px] bg-gradient-to-b from-[#f7f7f7] to-transparent transition-[box-shadow] duration-200 group-focus-within:shadow-[inset_0_0_40px_0_oklch(0.93_0.06_70_/_0.4)]">
66+
<input
67+
className="h-12 w-full bg-transparent px-4 font-medium text-[#1b1b1b] text-[14px] outline-none placeholder:text-[#6f7782]"
68+
maxLength={80}
69+
onChange={(event) => update("name", event.target.value)}
70+
placeholder="Give your Cheatcode a name"
71+
value={form.name}
72+
/>
73+
</div>
7274
</div>
7375
</section>
7476

@@ -77,16 +79,18 @@ function PersonalizationForm({ profile }: { profile: UserProfile }) {
7779
helper="Preferences and instructions for Cheatcode. No need to set the name here — that's handled above."
7880
label="Memory"
7981
/>
80-
<div className="mt-5 rounded-[20px] bg-white p-px">
81-
<textarea
82-
className="min-h-[200px] w-full resize-none bg-transparent px-4 py-3 font-medium text-[#1b1b1b] text-[14px] leading-5 outline-none placeholder:text-[#6f7782]"
83-
maxLength={MEMORY_MAX}
84-
onChange={(event) => update("memory", event.target.value)}
85-
placeholder={
86-
'Preferences and instructions — e.g. "I prefer short bullet points", "Always cite sources"...'
87-
}
88-
value={form.memory}
89-
/>
82+
<div className="group mt-5 rounded-[20px] bg-white p-px">
83+
<div className="rounded-[19px] bg-gradient-to-b from-[#f7f7f7] to-transparent transition-[box-shadow] duration-200 group-focus-within:shadow-[inset_0_0_40px_0_oklch(0.93_0.06_70_/_0.4)]">
84+
<textarea
85+
className="min-h-[200px] w-full resize-none bg-transparent px-4 py-3 font-medium text-[#1b1b1b] text-[14px] leading-5 outline-none placeholder:text-[#6f7782]"
86+
maxLength={MEMORY_MAX}
87+
onChange={(event) => update("memory", event.target.value)}
88+
placeholder={
89+
'Preferences and instructions — e.g. "I prefer short bullet points", "Always cite sources"...'
90+
}
91+
value={form.memory}
92+
/>
93+
</div>
9094
</div>
9195
</section>
9296

0 commit comments

Comments
 (0)