-
Notifications
You must be signed in to change notification settings - Fork 63
Added responsive Contact page with improved layout #196
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
Added responsive Contact page with improved layout #196
Conversation
✅ Deploy Preview for github-spy ready!
To edit notification comments on pull requests, go to your Netlify project 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.
🎉 Thank you @Sindhura-Karumuri for your contribution. Please make sure your PR follows https://github.com/GitMetricsLab/github_tracker/blob/main/CONTRIBUTING.md#-pull-request-guidelines
WalkthroughResponsive UI updates applied to the Contact page component, adjusting layout, typography, spacing, and containers for small and large screens. No changes to business logic, data handling, or exported signatures. All modifications are presentational within src/pages/Contact/Contact.tsx. Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Assessment against linked issues
Assessment against linked issues: Out-of-scope changes
Suggested labels
Poem
Tip 🔌 Remote MCP (Model Context Protocol) integration is now available!Pro plan users can now connect to remote MCP servers from the Integrations page. Connect with popular remote MCPs such as Notion and Linear to add more context to your reviews and chats. ✨ Finishing Touches
🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
CodeRabbit Configuration File (
|
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: 0
🔭 Outside diff range comments (1)
src/pages/Contact/Contact.tsx (1)
206-321: Critical: Built-in “required” validation isn’t triggered (no form submit). Make it a form and wire onSubmitRight now the button’s onClick bypasses native constraint validation. Wrap controls in a form, use onSubmit, and associate labels with inputs for accessibility. This also lets Enter submit the form.
Apply this diff within the form block:
- <div className="space-y-3 sm:space-y-4 flex-1 flex flex-col"> + <form onSubmit={handleSubmit} aria-busy={isSubmitting} className="space-y-3 sm:space-y-4 flex-1 flex flex-col"> <div className="space-y-3 flex-1"> {/* Full Name */} <div> - <label - className={`block text-xs font-medium mb-1 ${ + <label + htmlFor="fullName" + className={`block text-xs font-medium mb-1 ${ mode === "dark" ? "text-gray-300" : "text-gray-700" }`} > Full Name </label> <input type="text" placeholder="Enter your full name" required + id="fullName" + name="fullName" + autoComplete="name" className={`w-full p-2 sm:p-3 rounded-lg sm:rounded-xl text-sm sm:text-base transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-purple-500 ${ mode === "dark" ? "bg-white/5 border border-white/20 text-white placeholder-gray-400" : "bg-gray-50 border border-gray-300 text-gray-800 placeholder-gray-500" }`} /> </div> {/* Email */} <div> - <label - className={`block text-xs font-medium mb-1 ${ + <label + htmlFor="email" + className={`block text-xs font-medium mb-1 ${ mode === "dark" ? "text-gray-300" : "text-gray-700" }`} > Email Address </label> <input type="email" placeholder="your.email@example.com" required + id="email" + name="email" + autoComplete="email" className={`w-full p-2 sm:p-3 rounded-lg sm:rounded-xl text-sm sm:text-base transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-purple-500 ${ mode === "dark" ? "bg-white/5 border border-white/20 text-white placeholder-gray-400" : "bg-gray-50 border border-gray-300 text-gray-800 placeholder-gray-500" }`} /> </div> {/* Subject */} <div> - <label - className={`block text-xs font-medium mb-1 ${ + <label + htmlFor="subject" + className={`block text-xs font-medium mb-1 ${ mode === "dark" ? "text-gray-300" : "text-gray-700" }`} > Subject </label> - <select + <select + id="subject" + name="subject" className={`w-full p-2 sm:p-3 rounded-lg sm:rounded-xl text-sm sm:text-base transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-purple-500 ${ mode === "dark" ? "bg-white/5 border border-white/20 text-white placeholder-gray-400" : "bg-gray-50 border border-gray-300 text-gray-800 placeholder-gray-500" }`} required defaultValue="" > <option value="" disabled> Select a subject </option> <option>General Inquiry</option> <option>Bug Report</option> <option>Feature Request</option> <option>Other</option> </select> </div> {/* Message */} <div className="relative"> - <label - className={`block text-xs font-medium mb-1 ${ + <label + htmlFor="message" + className={`block text-xs font-medium mb-1 ${ mode === "dark" ? "text-gray-300" : "text-gray-700" }`} > Message </label> <textarea placeholder="Type your message here..." required rows={4} + id="message" + name="message" className={`w-full p-2 sm:p-3 rounded-lg sm:rounded-xl text-sm sm:text-base resize-none transition-all duration-300 focus:outline-none focus:ring-2 focus:ring-purple-500 ${ mode === "dark" ? "bg-white/5 border border-white/20 text-white placeholder-gray-400" : "bg-gray-50 border border-gray-300 text-gray-800 placeholder-gray-500" }`} ></textarea> <button - onClick={handleSubmit} + type="submit" disabled={isSubmitting} className={`absolute bottom-2 sm:bottom-3 right-2 sm:right-3 flex items-center gap-1.5 sm:gap-2 rounded-full px-3 sm:px-4 py-1.5 sm:py-2 text-xs sm:text-sm font-semibold transition-all duration-300 hover:scale-105 focus:outline-none focus:ring-2 focus:ring-purple-500 ${ isSubmitting ? "bg-purple-400 cursor-wait text-white" : "bg-purple-600 hover:bg-purple-700 text-white" }`} > {isSubmitting ? "Sending..." : "Send"} <Send className="w-4 h-4" /> </button> </div> </div> - </div> + </form>Additionally update handler and imports outside this range:
// imports (line 1) import { useState, useContext, useEffect, useRef, type FormEvent } from "react"; // inside Contact() const timeoutRef = useRef<number | null>(null); const handleSubmit = async (e: FormEvent<HTMLFormElement>) => { e.preventDefault(); // enable native constraint validation first setIsSubmitting(true); await new Promise((resolve) => setTimeout(resolve, 1500)); setIsSubmitting(false); setShowPopup(true); if (timeoutRef.current) clearTimeout(timeoutRef.current); timeoutRef.current = window.setTimeout(() => setShowPopup(false), 5000); }; useEffect(() => { return () => { if (timeoutRef.current) clearTimeout(timeoutRef.current); }; }, []); const handleClosePopup = () => { if (timeoutRef.current) { clearTimeout(timeoutRef.current); timeoutRef.current = null; } setShowPopup(false); };
🧹 Nitpick comments (5)
src/pages/Contact/Contact.tsx (5)
40-40: Prevent horizontal scrollbars on mobile and better handle dynamic viewport heightsUsing w-screen often introduces a subtle horizontal scrollbar on iOS and desktop when vertical scrollbars appear. Prefer w-full + overflow-x-hidden; also add min-h-dvh for better behavior with dynamic viewports.
- className={`min-h-screen w-screen relative overflow-y-auto ${ + className={`min-h-screen min-h-dvh w-full relative overflow-y-auto overflow-x-hidden ${
106-133: Avoid recomputing config inside map; iterate directly over dataThe current pattern builds contactTypes array on every iteration and indexes into it. Map directly over the array to improve clarity and avoid unnecessary work.
- <div className="space-y-3 sm:space-y-4 flex-1 flex flex-col justify-center"> - {[...Array(3)].map((_, index) => { - const contactTypes = [ - { - title: "Phone Support", - iconBg: "from-blue-500 to-cyan-500", - detail: "(123) 456-7890", - sub: "Mon-Fri, 9AM-6PM EST", - Icon: Phone, - }, - { - title: "Email Us", - iconBg: "from-purple-500 to-pink-500", - detail: "support@githubtracker.com", - sub: "We'll respond within 24 hours", - Icon: Mail, - }, - { - title: "GitHub Issues", - iconBg: "from-green-500 to-teal-500", - detail: "github.com/yourorg/githubtracker", - sub: "Report bugs & feature requests", - Icon: Github, - }, - ]; - const { title, iconBg, detail, sub, Icon } = - contactTypes[index]; - return ( + <div className="space-y-3 sm:space-y-4 flex-1 flex flex-col justify-center"> + {[ + { + title: "Phone Support", + iconBg: "from-blue-500 to-cyan-500", + detail: "(123) 456-7890", + sub: "Mon-Fri, 9AM-6PM EST", + Icon: Phone, + }, + { + title: "Email Us", + iconBg: "from-purple-500 to-pink-500", + detail: "support@githubtracker.com", + sub: "We'll respond within 24 hours", + Icon: Mail, + }, + { + title: "GitHub Issues", + iconBg: "from-green-500 to-teal-500", + detail: "github.com/yourorg/githubtracker", + sub: "Report bugs & feature requests", + Icon: Github, + }, + ].map(({ title, iconBg, detail, sub, Icon }) => ( <div key={title} className={`group p-3 sm:p-5 rounded-xl sm:rounded-2xl backdrop-blur-lg transition-all duration-300 hover:scale-105 ${ mode === "dark" ? "bg-white/10 border border-white/20 hover:bg-white/20" : "bg-white border border-gray-300 hover:bg-gray-100" }`} > <div className="flex items-center gap-3 sm:gap-4"> <div className={`p-2 sm:p-2.5 rounded-full transition-transform duration-300 group-hover:scale-110 bg-gradient-to-r ${iconBg}`} > <Icon className={`w-4 h-4 sm:w-5 sm:h-5 ${ mode === "dark" ? "text-white" : "text-gray-800" }`} /> </div> <div> <h3 className={`text-sm sm:text-base font-semibold ${ mode === "dark" ? "text-white" : "text-gray-800" }`} > {title} </h3> <p className={`text-xs sm:text-sm ${ mode === "dark" ? "text-gray-300" : "text-gray-600" }`} > {detail} </p> <p className={`text-xs ${ mode === "dark" ? "text-gray-400" : "text-gray-500" }`} > {sub} </p> </div> </div> </div> - ); - })} + ))} </div>
328-336: Toast a11y: announce success to screen readers and hide decorative iconsAdd role and aria-live to the toast; mark icons as aria-hidden.
- <div - className={`fixed top-4 sm:top-6 left-1/2 transform -translate-x-1/2 z-50 w-[90%] sm:w-auto max-w-sm sm:max-w-md px-4 sm:px-6 py-3 sm:py-4 rounded-xl sm:rounded-2xl shadow-lg flex items-center gap-3 sm:gap-4 ${ + <div + role="status" + aria-live="polite" + aria-atomic="true" + className={`fixed top-4 sm:top-6 left-1/2 transform -translate-x-1/2 z-50 w-[90%] sm:w-auto max-w-sm sm:max-w-md px-4 sm:px-6 py-3 sm:py-4 rounded-xl sm:rounded-2xl shadow-lg flex items-center gap-3 sm:gap-4 ${ mode === "dark" ? "bg-green-900 border border-green-700 text-green-100" : "bg-green-100 border border-green-400 text-green-900" }`} > - <CheckCircle className="w-6 h-6 sm:w-7 sm:h-7" /> + <CheckCircle aria-hidden="true" className="w-6 h-6 sm:w-7 sm:h-7" /> <div className="flex-1 text-xs sm:text-sm font-semibold"> Thank you for contacting us! We will get back to you shortly. </div> <button onClick={handleClosePopup} className="text-lg sm:text-xl px-2 sm:px-3 py-1 rounded-xl hover:bg-green-200/40 focus:outline-none focus:ring-2 focus:ring-green-400" aria-label="Close notification" > - <X /> + <X aria-hidden="true" /> </button> </div>Also applies to: 334-336, 340-345
for primary content
53-53: Optional semantic landmark: useUsing a main landmark improves navigation for assistive tech without affecting visuals.
- <div className="relative z-10 container mx-auto px-4 py-6 max-w-7xl flex flex-col pb-20"> + <main className="relative z-10 container mx-auto px-4 py-6 max-w-7xl flex flex-col pb-20"> ... - </div> + </main>Also applies to: 323-324
165-172: Make contact details actionable (tap-to-call, mailto, and link)Turning these into anchor tags improves UX on mobile:
If you’d like, I can wire this up by adding an href to each contactTypes item and rendering conditionally.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
💡 Knowledge Base configuration:
- MCP integration is disabled by default for public repositories
- Jira integration is disabled by default for public repositories
- Linear integration is disabled by default for public repositories
You can enable these sources in your CodeRabbit configuration.
📒 Files selected for processing (1)
src/pages/Contact/Contact.tsx(12 hunks)
🔇 Additional comments (1)
src/pages/Contact/Contact.tsx (1)
69-71: LGTM: Responsive typography scales well across breakpointsThe heading’s responsive size ramp and gradient text are clean and readable across sizes.
|
Please verify my pr |
|
🎉🎉 Thank you for your contribution! Your PR #196 has been merged! 🎉🎉 |
Related Issue
Description
This PR improves the Contact page by making it fully responsive across devices (mobile, tablet, and desktop).
Enhancements include:
How Has This Been Tested?
Screenshots (if applicable)
Before
After
Type of Change
Summary by CodeRabbit