Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs: adjust mobile website #82

Merged
merged 4 commits into from
Dec 18, 2024
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
2 changes: 0 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,12 @@
"scripts": {
"clean": "rm -rf node_modules",
"contributors": "(npx git-authors-cli && npx finepack && git add package.json && git commit -m 'build: contributors' --no-verify) || true",
"dev": "nodemon --exec \"npm start\" -e \"js\"",
"lint": "standard-markdown README.md && standard",
"postrelease": "npm run release:tags && npm run release:github && (ci-publish || npm publish --access=public)",
"pretest": "npm run lint",
"release": "standard-version -a",
"release:github": "conventional-github-releaser -p angular",
"release:tags": "git push --follow-tags origin HEAD:master",
"start": "node index.js",
"test": "c8 ava"
},
"license": "MIT",
Expand Down
94 changes: 46 additions & 48 deletions website/src/components/color-extractor.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/* eslint-disable @next/next/no-img-element */
'use client'

import { creatCopyToClipboard } from '@/lib/copy-to-clipboard'
import { Loader2, RefreshCcw } from 'lucide-react'
import { Button } from '@/components/ui/button'
import { useCallback, useState } from 'react'
import { useDropzone } from 'react-dropzone'
import { useToast } from '@/hooks/use-toast'
import { creatCopyToClipboard } from '@/lib/copy-to-clipboard'
import { useState } from 'react'

