-
-
Notifications
You must be signed in to change notification settings - Fork 891
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
Feature/blog share option #3928
Conversation
WalkthroughThis pull request introduces several new components and minor modifications. Two new icon components—one rendering a Facebook SVG and one rendering a Bluesky image—are added. The blog layout now includes a share functionality by integrating a SharePopup component, which provides a modal for social sharing and a copy-to-clipboard feature. Additionally, the MobileNavMenu’s link class names are reordered. Each component is implemented as a React function component, and styling is managed with Tailwind CSS and provided class names. Changes
Sequence Diagram(s)sequenceDiagram
participant U as User
participant BL as BlogLayout
participant SP as SharePopup
U->>BL: Clicks on ShareIcon
BL->>BL: Set showShare state to true
BL->>SP: Render SharePopup with post title
SP->>U: Display modal with social sharing options
U->>SP: Clicks close button or copy link
SP->>BL: Invoke closeSharePop callback
BL-->>SP: Unmount SharePopup (showShare set to false)
Suggested labels
Suggested reviewers
Poem
Warning There were issues while running some tools. Please review the errors and either fix the tool’s configuration or disable the tool if it’s a critical failure. 🔧 ESLint
npm warn config production Use ✨ Finishing Touches
🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Welcome to AsyncAPI. Thanks a lot for creating your first pull request. Please check out our contributors guide useful for opening a pull request.
Keep in mind there are also other channels you can use to interact with AsyncAPI community. For more details check out this issue.
✅ Deploy Preview for asyncapi-website ready!Built without sensitive environment variables
To edit notification comments on pull requests, go to your Netlify site configuration. |
We require all PRs to follow Conventional Commits specification.
|
✅ Deploy Preview for asyncapi-website ready!Built without sensitive environment variables
To edit notification comments on pull requests, go to your Netlify site configuration. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
🧹 Nitpick comments (12)
components/layout/BlogLayout.tsx (4)
15-16
: Fix import orderingThe import statements need to be properly ordered. The static analysis is flagging that imports from external packages should come before local imports.
Apply this change to fix the import ordering:
import AuthorAvatars from '../AuthorAvatars'; import AnnouncementHero from '../campaigns/AnnouncementHero'; import Head from '../Head'; import TOC from '../TOC'; import Container from './Container'; -import { ShareIcon } from '@heroicons/react/outline'; -import SharePopup from '../tools/SharePopup'; +import { ShareIcon } from '@heroicons/react/outline'; +import SharePopup from '../tools/SharePopup';The proper sorting would be:
- React and other standard libraries
- External packages like '@heroicons/react'
- Internal imports from your project
🧰 Tools
🪛 ESLint
[error] 1-16: Run autofix to sort these imports!
(simple-import-sort/imports)
[error] 15-15:
@heroicons/react/outline
import should occur before import of../../context/BlogContext
(import/order)
35-35
: Fix spacing in state declarationThere's a missing space after
const
in the state declaration.- const[showShare, setShowShare] = React.useState(false); + const [showShare, setShowShare] = React.useState(false);🧰 Tools
🪛 ESLint
[error] 35-35: Expected space(s) after "const".
(keyword-spacing)
[error] 35-35: Insert
·
(prettier/prettier)
87-87
: Fix formatting in the Share icon JSXThere are spacing issues in the onClick handler.
- <ShareIcon className='w-6 h-6 ml-auto text-gray-500 cursor-pointer hover:text-gray-800' onClick={()=>setShowShare(true)}/> + <ShareIcon + className='w-6 h-6 ml-auto text-gray-500 cursor-pointer hover:text-gray-800' + onClick={() => setShowShare(true)} + />🧰 Tools
🪛 ESLint
[error] 87-87: Replace
·className='w-6·h-6·ml-auto·text-gray-500·cursor-pointer·hover:text-gray-800'·onClick={()=>setShowShare(true)}
with⏎················className='w-6·h-6·ml-auto·text-gray-500·cursor-pointer·hover:text-gray-800'⏎················onClick={()·=>·setShowShare(true)}⏎··············
(prettier/prettier)
89-91
: Fix formatting in the SharePopup componentThe SharePopup component has formatting issues in its props.
- {showShare && ( - <SharePopup closeSharePop={()=>setShowShare(false)} posttitle={post.title}/> - )} + {showShare && ( + <SharePopup + closeSharePop={() => setShowShare(false)} + posttitle={post.title} + /> + )}🧰 Tools
🪛 ESLint
[error] 89-91: Replace
(⏎·············<SharePopup·closeSharePop={()=>setShowShare(false)}·posttitle={post.title}/>⏎············)
with<SharePopup·closeSharePop={()·=>·setShowShare(false)}·posttitle={post.title}·/>
(prettier/prettier)
components/tools/SharePopup.tsx (8)
1-6
: Fix import ordering and missing semicolonsThe imports need to be ordered properly and semicolons added.
-import React from 'react' -import IconTwitter from '../icons/Twitter' -import IconFacebook from '../icons/Facebook' -import IconLinkedIn from '../icons/LinkedIn' -import IconInstagram from '../icons/Instagram' +import React from 'react'; +import IconFacebook from '../icons/Facebook'; +import IconInstagram from '../icons/Instagram'; +import IconLinkedIn from '../icons/LinkedIn'; +import IconTwitter from '../icons/Twitter';🧰 Tools
🪛 ESLint
[error] 1-5: Run autofix to sort these imports!
(simple-import-sort/imports)
[error] 1-1: Insert
;
(prettier/prettier)
[error] 1-2: Missing semicolon.
(semi)
[error] 2-2: Insert
;
(prettier/prettier)
[error] 2-3: Missing semicolon.
(semi)
[error] 3-3: Insert
;
(prettier/prettier)
[error] 3-4: Missing semicolon.
(semi)
[error] 4-4: Insert
;
(prettier/prettier)
[error] 4-5: Missing semicolon.
(semi)
[error] 5-5: Insert
;
(prettier/prettier)
[error] 5-6: Missing semicolon.
(semi)
🪛 GitHub Actions: PR testing - if Node project
[error] 1-83: Multiple formatting errors detected: Missing semicolons, spacing issues, and incorrect usage of className.
7-10
: Fix interface formattingThe interface definition has spacing issues.
interface SharePopupProps { - closeSharePop:()=>void; - posttitle:string; + closeSharePop: () => void; + posttitle: string; }🧰 Tools
🪛 ESLint
[error] 8-8: Replace
()=>
with·()·=>·
(prettier/prettier)
[error] 9-9: Insert
·
(prettier/prettier)
12-21
: Fix formatting issues in function declaration and copy link handlerThere are several formatting issues in the component declaration and the copy link handler.
-const SharePopup = ({closeSharePop,posttitle}:SharePopupProps) => { - const[copied, setCopied] = React.useState(false); +const SharePopup = ({ closeSharePop, posttitle }: SharePopupProps) => { + const [copied, setCopied] = React.useState(false); const handleCopyLink = () => { const copyText = document.querySelector('input') as HTMLInputElement; + copyText.select(); document.execCommand('copy'); setCopied(true); - - } + };🧰 Tools
🪛 ESLint
[error] 12-12: A space is required after '{'.
(object-curly-spacing)
[error] 12-12: Replace
closeSharePop,posttitle}:
with·closeSharePop,·posttitle·}:·
(prettier/prettier)
[error] 12-12: A space is required after ','.
(comma-spacing)
[error] 12-12: A space is required before '}'.
(object-curly-spacing)
[error] 13-13: Expected space(s) after "const".
(keyword-spacing)
[error] 13-13: Insert
·
(prettier/prettier)
[error] 15-21: Expected blank line after variable declarations.
(newline-after-var)
[error] 16-16: Expected blank line after variable declarations.
(newline-after-var)
[error] 17-17: Expected blank line before this statement.
(padding-line-between-statements)
[error] 19-21: Block must not be padded by blank lines.
(padded-blocks)
[error] 20-21: Replace
⏎··}
with··};
(prettier/prettier)
23-24
: Fix modal accessibility and formattingThe modal implementation has several accessibility and formatting issues:
- Use proper semantic HTML for the modal
- Fix the quotation mark inconsistency (mixing single and double quotes)
- Add proper aria attributes for screen readers
- <div className=' fixed top-0 left-0 w-full h-full bg-gray-800/80 z-50 flex items-center justify-center' > - <div className=" md:scale-125 p-2 absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 md:-translate-y-[20%] bg-white w-[300px] rounded-lg shadow-lg"> + <div + className='fixed top-0 left-0 w-full h-full bg-gray-800/80 z-50 flex items-center justify-center' + role='dialog' + aria-modal='true' + aria-labelledby='share-modal-title' + > + <div className='md:scale-125 p-2 absolute top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 md:-translate-y-[20%] bg-white w-[300px] rounded-lg shadow-lg'>🧰 Tools
🪛 ESLint
[error] 23-23: Delete
·
(prettier/prettier)
[error] 24-24: Replace
····<div·className="·md:scale-125·p-2·absolute·top-1/2·left-1/2·-translate-x-1/2·-translate-y-1/2·md:-translate-y-[20%]·bg-white·w-[300px]·rounded-lg·shadow-lg"
with······<div·className='·md:scale-125·p-2·absolute·top-1/2·left-1/2·-translate-x-1/2·-translate-y-1/2·md:-translate-y-[20%]·bg-white·w-[300px]·rounded-lg·shadow-lg'
(prettier/prettier)
[error] 24-24: Unexpected usage of doublequote.
(jsx-quotes)
26-27
: Add accessibility improvements to the modal headerThe modal header needs accessibility improvements and consistent formatting.
- <h3 className='text-2xl font-bold'>Share</h3> - <button className='text-3xl' onClick={()=>closeSharePop()}>×</button> + <h3 id='share-modal-title' className='text-2xl font-bold'>Share</h3> + <button + className='text-3xl' + onClick={() => closeSharePop()} + aria-label='Close share dialog' + > + × + </button>🧰 Tools
🪛 ESLint
[error] 26-26: Insert
··
(prettier/prettier)
[error] 27-27: Replace
········<button·className='text-3xl'·onClick={()=>closeSharePop()}>×
with··········<button·className='text-3xl'·onClick={()·=>·closeSharePop()}>⏎············×⏎··········
(prettier/prettier)
70-75
: Enhance copy link functionalityThe copy link input needs accessibility improvements and the button needs better formatting and functionality.
<input + ref={inputRef} type='text' value={window.location.href} - className='w-3/4 p-2 border-[1px] border-gray-600 rounded-lg' + className='w-3/4 p-2 border-[1px] border-gray-600 rounded-lg' + readOnly + aria-label='Current page URL' /> - <button className='p-2 border-[1px] hover:bg-blue-500 rounded-lg bg-blue-600 text-white' onClick={()=>handleCopyLink()}>{copied?"copied":"copy"}</button> + <button + className='p-2 border-[1px] hover:bg-blue-500 rounded-lg bg-blue-600 text-white' + onClick={() => handleCopyLink()} + aria-label={copied ? 'Copied to clipboard' : 'Copy to clipboard'} + > + {copied ? 'Copied' : 'Copy'} + </button>🧰 Tools
🪛 ESLint
[error] 70-70: Insert
··
(prettier/prettier)
[error] 71-71: Insert
··
(prettier/prettier)
[error] 72-72: Insert
··
(prettier/prettier)
[error] 73-73: Insert
··
(prettier/prettier)
[error] 74-74: Insert
··
(prettier/prettier)
[error] 75-75: Replace
··········<button·className='p-2·border-[1px]·hover:bg-blue-500·rounded-lg·bg-blue-600·text-white'·onClick={()=>handleCopyLink()}>{copied?"copied":"copy"}
with············<button⏎··············className='p-2·border-[1px]·hover:bg-blue-500·rounded-lg·bg-blue-600·text-white'⏎··············onClick={()·=>·handleCopyLink()}⏎············>⏎··············{copied·?·'copied'·:·'copy'}⏎············
(prettier/prettier)
[error] 75-75: Operator '?' must be spaced.
(space-infix-ops)
[error] 75-75: Strings must use singlequote.
(quotes)
[error] 75-75: Operator ':' must be spaced.
(space-infix-ops)
[error] 75-75: Strings must use singlequote.
(quotes)
80-83
: Fix component closing syntax and add semicolonsFix the component's closing formatting and add missing semicolons.
) -} +}; -export default SharePopup +export default SharePopup;🧰 Tools
🪛 ESLint
[error] 80-80: Insert
;
(prettier/prettier)
[error] 80-81: Missing semicolon.
(semi)
[error] 81-81: Insert
;
(prettier/prettier)
[error] 81-82: Missing semicolon.
(semi)
[error] 83-83: Insert
;
(prettier/prettier)
🪛 GitHub Actions: PR testing - if Node project
[error] 1-83: Multiple formatting errors detected: Missing semicolons, spacing issues, and incorrect usage of className.
1-83
: Add keyboard navigation and UI improvementsThe share popup should support keyboard navigation and have improved UI for better accessibility and user experience.
Include the following improvements:
- Add ESC key handling to close the popup
- Ensure all interactive elements are tabbable
- Add focus trap to keep focus within the modal
- Improve responsive design
I can provide the complete implementation if you'd like.
Would you like me to provide a more comprehensive implementation with all these improvements?
🧰 Tools
🪛 ESLint
[error] 1-5: Run autofix to sort these imports!
(simple-import-sort/imports)
[error] 1-1: Insert
;
(prettier/prettier)
[error] 1-2: Missing semicolon.
(semi)
[error] 2-2: Insert
;
(prettier/prettier)
[error] 2-3: Missing semicolon.
(semi)
[error] 3-3: Insert
;
(prettier/prettier)
[error] 3-4: Missing semicolon.
(semi)
[error] 4-4: Insert
;
(prettier/prettier)
[error] 4-5: Missing semicolon.
(semi)
[error] 5-5: Insert
;
(prettier/prettier)
[error] 5-6: Missing semicolon.
(semi)
[error] 8-8: Replace
()=>
with·()·=>·
(prettier/prettier)
[error] 9-9: Insert
·
(prettier/prettier)
[error] 12-12: A space is required after '{'.
(object-curly-spacing)
[error] 12-12: Replace
closeSharePop,posttitle}:
with·closeSharePop,·posttitle·}:·
(prettier/prettier)
[error] 12-12: A space is required after ','.
(comma-spacing)
[error] 12-12: A space is required before '}'.
(object-curly-spacing)
[error] 13-13: Expected space(s) after "const".
(keyword-spacing)
[error] 13-13: Insert
·
(prettier/prettier)
[error] 15-21: Expected blank line after variable declarations.
(newline-after-var)
[error] 16-16: Expected blank line after variable declarations.
(newline-after-var)
[error] 17-17: Expected blank line before this statement.
(padding-line-between-statements)
[error] 19-21: Block must not be padded by blank lines.
(padded-blocks)
[error] 20-21: Replace
⏎··}
with··};
(prettier/prettier)
[error] 21-22: Missing semicolon.
(semi)
[error] 22-80: Expected blank line before this statement.
(padding-line-between-statements)
[error] 23-23: Delete
·
(prettier/prettier)
[error] 24-24: Replace
····<div·className="·md:scale-125·p-2·absolute·top-1/2·left-1/2·-translate-x-1/2·-translate-y-1/2·md:-translate-y-[20%]·bg-white·w-[300px]·rounded-lg·shadow-lg"
with······<div·className='·md:scale-125·p-2·absolute·top-1/2·left-1/2·-translate-x-1/2·-translate-y-1/2·md:-translate-y-[20%]·bg-white·w-[300px]·rounded-lg·shadow-lg'
(prettier/prettier)
[error] 24-24: Unexpected usage of doublequote.
(jsx-quotes)
[error] 25-25: Replace
······
with········
(prettier/prettier)
[error] 26-26: Insert
··
(prettier/prettier)
[error] 27-27: Replace
········<button·className='text-3xl'·onClick={()=>closeSharePop()}>×
with··········<button·className='text-3xl'·onClick={()·=>·closeSharePop()}>⏎············×⏎··········
(prettier/prettier)
[error] 28-28: Insert
··
(prettier/prettier)
[error] 29-29: Insert
··
(prettier/prettier)
[error] 30-30: Insert
··
(prettier/prettier)
[error] 31-31: Replace
········
with··········
(prettier/prettier)
[error] 32-32: Insert
··
(prettier/prettier)
[error] 33-33: Insert
··
(prettier/prettier)
[error] 34-34: Insert
··
(prettier/prettier)
[error] 35-35: Replace
············
with··············
(prettier/prettier)
[error] 36-36: Insert
··
(prettier/prettier)
[error] 37-37: Insert
··
(prettier/prettier)
[error] 38-38: Replace
············<IconTwitter·className='h-6'
with··············<IconTwitter·className='h-6'·
(prettier/prettier)
[error] 39-39: Insert
··
(prettier/prettier)
[error] 40-40: Insert
··
(prettier/prettier)
[error] 41-41: Insert
··
(prettier/prettier)
[error] 42-42: Insert
··
(prettier/prettier)
[error] 43-43: Insert
··
(prettier/prettier)
[error] 44-44: Insert
··
(prettier/prettier)
[error] 45-45: Insert
··
(prettier/prettier)
[error] 46-46: Replace
············<IconFacebook·className='h-6'
with··············<IconFacebook·className='h-6'·
(prettier/prettier)
[error] 47-47: Insert
··
(prettier/prettier)
[error] 48-48: Insert
··
(prettier/prettier)
[error] 49-49: Insert
··
(prettier/prettier)
[error] 50-50: Insert
··
(prettier/prettier)
[error] 51-51: Insert
··
(prettier/prettier)
[error] 52-52: Insert
··
(prettier/prettier)
[error] 53-53: Insert
··
(prettier/prettier)
[error] 54-54: Replace
<IconLinkedIn·className='h-6'
with··<IconLinkedIn·className='h-6'·
(prettier/prettier)
[error] 55-55: Insert
··
(prettier/prettier)
[error] 56-56: Insert
··
(prettier/prettier)
[error] 57-57: Insert
··
(prettier/prettier)
[error] 58-58: Insert
··
(prettier/prettier)
[error] 59-59: Insert
··
(prettier/prettier)
[error] 60-60: Insert
··
(prettier/prettier)
[error] 61-61: Insert
··
(prettier/prettier)
[error] 62-62: Replace
············<IconInstagram·className='h-6'
with··············<IconInstagram·className='h-6'·
(prettier/prettier)
[error] 63-64: Replace
··········</a>⏎
with············</a>
(prettier/prettier)
[error] 65-65: Insert
··
(prettier/prettier)
[error] 66-66: Insert
··
(prettier/prettier)
[error] 67-67: Insert
··
(prettier/prettier)
[error] 68-68: Insert
··
(prettier/prettier)
[error] 69-69: Insert
··
(prettier/prettier)
[error] 70-70: Insert
··
(prettier/prettier)
[error] 71-71: Insert
··
(prettier/prettier)
[error] 72-72: Insert
··
(prettier/prettier)
[error] 73-73: Insert
··
(prettier/prettier)
[error] 74-74: Insert
··
(prettier/prettier)
[error] 75-75: Replace
··········<button·className='p-2·border-[1px]·hover:bg-blue-500·rounded-lg·bg-blue-600·text-white'·onClick={()=>handleCopyLink()}>{copied?"copied":"copy"}
with············<button⏎··············className='p-2·border-[1px]·hover:bg-blue-500·rounded-lg·bg-blue-600·text-white'⏎··············onClick={()·=>·handleCopyLink()}⏎············>⏎··············{copied·?·'copied'·:·'copy'}⏎············
(prettier/prettier)
[error] 75-75: Operator '?' must be spaced.
(space-infix-ops)
[error] 75-75: Strings must use singlequote.
(quotes)
[error] 75-75: Operator ':' must be spaced.
(space-infix-ops)
[error] 75-75: Strings must use singlequote.
(quotes)
[error] 76-76: Insert
··
(prettier/prettier)
[error] 77-77: Insert
··
(prettier/prettier)
[error] 78-78: Insert
··
(prettier/prettier)
[error] 79-79: Insert
··
(prettier/prettier)
[error] 80-80: Insert
;
(prettier/prettier)
[error] 80-81: Missing semicolon.
(semi)
[error] 81-81: Insert
;
(prettier/prettier)
[error] 81-82: Missing semicolon.
(semi)
[error] 83-83: Insert
;
(prettier/prettier)
🪛 GitHub Actions: PR testing - if Node project
[error] 1-83: Multiple formatting errors detected: Missing semicolons, spacing issues, and incorrect usage of className.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (4)
components/icons/Facebook.tsx
(1 hunks)components/icons/Instagram.tsx
(1 hunks)components/layout/BlogLayout.tsx
(3 hunks)components/tools/SharePopup.tsx
(1 hunks)
🧰 Additional context used
🪛 ESLint
components/tools/SharePopup.tsx
[error] 1-5: Run autofix to sort these imports!
(simple-import-sort/imports)
[error] 1-1: Insert ;
(prettier/prettier)
[error] 1-2: Missing semicolon.
(semi)
[error] 2-2: Insert ;
(prettier/prettier)
[error] 2-3: Missing semicolon.
(semi)
[error] 3-3: Insert ;
(prettier/prettier)
[error] 3-4: Missing semicolon.
(semi)
[error] 4-4: Insert ;
(prettier/prettier)
[error] 4-5: Missing semicolon.
(semi)
[error] 5-5: Insert ;
(prettier/prettier)
[error] 5-6: Missing semicolon.
(semi)
[error] 8-8: Replace ()=>
with ·()·=>·
(prettier/prettier)
[error] 9-9: Insert ·
(prettier/prettier)
[error] 12-12: A space is required after '{'.
(object-curly-spacing)
[error] 12-12: Replace closeSharePop,posttitle}:
with ·closeSharePop,·posttitle·}:·
(prettier/prettier)
[error] 12-12: A space is required after ','.
(comma-spacing)
[error] 12-12: A space is required before '}'.
(object-curly-spacing)
[error] 13-13: Expected space(s) after "const".
(keyword-spacing)
[error] 13-13: Insert ·
(prettier/prettier)
[error] 15-21: Expected blank line after variable declarations.
(newline-after-var)
[error] 16-16: Expected blank line after variable declarations.
(newline-after-var)
[error] 17-17: Expected blank line before this statement.
(padding-line-between-statements)
[error] 19-21: Block must not be padded by blank lines.
(padded-blocks)
[error] 20-21: Replace ⏎··}
with ··};
(prettier/prettier)
[error] 21-22: Missing semicolon.
(semi)
[error] 22-80: Expected blank line before this statement.
(padding-line-between-statements)
[error] 23-23: Delete ·
(prettier/prettier)
[error] 24-24: Replace ····<div·className="·md:scale-125·p-2·absolute·top-1/2·left-1/2·-translate-x-1/2·-translate-y-1/2·md:-translate-y-[20%]·bg-white·w-[300px]·rounded-lg·shadow-lg"
with ······<div·className='·md:scale-125·p-2·absolute·top-1/2·left-1/2·-translate-x-1/2·-translate-y-1/2·md:-translate-y-[20%]·bg-white·w-[300px]·rounded-lg·shadow-lg'
(prettier/prettier)
[error] 24-24: Unexpected usage of doublequote.
(jsx-quotes)
[error] 25-25: Replace ······
with ········
(prettier/prettier)
[error] 26-26: Insert ··
(prettier/prettier)
[error] 27-27: Replace ········<button·className='text-3xl'·onClick={()=>closeSharePop()}>×
with ··········<button·className='text-3xl'·onClick={()·=>·closeSharePop()}>⏎············×⏎··········
(prettier/prettier)
[error] 28-28: Insert ··
(prettier/prettier)
[error] 29-29: Insert ··
(prettier/prettier)
[error] 30-30: Insert ··
(prettier/prettier)
[error] 31-31: Replace ········
with ··········
(prettier/prettier)
[error] 32-32: Insert ··
(prettier/prettier)
[error] 33-33: Insert ··
(prettier/prettier)
[error] 34-34: Insert ··
(prettier/prettier)
[error] 35-35: Replace ············
with ··············
(prettier/prettier)
[error] 36-36: Insert ··
(prettier/prettier)
[error] 37-37: Insert ··
(prettier/prettier)
[error] 38-38: Replace ············<IconTwitter·className='h-6'
with ··············<IconTwitter·className='h-6'·
(prettier/prettier)
[error] 39-39: Insert ··
(prettier/prettier)
[error] 40-40: Insert ··
(prettier/prettier)
[error] 41-41: Insert ··
(prettier/prettier)
[error] 42-42: Insert ··
(prettier/prettier)
[error] 43-43: Insert ··
(prettier/prettier)
[error] 44-44: Insert ··
(prettier/prettier)
[error] 45-45: Insert ··
(prettier/prettier)
[error] 46-46: Replace ············<IconFacebook·className='h-6'
with ··············<IconFacebook·className='h-6'·
(prettier/prettier)
[error] 47-47: Insert ··
(prettier/prettier)
[error] 48-48: Insert ··
(prettier/prettier)
[error] 49-49: Insert ··
(prettier/prettier)
[error] 50-50: Insert ··
(prettier/prettier)
[error] 51-51: Insert ··
(prettier/prettier)
[error] 52-52: Insert ··
(prettier/prettier)
[error] 53-53: Insert ··
(prettier/prettier)
[error] 54-54: Replace <IconLinkedIn·className='h-6'
with ··<IconLinkedIn·className='h-6'·
(prettier/prettier)
[error] 55-55: Insert ··
(prettier/prettier)
[error] 56-56: Insert ··
(prettier/prettier)
[error] 57-57: Insert ··
(prettier/prettier)
[error] 58-58: Insert ··
(prettier/prettier)
[error] 59-59: Insert ··
(prettier/prettier)
[error] 60-60: Insert ··
(prettier/prettier)
[error] 61-61: Insert ··
(prettier/prettier)
[error] 62-62: Replace ············<IconInstagram·className='h-6'
with ··············<IconInstagram·className='h-6'·
(prettier/prettier)
[error] 63-64: Replace ··········</a>⏎
with ············</a>
(prettier/prettier)
[error] 65-65: Insert ··
(prettier/prettier)
[error] 66-66: Insert ··
(prettier/prettier)
[error] 67-67: Insert ··
(prettier/prettier)
[error] 68-68: Insert ··
(prettier/prettier)
[error] 69-69: Insert ··
(prettier/prettier)
[error] 70-70: Insert ··
(prettier/prettier)
[error] 71-71: Insert ··
(prettier/prettier)
[error] 72-72: Insert ··
(prettier/prettier)
[error] 73-73: Insert ··
(prettier/prettier)
[error] 74-74: Insert ··
(prettier/prettier)
[error] 75-75: Replace ··········<button·className='p-2·border-[1px]·hover:bg-blue-500·rounded-lg·bg-blue-600·text-white'·onClick={()=>handleCopyLink()}>{copied?"copied":"copy"}
with ············<button⏎··············className='p-2·border-[1px]·hover:bg-blue-500·rounded-lg·bg-blue-600·text-white'⏎··············onClick={()·=>·handleCopyLink()}⏎············>⏎··············{copied·?·'copied'·:·'copy'}⏎············
(prettier/prettier)
[error] 75-75: Operator '?' must be spaced.
(space-infix-ops)
[error] 75-75: Strings must use singlequote.
(quotes)
[error] 75-75: Operator ':' must be spaced.
(space-infix-ops)
[error] 75-75: Strings must use singlequote.
(quotes)
[error] 76-76: Insert ··
(prettier/prettier)
[error] 77-77: Insert ··
(prettier/prettier)
[error] 78-78: Insert ··
(prettier/prettier)
[error] 79-79: Insert ··
(prettier/prettier)
[error] 80-80: Insert ;
(prettier/prettier)
[error] 80-81: Missing semicolon.
(semi)
[error] 81-81: Insert ;
(prettier/prettier)
[error] 81-82: Missing semicolon.
(semi)
[error] 83-83: Insert ;
(prettier/prettier)
components/icons/Facebook.tsx
[error] 1-1: Insert ;
(prettier/prettier)
[error] 1-2: Missing semicolon.
(semi)
[error] 3-3: A space is required after '{'.
(object-curly-spacing)
[error] 3-3: Replace className=''
with ·className·=·''·
(prettier/prettier)
[error] 3-3: Operator '=' must be spaced.
(space-infix-ops)
[error] 3-3: A space is required before '}'.
(object-curly-spacing)
[error] 7-7: Insert ··
(prettier/prettier)
[error] 8-8: Insert ;
(prettier/prettier)
[error] 8-9: Missing semicolon.
(semi)
[error] 9-9: Insert ;
(prettier/prettier)
[error] 9-10: Missing semicolon.
(semi)
[error] 11-11: Insert ;
(prettier/prettier)
components/icons/Instagram.tsx
[error] 1-1: Insert ;
(prettier/prettier)
[error] 1-2: Missing semicolon.
(semi)
[error] 3-3: A space is required after '{'.
(object-curly-spacing)
[error] 3-3: Replace className=''
with ·className·=·''·
(prettier/prettier)
[error] 3-3: Operator '=' must be spaced.
(space-infix-ops)
[error] 3-3: A space is required before '}'.
(object-curly-spacing)
[error] 5-5: Insert ····
(prettier/prettier)
[error] 6-6: Insert ····
(prettier/prettier)
[error] 7-7: Insert ····
(prettier/prettier)
[error] 8-8: Insert ;
(prettier/prettier)
[error] 8-9: Missing semicolon.
(semi)
[error] 9-9: Insert ;
(prettier/prettier)
[error] 9-10: Missing semicolon.
(semi)
[error] 11-11: Insert ;
(prettier/prettier)
components/layout/BlogLayout.tsx
[error] 1-16: Run autofix to sort these imports!
(simple-import-sort/imports)
[error] 15-15: @heroicons/react/outline
import should occur before import of ../../context/BlogContext
(import/order)
[error] 35-35: Expected space(s) after "const".
(keyword-spacing)
[error] 35-35: Insert ·
(prettier/prettier)
[error] 87-87: Replace ·className='w-6·h-6·ml-auto·text-gray-500·cursor-pointer·hover:text-gray-800'·onClick={()=>setShowShare(true)}
with ⏎················className='w-6·h-6·ml-auto·text-gray-500·cursor-pointer·hover:text-gray-800'⏎················onClick={()·=>·setShowShare(true)}⏎··············
(prettier/prettier)
[error] 89-91: Replace (⏎·············<SharePopup·closeSharePop={()=>setShowShare(false)}·posttitle={post.title}/>⏎············)
with <SharePopup·closeSharePop={()·=>·setShowShare(false)}·posttitle={post.title}·/>
(prettier/prettier)
🪛 GitHub Actions: PR testing - if Node project
components/tools/SharePopup.tsx
[error] 1-83: Multiple formatting errors detected: Missing semicolons, spacing issues, and incorrect usage of className.
components/icons/Facebook.tsx
[error] 1-11: Multiple formatting errors detected: Missing semicolons, spacing issues, and incorrect usage of className.
components/icons/Instagram.tsx
[error] 1-11: Multiple formatting errors detected: Missing semicolons, spacing issues, and incorrect usage of className.
components/layout/BlogLayout.tsx
[error] 1-89: Multiple formatting errors detected: Import sorting, spacing issues, and incorrect usage of className.
components/icons/Instagram.tsx
Outdated
import React from 'react' | ||
|
||
const IconInstagram = ({className=''}) => { | ||
return ( | ||
<svg className={className} fill='currentColor' viewBox='0 0 23 23'> | ||
<path d='M11.5 3.5c-3.45 0-3.75.02-5.05.1-2.5.15-3.77 1.43-3.92 3.92-.08 1.3-.1 1.6-.1 5.05s.02 3.75.1 5.05c.15 2.5 1.43 3.77 3.92 3.92 1.3.08 1.6.1 5.05.1s3.75-.02 5.05-.1c2.5-.15 3.77-1.43 3.92-3.92.08-1.3.1-1.6.1-5.05s-.02-3.75-.1-5.05c-.15-2.5-1.43-3.77-3.92-3.92-1.3-.08-1.6-.1-5.05-.1zm0 1.8c3.4 0 3.68.02 4.95.09 2.02.12 3.12 1.22 3.24 3.24.07 1.27.09 1.55.09 4.95s-.02 3.68-.09 4.95c-.12 2.02-1.22 3.12-3.24 3.24-1.27.07-1.55.09-4.95.09s-3.68-.02-4.95-.09c-2.02-.12-3.12-1.22-3.24-3.24-.07-1.27-.09-1.55-.09-4.95s.02-3.68.09-4.95c.12-2.02 1.22-3.12 3.24-3.24 1.27-.07 1.55-.09 4.95-.09zm0 3.3a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9zm0 7.5a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm5.85-9.3a1.05 1.05 0 1 0 0 2.1 1.05 1.05 0 0 0 0-2.1z' /> | ||
</svg> | ||
) | ||
} | ||
|
||
export default IconInstagram |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix formatting issues in the Instagram icon component
Similar to the Facebook component, this file has formatting issues causing pipeline failures:
- Missing semicolons
- Missing spaces in the prop destructuring
- Improper indentation of the SVG content
Apply these changes to fix the formatting issues:
-import React from 'react'
+import React from 'react';
-const IconInstagram = ({className=''}) => {
+const IconInstagram = ({ className = '' }) => {
return (
-<svg className={className} fill='currentColor' viewBox='0 0 23 23'>
- <path d='M11.5 3.5c-3.45 0-3.75.02-5.05.1-2.5.15-3.77 1.43-3.92 3.92-.08 1.3-.1 1.6-.1 5.05s.02 3.75.1 5.05c.15 2.5 1.43 3.77 3.92 3.92 1.3.08 1.6.1 5.05.1s3.75-.02 5.05-.1c2.5-.15 3.77-1.43 3.92-3.92.08-1.3.1-1.6.1-5.05s-.02-3.75-.1-5.05c-.15-2.5-1.43-3.77-3.92-3.92-1.3-.08-1.6-.1-5.05-.1zm0 1.8c3.4 0 3.68.02 4.95.09 2.02.12 3.12 1.22 3.24 3.24.07 1.27.09 1.55.09 4.95s-.02 3.68-.09 4.95c-.12 2.02-1.22 3.12-3.24 3.24-1.27.07-1.55.09-4.95.09s-3.68-.02-4.95-.09c-2.02-.12-3.12-1.22-3.24-3.24-.07-1.27-.09-1.55-.09-4.95s.02-3.68.09-4.95c.12-2.02 1.22-3.12 3.24-3.24 1.27-.07 1.55-.09 4.95-.09zm0 3.3a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9zm0 7.5a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm5.85-9.3a1.05 1.05 0 1 0 0 2.1 1.05 1.05 0 0 0 0-2.1z' />
-</svg>
+ <svg className={className} fill='currentColor' viewBox='0 0 23 23'>
+ <path d='M11.5 3.5c-3.45 0-3.75.02-5.05.1-2.5.15-3.77 1.43-3.92 3.92-.08 1.3-.1 1.6-.1 5.05s.02 3.75.1 5.05c.15 2.5 1.43 3.77 3.92 3.92 1.3.08 1.6.1 5.05.1s3.75-.02 5.05-.1c2.5-.15 3.77-1.43 3.92-3.92.08-1.3.1-1.6.1-5.05s-.02-3.75-.1-5.05c-.15-2.5-1.43-3.77-3.92-3.92-1.3-.08-1.6-.1-5.05-.1zm0 1.8c3.4 0 3.68.02 4.95.09 2.02.12 3.12 1.22 3.24 3.24.07 1.27.09 1.55.09 4.95s-.02 3.68-.09 4.95c-.12 2.02-1.22 3.12-3.24 3.24-1.27.07-1.55.09-4.95.09s-3.68-.02-4.95-.09c-2.02-.12-3.12-1.22-3.24-3.24-.07-1.27-.09-1.55-.09-4.95s.02-3.68.09-4.95c.12-2.02 1.22-3.12 3.24-3.24 1.27-.07 1.55-.09 4.95-.09zm0 3.3a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9zm0 7.5a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm5.85-9.3a1.05 1.05 0 1 0 0 2.1 1.05 1.05 0 0 0 0-2.1z' />
+ </svg>
)
-}
+};
-export default IconInstagram
+export default IconInstagram;
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
import React from 'react' | |
const IconInstagram = ({className=''}) => { | |
return ( | |
<svg className={className} fill='currentColor' viewBox='0 0 23 23'> | |
<path d='M11.5 3.5c-3.45 0-3.75.02-5.05.1-2.5.15-3.77 1.43-3.92 3.92-.08 1.3-.1 1.6-.1 5.05s.02 3.75.1 5.05c.15 2.5 1.43 3.77 3.92 3.92 1.3.08 1.6.1 5.05.1s3.75-.02 5.05-.1c2.5-.15 3.77-1.43 3.92-3.92.08-1.3.1-1.6.1-5.05s-.02-3.75-.1-5.05c-.15-2.5-1.43-3.77-3.92-3.92-1.3-.08-1.6-.1-5.05-.1zm0 1.8c3.4 0 3.68.02 4.95.09 2.02.12 3.12 1.22 3.24 3.24.07 1.27.09 1.55.09 4.95s-.02 3.68-.09 4.95c-.12 2.02-1.22 3.12-3.24 3.24-1.27.07-1.55.09-4.95.09s-3.68-.02-4.95-.09c-2.02-.12-3.12-1.22-3.24-3.24-.07-1.27-.09-1.55-.09-4.95s.02-3.68.09-4.95c.12-2.02 1.22-3.12 3.24-3.24 1.27-.07 1.55-.09 4.95-.09zm0 3.3a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9zm0 7.5a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm5.85-9.3a1.05 1.05 0 1 0 0 2.1 1.05 1.05 0 0 0 0-2.1z' /> | |
</svg> | |
) | |
} | |
export default IconInstagram | |
import React from 'react'; | |
const IconInstagram = ({ className = '' }) => { | |
return ( | |
<svg className={className} fill='currentColor' viewBox='0 0 23 23'> | |
<path d='M11.5 3.5c-3.45 0-3.75.02-5.05.1-2.5.15-3.77 1.43-3.92 3.92-.08 1.3-.1 1.6-.1 5.05s.02 3.75.1 5.05c.15 2.5 1.43 3.77 3.92 3.92 1.3.08 1.6.1 5.05.1s3.75-.02 5.05-.1c2.5-.15 3.77-1.43 3.92-3.92.08-1.3.1-1.6.1-5.05s-.02-3.75-.1-5.05c-.15-2.5-1.43-3.77-3.92-3.92-1.3-.08-1.6-.1-5.05-.1zm0 1.8c3.4 0 3.68.02 4.95.09 2.02.12 3.12 1.22 3.24 3.24.07 1.27.09 1.55.09 4.95s-.02 3.68-.09 4.95c-.12 2.02-1.22 3.12-3.24 3.24-1.27.07-1.55.09-4.95.09s-3.68-.02-4.95-.09c-2.02-.12-3.12-1.22-3.24-3.24-.07-1.27-.09-1.55-.09-4.95s.02-3.68.09-4.95c.12-2.02 1.22-3.12 3.24-3.24 1.27-.07 1.55-.09 4.95-.09zm0 3.3a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9zm0 7.5a3 3 0 1 1 0-6 3 3 0 0 1 0 6zm5.85-9.3a1.05 1.05 0 1 0 0 2.1 1.05 1.05 0 0 0 0-2.1z' /> | |
</svg> | |
) | |
}; | |
export default IconInstagram; |
🧰 Tools
🪛 ESLint
[error] 1-1: Insert ;
(prettier/prettier)
[error] 1-2: Missing semicolon.
(semi)
[error] 3-3: A space is required after '{'.
(object-curly-spacing)
[error] 3-3: Replace className=''
with ·className·=·''·
(prettier/prettier)
[error] 3-3: Operator '=' must be spaced.
(space-infix-ops)
[error] 3-3: A space is required before '}'.
(object-curly-spacing)
[error] 5-5: Insert ····
(prettier/prettier)
[error] 6-6: Insert ····
(prettier/prettier)
[error] 7-7: Insert ····
(prettier/prettier)
[error] 8-8: Insert ;
(prettier/prettier)
[error] 8-9: Missing semicolon.
(semi)
[error] 9-9: Insert ;
(prettier/prettier)
[error] 9-10: Missing semicolon.
(semi)
[error] 11-11: Insert ;
(prettier/prettier)
🪛 GitHub Actions: PR testing - if Node project
[error] 1-11: Multiple formatting errors detected: Missing semicolons, spacing issues, and incorrect usage of className.
@himal-13 There's already a PR open for this issue, but I had a look at the deploy preview of your PR, and it looks great and works properly. So, maybe we can consider this PR as well. However, some checks are failing. To fix that, you need to change your PR title — make everything lowercase and add the prefix "feat: ". Also, try running "npm run lint:fix" locally to resolve lint errors. Additionally, the links for Facebook and Instagram aren't working as expected. I think we don't need them, so you could replace them with a link to Bluesky instead |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 7
♻️ Duplicate comments (1)
components/tools/SharePopup.tsx (1)
15-23
:⚠️ Potential issueUse a ref instead of direct DOM query selection.
Using
document.querySelector('input')
is brittle because it selects the first input element in the entire document, which could be any input field.+ const inputRef = React.useRef<HTMLInputElement>(null); + const handleCopyLink = () => { - const copyText = document.querySelector('input') as HTMLInputElement; + if (!inputRef.current) return; - copyText.select(); - navigator.clipboard.writeText(copyText.value).then(() => { + navigator.clipboard.writeText(inputRef.current.value).then(() => { setCopied(true); + // Reset the "copied" state after 2 seconds + setTimeout(() => setCopied(false), 2000); } - ); + ).catch(err => { + console.error('Failed to copy text: ', err); + }); };Also, don't forget to add the ref to the input element:
- <input type='text' value={window.location.href} className='w-3/4 rounded-lg border border-gray-600 p-2' /> + <input + ref={inputRef} + type='text' + value={window.location.href} + className='w-3/4 rounded-lg border border-gray-600 p-2' + />
🧹 Nitpick comments (5)
components/icons/Bluesky.tsx (2)
5-5
: Consider hosting the image locally instead of using an external source.Using an external image source from Wikipedia creates a dependency on an external service. If the image URL changes or becomes unavailable, it could break your icon.
Download and store the image locally in your project's assets directory, then import and use it:
- <img className={className} src="https://upload.wikimedia.org/wikipedia/commons/7/7a/Bluesky_Logo.svg" alt="Bluesky Logo" /> + <img className={className} src='/assets/images/bluesky-logo.svg' alt='Bluesky Logo' />This approach would also improve performance by eliminating an external network request.
🧰 Tools
🪛 GitHub Actions: PR testing - if Node project
[error] 5-5: ESLint: Unexpected usage of doublequote. (jsx-quotes)
3-7
: Add proper TypeScript typing for the component props.The component is missing proper TypeScript type definitions, which would improve code quality and provide better IDE support.
-const IconBlueSky = ({className=''}) => { +interface IconBlueSkyProps { + className?: string; +} + +const IconBlueSky: React.FC<IconBlueSkyProps> = ({ className='' }) => { return ( <img className={className} src="https://upload.wikimedia.org/wikipedia/commons/7/7a/Bluesky_Logo.svg" alt="Bluesky Logo" /> )🧰 Tools
🪛 GitHub Actions: PR testing - if Node project
[error] 1-7: Prettier formatting check failed. Multiple formatting issues detected including missing semicolons and spacing errors.
[error] 3-3: ESLint: A space is required after '{'. (object-curly-spacing)
[error] 5-5: ESLint: Unexpected usage of doublequote. (jsx-quotes)
components/tools/SharePopup.tsx (3)
30-32
: Replace HTML entity with a proper close icon.Using the HTML entity
×
for the close button isn't ideal for accessibility. Consider using a proper semantic close icon.- <button className='text-3xl' onClick={() => closeSharePop()}> - × - </button> + <button + className='text-3xl' + onClick={() => closeSharePop()} + aria-label='Close' + > + <span aria-hidden='true'>×</span> + </button>Alternatively, you could use an SVG icon from your icon library for better visual consistency.
67-67
: Make the URL input read-only.The URL input field should be read-only since users don't need to edit the URL before copying it.
- <input type='text' value={window.location.href} className='w-3/4 rounded-lg border border-gray-600 p-2' /> + <input + type='text' + value={window.location.href} + readOnly + className='w-3/4 rounded-lg border border-gray-600 p-2' + />
12-23
: Add error handling for the Clipboard API.The Clipboard API might fail in certain environments or with certain permissions. Add proper error handling.
const handleCopyLink = () => { const copyText = document.querySelector('input') as HTMLInputElement; copyText.select(); - navigator.clipboard.writeText(copyText.value).then(() => { - setCopied(true); - } - ); + navigator.clipboard.writeText(copyText.value) + .then(() => { + setCopied(true); + // Reset the copied state after 2 seconds + setTimeout(() => setCopied(false), 2000); + }) + .catch(err => { + console.error('Failed to copy text:', err); + // Fallback to older method if Clipboard API fails + try { + document.execCommand('copy'); + setCopied(true); + setTimeout(() => setCopied(false), 2000); + } catch (e) { + console.error('Fallback copy method failed:', e); + alert('Copy failed. Please copy the URL manually.'); + } + }); };
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (5)
components/icons/Bluesky.tsx
(1 hunks)components/icons/Facebook.tsx
(1 hunks)components/layout/BlogLayout.tsx
(4 hunks)components/navigation/MobileNavMenu.tsx
(3 hunks)components/tools/SharePopup.tsx
(1 hunks)
✅ Files skipped from review due to trivial changes (1)
- components/navigation/MobileNavMenu.tsx
🚧 Files skipped from review as they are similar to previous changes (2)
- components/icons/Facebook.tsx
- components/layout/BlogLayout.tsx
🧰 Additional context used
🪛 GitHub Actions: PR testing - if Node project
components/icons/Bluesky.tsx
[error] 1-7: Prettier formatting check failed. Multiple formatting issues detected including missing semicolons and spacing errors.
[error] 1-1: ESLint: Missing semicolon. (semi)
[error] 3-3: ESLint: A space is required after '{'. (object-curly-spacing)
[error] 5-5: ESLint: Unexpected usage of doublequote. (jsx-quotes)
components/tools/SharePopup.tsx
[error] 1-1: ESLint: Run autofix to sort these imports! (simple-import-sort/imports)
[warning] 27-27: Arbitrary value classname 'md:-translate-y-[20%]' should not start with a dash (-) (tailwindcss/enforces-negative-arbitrary-values)
[error] 55-55: ESLint: Unexpected usage of doublequote. (jsx-quotes)
import React from 'react' | ||
|
||
const IconBlueSky = ({className=''}) => { | ||
return ( | ||
<img className={className} src="https://upload.wikimedia.org/wikipedia/commons/7/7a/Bluesky_Logo.svg" alt="Bluesky Logo" /> | ||
) | ||
} | ||
|
||
export default IconBlueSky; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix linting and formatting issues.
There are multiple linting and formatting issues that need to be addressed:
- Missing semicolon after import statement
- Missing space after opening curly brace in props destructuring
- Using double quotes instead of single quotes for JSX attributes
-import React from 'react'
+import React from 'react';
-const IconBlueSky = ({className=''}) => {
+const IconBlueSky = ({ className='' }) => {
return (
- <img className={className} src="https://upload.wikimedia.org/wikipedia/commons/7/7a/Bluesky_Logo.svg" alt="Bluesky Logo" />
+ <img className={className} src='https://upload.wikimedia.org/wikipedia/commons/7/7a/Bluesky_Logo.svg' alt='Bluesky Logo' />
)
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
import React from 'react' | |
const IconBlueSky = ({className=''}) => { | |
return ( | |
<img className={className} src="https://upload.wikimedia.org/wikipedia/commons/7/7a/Bluesky_Logo.svg" alt="Bluesky Logo" /> | |
) | |
} | |
export default IconBlueSky; | |
import React from 'react'; | |
const IconBlueSky = ({ className='' }) => { | |
return ( | |
<img className={className} src='https://upload.wikimedia.org/wikipedia/commons/7/7a/Bluesky_Logo.svg' alt='Bluesky Logo' /> | |
) | |
} | |
export default IconBlueSky; |
🧰 Tools
🪛 GitHub Actions: PR testing - if Node project
[error] 1-7: Prettier formatting check failed. Multiple formatting issues detected including missing semicolons and spacing errors.
[error] 1-1: ESLint: Missing semicolon. (semi)
[error] 3-3: ESLint: A space is required after '{'. (object-curly-spacing)
[error] 5-5: ESLint: Unexpected usage of doublequote. (jsx-quotes)
href={`https://twitter.com/intent/tweet?url=${window.location.href}&text=${posttitle}`} | ||
target='_blank' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add URL encoding for sharing parameters.
The URL and title parameters in sharing links should be properly URL-encoded to handle special characters.
<a
- href={`https://twitter.com/intent/tweet?url=${window.location.href}&text=${posttitle}`}
+ href={`https://twitter.com/intent/tweet?url=${encodeURIComponent(window.location.href)}&text=${encodeURIComponent(posttitle)}`}
target='_blank'
rel='noreferrer'
className='flex items-center justify-center rounded-full border border-gray-600 p-4'
>
<IconTwitter className='h-6' />
</a>
<a
- href={`https://www.linkedin.com/shareArticle?mini=true&url=${window.location.href}&title=${posttitle}`}
+ href={`https://www.linkedin.com/shareArticle?mini=true&url=${encodeURIComponent(window.location.href)}&title=${encodeURIComponent(posttitle)}`}
target='_blank'
rel='noreferrer'
className='flex items-center justify-center rounded-full border border-gray-600 p-4 text-blue-700'
>
<IconLinkedIn className='h-6' />
</a>
<a
- href={`https://bsky.app/share?url=${window.location.href}&title=${posttitle}`}
+ href={`https://bsky.app/share?url=${encodeURIComponent(window.location.href)}&title=${encodeURIComponent(posttitle)}`}
target="_blank"
rel="noreferrer"
className="flex items-center justify-center rounded-full border border-gray-600 p-4 text-orange-700"
>
<IconBlueSky className="h-6" />
</a>
Also applies to: 46-47, 54-55
<a | ||
href={`https://bsky.app/share?url=${window.location.href}&title=${posttitle}`} | ||
target="_blank" | ||
rel="noreferrer" | ||
className="flex items-center justify-center rounded-full border border-gray-600 p-4 text-orange-700" | ||
> | ||
<IconBlueSky className="h-6" /> | ||
</a> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix quote style for Bluesky link attributes.
The project's linting rules require using single quotes instead of double quotes in JSX attributes.
<a
href={`https://bsky.app/share?url=${window.location.href}&title=${posttitle}`}
- target="_blank"
- rel="noreferrer"
- className="flex items-center justify-center rounded-full border border-gray-600 p-4 text-orange-700"
+ target='_blank'
+ rel='noreferrer'
+ className='flex items-center justify-center rounded-full border border-gray-600 p-4 text-orange-700'
>
- <IconBlueSky className="h-6" />
+ <IconBlueSky className='h-6' />
</a>
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
<a | |
href={`https://bsky.app/share?url=${window.location.href}&title=${posttitle}`} | |
target="_blank" | |
rel="noreferrer" | |
className="flex items-center justify-center rounded-full border border-gray-600 p-4 text-orange-700" | |
> | |
<IconBlueSky className="h-6" /> | |
</a> | |
<a | |
href={`https://bsky.app/share?url=${window.location.href}&title=${posttitle}`} | |
target='_blank' | |
rel='noreferrer' | |
className='flex items-center justify-center rounded-full border border-gray-600 p-4 text-orange-700' | |
> | |
<IconBlueSky className='h-6' /> | |
</a> |
🧰 Tools
🪛 GitHub Actions: PR testing - if Node project
[error] 55-55: ESLint: Unexpected usage of doublequote. (jsx-quotes)
<div className=' fixed left-0 top-0 z-50 flex size-full items-center justify-center bg-gray-800/80'> | ||
<div className=' absolute left-1/2 top-1/2 w-[300px] -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white p-2 shadow-lg md:-translate-y-[20%] md:scale-125'> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix Tailwind CSS arbitrary value warning.
The arbitrary value class name md:-translate-y-[20%]
should not start with a dash.
- <div className=' fixed left-0 top-0 z-50 flex size-full items-center justify-center bg-gray-800/80'>
- <div className=' absolute left-1/2 top-1/2 w-[300px] -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white p-2 shadow-lg md:-translate-y-[20%] md:scale-125'>
+ <div className='fixed left-0 top-0 z-50 flex size-full items-center justify-center bg-gray-800/80'>
+ <div className='absolute left-1/2 top-1/2 w-[300px] -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white p-2 shadow-lg md:translate-y-[-20%] md:scale-125'>
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
<div className=' fixed left-0 top-0 z-50 flex size-full items-center justify-center bg-gray-800/80'> | |
<div className=' absolute left-1/2 top-1/2 w-[300px] -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white p-2 shadow-lg md:-translate-y-[20%] md:scale-125'> | |
<div className='fixed left-0 top-0 z-50 flex size-full items-center justify-center bg-gray-800/80'> | |
<div className='absolute left-1/2 top-1/2 w-[300px] -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white p-2 shadow-lg md:translate-y-[-20%] md:scale-125'> |
🧰 Tools
🪛 GitHub Actions: PR testing - if Node project
[warning] 27-27: Arbitrary value classname 'md:-translate-y-[20%]' should not start with a dash (-) (tailwindcss/enforces-negative-arbitrary-values)
import IconLinkedIn from '../icons/LinkedIn'; | ||
import IconTwitter from '../icons/Twitter'; | ||
import IconBlueSky from '../icons/Bluesky'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix import sorting according to linting rules.
The imports need to be sorted according to the project's linting rules.
import React from 'react';
-import IconLinkedIn from '../icons/LinkedIn';
-import IconTwitter from '../icons/Twitter';
import IconBlueSky from '../icons/Bluesky';
+import IconLinkedIn from '../icons/LinkedIn';
+import IconTwitter from '../icons/Twitter';
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
import IconLinkedIn from '../icons/LinkedIn'; | |
import IconTwitter from '../icons/Twitter'; | |
import IconBlueSky from '../icons/Bluesky'; | |
import React from 'react'; | |
import IconBlueSky from '../icons/Bluesky'; | |
import IconLinkedIn from '../icons/LinkedIn'; | |
import IconTwitter from '../icons/Twitter'; |
return ( | ||
<div className=' fixed left-0 top-0 z-50 flex size-full items-center justify-center bg-gray-800/80'> | ||
<div className=' absolute left-1/2 top-1/2 w-[300px] -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white p-2 shadow-lg md:-translate-y-[20%] md:scale-125'> | ||
<section className='flex items-center justify-between border-b border-gray-200 p-2'> | ||
<h3 className='text-2xl font-bold'>Share</h3> | ||
<button className='text-3xl' onClick={() => closeSharePop()}> | ||
× | ||
</button> | ||
</section> | ||
<section className='p-2'> | ||
<h4 className='text-sm'>Share this Blog link via</h4> | ||
<div className='flex items-center justify-center gap-4 p-2'> | ||
<a | ||
href={`https://twitter.com/intent/tweet?url=${window.location.href}&text=${posttitle}`} | ||
target='_blank' | ||
rel='noreferrer' | ||
className='flex items-center justify-center rounded-full border border-gray-600 p-4' | ||
> | ||
<IconTwitter className='h-6' /> | ||
</a> | ||
<a | ||
href={`https://www.linkedin.com/shareArticle?mini=true&url=${window.location.href}&title=${posttitle}`} | ||
target='_blank' | ||
rel='noreferrer' | ||
className='flex items-center justify-center rounded-full border border-gray-600 p-4 text-blue-700' | ||
> | ||
<IconLinkedIn className='h-6' /> | ||
</a> | ||
<a | ||
href={`https://bsky.app/share?url=${window.location.href}&title=${posttitle}`} | ||
target="_blank" | ||
rel="noreferrer" | ||
className="flex items-center justify-center rounded-full border border-gray-600 p-4 text-orange-700" | ||
> | ||
<IconBlueSky className="h-6" /> | ||
</a> | ||
|
||
</div> | ||
</section> | ||
<section className='p-2'> | ||
<h4 className='text-sm'>Copy Link</h4> | ||
<div className='flex items-center justify-center gap-4 p-2'> | ||
<input type='text' value={window.location.href} className='w-3/4 rounded-lg border border-gray-600 p-2' /> | ||
<button | ||
className='rounded-lg border bg-blue-600 p-2 text-white hover:bg-blue-500' | ||
onClick={() => handleCopyLink()} | ||
> | ||
{copied ? 'copied' : 'copy'} | ||
</button> | ||
</div> | ||
</section> | ||
</div> | ||
</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add keyboard accessibility features to the modal.
The modal is missing keyboard navigation support and proper ARIA attributes for accessibility.
Enhance the accessibility by adding:
- The ESC key listener to close the modal
- Focus trapping within the modal
- Proper ARIA roles and attributes
Here's how to implement the ESC key handler:
const SharePopup = ({ closeSharePop, posttitle }: SharePopupProps) => {
const [copied, setCopied] = React.useState(false);
+
+ React.useEffect(() => {
+ const handleEscKey = (event: KeyboardEvent) => {
+ if (event.key === 'Escape') {
+ closeSharePop();
+ }
+ };
+
+ document.addEventListener('keydown', handleEscKey);
+ return () => {
+ document.removeEventListener('keydown', handleEscKey);
+ };
+ }, [closeSharePop]);
// Rest of the component
And update the modal wrapper div:
- <div className='fixed left-0 top-0 z-50 flex size-full items-center justify-center bg-gray-800/80'>
+ <div
+ role='dialog'
+ aria-modal='true'
+ aria-labelledby='share-dialog-title'
+ className='fixed left-0 top-0 z-50 flex size-full items-center justify-center bg-gray-800/80'
+ >
<div className='absolute left-1/2 top-1/2 w-[300px] -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white p-2 shadow-lg md:translate-y-[-20%] md:scale-125'>
<section className='flex items-center justify-between border-b border-gray-200 p-2'>
- <h3 className='text-2xl font-bold'>Share</h3>
+ <h3 id='share-dialog-title' className='text-2xl font-bold'>Share</h3>
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
return ( | |
<div className=' fixed left-0 top-0 z-50 flex size-full items-center justify-center bg-gray-800/80'> | |
<div className=' absolute left-1/2 top-1/2 w-[300px] -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white p-2 shadow-lg md:-translate-y-[20%] md:scale-125'> | |
<section className='flex items-center justify-between border-b border-gray-200 p-2'> | |
<h3 className='text-2xl font-bold'>Share</h3> | |
<button className='text-3xl' onClick={() => closeSharePop()}> | |
× | |
</button> | |
</section> | |
<section className='p-2'> | |
<h4 className='text-sm'>Share this Blog link via</h4> | |
<div className='flex items-center justify-center gap-4 p-2'> | |
<a | |
href={`https://twitter.com/intent/tweet?url=${window.location.href}&text=${posttitle}`} | |
target='_blank' | |
rel='noreferrer' | |
className='flex items-center justify-center rounded-full border border-gray-600 p-4' | |
> | |
<IconTwitter className='h-6' /> | |
</a> | |
<a | |
href={`https://www.linkedin.com/shareArticle?mini=true&url=${window.location.href}&title=${posttitle}`} | |
target='_blank' | |
rel='noreferrer' | |
className='flex items-center justify-center rounded-full border border-gray-600 p-4 text-blue-700' | |
> | |
<IconLinkedIn className='h-6' /> | |
</a> | |
<a | |
href={`https://bsky.app/share?url=${window.location.href}&title=${posttitle}`} | |
target="_blank" | |
rel="noreferrer" | |
className="flex items-center justify-center rounded-full border border-gray-600 p-4 text-orange-700" | |
> | |
<IconBlueSky className="h-6" /> | |
</a> | |
</div> | |
</section> | |
<section className='p-2'> | |
<h4 className='text-sm'>Copy Link</h4> | |
<div className='flex items-center justify-center gap-4 p-2'> | |
<input type='text' value={window.location.href} className='w-3/4 rounded-lg border border-gray-600 p-2' /> | |
<button | |
className='rounded-lg border bg-blue-600 p-2 text-white hover:bg-blue-500' | |
onClick={() => handleCopyLink()} | |
> | |
{copied ? 'copied' : 'copy'} | |
</button> | |
</div> | |
</section> | |
</div> | |
</div> | |
const SharePopup = ({ closeSharePop, posttitle }: SharePopupProps) => { | |
const [copied, setCopied] = React.useState(false); | |
React.useEffect(() => { | |
const handleEscKey = (event: KeyboardEvent) => { | |
if (event.key === 'Escape') { | |
closeSharePop(); | |
} | |
}; | |
document.addEventListener('keydown', handleEscKey); | |
return () => { | |
document.removeEventListener('keydown', handleEscKey); | |
}; | |
}, [closeSharePop]); | |
return ( | |
<div | |
role='dialog' | |
aria-modal='true' | |
aria-labelledby='share-dialog-title' | |
className='fixed left-0 top-0 z-50 flex size-full items-center justify-center bg-gray-800/80' | |
> | |
<div className='absolute left-1/2 top-1/2 w-[300px] -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white p-2 shadow-lg md:-translate-y-[20%] md:scale-125'> | |
<section className='flex items-center justify-between border-b border-gray-200 p-2'> | |
<h3 id='share-dialog-title' className='text-2xl font-bold'>Share</h3> | |
<button className='text-3xl' onClick={() => closeSharePop()}> | |
× | |
</button> | |
</section> | |
<section className='p-2'> | |
<h4 className='text-sm'>Share this Blog link via</h4> | |
<div className='flex items-center justify-center gap-4 p-2'> | |
<a | |
href={`https://twitter.com/intent/tweet?url=${window.location.href}&text=${posttitle}`} | |
target='_blank' | |
rel='noreferrer' | |
className='flex items-center justify-center rounded-full border border-gray-600 p-4' | |
> | |
<IconTwitter className='h-6' /> | |
</a> | |
<a | |
href={`https://www.linkedin.com/shareArticle?mini=true&url=${window.location.href}&title=${posttitle}`} | |
target='_blank' | |
rel='noreferrer' | |
className='flex items-center justify-center rounded-full border border-gray-600 p-4 text-blue-700' | |
> | |
<IconLinkedIn className='h-6' /> | |
</a> | |
<a | |
href={`https://bsky.app/share?url=${window.location.href}&title=${posttitle}`} | |
target="_blank" | |
rel="noreferrer" | |
className="flex items-center justify-center rounded-full border border-gray-600 p-4 text-orange-700" | |
> | |
<IconBlueSky className="h-6" /> | |
</a> | |
</div> | |
</section> | |
<section className='p-2'> | |
<h4 className='text-sm'>Copy Link</h4> | |
<div className='flex items-center justify-center gap-4 p-2'> | |
<input type='text' value={window.location.href} className='w-3/4 rounded-lg border border-gray-600 p-2' /> | |
<button | |
className='rounded-lg border bg-blue-600 p-2 text-white hover:bg-blue-500' | |
onClick={() => handleCopyLink()} | |
> | |
{copied ? 'copied' : 'copy'} | |
</button> | |
</div> | |
</section> | |
</div> | |
</div> | |
); | |
}; |
🧰 Tools
🪛 GitHub Actions: PR testing - if Node project
[warning] 27-27: Arbitrary value classname 'md:-translate-y-[20%]' should not start with a dash (-) (tailwindcss/enforces-negative-arbitrary-values)
[error] 55-55: ESLint: Unexpected usage of doublequote. (jsx-quotes)
import React from 'react'; | ||
|
||
import IconLinkedIn from '../icons/LinkedIn'; | ||
import IconTwitter from '../icons/Twitter'; | ||
import IconBlueSky from '../icons/Bluesky'; | ||
|
||
interface SharePopupProps { | ||
closeSharePop: () => void; | ||
posttitle: string; | ||
} | ||
|
||
const SharePopup = ({ closeSharePop, posttitle }: SharePopupProps) => { | ||
const [copied, setCopied] = React.useState(false); | ||
|
||
const handleCopyLink = () => { | ||
const copyText = document.querySelector('input') as HTMLInputElement; | ||
|
||
copyText.select(); | ||
navigator.clipboard.writeText(copyText.value).then(() => { | ||
setCopied(true); | ||
} | ||
); | ||
}; | ||
|
||
return ( | ||
<div className=' fixed left-0 top-0 z-50 flex size-full items-center justify-center bg-gray-800/80'> | ||
<div className=' absolute left-1/2 top-1/2 w-[300px] -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white p-2 shadow-lg md:-translate-y-[20%] md:scale-125'> | ||
<section className='flex items-center justify-between border-b border-gray-200 p-2'> | ||
<h3 className='text-2xl font-bold'>Share</h3> | ||
<button className='text-3xl' onClick={() => closeSharePop()}> | ||
× | ||
</button> | ||
</section> | ||
<section className='p-2'> | ||
<h4 className='text-sm'>Share this Blog link via</h4> | ||
<div className='flex items-center justify-center gap-4 p-2'> | ||
<a | ||
href={`https://twitter.com/intent/tweet?url=${window.location.href}&text=${posttitle}`} | ||
target='_blank' | ||
rel='noreferrer' | ||
className='flex items-center justify-center rounded-full border border-gray-600 p-4' | ||
> | ||
<IconTwitter className='h-6' /> | ||
</a> | ||
<a | ||
href={`https://www.linkedin.com/shareArticle?mini=true&url=${window.location.href}&title=${posttitle}`} | ||
target='_blank' | ||
rel='noreferrer' | ||
className='flex items-center justify-center rounded-full border border-gray-600 p-4 text-blue-700' | ||
> | ||
<IconLinkedIn className='h-6' /> | ||
</a> | ||
<a | ||
href={`https://bsky.app/share?url=${window.location.href}&title=${posttitle}`} | ||
target="_blank" | ||
rel="noreferrer" | ||
className="flex items-center justify-center rounded-full border border-gray-600 p-4 text-orange-700" | ||
> | ||
<IconBlueSky className="h-6" /> | ||
</a> | ||
|
||
</div> | ||
</section> | ||
<section className='p-2'> | ||
<h4 className='text-sm'>Copy Link</h4> | ||
<div className='flex items-center justify-center gap-4 p-2'> | ||
<input type='text' value={window.location.href} className='w-3/4 rounded-lg border border-gray-600 p-2' /> | ||
<button | ||
className='rounded-lg border bg-blue-600 p-2 text-white hover:bg-blue-500' | ||
onClick={() => handleCopyLink()} | ||
> | ||
{copied ? 'copied' : 'copy'} | ||
</button> | ||
</div> | ||
</section> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
export default SharePopup; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Add server-side rendering compatibility.
The component uses window.location.href
directly, which will cause issues during server-side rendering because window
is not available on the server.
Use a React hook to safely access the window object only in the client:
import React from 'react';
+import { useEffect, useState } from 'react';
import IconBlueSky from '../icons/Bluesky';
import IconLinkedIn from '../icons/LinkedIn';
import IconTwitter from '../icons/Twitter';
interface SharePopupProps {
closeSharePop: () => void;
posttitle: string;
}
const SharePopup = ({ closeSharePop, posttitle }: SharePopupProps) => {
const [copied, setCopied] = React.useState(false);
+ const [currentUrl, setCurrentUrl] = useState('');
+
+ useEffect(() => {
+ // Only access window in the client
+ setCurrentUrl(window.location.href);
+ }, []);
const handleCopyLink = () => {
// ... updated copy logic
};
return (
// ... in the JSX:
- <input type='text' value={window.location.href} className='w-3/4 rounded-lg border border-gray-600 p-2' />
+ <input type='text' value={currentUrl} className='w-3/4 rounded-lg border border-gray-600 p-2' />
// ... and in the sharing links:
- href={`https://twitter.com/intent/tweet?url=${window.location.href}&text=${posttitle}`}
+ href={`https://twitter.com/intent/tweet?url=${encodeURIComponent(currentUrl)}&text=${encodeURIComponent(posttitle)}`}
// ... other social links similarly updated
);
};
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
import React from 'react'; | |
import IconLinkedIn from '../icons/LinkedIn'; | |
import IconTwitter from '../icons/Twitter'; | |
import IconBlueSky from '../icons/Bluesky'; | |
interface SharePopupProps { | |
closeSharePop: () => void; | |
posttitle: string; | |
} | |
const SharePopup = ({ closeSharePop, posttitle }: SharePopupProps) => { | |
const [copied, setCopied] = React.useState(false); | |
const handleCopyLink = () => { | |
const copyText = document.querySelector('input') as HTMLInputElement; | |
copyText.select(); | |
navigator.clipboard.writeText(copyText.value).then(() => { | |
setCopied(true); | |
} | |
); | |
}; | |
return ( | |
<div className=' fixed left-0 top-0 z-50 flex size-full items-center justify-center bg-gray-800/80'> | |
<div className=' absolute left-1/2 top-1/2 w-[300px] -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white p-2 shadow-lg md:-translate-y-[20%] md:scale-125'> | |
<section className='flex items-center justify-between border-b border-gray-200 p-2'> | |
<h3 className='text-2xl font-bold'>Share</h3> | |
<button className='text-3xl' onClick={() => closeSharePop()}> | |
× | |
</button> | |
</section> | |
<section className='p-2'> | |
<h4 className='text-sm'>Share this Blog link via</h4> | |
<div className='flex items-center justify-center gap-4 p-2'> | |
<a | |
href={`https://twitter.com/intent/tweet?url=${window.location.href}&text=${posttitle}`} | |
target='_blank' | |
rel='noreferrer' | |
className='flex items-center justify-center rounded-full border border-gray-600 p-4' | |
> | |
<IconTwitter className='h-6' /> | |
</a> | |
<a | |
href={`https://www.linkedin.com/shareArticle?mini=true&url=${window.location.href}&title=${posttitle}`} | |
target='_blank' | |
rel='noreferrer' | |
className='flex items-center justify-center rounded-full border border-gray-600 p-4 text-blue-700' | |
> | |
<IconLinkedIn className='h-6' /> | |
</a> | |
<a | |
href={`https://bsky.app/share?url=${window.location.href}&title=${posttitle}`} | |
target="_blank" | |
rel="noreferrer" | |
className="flex items-center justify-center rounded-full border border-gray-600 p-4 text-orange-700" | |
> | |
<IconBlueSky className="h-6" /> | |
</a> | |
</div> | |
</section> | |
<section className='p-2'> | |
<h4 className='text-sm'>Copy Link</h4> | |
<div className='flex items-center justify-center gap-4 p-2'> | |
<input type='text' value={window.location.href} className='w-3/4 rounded-lg border border-gray-600 p-2' /> | |
<button | |
className='rounded-lg border bg-blue-600 p-2 text-white hover:bg-blue-500' | |
onClick={() => handleCopyLink()} | |
> | |
{copied ? 'copied' : 'copy'} | |
</button> | |
</div> | |
</section> | |
</div> | |
</div> | |
); | |
}; | |
export default SharePopup; | |
import React, { useEffect, useState } from 'react'; | |
import IconLinkedIn from '../icons/LinkedIn'; | |
import IconTwitter from '../icons/Twitter'; | |
import IconBlueSky from '../icons/Bluesky'; | |
interface SharePopupProps { | |
closeSharePop: () => void; | |
posttitle: string; | |
} | |
const SharePopup = ({ closeSharePop, posttitle }: SharePopupProps) => { | |
const [copied, setCopied] = React.useState(false); | |
const [currentUrl, setCurrentUrl] = useState(''); | |
useEffect(() => { | |
// Only access window in the client | |
setCurrentUrl(window.location.href); | |
}, []); | |
const handleCopyLink = () => { | |
const copyText = document.querySelector('input') as HTMLInputElement; | |
copyText.select(); | |
navigator.clipboard.writeText(copyText.value).then(() => { | |
setCopied(true); | |
}); | |
}; | |
return ( | |
<div className=" fixed left-0 top-0 z-50 flex size-full items-center justify-center bg-gray-800/80"> | |
<div className=" absolute left-1/2 top-1/2 w-[300px] -translate-x-1/2 -translate-y-1/2 rounded-lg bg-white p-2 shadow-lg md:-translate-y-[20%] md:scale-125"> | |
<section className="flex items-center justify-between border-b border-gray-200 p-2"> | |
<h3 className="text-2xl font-bold">Share</h3> | |
<button className="text-3xl" onClick={() => closeSharePop()}> | |
× | |
</button> | |
</section> | |
<section className="p-2"> | |
<h4 className="text-sm">Share this Blog link via</h4> | |
<div className="flex items-center justify-center gap-4 p-2"> | |
<a | |
href={`https://twitter.com/intent/tweet?url=${encodeURIComponent( | |
currentUrl | |
)}&text=${encodeURIComponent(posttitle)}`} | |
target="_blank" | |
rel="noreferrer" | |
className="flex items-center justify-center rounded-full border border-gray-600 p-4" | |
> | |
<IconTwitter className="h-6" /> | |
</a> | |
<a | |
href={`https://www.linkedin.com/shareArticle?mini=true&url=${encodeURIComponent( | |
currentUrl | |
)}&title=${encodeURIComponent(posttitle)}`} | |
target="_blank" | |
rel="noreferrer" | |
className="flex items-center justify-center rounded-full border border-gray-600 p-4 text-blue-700" | |
> | |
<IconLinkedIn className="h-6" /> | |
</a> | |
<a | |
href={`https://bsky.app/share?url=${encodeURIComponent( | |
currentUrl | |
)}&title=${encodeURIComponent(posttitle)}`} | |
target="_blank" | |
rel="noreferrer" | |
className="flex items-center justify-center rounded-full border border-gray-600 p-4 text-orange-700" | |
> | |
<IconBlueSky className="h-6" /> | |
</a> | |
</div> | |
</section> | |
<section className="p-2"> | |
<h4 className="text-sm">Copy Link</h4> | |
<div className="flex items-center justify-center gap-4 p-2"> | |
<input | |
type="text" | |
value={currentUrl} | |
className="w-3/4 rounded-lg border border-gray-600 p-2" | |
/> | |
<button | |
className="rounded-lg border bg-blue-600 p-2 text-white hover:bg-blue-500" | |
onClick={() => handleCopyLink()} | |
> | |
{copied ? 'copied' : 'copy'} | |
</button> | |
</div> | |
</section> | |
</div> | |
</div> | |
); | |
}; | |
export default SharePopup; |
🧰 Tools
🪛 GitHub Actions: PR testing - if Node project
[error] 1-1: ESLint: Run autofix to sort these imports! (simple-import-sort/imports)
[warning] 27-27: Arbitrary value classname 'md:-translate-y-[20%]' should not start with a dash (-) (tailwindcss/enforces-negative-arbitrary-values)
[error] 55-55: ESLint: Unexpected usage of doublequote. (jsx-quotes)
closing this as we already have a pr for this |
Description
This is my first open source contribution in AsyncAPi so I may have made mistake something.
It's really exciting to do the project. I've created share option on blog which issue I found in good first issue.
Related issue(s)
feat: social sharing buttons on blogs #3649
Summary by CodeRabbit