SuperShipped // Item 24

SNIPPET VIEW

Live Render

HTML CODE

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Interactive Glass Menu</title>
    <style>
        :root {
            --bg-color: #e2e4e9;
            --menu-bg: rgba(255, 255, 255, 0.85);
            --text-main: #6e6e80;
            --accent: #5e5ce6;
            --hover-bg: rgba(0, 0, 0, 0.04);
            --key-bg: #ffffff;
        }

        body, html {
            margin: 0;
            padding: 0;
            height: 100%;
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
            background: var(--bg-color);
            display: flex;
            justify-content: center;
            align-items: center;
            overflow: hidden;
        }

        /* WebGL Background Canvas */
        #gl-canvas {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            z-index: -1;
        }

        /* Menu Container */
        .wrapper {
            display: flex;
            flex-direction: column;
            align-items: center;
            gap: 20px;
            filter: drop-shadow(0 20px 40px rgba(0,0,0,0.1));
            transform: translateY(20px);
            opacity: 0;
            animation: slideUp 0.6s cubic-bezier(0.16, 1, 0.3, 1) forwards;
        }

        @keyframes slideUp {
            to { transform: translateY(0); opacity: 1; }
        }

        .menu-card {
            background: var(--menu-bg);
            backdrop-filter: blur(20px);
            -webkit-backdrop-filter: blur(20px);
            border-radius: 28px;
            padding: 12px;
            width: 320px;
            border: 1px solid rgba(255, 255, 255, 0.4);
            position: relative;
        }

        /* Triangle Pointer */
        .menu-card::after {
            content: '';
            position: absolute;
            bottom: -10px;
            left: 50%;
            transform: translateX(-50%);
            border-left: 10px solid transparent;
            border-right: 10px solid transparent;
            border-top: 10px solid var(--menu-bg);
        }

        .menu-item {
            display: flex;
            align-items: center;
            padding: 12px 16px;
            border-radius: 18px;
            cursor: pointer;
            transition: all 0.2s ease;
            color: var(--text-main);
            gap: 15px;
            user-select: none;
        }

        .menu-item:hover {
            background: var(--hover-bg);
            transform: scale(1.02);
        }

        .menu-item:active {
            transform: scale(0.98);
        }

        .icon {
            font-size: 20px;
            width: 24px;
            display: flex;
            justify-content: center;
        }

        .label {
            flex-grow: 1;
            font-weight: 500;
            font-size: 15px;
        }

        /* Keyboard Shortcut Styling */
        .shortcuts {
            display: flex;
            gap: 6px;
        }

        .key {
            background: var(--key-bg);
            border: 1px solid rgba(0,0,0,0.05);
            box-shadow: 0 2px 4px rgba(0,0,0,0.05);
            border-radius: 6px;
            width: 32px;
            height: 32px;
            display: flex;
            align-items: center;
            justify-content: center;
            font-size: 14px;
            color: #a0a0b0;
        }

        /* Bottom Toolbar */
        .toolbar {
            background: var(--menu-bg);
            backdrop-filter: blur(20px);
            border-radius: 40px;
            padding: 8px 20px;
            display: flex;
            gap: 20px;
            align-items: center;
            border: 1px solid rgba(255, 255, 255, 0.4);
        }

        .tool-btn {
            opacity: 0.6;
            cursor: pointer;
            transition: opacity 0.2s;
            font-size: 20px;
        }

        .tool-btn:hover { opacity: 1; }
        
        .active-tool {
            background: rgba(0,0,0,0.05);
            padding: 8px;
            border-radius: 50%;
            opacity: 1;
        }
    </style>