interface ColorFormat {
rgb: string
Expand Down Expand Up @@ -45,41 +45,38 @@ export function ColorExtractor () {
const { toast } = useToast()
const copyToClipboard = creatCopyToClipboard(toast)

const [imageUrl, setImageUrl] = useState('')
const [imageUrl, setImageUrl] = useState<string | undefined>(undefined)
const [colors, setColors] = useState<ColorFormat[]>([])
const [isLoading, setIsLoading] = useState(false)

const onDrop = useCallback(async (acceptedFiles: File[]) => {
const onDrop = async (acceptedFiles: File[]) => {
const formData = new FormData()
const base64data = await getBase64(acceptedFiles[0])
formData.append('file', acceptedFiles[0])
await processFiles(formData)
await setImageUrl(base64data)
}, [])
}

const { getRootProps, getInputProps } = useDropzone({ onDrop })

const handleUrlSubmit = async (e: React.FormEvent) => {
console.log('ola puto')
e.preventDefault()
if (imageUrl) {
console.log('TODO')
// await processFiles(imageUrl)
const res = await fetch(imageUrl)
const buffer = Buffer.from(await res.arrayBuffer())
const formData = new FormData()
formData.append('file', new Blob([buffer]))
await processFiles(formData)
}
}

const processFiles = async (formData: FormData) => {
setIsLoading(true)
const res = await fetch('/api/', {
method: 'POST',
body: formData
})

const palette = await res.json()
console.log(palette)
setColors(palette)
setColors(await res.json())
if (!imageUrl) setImageUrl(await getBase64(formData.get('file') as File))
setIsLoading(false)
setImageUrl('') // Clear the input field after processing
}

const resetState = () => {
Expand All @@ -93,40 +90,45 @@ export function ColorExtractor () {
}

return (
<div className=''>
<div className='lg:w-full w-[90%] mx-auto'>
{colors.length === 0 ? (
<div>
<div
{...getRootProps()}
className='border-2 rounded-2xl h-[400px] flex flex-col items-center justify-center cursor-pointer border-primary bg-primary/5'
className='border-2 rounded-2xl lg:h-[400px] h-[200px] flex flex-col items-center justify-center cursor-pointer border-primary bg-primary/5'
>
<input {...getInputProps()} />
<p className='text-2xl lg:text-4xl font-bold text-primary'>DRAG AN IMAGE HERE</p>
<p className='text-2xl lg:text-4xl font-bold text-primary'>
{isLoading && <Loader2 className='animate-spin h-10 w-10' />}
{!isLoading && 'DRAG AN IMAGE HERE'}
</p>
</div>
<form
onSubmit={handleUrlSubmit}
onClick={handleFormClick}
className='flex pt-4 space-x-3 items-center'
>
<input
type='url'
value={imageUrl}
onChange={e => setImageUrl(e.target.value)}
onClick={handleFormClick}
placeholder='or paste an image URL'
className='flex-grow px-4 py-2 border-2 border-zinc-400 hover:border-primary focus:border-primary hover:outline-none focus:outline-none rounded-lg h-10'
/>
<Button
type='submit'
variant='outline'
className='border-2 hover:border-primary hover:text-primary font-bold h-10 border-zinc-400 text-zinc-400'
disabled={isLoading}
{!isLoading && (
<form
onSubmit={handleUrlSubmit}
onClick={handleFormClick}
className='flex flex-col lg:flex-row pt-4 lg:space-x-3 items-center'
>
{isLoading && <Loader2 className='animate-spin' />}
{isLoading ? 'HOLD ON...' : 'DO IT'}
</Button>
</form>
<input
type='url'
value={undefined}
onChange={e => setImageUrl(e.target.value)}
onClick={handleFormClick}
placeholder='or paste an image URL'
className='flex-grow px-4 py-2 border-2 border-zinc-400 hover:border-primary focus:border-primary hover:outline-none focus:outline-none rounded-lg h-10 w-full'
/>
<Button
type='submit'
variant='outline'
className='border-2 hover:border-primary hover:text-primary font-bold h-10 border-zinc-400 text-zinc-400 w-full lg:w-[inherit] lg:mt-0 mt-2'
disabled={isLoading}
onClick={handleFormClick}
>
{isLoading && <Loader2 className='animate-spin' />}
{isLoading ? 'HOLD ON...' : 'DO IT'}
</Button>
</form>
)}
</div>
) : (
<div className='flex justify-center items-center flex-col space-y-4'>
Expand All @@ -143,12 +145,8 @@ export function ColorExtractor () {
<div
onClick={() => copyToClipboard(color.hex, `Color ${color.hex}`)}
key={index}
className='cursor-pointer rounded-lg shadow-md'
style={{
height: '6rem',
width: '6rem',
backgroundColor: color.hex
}}
className='cursor-pointer rounded-lg shadow-md lg:h-24 lg:w-24 h-20 w-20'
style={{ backgroundColor: color.hex }}
>
<div className='w-full h-full flex items-end justify-center p-1 bg-gradient-to-t from-black/50 to-transparent rounded-lg pb-2'>
<span className='text-xs text-white font-medium'>
Expand All @@ -161,14 +159,14 @@ export function ColorExtractor () {
</div>
<div className='space-x-2 flex items-center justify-center'>
<Button
onClick={() => copyToClipboard(generateCSSVariables(colors))}
onClick={() => copyToClipboard(generateCSSVariables(colors), 'CSS Variables')}
className='w-auto'
variant='default'
>
Copy as CSS
</Button>
<Button
onClick={() => copyToClipboard(generateJSONObject(colors))}
onClick={() => copyToClipboard(generateJSONObject(colors), 'JSON')}
className='w-auto'
variant='secondary'
>
Expand Down
6 changes: 0 additions & 6 deletions website/src/components/debugger.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,6 @@ export function Debugger () {
<Button onClick={handleVisualize}>Visualize</Button>
</div>
</div>
<div className='mt-8 text-center text-gray-600 dark:text-gray-400'>
<p>Adjust the colors above or click &apos;Randomize&apos; for a surprise palette.</p>
<p>
When you&apos;re ready, click &apos;Visualize&apos; to see your palette in full screen!
</p>
</div>
</main>
</div>
)
Expand Down
11 changes: 8 additions & 3 deletions website/src/components/faq.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export function FAQ () {
const copyToClipboard = creatCopyToClipboard(toast)

return (
<section id='faq' className='space-y-8 pb-24'>
<section id='faq' className='space-y-8'>
<div className='space-y-6'>
<div>
<h3 className='text-xl font-semibold mb-6'>What is Splashy?</h3>
Expand All @@ -46,7 +46,7 @@ export function FAQ () {
</p>
<Code
className='pt-6 cursor-pointer'
onClick={() => copyToClipboard(microlinkSnippet, 'npm install')}
onClick={() => copyToClipboard('npm install splashy --save', 'npm install')}
>
npm install splashy --save
</Code>
Expand All @@ -65,7 +65,12 @@ export function FAQ () {
<Link href='https://microlink.io/docs/api/getting-started/overview'>Microlink API</Link>{' '}
is already provisioned and ready to be used passing `palette` query parameter:
</p>
<Code className='pt-6'>{microlinkSnippet}</Code>
<Code
className='pt-6 cursor-pointer'
onClick={() => copyToClipboard(microlinkSnippet, 'microlink snippet')}
>
{microlinkSnippet}
</Code>
<p className='pt-6'>We recommend to consume splashy from Microlink API.</p>
</div>
<div>
Expand Down
2 changes: 1 addition & 1 deletion website/src/components/footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { cn } from '@/lib/utils'
export const Footer = () => {
const pathname = usePathname()
return (
<footer className='py-4 w-full text-neutral-600 fixed bottom-0 bg-slate-50 bg-opacity-10 backdrop-blur'>
<footer className='py-6 w-full text-neutral-600 fixed bottom-0 bg-slate-50 bg-opacity-10 backdrop-blur'>
<nav>
<ul className='flex justify-center space-x-4'>
{[
Expand Down
12 changes: 6 additions & 6 deletions website/src/components/layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,27 +42,27 @@ export const ContainerLayout = ({ children }: { children: React.ReactNode }) =>
<div className={`${inter.className} bg-slate-50`}>
<div
aria-hidden='true'
className='-z-10 absolute inset-0 grid grid-cols-2 -space-x-52 opacity-40 dark:opacity-20'
className='pointer-events-none absolute inset-0 grid grid-cols-2 -space-x-52 opacity-40 dark:opacity-20'
>
<div className='blur-[106px] h-32 bg-gradient-to-br from-primary to-purple-400 dark:from-blue-700' />
<div className='blur-[106px] h-24 bg-gradient-to-r from-cyan-400 to-sky-300 dark:to-indigo-600' />
</div>
<header className='container pt-8 max-w-xl mx-auto px-4 text-center'>
<header className='container pt-8 max-w-xl mx-auto px-4 text-center z-10 relative'>
<NextLink href='/'>
<h1 className='text-5xl lg:text-8xl font-extrabold mb-3 tracking-tight bg-clip-text text-transparent text-center bg-gradient-to-b from-neutral-900 to-neutral-700'>
SPLASHY
</h1>
</NextLink>

<p className='text-xl'>Get predominant colors for any image.</p>
<p className='text-neutral-600 pt-2'>
<p className='lg:text-xl'>Get predominant colors for any image.</p>
<p className='text-neutral-600 pt-2 flex items-center justify-center'>
Powered by{' '}
<Link href='https://microlink.io'>
<MicrolinkLogo className='inline h-4 mr-2' /> Microlink.io
<MicrolinkLogo className='inline h-4 mx-2' /> Microlink.io
</Link>
</p>
</header>
<main className='pt-8 max-w-xl mx-auto px-4'>{children}</main>
<main className='pt-8 max-w-xl mx-auto px-4 pb-24'>{children}</main>
<Toaster />
<Footer />
</div>
Expand Down
51 changes: 32 additions & 19 deletions website/src/lib/copy-to-clipboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,35 @@ type ToastProps = {

type Toast = (props: ToastProps) => void

export const creatCopyToClipboard =
(toast: Toast) => (text: string, type?: string) => {
navigator.clipboard.writeText(text).then(
() => {
toast({
title: 'Copied to clipboard',
description: `${type} has been copied to your clipboard.`
})
},
err => {
console.error('Could not copy text: ', err)
toast({
title: 'Error',
description: 'Failed to copy to clipboard.',
variant: 'destructive'
})
}
)
}
const toClipboard = async (text: string) => {
if (navigator.clipboard) return navigator.clipboard.writeText(text)
const textArea = document.createElement('textarea')
textArea.value = text
textArea.style.top = '0'
textArea.style.left = '0'
textArea.style.position = 'fixed'
document.body.appendChild(textArea)
textArea.focus()
textArea.select()
document.execCommand('copy')
document.body.removeChild(textArea)
}

export const creatCopyToClipboard = (toast: Toast) => (text: string, type?: string) => {
toClipboard(text).then(
() => {
toast({
title: 'Copied to clipboard',
description: `${type} has been copied to your clipboard.`
})
},
err => {
console.error('Could not copy text: ', err)
toast({
title: 'Error',
description: 'Failed to copy to clipboard.',
variant: 'destructive'
})
}
)
}
Loading