Skip to content

Commit 86e8e0b

Browse files
Merge pull request #199 from Shaily-62/feature/uuid-generator
Feature/UUID generator
2 parents 79f1a5c + 74c55e2 commit 86e8e0b

File tree

4 files changed

+411
-1
lines changed

4 files changed

+411
-1
lines changed

assets/styles.css

Lines changed: 164 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,10 @@ body:not(.dark-mode) .theme-toggle .moon-icon {
185185
}
186186

187187
.card a:hover {
188-
filter: brightness(1.05);
188+
background: linear-gradient(135deg, var(--accent-2), var(--accent));
189+
background-size: 200% auto;
190+
transition: background-position 0.4s ease;
191+
background-position: right center;
189192
}
190193

191194
.site-footer {
@@ -204,3 +207,163 @@ body:not(.dark-mode) .theme-toggle .moon-icon {
204207
.site-footer a:hover {
205208
text-decoration: underline;
206209
}
210+
211+
212+
/* ================================
213+
📱 RESPONSIVE DESIGN ENHANCEMENTS
214+
================================ */
215+
216+
/* --- Tablet (≤ 1024px) --- */
217+
@media (max-width: 1024px) {
218+
.site-header {
219+
padding: 1.5rem 1rem;
220+
}
221+
222+
.site-header h1 {
223+
font-size: 1.75rem;
224+
}
225+
226+
.controls {
227+
flex-direction: column;
228+
align-items: stretch;
229+
gap: 0.75rem;
230+
}
231+
232+
.controls input,
233+
.controls select {
234+
width: 100%;
235+
font-size: 1rem;
236+
}
237+
238+
.project-grid {
239+
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
240+
gap: 0.75rem;
241+
}
242+
}
243+
244+
/* --- Mobile (≤ 600px) --- */
245+
@media (max-width: 600px) {
246+
body {
247+
font-size: 0.95rem;
248+
}
249+
250+
.site-header {
251+
padding: 1rem 0.75rem;
252+
}
253+
254+
.site-header h1 {
255+
font-size: 1.5rem;
256+
}
257+
258+
.site-header p {
259+
font-size: 0.9rem;
260+
}
261+
262+
.theme-toggle {
263+
width: 40px;
264+
height: 40px;
265+
top: 0.75rem;
266+
right: 0.75rem;
267+
}
268+
269+
.controls {
270+
flex-direction: column;
271+
gap: 0.5rem;
272+
width: 100%;
273+
}
274+
275+
.controls input,
276+
.controls select {
277+
width: 100%;
278+
font-size: 0.95rem;
279+
}
280+
281+
.project-grid {
282+
grid-template-columns: 1fr;
283+
padding: 0.75rem;
284+
}
285+
286+
.card {
287+
padding: 0.75rem;
288+
}
289+
290+
.site-footer {
291+
font-size: 0.85rem;
292+
padding: 1rem;
293+
}
294+
}
295+
296+
297+
/* ================================
298+
✨ TRANSITIONS & ANIMATIONS
299+
================================ */
300+
301+
/* Smooth transitions on layout adjustments */
302+
.controls,
303+
.project-grid,
304+
.card,
305+
.site-header,
306+
.site-footer {
307+
transition:
308+
all 0.3s ease-in-out,
309+
grid-template-columns 0.3s ease-in-out,
310+
padding 0.3s ease-in-out,
311+
font-size 0.2s ease-in-out;
312+
}
313+
314+
/* Animate cards when the grid rearranges */
315+
.project-grid {
316+
transition:
317+
grid-template-columns 0.4s ease,
318+
gap 0.3s ease;
319+
}
320+
321+
/* Subtle hover animation for cards */
322+
.card {
323+
transition:
324+
transform 0.25s ease,
325+
box-shadow 0.25s ease,
326+
background 0.3s ease;
327+
}
328+
329+
.card:hover {
330+
border-color: var(--accent);
331+
box-shadow: 0 6px 20px rgba(110, 231, 183, 0.15);
332+
transform: translateY(-5px);
333+
}
334+
335+
.card:active {
336+
transform: scale(0.98);
337+
}
338+
339+
/* Smoothly scale theme toggle when viewport changes */
340+
.theme-toggle {
341+
transition:
342+
all 0.25s ease,
343+
transform 0.3s ease;
344+
}
345+
346+
/* Fade animation when switching between dark/light themes */
347+
body {
348+
transition:
349+
background 0.4s ease,
350+
color 0.4s ease,
351+
filter 0.4s ease;
352+
}
353+
354+
/* Optional: add a slight fade-in effect when content loads */
355+
body {
356+
opacity: 0;
357+
animation: fadeIn 0.6s ease-out forwards;
358+
}
359+
360+
@keyframes fadeIn {
361+
from {
362+
opacity: 0;
363+
transform: translateY(10px);
364+
}
365+
to {
366+
opacity: 1;
367+
transform: translateY(0);
368+
}
369+
}

projects/UUID/index.html

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
<!doctype html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="utf-8" />
6+
<meta name="viewport" content="width=device-width,initial-scale=1" />
7+
<title>Quick UUID Generator</title>
8+
<link rel="stylesheet" href="styles.css">
9+
</head>
10+
11+
<body>
12+
<button id="themeToggle" class="theme-toggle" title="Toggle Theme">🌙</button>
13+
14+
<main class="card" role="main">
15+
<h1>Quick UUID Generator</h1><br>
16+
<p>Click the button to generate a Version 4 UUID.</p>
17+
18+
<div class="controls">
19+
<button id="generate">Generate UUID</button>
20+
<div id="uuid" aria-live="polite"></div>
21+
<button id="copy" class="small-btn" title="Copy UUID">Copy</button>
22+
</div>
23+
24+
<div class="hint">Tip: Click <em>Copy</em> or click the UUID itself to copy it to your clipboard.</div>
25+
</main>
26+
27+
<script src="main.js"></script>
28+
</body>
29+
30+
</html>

projects/UUID/main.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
const btn = document.getElementById('generate');
2+
const out = document.getElementById('uuid');
3+
const copyBtn = document.getElementById('copy');
4+
const themeToggle = document.getElementById('themeToggle');
5+
6+
// Theme toggle with persistence
7+
function setTheme(theme) {
8+
document.documentElement.setAttribute('data-theme', theme);
9+
localStorage.setItem('theme', theme);
10+
themeToggle.textContent = theme === 'dark' ? '🌙' : '☀️';
11+
}
12+
13+
const savedTheme = localStorage.getItem('theme') || 'dark';
14+
setTheme(savedTheme);
15+
16+
themeToggle.addEventListener('click', () => {
17+
const current = document.documentElement.getAttribute('data-theme');
18+
setTheme(current === 'dark' ? 'light' : 'dark');
19+
});
20+
21+
// UUID generation (v4)
22+
function uuidv4_fallback() {
23+
const bytes = crypto.getRandomValues(new Uint8Array(16));
24+
bytes[6] = (bytes[6] & 0x0f) | 0x40;
25+
bytes[8] = (bytes[8] & 0x3f) | 0x80;
26+
const hex = Array.from(bytes, b => b.toString(16).padStart(2, '0'));
27+
return `${hex.slice(0, 4).join('')}-${hex.slice(4, 6).join('')}-${hex.slice(6, 8).join('')}-${hex.slice(8, 10).join('')}-${hex.slice(10, 16).join('')}`;
28+
}
29+
30+
function generateUUID() {
31+
try {
32+
if (typeof crypto.randomUUID === 'function') return crypto.randomUUID();
33+
} catch (e) { }
34+
return uuidv4_fallback();
35+
}
36+
37+
function showCopiedToast() {
38+
const t = document.createElement('div');
39+
t.className = 'copied';
40+
t.textContent = 'Copied to clipboard';
41+
document.body.appendChild(t);
42+
setTimeout(() => t.remove(), 1400);
43+
}
44+
45+
btn.addEventListener('click', () => {
46+
const id = generateUUID();
47+
out.textContent = id;
48+
});
49+
50+
copyBtn.addEventListener('click', async () => {
51+
const text = out.textContent;
52+
if (!text || text === '—') return;
53+
try {
54+
await navigator.clipboard.writeText(text);
55+
showCopiedToast();
56+
} catch (e) {
57+
const ta = document.createElement('textarea');
58+
ta.value = text;
59+
document.body.appendChild(ta);
60+
ta.select();
61+
try { document.execCommand('copy'); showCopiedToast(); }
62+
catch (err) { alert('Copy failed — select the UUID and press Ctrl/Cmd+C'); }
63+
ta.remove();
64+
}
65+
});
66+
67+
out.addEventListener('click', async () => {
68+
const text = out.textContent;
69+
if (!text || text === '—') return;
70+
try { await navigator.clipboard.writeText(text); showCopiedToast(); } catch (e) { }
71+
});

0 commit comments

Comments
 (0)