init proj

This commit is contained in:
ld3zian 2025-03-07 15:04:34 -07:00
parent aa0c03b86b
commit fd14c1a80c
48 changed files with 10041 additions and 1 deletions

View file

@ -0,0 +1,111 @@
---
import type { Announcement } from '../lib/types';
interface Props {
announcement: Announcement;
}
const { announcement } = Astro.props;
const bgColorClass = {
info: 'bg-[rgb(var(--accent))] text-[rgb(var(--accent-text))]',
warning: 'bg-yellow-500 text-white',
success: 'bg-emerald-500 text-white'
}[announcement.type];
// Create a simple hash of the announcement content
const announcementHash = btoa(JSON.stringify({
message: announcement.message,
type: announcement.type,
link: announcement.link
}));
---
<div class={`announcement-banner hidden w-full ${bgColorClass} px-6 py-4 shadow-lg`}>
<div class="container mx-auto flex items-center justify-between">
<div class="flex items-center gap-3 text-lg">
{announcement.type === 'info' && (
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
)}
{announcement.type === 'warning' && (
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z" />
</svg>
)}
{announcement.type === 'success' && (
<svg class="w-6 h-6" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
</svg>
)}
<span class="font-medium">{announcement.message}</span>
{announcement.link && (
<a
href={announcement.link.url}
class="underline hover:opacity-80 transition-opacity font-semibold ml-2"
>
{announcement.link.text} →
</a>
)}
</div>
{announcement.dismissible && (
<button
class="dismiss-announcement p-2 hover:bg-black/10 rounded-full transition-colors"
aria-label="Dismiss announcement"
>
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
)}
</div>
</div>
<script define:vars={{ dismissible: announcement.dismissible, announcementHash }}>
const banner = document.querySelector('.announcement-banner');
const dismissBtn = document.querySelector('.dismiss-announcement');
const storageKey = `announcement-dismissed-${announcementHash}`;
// Check if announcement should be shown
function checkVisibility() {
// Only check localStorage if the banner is dismissible
const isDismissed = dismissible ?
localStorage.getItem(storageKey) === 'true' :
false;
if (!isDismissed && banner) {
banner.classList.remove('hidden');
}
}
// Run after DOM is loaded
document.addEventListener('DOMContentLoaded', checkVisibility);
dismissBtn?.addEventListener('click', () => {
if (dismissible) {
banner?.classList.add('hidden');
localStorage.setItem(storageKey, 'true');
}
});
</script>
<style>
.announcement-banner {
animation: slideDown 0.5s ease-out;
}
@keyframes slideDown {
from {
transform: translateY(-100%);
opacity: 0;
}
to {
transform: translateY(0);
opacity: 1;
}
}
</style>