</head>
<body>

    <canvas id="gl-canvas"></canvas>

    <div class="wrapper">
        <div class="menu-card">
            <div class="menu-item">
                <span class="icon">📄</span>
                <span class="label">Share File</span>
                <div class="shortcuts"><div class="key">⌘</div><div class="key">F</div></div>
            </div>
            <div class="menu-item">
                <span class="icon">🔗</span>
                <span class="label">Open Link</span>
                <div class="shortcuts"><div class="key">⌘</div><div class="key">L</div></div>
            </div>
            <div class="menu-item" style="background: var(--hover-bg);">
                <span class="icon">{ }</span>
                <span class="label">Embed Tool</span>
                <div class="shortcuts"><div class="key">⌘</div><div class="key">E</div></div>
            </div>
            <div class="menu-item">
                <span class="icon">📅</span>
                <span class="label">Add Agenda</span>
                <div class="shortcuts"><div class="key">⌘</div><div class="key">A</div></div>
            </div>
            <div class="menu-item">
                <span class="icon">🖥️</span>
                <span class="label">Share Screen</span>
                <div class="shortcuts"><div class="key">⌘</div><div class="key">W</div></div>
            </div>
        </div>

        <div class="toolbar">
            <div class="tool-btn">🚫</div>
            <div class="tool-btn">✋</div>
            <div class="tool-btn active-tool">⠿</div>
            <div class="tool-btn">⭕</div>
            <div class="tool-btn">🚪</div>
        </div>
    </div>

    <script>
        /** WEBGL BACKGROUND GENERATOR **/
        const canvas = document.getElementById('gl-canvas');
        const gl = canvas.getContext('webgl');

        if (gl) {
            const vsSource = `
                attribute vec4 aVertexPosition;
                void main() { gl_Position = aVertexPosition; }
            `;

            const fsSource = `
                precision highp float;
                uniform float uTime;
                uniform vec2 uResolution;
                void main() {
                    vec2 uv = gl_FragCoord.xy / uResolution.xy;
                    float color = 0.88 + 0.05 * sin(uv.x * 10.0 + uTime * 0.5) + 0.05 * cos(uv.y * 10.0 + uTime * 0.5);
                    gl_FragColor = vec4(vec3(color, color, color + 0.02), 1.0);
                }
            `;

            function createShader(gl, type, source) {
                const shader = gl.createShader(type);
                gl.shaderSource(shader, source);
                gl.compileShader(shader);
                return shader;
            }

            const program = gl.createProgram();
            gl.attachShader(program, createShader(gl, gl.VERTEX_SHADER, vsSource));
            gl.attachShader(program, createShader(gl, gl.FRAGMENT_SHADER, fsSource));
            gl.linkProgram(program);
            gl.useProgram(program);

            const positionBuffer = gl.createBuffer();
            gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
            gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1,1, 1,1, -1,-1, 1,-1]), gl.STATIC_DRAW);

            const posAttrib = gl.getAttribLocation(program, "aVertexPosition");
            gl.enableVertexAttribArray(posAttrib);
            gl.vertexAttribPointer(posAttrib, 2, gl.FLOAT, false, 0, 0);

            const timeLoc = gl.getUniformLocation(program, "uTime");
            const resLoc = gl.getUniformLocation(program, "uResolution");

            function render(time) {
                canvas.width = window.innerWidth;
                canvas.height = window.innerHeight;
                gl.viewport(0, 0, canvas.width, canvas.height);
                gl.uniform1f(timeLoc, time * 0.001);
                gl.uniform2f(resLoc, canvas.width, canvas.height);
                gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
                requestAnimationFrame(render);
            }
            requestAnimationFrame(render);
        }

        /** INTERACTIVITY **/
        document.querySelectorAll('.menu-item').forEach(item => {
            item.addEventListener('mouseenter', () => {
                // Remove highlight from others
                document.querySelectorAll('.menu-item').forEach(i => i.style.background = 'transparent');
                item.style.background = 'var(--hover-bg)';
            });
        });
    </script>
</body>
</html>

AI PROMPT

Create a "Interactive Glass Menu" component. Implement custom GLSL shaders for visual effects. Apply keyframe animations, glass-morphism / backdrop blur, layered shadows, hover transitions. Color palette: #e2e4e9, #6e6e80, #5e5ce6, #ffffff. Layout: Flexbox, full-screen fixed canvas background. Interactivity: mouse tracking, continuous animation loop.