Skip to content
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
24 changes: 14 additions & 10 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@
--chart-3: 197 37% 24%;
--chart-4: 43 74% 66%;
--chart-5: 27 87% 67%;
--color-1: 0 100% 63%;
--color-2: 270 100% 63%;
--color-3: 210 100% 63%;
--color-4: 195 100% 63%;
--color-5: 90 100% 63%;
/* Apple retro colors (1977-1999 logo) */
--color-1: 107 48% 50%; /* green #61bb46 */
--color-2: 42 98% 57%; /* yellow #fdb827 */
--color-3: 28 91% 54%; /* orange #f5821f */
--color-4: 358 73% 55%; /* red #e03a3e */
--color-5: 300 42% 41%; /* purple #963d97 */
--color-6: 197 100% 43%; /* blue #009ddc */
}

.dark {
Expand Down Expand Up @@ -61,11 +63,13 @@
--chart-3: 30 80% 55%;
--chart-4: 280 65% 60%;
--chart-5: 340 75% 55%;
--color-1: 180 100% 63%;
--color-2: 270 100% 63%;
--color-3: 210 100% 63%;
--color-4: 195 100% 63%;
--color-5: 90 100% 63%;
/* Apple retro colors (1977-1999 logo) */
--color-1: 107 48% 50%; /* green #61bb46 */
--color-2: 42 98% 57%; /* yellow #fdb827 */
--color-3: 28 91% 54%; /* orange #f5821f */
--color-4: 358 73% 55%; /* red #e03a3e */
--color-5: 300 42% 41%; /* purple #963d97 */
--color-6: 197 100% 43%; /* blue #009ddc */
}

