hello world

Terminal-style greeting with a blinking cursor. Hover to resolve the command.

  • react
  • hooks
  • interaction

preview

hello
Hello, World!

source · HelloWorld.tsx

import { useState, useEffect } from 'react';

/**
 * Hello World snippet — a minimal macOS-style terminal card.
 *
 * At rest: renders `❯ hello` followed by `Hello, World!` with a blinking
 * block cursor. The cursor is driven by a JS interval (not CSS @keyframes)
 * so the blink phase stays coherent across browsers without a global rule.
 *
 * On hover: text transitions to emerald green and a ✓ replaces the cursor,
 * simulating a resolved shell command.
 *
 * Controlled mode (Remotion): when `hovered` or `cursorOn` props are provided
 * they take precedence over internal mouse/interval state. This makes the
 * component usable as a thin-wrapper inside Remotion compositions without any
 * Tailwind dependency — all styles are inline.
 */

type Props = {
    /** When defined, overrides internal mouse-enter/leave state. */
    hovered?: boolean;
    /** When defined, overrides internal interval-driven cursor blink state. */
    cursorOn?: boolean;
    /**
     * When defined, overrides the computed output text colour entirely.
     * Used by Remotion to pass a frame-interpolated RGB string so the zinc→emerald
     * transition is driven by `interpolate()` rather than CSS `transition` (which
     * has no effect in Remotion's headless renderer — each frame is fresh).
     */
    textColor?: string;
    /**
     * 0–1 opacity for the ✓ success indicator. Lets Remotion fade it in smoothly
     * instead of popping in when `hovered` flips.
     */
    checkOpacity?: number;
};

export default function HelloWorld({ hovered: hoveredProp, cursorOn: cursorOnProp, textColor, checkOpacity }: Props) {
    const isControlled = hoveredProp !== undefined;

    const [hoveredInternal, setHoveredInternal] = useState(false);
    const [cursorOnInternal, setCursorOnInternal] = useState(true);

    const hovered = hoveredProp ?? hoveredInternal;
    const cursorOn = cursorOnProp ?? cursorOnInternal;

    // Drive cursor blink only when idle (not hovered) and not externally controlled.
    // Cleanup on hover so the cursor doesn't flash between on/off during transition.
    useEffect(() => {
        if (isControlled) return;
        if (hovered) return;
        const id = setInterval(() => setCursorOnInternal((v) => !v), 530);
        return () => clearInterval(id);
    }, [hovered, isControlled]);

    return (
        <div
            style={{
                width: '100%',
                display: 'flex',
                alignItems: 'center',
                justifyContent: 'center',
                padding: 20,
                userSelect: 'none',
                touchAction: 'manipulation',
                fontFamily: '"Geist Mono", "JetBrains Mono", "SF Mono", "Fira Code", monospace',
            }}
            onMouseEnter={isControlled ? undefined : () => setHoveredInternal(true)}
            onMouseLeave={isControlled ? undefined : () => setHoveredInternal(false)}
        >
            {/* Terminal card */}
            <div
                style={{
                    width: '100%',
                    maxWidth: 220,
                    borderRadius: 10,
                    overflow: 'hidden',
                    boxShadow: '0 25px 50px -12px rgba(0,0,0,0.8)',
                    outline: '1px solid rgba(255,255,255,0.06)',
                }}
            >
                {/* Window chrome — purely decorative, hidden from a11y tree */}
                <div
                    aria-hidden="true"
                    style={{
                        background: '#27272a',
                        padding: '8px 12px',
                        display: 'flex',
                        gap: 6,
                        alignItems: 'center',
                    }}
                >
                    <span style={{ width: 10, height: 10, borderRadius: '50%', background: 'rgba(239,68,68,0.8)', display: 'inline-block' }} />
                    <span style={{ width: 10, height: 10, borderRadius: '50%', background: 'rgba(234,179,8,0.8)', display: 'inline-block' }} />
                    <span style={{ width: 10, height: 10, borderRadius: '50%', background: 'rgba(34,197,94,0.8)', display: 'inline-block' }} />
                </div>

                {/* Terminal body */}
                <div
                    style={{
                        background: '#09090b',
                        padding: '14px 16px',
                        fontSize: 11,
                        lineHeight: 1.6,
                        minHeight: 68,
                    }}
                >
                    {/* Input line */}
                    <div style={{ display: 'flex', gap: 4, marginBottom: 6, alignItems: 'center' }}>
                        <span style={{ color: '#34d399' }}></span>
                        <span style={{ color: '#52525b' }}>hello</span>
                    </div>

                    {/* Output line + cursor / checkmark */}
                    <div style={{ display: 'flex', alignItems: 'center' }} aria-live="polite" aria-atomic="true">
                        <span
                            style={{
                                // textColor prop bypasses internal logic for Remotion (frame-interpolated).
                                // In the browser, fall back to the hovered boolean.
                                color: textColor ?? (hovered ? 'rgb(134, 239, 172)' : 'rgb(228, 228, 231)'),
                                transition: textColor ? 'none' : 'color 200ms',
                            }}
                        >
                            Hello, World!
                        </span>

                        {/* Block cursor: opacity-toggled so no layout shift */}
                        {!hovered && (
                            <span
                                aria-hidden="true"
                                style={{
                                    display: 'inline-block',
                                    width: 7,
                                    height: 10,
                                    marginLeft: 3,
                                    background: '#a1a1aa',
                                    verticalAlign: 'middle',
                                    opacity: cursorOn ? 1 : 0,
                                    transition: 'opacity 60ms',
                                }}
                            />
                        )}

                        {/* Success indicator — checkOpacity drives a smooth Remotion fade-in;
                            in the browser it simply appears/disappears with hovered. */}
                        {hovered && (
                            <span
                                aria-hidden="true"
                                style={{
                                    marginLeft: 6,
                                    color: '#34d399',
                                    opacity: checkOpacity ?? 1,
                                }}
                            >

                            </span>
                        )}
                    </div>
                </div>
            </div>
        </div>
    );
}