Skip to content

Instantly share code, notes, and snippets.

@simonw
Last active August 10, 2024 00:43
Show Gist options
  • Save simonw/ffbf7d7abbf56a126c89e7d62442696a to your computer and use it in GitHub Desktop.
Save simonw/ffbf7d7abbf56a126c89e7d62442696a to your computer and use it in GitHub Desktop.

CSS for a slight box shadow, build me a tool that helps me twiddle settings and preview them and copy and paste out the CSS

Certainly! I'll create a React component that allows you to adjust box shadow settings and preview the result in real-time. This tool will also provide the CSS code for you to copy and paste.

import React, { useState } from 'react';
import { Slider } from '@/components/ui/slider';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';

const BoxShadowTool = () => {
  const [horizontalOffset, setHorizontalOffset] = useState(0);
  const [verticalOffset, setVerticalOffset] = useState(4);
  const [blurRadius, setBlurRadius] = useState(8);
  const [spreadRadius, setSpreadRadius] = useState(0);
  const [color, setColor] = useState('#000000');
  const [opacity, setOpacity] = useState(20);

  const boxShadow = `${horizontalOffset}px ${verticalOffset}px ${blurRadius}px ${spreadRadius}px ${color}${Math.round(opacity * 2.55).toString(16).padStart(2, '0')}`;
  const cssCode = `box-shadow: ${boxShadow};`;

  const copyToClipboard = () => {
    navigator.clipboard.writeText(cssCode);
  };

  return (
    <div className="p-4 max-w-md mx-auto">
      <div className="mb-4 p-8 border rounded" style={{ boxShadow }}>
        Preview
      </div>
      
      <div className="space-y-4">
        <div>
          <label className="block text-sm font-medium text-gray-700">Horizontal Offset</label>
          <Slider
            value={[horizontalOffset]}
            onValueChange={(value) => setHorizontalOffset(value[0])}
            max={50}
            min={-50}
            step={1}
          />
        </div>
        
        <div>
          <label className="block text-sm font-medium text-gray-700">Vertical Offset</label>
          <Slider
            value={[verticalOffset]}
            onValueChange={(value) => setVerticalOffset(value[0])}
            max={50}
            min={-50}
            step={1}
          />
        </div>
        
        <div>
          <label className="block text-sm font-medium text-gray-700">Blur Radius</label>
          <Slider
            value={[blurRadius]}
            onValueChange={(value) => setBlurRadius(value[0])}
            max={50}
            min={0}
            step={1}
          />
        </div>
        
        <div>
          <label className="block text-sm font-medium text-gray-700">Spread Radius</label>
          <Slider
            value={[spreadRadius]}
            onValueChange={(value) => setSpreadRadius(value[0])}
            max={50}
            min={-50}
            step={1}
          />
        </div>
        
        <div>
          <label className="block text-sm font-medium text-gray-700">Color</label>
          <Input
            type="color"
            value={color}
            onChange={(e) => setColor(e.target.value)}
            className="w-full"
          />
        </div>
        
        <div>
          <label className="block text-sm font-medium text-gray-700">Opacity</label>
          <Slider
            value={[opacity]}
            onValueChange={(value) => setOpacity(value[0])}
            max={100}
            min={0}
            step={1}
          />
        </div>
      </div>
      
      <div className="mt-4">
        <p className="text-sm font-medium text-gray-700">CSS Code:</p>
        <code className="block p-2 bg-gray-100 rounded">{cssCode}</code>
        <Button onClick={copyToClipboard} className="mt-2">Copy to Clipboard</Button>
      </div>
    </div>
  );
};

export default BoxShadowTool;

I've created a React component that allows you to adjust various box shadow settings and see the results in real-time. Here's a breakdown of the features:

  1. Preview: A box at the top shows you how the shadow looks with your current settings.
  2. Sliders for adjusting:
    • Horizontal offset
    • Vertical offset
    • Blur radius
    • Spread radius
  3. Color picker for shadow color
  4. Opacity slider
  5. CSS code display
  6. Copy to clipboard button

To use this tool:

  1. Adjust the sliders and color picker to get the desired shadow effect.
  2. The preview box will update in real-time.
  3. The CSS code will be displayed below the controls.
  4. Click the "Copy to Clipboard" button to copy the CSS code.

This component uses some UI components from the shadcn/ui library, such as Slider, Input, and Button. If you need help setting up these components in your project, let me know, and I can guide you through the process.

Would you like me to explain any part of the code in more detail?

Give me step by step instructions for turning this into an HTML page I can deploy on static hosting

Certainly! I'll guide you through the process of turning this React component into a standalone HTML page that you can deploy on static hosting. This will involve creating a simple HTML file with embedded JavaScript and CSS.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Box Shadow CSS Generator</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/7.22.10/babel.min.js"></script>
    <style>
        body {
            font-family: Arial, sans-serif;
            line-height: 1.6;
            color: #333;
            max-width: 600px;
            margin: 0 auto;
            padding: 20px;
        }
        .preview-box {
            width: 200px;
            height: 200px;
            margin: 20px auto;
            background-color: white;
            display: flex;
            align-items: center;
            justify-content: center;
            border: 1px solid #ccc;
        }
        .control-group {
            margin-bottom: 15px;
        }
        label {
            display: block;
            margin-bottom: 5px;
        }
        input[type="range"], input[type="color"] {
            width: 100%;
        }
        .css-output {
            background-color: #f4f4f4;
            padding: 10px;
            border-radius: 4px;
            font-family: monospace;
            white-space: pre-wrap;
        }
        button {
            background-color: #4CAF50;
            border: none;
            color: white;
            padding: 10px 20px;
            text-align: center;
            text-decoration: none;
            display: inline-block;
            font-size: 16px;
            margin: 4px 2px;
            cursor: pointer;
            border-radius: 4px;
        }
    </style>