* {
Expand Down
2 changes: 1 addition & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export default function RootLayout({
children: React.ReactNode;
}>) {
return (
<html lang="en" className="dark">
<html lang="en">
<body className={`${jetbrainsMono.variable} font-mono antialiased`}>
<ErrorBoundary>
<MobileBlock>{children}</MobileBlock>
Expand Down
4 changes: 2 additions & 2 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { DotPattern } from "@/components/ui/dot-pattern";

export default function Home() {
return (
<div className="relative min-h-screen bg-neutral-950 overflow-hidden">
<DotPattern className="text-neutral-700/50" width={24} height={24} cr={1.5} glow />
<div className="relative min-h-screen bg-stone-100 overflow-hidden">
<DotPattern width={32} height={32} glow />
<div className="relative z-10">
<AppPreviewContainer />
</div>
Expand Down
19 changes: 17 additions & 2 deletions src/components/app-preview-container.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,16 @@ import { UploadButtonProvider } from "@/components/providers/upload-button-provi
import VideoConvertFlow from "@/components/video-convert/VideoConvertFlow";
import { Confetti, type ConfettiRef } from "./ui/confetti";

// Apple retro rainbow colors (1977-1999 logo)
const APPLE_CONFETTI_COLORS = [
"#61bb46", // green
"#fdb827", // yellow
"#f5821f", // orange
"#e03a3e", // red
"#963d97", // purple
"#009ddc", // blue
];

export default function AppPreviewContainer() {
const confettiRef = useRef<ConfettiRef>(null);
const [isMounted, setIsMounted] = useState(false);
Expand All @@ -14,15 +24,20 @@ export default function AppPreviewContainer() {
}, []);

const handleConversionComplete = () => {
confettiRef.current?.fire();
confettiRef.current?.fire({
colors: APPLE_CONFETTI_COLORS,
particleCount: 100,
spread: 70,
origin: { y: 0.6 },
});
};

if (!isMounted) {
return (
<UploadButtonProvider>
<div className="flex justify-center items-center min-h-screen">
<div className="max-w-3xl w-full mx-auto px-4 py-24">
<div className="animate-pulse bg-neutral-900 h-96 rounded-xl"></div>
<div className="animate-pulse bg-stone-200 h-96 rounded-xl"></div>
</div>
</div>
</UploadButtonProvider>
Expand Down
12 changes: 5 additions & 7 deletions src/components/terminal-buttons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { AnimatedUploadButton } from "@/components/ui/animated-upload-button";
import { BMCButton } from "@/components/ui/bmc-button";
import { Button } from "@/components/ui/button";
import { RainbowButton } from "@/components/ui/rainbow-button";
import { cn } from "@/lib/utils";
import type { Button as ButtonType } from "@/types/terminal";

interface TerminalButtonsProps {
Expand Down Expand Up @@ -75,15 +74,14 @@ export function TerminalButtons({
);
}

// Use variant from button config, fallback to outline for restart, default otherwise
const variant = button.variant ?? (button.action === "restart" ? "outline" : "default");

return (
<Button
key={button.action}
variant={button.action === "restart" ? "outline" : "default"}
className={cn(
"w-fit",
button.action === "restart" &&
"border-neutral-700 text-neutral-300 hover:bg-neutral-800 hover:text-neutral-100",
)}
variant={variant}
className="w-fit"
onClick={() => onButtonClick(button)}
>
{button.text}
Expand Down
8 changes: 4 additions & 4 deletions src/components/terminal-content.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,10 @@ export default function TerminalContent({

const textClassName = cn(
"break-words w-full",
message.type === "prompt" && "text-cyan-400",
message.type === "info" && "text-neutral-400",
message.type === "success" && "text-emerald-400",
message.type === "error" && "text-red-400",
message.type === "prompt" && "text-cyan-600",
message.type === "info" && "text-stone-500",
message.type === "success" && "text-emerald-600",
message.type === "error" && "text-red-600",
);

// Live messages render instantly and update in real-time
Expand Down
6 changes: 3 additions & 3 deletions src/components/ui/animated-upload-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export const AnimatedUploadButton = React.forwardRef<HTMLButtonElement, Animated
<motion.button
ref={ref}
className={cn(
"relative flex h-10 w-fit items-center justify-center overflow-hidden rounded-lg bg-primary px-6 text-primary-foreground",
"relative flex h-10 w-fit items-center justify-center overflow-hidden rounded-lg bg-[#61bb46] px-6 text-white",
className,
)}
onClick={handleClick}
Expand All @@ -52,7 +52,7 @@ export const AnimatedUploadButton = React.forwardRef<HTMLButtonElement, Animated
<motion.button
ref={ref}
className={cn(
"relative flex h-10 w-fit cursor-wait items-center justify-center rounded-lg border-none bg-primary/80 px-6 text-primary-foreground",
"relative flex h-10 w-fit cursor-wait items-center justify-center rounded-lg border-none bg-[#61bb46]/80 px-6 text-white",
className,
)}
onClick={handleClick}
Expand All @@ -76,7 +76,7 @@ export const AnimatedUploadButton = React.forwardRef<HTMLButtonElement, Animated
<motion.button
ref={ref}
className={cn(
"relative flex h-10 w-fit cursor-pointer items-center justify-center rounded-lg border-none bg-primary px-6 text-primary-foreground",
"relative flex h-10 w-fit cursor-pointer items-center justify-center rounded-lg border-none bg-[#61bb46] hover:bg-[#4fa336] px-6 text-white transition-colors",
className,
)}
onClick={handleClick}
Expand Down
17 changes: 12 additions & 5 deletions src/components/ui/button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,20 @@ const buttonVariants = cva(
{
variants: {
variant: {
default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
default: "bg-[#61bb46] text-white shadow hover:bg-[#4fa336]",
destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
outline:
"border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
ghost: "hover:bg-accent hover:text-accent-foreground",
link: "text-primary underline-offset-4 hover:underline",
"border border-stone-300 bg-white text-stone-700 shadow-sm hover:bg-stone-50 hover:text-stone-900",
secondary: "bg-stone-100 text-stone-800 shadow-sm hover:bg-stone-200",
ghost: "hover:bg-stone-100 hover:text-stone-900",
link: "text-[#009ddc] underline-offset-4 hover:underline",
// Apple retro color variants
"apple-blue": "bg-[#009ddc] text-white shadow hover:bg-[#0087c1]",
"apple-purple": "bg-[#963d97] text-white shadow hover:bg-[#7a3279]",
"apple-orange": "bg-[#f5821f] text-white shadow hover:bg-[#dd7119]",
"apple-red": "bg-[#e03a3e] text-white shadow hover:bg-[#c4282c]",
"apple-yellow": "bg-[#fdb827] text-stone-900 shadow hover:bg-[#e5a520]",
"apple-green": "bg-[#61bb46] text-white shadow hover:bg-[#4fa336]",
},
size: {
default: "h-9 px-4 py-2",
Expand Down
2 changes: 1 addition & 1 deletion src/components/ui/ciderpress-logo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export function CiderpressLogo({ size = "md", className, showText = false }: Cid

{/* Wordmark */}
{showText && (
<span className={cn("font-mono font-bold tracking-tight text-white", text)}>
<span className={cn("font-mono font-bold tracking-tight text-stone-800", text)}>
Ciderpress
</span>
)}
Expand Down
81 changes: 42 additions & 39 deletions src/components/ui/dot-pattern.tsx
Original file line number Diff line number Diff line change
@@ -1,59 +1,62 @@
"use client";

import type React from "react";
import { useId } from "react";
import { Apple } from "lucide-react";
import { cn } from "@/lib/utils";

interface DotPatternProps extends React.SVGProps<SVGSVGElement> {
const APPLE_COLORS = [
"#61bb46", // green
"#fdb827", // yellow
"#f5821f", // orange
"#e03a3e", // red
"#963d97", // purple
"#009ddc", // blue
];

interface DotPatternProps {
width?: number;
height?: number;
x?: number;
y?: number;
cx?: number;
cy?: number;
cr?: number;
className?: string;
glow?: boolean;
}

export function DotPattern({
width = 16,
height = 16,
x = 0,
y = 0,
cx = 1,
cy = 1,
cr = 1,
className,
glow = false,
...props
}: DotPatternProps) {
const id = useId();
export function DotPattern({ width = 48, height = 48, className, glow = false }: DotPatternProps) {
// Calculate grid dimensions based on a reasonable viewport
const cols = Math.ceil(1920 / width);
const rows = Math.ceil(1080 / height);

// Create a grid of apples with deterministic colors
const apples = [];
for (let row = 0; row < rows; row++) {
for (let col = 0; col < cols; col++) {
// Deterministic "random" color based on position
const colorIndex = (col * 7 + row * 13) % APPLE_COLORS.length;
const color = APPLE_COLORS[colorIndex];

apples.push(
<div
key={`${row}-${col}`}
className="absolute"
style={{
left: col * width + width / 2 - 6,
top: row * height + height / 2 - 6,
}}
>
<Apple size={12} color={color} strokeWidth={1.5} style={{ opacity: 0.35 }} />
</div>,
);
}
}

return (
<svg
<div
aria-hidden="true"
className={cn(
"pointer-events-none absolute inset-0 h-full w-full text-neutral-400/80",
"pointer-events-none absolute inset-0 overflow-hidden",
glow && "animate-dot-glow",
className,
)}
{...props}
>
<defs>
<pattern
id={`${id}-pattern`}
width={width}
height={height}
patternUnits="userSpaceOnUse"
patternContentUnits="userSpaceOnUse"
x={x}
y={y}
>
<circle cx={cx} cy={cy} r={cr} fill="currentColor" />
</pattern>
</defs>
<rect width="100%" height="100%" fill={`url(#${id}-pattern)`} strokeWidth={0} />
</svg>
{apples}
</div>
);
}
10 changes: 4 additions & 6 deletions src/components/ui/rainbow-button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,10 @@ export const RainbowButton = ({ className, children, ...props }: RainbowButtonPr
<button
className={cn(
"group relative inline-flex h-9 animate-rainbow cursor-pointer items-center justify-center rounded-xl border-0 bg-[length:200%] px-8 py-2 font-medium text-primary-foreground transition-colors [background-clip:padding-box,border-box,border-box] [background-origin:border-box] [border:calc(0.08*1rem)_solid_transparent] focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
// before styles
"before:absolute before:bottom-[-20%] before:left-1/2 before:z-0 before:h-1/5 before:w-3/5 before:-translate-x-1/2 before:animate-rainbow before:bg-[linear-gradient(90deg,hsl(var(--color-1)),hsl(var(--color-5)),hsl(var(--color-3)),hsl(var(--color-4)),hsl(var(--color-2)))] before:[filter:blur(calc(0.8*1rem))]",
// light mode colors
"bg-[linear-gradient(#121213,#121213),linear-gradient(#121213_50%,rgba(18,18,19,0.6)_80%,rgba(18,18,19,0)),linear-gradient(90deg,hsl(var(--color-1)),hsl(var(--color-5)),hsl(var(--color-3)),hsl(var(--color-4)),hsl(var(--color-2)))]",
// dark mode colors
"dark:bg-[linear-gradient(#fff,#fff),linear-gradient(#fff_50%,rgba(255,255,255,0.6)_80%,rgba(0,0,0,0)),linear-gradient(90deg,hsl(var(--color-1)),hsl(var(--color-5)),hsl(var(--color-3)),hsl(var(--color-4)),hsl(var(--color-2)))]",
// before styles - Apple 6-color gradient glow
"before:absolute before:bottom-[-20%] before:left-1/2 before:z-0 before:h-1/5 before:w-3/5 before:-translate-x-1/2 before:animate-rainbow before:bg-[linear-gradient(90deg,hsl(var(--color-1)),hsl(var(--color-2)),hsl(var(--color-3)),hsl(var(--color-4)),hsl(var(--color-5)),hsl(var(--color-6)))] before:[filter:blur(calc(0.8*1rem))]",
// light mode colors - Apple 6-color rainbow
"bg-[linear-gradient(#1c1c1e,#1c1c1e),linear-gradient(#1c1c1e_50%,rgba(28,28,30,0.6)_80%,rgba(28,28,30,0)),linear-gradient(90deg,hsl(var(--color-1)),hsl(var(--color-2)),hsl(var(--color-3)),hsl(var(--color-4)),hsl(var(--color-5)),hsl(var(--color-6)))]",
className,
)}
{...props}
Expand Down
24 changes: 10 additions & 14 deletions src/components/ui/terminal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -134,16 +134,16 @@ export const TypingAnimation = ({
"text-sm font-mono tracking-tight cursor-pointer",
className,
"break-words w-full",
messageType === "prompt" && "text-cyan-400",
messageType === "info" && "text-neutral-400",
messageType === "success" && "text-emerald-400",
messageType === "error" && "text-red-400",
messageType === "prompt" && "text-cyan-600",
messageType === "info" && "text-stone-500",
messageType === "success" && "text-emerald-600",
messageType === "error" && "text-red-600",
)}
>
<span ref={textRef}></span>
<span
ref={cursorRef}
className="animate-pulse text-neutral-500"
className="animate-pulse text-stone-400"
style={{ display: started && !completed ? "inline" : "none" }}
>
Expand Down Expand Up @@ -226,20 +226,20 @@ export const Terminal = ({ children, className, title }: TerminalProps) => {
return (
<div
className={cn(
"relative isolate z-0 h-[75vh] w-full rounded-xl border border-neutral-800 bg-neutral-950 shadow-2xl flex flex-col",
"relative isolate z-0 h-[75vh] w-full rounded-xl border border-stone-300 bg-white shadow-2xl flex flex-col",
className,
)}
>
{/* Fixed Header */}
<div className="flex-none border-b border-neutral-800 p-4">
<div className="flex-none border-b border-stone-200 p-4 bg-stone-50">
<div className="relative flex flex-row items-center justify-center">
<div className="absolute left-0 flex gap-x-2">
<div className="h-3 w-3 rounded-full bg-red-500/80 hover:bg-red-500 transition-colors"></div>
<div className="h-3 w-3 rounded-full bg-yellow-500/80 hover:bg-yellow-500 transition-colors"></div>
<div className="h-3 w-3 rounded-full bg-green-500/80 hover:bg-green-500 transition-colors"></div>
</div>
{title ? (
<div className="text-sm font-mono text-neutral-300 tracking-tight">{title}</div>
<div className="text-sm font-mono text-stone-600 tracking-tight">{title}</div>
) : (
<CiderpressLogo size="sm" showText />
)}
Expand All @@ -255,16 +255,12 @@ export const Terminal = ({ children, className, title }: TerminalProps) => {
</pre>
</div>

<BorderBeam
duration={6}
size={400}
className="from-transparent via-cyan-500/50 to-transparent"
/>
<BorderBeam duration={6} size={400} className="from-[#61bb46] via-[#fdb827] to-[#f5821f]" />
<BorderBeam
duration={6}
delay={3}
size={400}
className="from-transparent via-purple-500/50 to-transparent"
className="from-[#e03a3e] via-[#963d97] to-[#009ddc]"
/>
</div>
);
Expand Down
Loading