From 63ad6a277d77d692c410da5d7817006b000a5198 Mon Sep 17 00:00:00 2001 From: aaniya22 Date: Fri, 12 Jun 2026 14:06:01 +0530 Subject: [PATCH] feat: add Daily Coding Tip widget with category badges and refresh button --- src/components/DailyCodingTip.module.css | 102 +++++++++++++++++++++++ src/components/DailyCodingTip.tsx | 85 +++++++++++++++++++ src/data/codingTips.json | 22 +++++ 3 files changed, 209 insertions(+) create mode 100644 src/components/DailyCodingTip.module.css create mode 100644 src/components/DailyCodingTip.tsx create mode 100644 src/data/codingTips.json diff --git a/src/components/DailyCodingTip.module.css b/src/components/DailyCodingTip.module.css new file mode 100644 index 00000000..0a99e3da --- /dev/null +++ b/src/components/DailyCodingTip.module.css @@ -0,0 +1,102 @@ +.container { + background: var(--ifm-card-background-color, #ffffff); + border: 1px solid var(--ifm-color-emphasis-200, #e5e7eb); + border-radius: 12px; + padding: 24px; + max-width: 600px; + margin: 24px auto; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06); + transition: box-shadow 0.2s ease; +} + +.container:hover { + box-shadow: 0 4px 16px rgba(0, 0, 0, 0.12); +} + +.header { + display: flex; + align-items: center; + gap: 8px; + margin-bottom: 16px; +} + +.headerIcon { + font-size: 20px; +} + +.headerTitle { + font-size: 18px; + font-weight: 700; + margin: 0; + color: var(--ifm-heading-color); +} + +.tipCard { + background: var(--ifm-color-emphasis-100, #f9fafb); + border-radius: 8px; + padding: 16px; + margin-bottom: 16px; +} + +.fadeIn { + animation: fadeInUp 0.3s ease forwards; +} + +@keyframes fadeInUp { + from { + opacity: 0; + transform: translateY(8px); + } + to { + opacity: 1; + transform: translateY(0); + } +} + +.categoryBadge { + display: inline-block; + font-size: 11px; + font-weight: 600; + padding: 3px 10px; + border-radius: 999px; + border: 1px solid; + margin-bottom: 10px; + text-transform: uppercase; + letter-spacing: 0.05em; +} + +.tipText { + font-size: 15px; + line-height: 1.6; + color: var(--ifm-font-color-base); + margin: 0; +} + +.refreshButton { + background: var(--ifm-color-primary, #2563eb); + color: #ffffff; + border: none; + border-radius: 8px; + padding: 10px 20px; + font-size: 14px; + font-weight: 600; + cursor: pointer; + transition: opacity 0.2s ease, transform 0.1s ease; + width: 100%; +} + +.refreshButton:hover { + opacity: 0.9; + transform: translateY(-1px); +} + +.refreshButton:active { + transform: translateY(0); +} + +@media (max-width: 768px) { + .container { + margin: 16px; + padding: 16px; + } +} \ No newline at end of file diff --git a/src/components/DailyCodingTip.tsx b/src/components/DailyCodingTip.tsx new file mode 100644 index 00000000..95cfa8dc --- /dev/null +++ b/src/components/DailyCodingTip.tsx @@ -0,0 +1,85 @@ +import React, { useState, useEffect } from "react"; +import styles from "./DailyCodingTip.module.css"; +import codingTips from "../data/codingTips.json"; + +type Tip = { + id: number; + category: string; + tip: string; +}; + +const CATEGORY_COLORS: Record = { + "Git & GitHub Tips": "#f97316", + "JavaScript/React Tips": "#3b82f6", + "Open Source Contribution Tips": "#10b981", + "VS Code Shortcuts": "#8b5cf6", + "Productivity Tricks": "#ec4899", +}; + +function getTipOfTheDay(): Tip { + try { + const stored = localStorage.getItem("dailyCodingTip"); + const today = new Date().toDateString(); + if (stored) { + const parsed = JSON.parse(stored); + if (parsed.date === today) return parsed.tip; + } + const randomTip = codingTips[Math.floor(Math.random() * codingTips.length)] as Tip; + localStorage.setItem("dailyCodingTip", JSON.stringify({ date: today, tip: randomTip })); + return randomTip; + } catch { + return codingTips[0] as Tip; + } +} + +export default function DailyCodingTip(): React.ReactElement { + const [tip, setTip] = useState(null); + const [animate, setAnimate] = useState(false); + + useEffect(() => { + setTip(getTipOfTheDay()); + setAnimate(true); + }, []); + + const handleRefresh = () => { + const randomTip = codingTips[Math.floor(Math.random() * codingTips.length)] as Tip; + setAnimate(false); + setTimeout(() => { + setTip(randomTip); + setAnimate(true); + }, 150); + }; + + if (!tip) return <>; + + const categoryColor = CATEGORY_COLORS[tip.category] || "#6b7280"; + + return ( +
+
+ 💡 +

Daily Coding Tip

+
+
+ + {tip.category} + +

{tip.tip}

+
+ +
+ ); +} \ No newline at end of file diff --git a/src/data/codingTips.json b/src/data/codingTips.json new file mode 100644 index 00000000..4451589e --- /dev/null +++ b/src/data/codingTips.json @@ -0,0 +1,22 @@ +[ + { "id": 1, "category": "Git & GitHub Tips", "tip": "Use `git stash` to temporarily save uncommitted changes before switching branches." }, + { "id": 2, "category": "Git & GitHub Tips", "tip": "Use `git log --oneline` for a compact view of your commit history." }, + { "id": 3, "category": "Git & GitHub Tips", "tip": "Always write meaningful commit messages — future you will thank present you." }, + { "id": 4, "category": "Git & GitHub Tips", "tip": "Use `git bisect` to find the commit that introduced a bug using binary search." }, + { "id": 5, "category": "JavaScript/React Tips", "tip": "Use optional chaining (`?.`) to safely access deeply nested object properties." }, + { "id": 6, "category": "JavaScript/React Tips", "tip": "Prefer `const` over `let` when the variable won't be reassigned." }, + { "id": 7, "category": "JavaScript/React Tips", "tip": "Use React.memo() to prevent unnecessary re-renders of functional components." }, + { "id": 8, "category": "JavaScript/React Tips", "tip": "Use the nullish coalescing operator (`??`) instead of `||` when 0 or empty string are valid values." }, + { "id": 9, "category": "Open Source Contribution Tips", "tip": "Always read CONTRIBUTING.md before opening a pull request." }, + { "id": 10, "category": "Open Source Contribution Tips", "tip": "Start with 'good first issue' labeled issues when contributing to a new project." }, + { "id": 11, "category": "Open Source Contribution Tips", "tip": "Keep your PRs small and focused — one feature or fix per PR." }, + { "id": 12, "category": "Open Source Contribution Tips", "tip": "Sync your fork with the upstream repo regularly to avoid merge conflicts." }, + { "id": 13, "category": "VS Code Shortcuts", "tip": "Use `Ctrl + P` to quickly open any file in your project." }, + { "id": 14, "category": "VS Code Shortcuts", "tip": "Use `Ctrl + Shift + K` to delete an entire line instantly." }, + { "id": 15, "category": "VS Code Shortcuts", "tip": "Use `Alt + Click` to place multiple cursors for simultaneous editing." }, + { "id": 16, "category": "VS Code Shortcuts", "tip": "Use `Ctrl + backtick` to toggle the integrated terminal." }, + { "id": 17, "category": "Productivity Tricks", "tip": "Use the Pomodoro technique — 25 minutes of focused work followed by a 5-minute break." }, + { "id": 18, "category": "Productivity Tricks", "tip": "Rubber duck debugging: explain your code out loud to find bugs faster." }, + { "id": 19, "category": "Productivity Tricks", "tip": "Write TODO comments in code to track unfinished work." }, + { "id": 20, "category": "Productivity Tricks", "tip": "Take breaks — stepping away from a problem often leads to the solution faster." } +] \ No newline at end of file