</head>
<body>
    <div id="root"></div>

    <script type="text/babel">
        const BoxShadowTool = () => {
            const [horizontalOffset, setHorizontalOffset] = React.useState(0);
            const [verticalOffset, setVerticalOffset] = React.useState(4);
            const [blurRadius, setBlurRadius] = React.useState(8);
            const [spreadRadius, setSpreadRadius] = React.useState(0);
            const [color, setColor] = React.useState('#000000');
            const [opacity, setOpacity] = React.useState(20);

            const boxShadow = `${horizontalOffset}px ${verticalOffset}px ${blurRadius}px ${spreadRadius}px ${color}${Math.round(opacity * 2.55).toString(16).padStart(2, '0')}`;
            const cssCode = `box-shadow: ${boxShadow};`;

            const copyToClipboard = () => {
                navigator.clipboard.writeText(cssCode);
                alert('CSS copied to clipboard!');
            };

            return (
                <div>
                    <h1>Box Shadow CSS Generator</h1>
                    <div className="preview-box" style={{ boxShadow }}>
                        Preview
                    </div>
                    
                    <div className="control-group">
                        <label>Horizontal Offset: {horizontalOffset}px</label>
                        <input
                            type="range"
                            min="-50"
                            max="50"
                            value={horizontalOffset}
                            onChange={(e) => setHorizontalOffset(Number(e.target.value))}
                        />
                    </div>
                    
                    <div className="control-group">
                        <label>Vertical Offset: {verticalOffset}px</label>
                        <input
                            type="range"
                            min="-50"
                            max="50"
                            value={verticalOffset}
                            onChange={(e) => setVerticalOffset(Number(e.target.value))}
                        />
                    </div>
                    
                    <div className="control-group">
                        <label>Blur Radius: {blurRadius}px</label>
                        <input
                            type="range"
                            min="0"
                            max="50"
                            value={blurRadius}
                            onChange={(e) => setBlurRadius(Number(e.target.value))}
                        />
                    </div>
                    
                    <div className="control-group">
                        <label>Spread Radius: {spreadRadius}px</label>
                        <input
                            type="range"
                            min="-50"
                            max="50"
                            value={spreadRadius}
                            onChange={(e) => setSpreadRadius(Number(e.target.value))}
                        />
                    </div>
                    
                    <div className="control-group">
                        <label>Color</label>
                        <input
                            type="color"
                            value={color}
                            onChange={(e) => setColor(e.target.value)}
                        />
                    </div>
                    
                    <div className="control-group">
                        <label>Opacity: {opacity}%</label>
                        <input
                            type="range"
                            min="0"
                            max="100"
                            value={opacity}
                            onChange={(e) => setOpacity(Number(e.target.value))}
                        />
                    </div>
                    
                    <div className="control-group">
                        <label>CSS Code:</label>
                        <div className="css-output">{cssCode}</div>
                        <button onClick={copyToClipboard}>Copy to Clipboard</button>
                    </div>
                </div>
            );
        };

        ReactDOM.render(<BoxShadowTool />, document.getElementById('root'));
    </script>
</body>
</html>

Now, I'll provide you with step-by-step instructions to deploy this HTML page on static hosting:

  1. Create a new file: Create a new file and name it index.html.

  2. Copy the code: Copy the entire HTML code from the artifact above and paste it into your index.html file.

  3. Save the file: Save the index.html file on your local machine.

  4. Choose a static hosting provider: There are many free static hosting providers available. Some popular options include:

    • GitHub Pages
    • Netlify
    • Vercel
    • Surge
  5. Deploy the file: The deployment process may vary slightly depending on your chosen hosting provider. Here's a general outline:

    a. For GitHub Pages:

    • Create a new repository on GitHub
    • Upload your index.html file to the repository
    • Go to repository settings, find the "Pages" section
    • Set the source to the branch containing your index.html file
    • GitHub will provide you with a URL for your deployed page

    b. For Netlify:

    • Sign up for a Netlify account
    • Drag and drop your index.html file onto the Netlify dashboard
    • Netlify will automatically deploy your site and provide you with a URL

    c. For Vercel:

    • Sign up for a Vercel account
    • Install the Vercel CLI: npm i -g vercel
    • Navigate to the directory containing your index.html file in the terminal
    • Run vercel and follow the prompts
    • Vercel will deploy your site and provide you with a URL

    d. For Surge:

    • Install Surge: npm install --global surge
    • Navigate to the directory containing your index.html file in the terminal
    • Run surge
    • Follow the prompts to create an account and deploy your site
    • Surge will provide you with a URL for your deployed page
  6. Access your deployed page: Once deployed, you can access your Box Shadow CSS Generator tool using the URL provided by your hosting service.

  7. Share and enjoy: You can now share the URL with others or use it yourself whenever you need to generate box shadow CSS.

Remember, this is a client-side only application, so it will work entirely in the browser without needing any server-side processing.

Would you like any clarification on any of these steps?

@simonw
Copy link
Author

simonw commented Jul 8, 2024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment