diff --git a/index.html b/index.html index e4b78ea..93df9d1 100644 --- a/index.html +++ b/index.html @@ -1,13 +1,13 @@ -<!doctype html> +<!DOCTYPE html> <html lang="en"> - <head> - <meta charset="UTF-8" /> - <link rel="icon" type="image/svg+xml" href="/vite.svg" /> - <meta name="viewport" content="width=device-width, initial-scale=1.0" /> - <title>Vite + React + TS</title> - </head> - <body> - <div id="root"></div> - <script type="module" src="/src/main.tsx"></script> - </body> + <head> + <meta charset="UTF-8" /> + <link rel="icon" type="image/svg+xml" href="/vite.svg" /> + <meta name="viewport" content="width=device-width, initial-scale=1.0" /> + <title>ByteBelli</title> + </head> + <body style="margin: 0; background-color: transparent" class="linklib-ext"> + <div id="root" class="linklib-ext"></div> + <script type="module" src="/src/main.tsx"></script> + </body> </html> diff --git a/package-lock.json b/package-lock.json index 7c53fae..e343a40 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "@radix-ui/react-popover": "^1.0.7", "@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-toast": "^1.1.5", + "@radix-ui/react-tooltip": "^1.1.2", "@supabase/ssr": "^0.4.0", "@supabase/supabase-js": "^2.45.0", "@vitejs/plugin-react": "^4.2.1", @@ -1947,6 +1948,376 @@ } } }, + "node_modules/@radix-ui/react-tooltip": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.1.2.tgz", + "integrity": "sha512-9XRsLwe6Yb9B/tlnYCPVUd/TFS4J7HuOZW345DCeC6vKIxQGMZdx21RK4VoZauPD5frgkXTYVS5y90L+3YBn4w==", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-dismissable-layer": "1.1.0", + "@radix-ui/react-id": "1.1.0", + "@radix-ui/react-popper": "1.2.0", + "@radix-ui/react-portal": "1.1.1", + "@radix-ui/react-presence": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-slot": "1.1.0", + "@radix-ui/react-use-controllable-state": "1.1.0", + "@radix-ui/react-visually-hidden": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.0.tgz", + "integrity": "sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==" + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-arrow": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-arrow/-/react-arrow-1.1.0.tgz", + "integrity": "sha512-FmlW1rCg7hBpEBwFbjHwCW6AmWLQM6g/v0Sn8XbP9NvmSZ2San1FpQeyPtufzOMSIx7Y4dzjlHoifhp+7NkZhw==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-compose-refs": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.0.tgz", + "integrity": "sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-context": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-context/-/react-context-1.1.0.tgz", + "integrity": "sha512-OKrckBy+sMEgYM/sMmqmErVn0kZqrHPJze+Ql3DzYsDDp0hl0L62nx/2122/Bvps1qz645jlcu2tD9lrRSdf8A==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-dismissable-layer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.0.tgz", + "integrity": "sha512-/UovfmmXGptwGcBQawLzvn2jOfM0t4z3/uKffoBlj724+n3FvBbZ7M0aaBOmkp6pqFYpO4yx8tSVJjx3Fl2jig==", + "dependencies": { + "@radix-ui/primitive": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-escape-keydown": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-id": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.0.tgz", + "integrity": "sha512-EJUrI8yYh7WOjNOqpoJaf1jlFIH2LvtgAl+YcFqNCa+4hj64ZXmPkAKOFs/ukjz3byN6bdb/AVUqHkI8/uWWMA==", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-popper": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.2.0.tgz", + "integrity": "sha512-ZnRMshKF43aBxVWPWvbj21+7TQCvhuULWJ4gNIKYpRlQt5xGRhLx66tMp8pya2UkGHTSlhpXwmjqltDYHhw7Vg==", + "dependencies": { + "@floating-ui/react-dom": "^2.0.0", + "@radix-ui/react-arrow": "1.1.0", + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-context": "1.1.0", + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-callback-ref": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0", + "@radix-ui/react-use-rect": "1.1.0", + "@radix-ui/react-use-size": "1.1.0", + "@radix-ui/rect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-portal": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.1.tgz", + "integrity": "sha512-A3UtLk85UtqhzFqtoC8Q0KvR2GbXF3mtPgACSazajqq6A41mEQgo53iPzY4i6BwDxlIFqWIhiQ2G729n+2aw/g==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-presence": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.0.tgz", + "integrity": "sha512-Gq6wuRN/asf9H/E/VzdKoUtT8GC9PQc9z40/vEr0VCJ4u5XvvhWIrSsCB6vD2/cH7ugTdSfYq9fLJCcM00acrQ==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0", + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-primitive": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.0.tgz", + "integrity": "sha512-ZSpFm0/uHa8zTvKBDjLFWLo8dkr4MBsiDLz0g3gMUwqgLHz9rTaRRGYDgvZPtBJgYCBKXkS9fzmoySgr8CO6Cw==", + "dependencies": { + "@radix-ui/react-slot": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-slot/-/react-slot-1.1.0.tgz", + "integrity": "sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==", + "dependencies": { + "@radix-ui/react-compose-refs": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-callback-ref": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.1.0.tgz", + "integrity": "sha512-CasTfvsy+frcFkbXtSJ2Zu9JHpN8TYKxkgJGWbjiZhFivxaeW7rMeZt7QELGVLaYVfFMsKHjb7Ak0nMEe+2Vfw==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-controllable-state": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-controllable-state/-/react-use-controllable-state-1.1.0.tgz", + "integrity": "sha512-MtfMVJiSr2NjzS0Aa90NPTnvTSg6C/JLCV7ma0W6+OMV78vd8OyRpID+Ng9LxzsPbLeuBnWBA1Nq30AtBIDChw==", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-escape-keydown": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-escape-keydown/-/react-use-escape-keydown-1.1.0.tgz", + "integrity": "sha512-L7vwWlR1kTTQ3oh7g1O0CBF3YCyyTj8NmhLR+phShpyA50HCfBFKVJTpshm9PzLiKmehsrQzTYTpX9HvmC9rhw==", + "dependencies": { + "@radix-ui/react-use-callback-ref": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-layout-effect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-layout-effect/-/react-use-layout-effect-1.1.0.tgz", + "integrity": "sha512-+FPE0rOdziWSrH9athwI1R0HDVbWlEhd+FR+aSDk4uWGmSJ9Z54sdZVDQPZAinJhJXwfT+qnj969mCsT2gfm5w==", + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-rect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-rect/-/react-use-rect-1.1.0.tgz", + "integrity": "sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==", + "dependencies": { + "@radix-ui/rect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-use-size": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-use-size/-/react-use-size-1.1.0.tgz", + "integrity": "sha512-XW3/vWuIXHa+2Uwcc2ABSfcCledmXhhQPlGbfcRXbiUQI5Icjcg19BGCZVKKInYbvUCut/ufbbLLPFC5cbb1hw==", + "dependencies": { + "@radix-ui/react-use-layout-effect": "1.1.0" + }, + "peerDependencies": { + "@types/react": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/react-visually-hidden": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.1.0.tgz", + "integrity": "sha512-N8MDZqtgCgG5S3aV60INAB475osJousYpZ4cTJ2cFbMpdHS5Y6loLTH8LPtkj2QN0x93J30HT/M3qJXM0+lyeQ==", + "dependencies": { + "@radix-ui/react-primitive": "2.0.0" + }, + "peerDependencies": { + "@types/react": "*", + "@types/react-dom": "*", + "react": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc", + "react-dom": "^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "@types/react-dom": { + "optional": true + } + } + }, + "node_modules/@radix-ui/react-tooltip/node_modules/@radix-ui/rect": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@radix-ui/rect/-/rect-1.1.0.tgz", + "integrity": "sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==" + }, "node_modules/@radix-ui/react-use-callback-ref": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz", diff --git a/package.json b/package.json index da39d95..9533356 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "@radix-ui/react-popover": "^1.0.7", "@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-toast": "^1.1.5", + "@radix-ui/react-tooltip": "^1.1.2", "@supabase/ssr": "^0.4.0", "@supabase/supabase-js": "^2.45.0", "@vitejs/plugin-react": "^4.2.1", diff --git a/src/App.tsx b/src/App.tsx index eb9269e..ceb1e75 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,37 +1,213 @@ +import iconImage from '@/assets/icon.png'; +import { Button } from '@/components/ui/button'; +import { Textarea } from '@/components/ui/textarea'; +import { + ArrowLeft, + Bug, + CircleUserRound, + ExternalLink, + Heart, + Lightbulb, + Linkedin, + Mail, + NotebookPen, +} from 'lucide-react'; import { useState } from 'react'; import './App.css'; -import reactLogo from './assets/react.svg'; -import viteLogo from '/vite.svg'; function App() { - const [count, setCount] = useState(0); + const [showContact, setShowContact] = useState(false); - return ( + const MainContent = () => ( <> - <div> - <a href='https://vitejs.dev' target='_blank'> - <img src={viteLogo} className='logo' alt='Vite logo' /> - </a> - <a href='https://react.dev' target='_blank'> - <img - src={reactLogo} - className='logo react' - alt='React logo' - /> - </a> + <div className='flex items-center align-middle justify-center'> + <img + src={chrome.runtime.getURL(iconImage)} + alt='Linklib Icon' + className='w-8 h-8 p-1 object-cover rounded-full' + /> + <span className='font-bold text-lg pl-2'>Bytebelli</span> </div> - <h1>Linklib</h1> - <div className='card'> - <button - className='pb-2 mb-3' - onClick={() => setCount((count) => count + 1)} - > - count is {count} - </button> - <p className='text-center'>I don' think this is working</p> + <Button variant='outline'> + <Heart className='mr-2 h-4 w-4 ' /> Save page + </Button> + <Button + variant='outline' + onClick={() => { + window.open( + 'https://bytebelli.com', + '_blank', + 'noopener,noreferrer' + ); + }} + > + <ExternalLink className='mr-2 h-4 w-4' /> Open Bytebelli + </Button> + <FeedbackSection /> + <Button variant='outline' onClick={() => setShowContact(true)}> + <CircleUserRound className='mr-2 h-4 w-4' /> + Contact Us :) + </Button> + </> + ); + + const ContactContent = () => ( + <> + <Button + variant='outline' + onClick={() => setShowContact(false)} + className='' + > + <ArrowLeft className='mr-2 h-4 w-4' /> Back + </Button> + <div className='grid gap-4 py-4'> + <div className='grid gap-4'> + <span className='font-semibold'>Isabelle</span> + <Button + variant='outline' + size='sm' + className='w-full justify-start' + > + <Mail className='mr-2 h-4 w-4' /> + isabelle.ilyia@gmail.com + </Button> + <Button + variant='outline' + size='sm' + className='w-full justify-start' + asChild + > + <a + href='https://www.linkedin.com/in/isabelle-i/' + target='_blank' + rel='noopener noreferrer' + > + <Linkedin className='mr-2 h-4 w-4' /> + LinkedIn + </a> + </Button> + </div> + <div className='grid gap-4'> + <span className='font-semibold'>Jesse</span> + <Button + variant='outline' + size='sm' + className='w-full justify-start' + > + <Mail className='mr-2 h-4 w-4' /> + jesseli751@gmail.com + </Button> + <Button + variant='outline' + size='sm' + className='w-full justify-start' + asChild + > + <a + href='https://www.linkedin.com/in/jesseli751/' + target='_blank' + rel='noopener noreferrer' + > + <Linkedin className='mr-2 h-4 w-4' /> + LinkedIn + </a> + </Button> + <Button + variant='outline' + size='sm' + className='w-full justify-start' + asChild + > + <a + href='https://fishinapool.substack.com/' + target='_blank' + rel='noopener noreferrer' + > + <NotebookPen className='mr-2 h-4 w-4' /> + Substack + </a> + </Button> + </div> </div> </> ); + + return ( + <div className='linklib-ext w-60'> + <div className='bytebelli-internal text-primary'> + <div className='p-4 flex flex-col space-y-4 bg-popover'> + {showContact ? <ContactContent /> : <MainContent />} + </div> + </div> + </div> + ); } +const FeedbackSection: React.FC = () => { + const [feedbackType, setFeedbackType] = useState<'bug' | 'feature' | null>( + null + ); + const [feedbackText, setFeedbackText] = useState(''); + + const handleSubmit = (type: 'bug' | 'feature') => { + // Here you would typically send this data to your backend + // TODO:// BACKEND + console.log(type); + // Reset the form + setFeedbackType(null); + setFeedbackText(''); + }; + + return ( + <div className='space-y-4'> + {feedbackType === null ? ( + <div className='space-y-4'> + <Button + onClick={() => setFeedbackType('bug')} + className='w-full ' + variant='outline' + > + <Bug className='mr-2 h-4 w-4' /> + Report a Bug + </Button> + <Button + onClick={() => setFeedbackType('feature')} + className='w-full ' + variant='outline' + > + <Lightbulb className='mr-2 h-4 w-4' /> + Request a Feature + </Button> + </div> + ) : ( + <div className='space-y-4'> + <Textarea + placeholder={ + feedbackType === 'bug' + ? 'Describe the bug...' + : 'Describe the feature...' + } + value={feedbackText} + onChange={(e) => setFeedbackText(e.target.value)} + /> + <div className='flex space-x-2 justify-center w-full'> + <Button + onClick={() => handleSubmit(feedbackType)} + disabled={!feedbackText.trim()} + > + Submit + </Button> + <Button + onClick={() => setFeedbackType(null)} + variant='outline' + > + Cancel + </Button> + </div> + </div> + )} + </div> + ); +}; + export default App; diff --git a/src/components/ui/dialog.tsx b/src/components/ui/dialog.tsx index 5d16351..3276b12 100644 --- a/src/components/ui/dialog.tsx +++ b/src/components/ui/dialog.tsx @@ -1,120 +1,120 @@ -import * as React from "react" -import * as DialogPrimitive from "@radix-ui/react-dialog" -import { Cross2Icon } from "@radix-ui/react-icons" +import * as React from 'react'; +import * as DialogPrimitive from '@radix-ui/react-dialog'; +import { Cross2Icon } from '@radix-ui/react-icons'; -import { cn } from "@/lib/utils" +import { cn } from '@/lib/utils'; -const Dialog = DialogPrimitive.Root +const Dialog = DialogPrimitive.Root; -const DialogTrigger = DialogPrimitive.Trigger +const DialogTrigger = DialogPrimitive.Trigger; -const DialogPortal = DialogPrimitive.Portal +const DialogPortal = DialogPrimitive.Portal; -const DialogClose = DialogPrimitive.Close +const DialogClose = DialogPrimitive.Close; const DialogOverlay = React.forwardRef< - React.ElementRef<typeof DialogPrimitive.Overlay>, - React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay> + React.ElementRef<typeof DialogPrimitive.Overlay>, + React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay> >(({ className, ...props }, ref) => ( - <DialogPrimitive.Overlay - ref={ref} - className={cn( - "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", - className - )} - {...props} - /> -)) -DialogOverlay.displayName = DialogPrimitive.Overlay.displayName + <DialogPrimitive.Overlay + ref={ref} + className={cn( + 'linklib-ext fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0', + className + )} + {...props} + /> +)); +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName; const DialogContent = React.forwardRef< - React.ElementRef<typeof DialogPrimitive.Content>, - React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> + React.ElementRef<typeof DialogPrimitive.Content>, + React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> >(({ className, children, ...props }, ref) => ( - <DialogPortal> - <DialogOverlay /> - <DialogPrimitive.Content - ref={ref} - className={cn( - "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg", - className - )} - {...props} - > - {children} - <DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"> - <Cross2Icon className="h-4 w-4" /> - <span className="sr-only">Close</span> - </DialogPrimitive.Close> - </DialogPrimitive.Content> - </DialogPortal> -)) -DialogContent.displayName = DialogPrimitive.Content.displayName + <DialogPortal> + <DialogOverlay /> + <DialogPrimitive.Content + ref={ref} + className={cn( + 'linklib-ext fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg', + className + )} + {...props} + > + {children} + <DialogPrimitive.Close className='absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground'> + <Cross2Icon className='h-4 w-4' /> + <span className='sr-only'>Close</span> + </DialogPrimitive.Close> + </DialogPrimitive.Content> + </DialogPortal> +)); +DialogContent.displayName = DialogPrimitive.Content.displayName; const DialogHeader = ({ - className, - ...props + className, + ...props }: React.HTMLAttributes<HTMLDivElement>) => ( - <div - className={cn( - "flex flex-col space-y-1.5 text-center sm:text-left", - className - )} - {...props} - /> -) -DialogHeader.displayName = "DialogHeader" + <div + className={cn( + 'linklib-ext flex flex-col space-y-1.5 text-center sm:text-left', + className + )} + {...props} + /> +); +DialogHeader.displayName = 'DialogHeader'; const DialogFooter = ({ - className, - ...props + className, + ...props }: React.HTMLAttributes<HTMLDivElement>) => ( - <div - className={cn( - "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", - className - )} - {...props} - /> -) -DialogFooter.displayName = "DialogFooter" + <div + className={cn( + 'linklib-ext flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2', + className + )} + {...props} + /> +); +DialogFooter.displayName = 'DialogFooter'; const DialogTitle = React.forwardRef< - React.ElementRef<typeof DialogPrimitive.Title>, - React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title> + React.ElementRef<typeof DialogPrimitive.Title>, + React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title> >(({ className, ...props }, ref) => ( - <DialogPrimitive.Title - ref={ref} - className={cn( - "text-lg font-semibold leading-none tracking-tight", - className - )} - {...props} - /> -)) -DialogTitle.displayName = DialogPrimitive.Title.displayName + <DialogPrimitive.Title + ref={ref} + className={cn( + 'linklib-ext text-lg font-semibold leading-none tracking-tight', + className + )} + {...props} + /> +)); +DialogTitle.displayName = DialogPrimitive.Title.displayName; const DialogDescription = React.forwardRef< - React.ElementRef<typeof DialogPrimitive.Description>, - React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description> + React.ElementRef<typeof DialogPrimitive.Description>, + React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description> >(({ className, ...props }, ref) => ( - <DialogPrimitive.Description - ref={ref} - className={cn("text-sm text-muted-foreground", className)} - {...props} - /> -)) -DialogDescription.displayName = DialogPrimitive.Description.displayName + <DialogPrimitive.Description + ref={ref} + className={cn('linklib-ext text-sm text-muted-foreground', className)} + {...props} + /> +)); +DialogDescription.displayName = DialogPrimitive.Description.displayName; export { - Dialog, - DialogPortal, - DialogOverlay, - DialogTrigger, - DialogClose, - DialogContent, - DialogHeader, - DialogFooter, - DialogTitle, - DialogDescription, -} + Dialog, + DialogPortal, + DialogOverlay, + DialogTrigger, + DialogClose, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription, +}; diff --git a/src/components/ui/tooltip.tsx b/src/components/ui/tooltip.tsx new file mode 100644 index 0000000..6d396ed --- /dev/null +++ b/src/components/ui/tooltip.tsx @@ -0,0 +1,28 @@ +import * as React from 'react'; +import * as TooltipPrimitive from '@radix-ui/react-tooltip'; + +import { cn } from '@/lib/utils'; + +const TooltipProvider = TooltipPrimitive.Provider; + +const Tooltip = TooltipPrimitive.Root; + +const TooltipTrigger = TooltipPrimitive.Trigger; + +const TooltipContent = React.forwardRef< + React.ElementRef<typeof TooltipPrimitive.Content>, + React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> +>(({ className, sideOffset = 4, ...props }, ref) => ( + <TooltipPrimitive.Content + ref={ref} + sideOffset={sideOffset} + className={cn( + 'z-50 overflow-hidden rounded-md bg-popover px-3 py-1.5 text-xs text-popover-foreground animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2', + className + )} + {...props} + /> +)); +TooltipContent.displayName = TooltipPrimitive.Content.displayName; + +export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }; diff --git a/src/index.css b/src/index.css index 19a185a..bf25400 100644 --- a/src/index.css +++ b/src/index.css @@ -5,7 +5,7 @@ @layer base { .linklib-ext { - --background: 225 7% 19%; + --background: 0 0% 9%; --foreground: 210 40% 98%; --card: 222.2 84% 4.9%; @@ -46,7 +46,7 @@ .bytebelli-internal * { font-family: 'Inter', sans-serif; font-size: var(--rem) !important; - color: var(--primary); + /* color: hsl(var(--primary)); */ } .dark { @@ -115,6 +115,11 @@ /* font-size: 16px !important; */ } + .highlight { + -webkit-appearance: none !important; + appearance: none !important; + } + body { margin: 0; /* 1 */ line-height: inherit; /* 2 */ diff --git a/src/scripts/ImageDrop/ImageDrop.tsx b/src/scripts/ImageDrop/ImageDrop.tsx index a39a846..b0462a2 100644 --- a/src/scripts/ImageDrop/ImageDrop.tsx +++ b/src/scripts/ImageDrop/ImageDrop.tsx @@ -5,10 +5,11 @@ import iconEating from '@/assets/iconEating.png'; import { saveImage } from '@/backend/saveImage'; import { Button } from '@/components/ui/button'; import { - HoverCard, - HoverCardContent, - HoverCardTrigger, -} from '@/components/ui/hover-card'; + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from '@/components/ui/tooltip'; import { useToast } from '@/components/ui/use-toast'; import { useContext } from 'react'; import { @@ -217,28 +218,59 @@ const ImageDrop = () => { </div> ) : isHovered || isSelectingFile ? ( <div className='bg-popover p-2 rounded-lg flex items-center gap-2'> - <HoverCard> - <HoverCardTrigger> - <Button - onClick={handleButtonClick} - variant='outline' - > - <ImageUp className='w-4 h-4' /> - </Button> - </HoverCardTrigger> - <HoverCardContent> - Drag and drop any image directly on bytey to save to - ByteBelli! - </HoverCardContent> - </HoverCard> + <TooltipProvider> + <Tooltip> + <TooltipTrigger> + <Button + onClick={handleButtonClick} + variant='outline' + > + <ImageUp className='w-4 h-4' /> + </Button> + </TooltipTrigger> + <TooltipContent> + <p> + Drag and drop any image directly on bytey to + save to ByteBelli! + </p> + </TooltipContent> + </Tooltip> + </TooltipProvider> + + <TooltipProvider> + <Tooltip> + <TooltipTrigger> + <Button + onClick={handleSaveLink} + variant='outline' + > + {/* TODO: Fill heart if link is already saved */} + <Heart className='w-4 h-4' /> + </Button> + </TooltipTrigger> + <TooltipContent> + <p>Click to save the link to this site!</p> + </TooltipContent> + </Tooltip> + </TooltipProvider> + + <TooltipProvider> + <Tooltip> + <TooltipTrigger> + <Button + onClick={handleOpenDrawer} + variant='outline' + disabled + > + <ArrowLeftFromLine className='w-4 h-4' /> + </Button> + </TooltipTrigger> + <TooltipContent> + <p>See all highlights on this page!</p> + </TooltipContent> + </Tooltip> + </TooltipProvider> - <Button onClick={handleSaveLink} variant='outline'> - {/* TODO: Fill heart if link is already saved */} - <Heart className='w-4 h-4' /> - </Button> - <Button onClick={handleOpenDrawer} variant='outline'> - <ArrowLeftFromLine className='w-4 h-4' /> - </Button> <form onSubmit={handleFileChange} className='hidden'> <input type='file' ref={fileInputRef} /> <input type='submit' role='button' /> diff --git a/src/scripts/highlighter/components/Highlight.tsx b/src/scripts/highlighter/components/Highlight.tsx index f379565..9837bc9 100644 --- a/src/scripts/highlighter/components/Highlight.tsx +++ b/src/scripts/highlighter/components/Highlight.tsx @@ -156,7 +156,7 @@ export const Highlight = ({ <PopoverTrigger asChild> <span highlight-id={`highlight-${highlightData.uuid}`} - className='bg-yellow-400 cursor-pointer' + className='bg-yellow-400 cursor-pointer highlight' onClick={(e) => { e.preventDefault(); e.stopPropagation();