Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions src/components/DailyCodingTip.module.css
Original file line number Diff line number Diff line change
@@ -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;
}
}
85 changes: 85 additions & 0 deletions src/components/DailyCodingTip.tsx
Original file line number Diff line number Diff line change
@@ -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<string, string> = {
"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<Tip | null>(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 (
<div className={styles.container}>
<div className={styles.header}>
<span className={styles.headerIcon}>πŸ’‘</span>
<h3 className={styles.headerTitle}>Daily Coding Tip</h3>
</div>
<div className={`${styles.tipCard} ${animate ? styles.fadeIn : ""}`}>
<span
className={styles.categoryBadge}
style={{
backgroundColor: `${categoryColor}20`,
color: categoryColor,
borderColor: `${categoryColor}40`,
}}
>
{tip.category}
</span>
<p className={styles.tipText}>{tip.tip}</p>
</div>
<button
className={styles.refreshButton}
onClick={handleRefresh}
aria-label="Get a new random coding tip"
>
πŸ”€ Get Another Tip
</button>
</div>
);
}
22 changes: 22 additions & 0 deletions src/data/codingTips.json
Original file line number Diff line number Diff line change
@@ -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." }
]
Loading