Dodałem Hero
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
import React from 'react';
|
||||
|
||||
const BentoCard = ({ type, badge, title, category, readTime, bgImage, hero = false, style = {} }) => {
|
||||
return (
|
||||
<article
|
||||
className={`bento-card${hero ? ' hero-article' : ''}`}
|
||||
style={style}
|
||||
tabIndex={0}
|
||||
aria-label={`${category}: ${title}`}
|
||||
>
|
||||
<div
|
||||
className="bento-bg"
|
||||
style={{ backgroundImage: `url(${bgImage})` }}
|
||||
role="img"
|
||||
aria-label={title}
|
||||
/>
|
||||
<div className="bento-overlay" aria-hidden="true" />
|
||||
|
||||
{badge && (
|
||||
<div className={`bento-badge badge-${type}`} aria-label={`Etykieta: ${badge}`}>
|
||||
{badge}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="bento-content">
|
||||
<h2 className="article-title">{title}</h2>
|
||||
<div className="article-meta">
|
||||
<span>{category}</span>
|
||||
<span className="dot" aria-hidden="true" />
|
||||
<span>{readTime}</span>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
);
|
||||
};
|
||||
|
||||
export default BentoCard;
|
||||
@@ -0,0 +1,69 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
|
||||
const BentoSlideshow = ({ slides, style = {} }) => {
|
||||
const [current, setCurrent] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
const timer = setInterval(() => {
|
||||
setCurrent((prev) => (prev + 1) % slides.length);
|
||||
}, 5000);
|
||||
return () => clearInterval(timer);
|
||||
}, [slides.length]);
|
||||
|
||||
return (
|
||||
<div
|
||||
className="bento-card slideshow-card"
|
||||
style={style}
|
||||
role="region"
|
||||
aria-label="Wyróżnione artykuły"
|
||||
aria-roledescription="karuzela"
|
||||
>
|
||||
{slides.map((slide, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="bento-bg"
|
||||
style={{ backgroundImage: `url(${slide.bgImage})` }}
|
||||
role="img"
|
||||
aria-label={slide.title}
|
||||
aria-hidden={index !== current}
|
||||
data-active={index === current}
|
||||
/>
|
||||
))}
|
||||
|
||||
<div className="bento-overlay" aria-hidden="true" />
|
||||
|
||||
<div className="slideshow-content">
|
||||
{slides.map((slide, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className={`slideshow-slide${index === current ? ' slideshow-slide--active' : ''}`}
|
||||
aria-hidden={index !== current}
|
||||
>
|
||||
<div className={`bento-badge badge-${slide.type}`}>{slide.badge}</div>
|
||||
<h2 className="article-title slideshow-title">{slide.title}</h2>
|
||||
<div className="article-meta">
|
||||
<span>{slide.category}</span>
|
||||
<span className="dot" aria-hidden="true" />
|
||||
<span>{slide.readTime}</span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
<div className="slideshow-dots" role="tablist" aria-label="Slajdy">
|
||||
{slides.map((slide, index) => (
|
||||
<button
|
||||
key={index}
|
||||
role="tab"
|
||||
aria-selected={index === current}
|
||||
aria-label={`Slajd ${index + 1}: ${slide.title}`}
|
||||
className={`slideshow-dot${index === current ? ' slideshow-dot--active' : ''}`}
|
||||
onClick={(e) => { e.stopPropagation(); setCurrent(index); }}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default BentoSlideshow;
|
||||
@@ -0,0 +1,33 @@
|
||||
import React, { useState } from 'react';
|
||||
|
||||
const STORAGE_KEY = 'dexos-cookie-consent';
|
||||
|
||||
const CookieBanner = () => {
|
||||
const [visible, setVisible] = useState(() => !localStorage.getItem(STORAGE_KEY));
|
||||
|
||||
const handleConsent = (accepted) => {
|
||||
localStorage.setItem(STORAGE_KEY, accepted ? 'accepted' : 'rejected');
|
||||
setVisible(false);
|
||||
};
|
||||
|
||||
if (!visible) return null;
|
||||
|
||||
return (
|
||||
<div className="cookie-banner" role="dialog" aria-modal="true" aria-label="Zgoda na pliki cookie">
|
||||
<div className="cookie-content">
|
||||
<h4>Ciasteczka</h4>
|
||||
<p>Używamy plików cookie, aby dostarczać spersonalizowane treści i analizować ruch na stronie.</p>
|
||||
<div className="cookie-actions">
|
||||
<button className="button-secondary" onClick={() => handleConsent(false)}>
|
||||
Odrzuć
|
||||
</button>
|
||||
<button className="button-primary" onClick={() => handleConsent(true)}>
|
||||
Akceptuj
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default CookieBanner;
|
||||
@@ -0,0 +1,40 @@
|
||||
import React, { useState } from 'react';
|
||||
|
||||
const Nav = () => {
|
||||
const [menuOpen, setMenuOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<nav className="main-nav" aria-label="Główna nawigacja">
|
||||
<div className="nav-container">
|
||||
<div className="nav-logo">
|
||||
<span className="pulse-dot" aria-hidden="true"></span>
|
||||
DEX_OS
|
||||
</div>
|
||||
|
||||
<button
|
||||
className={`nav-hamburger ${menuOpen ? 'nav-hamburger--open' : ''}`}
|
||||
onClick={() => setMenuOpen((prev) => !prev)}
|
||||
aria-label={menuOpen ? 'Zamknij menu' : 'Otwórz menu'}
|
||||
aria-expanded={menuOpen}
|
||||
>
|
||||
<span></span>
|
||||
<span></span>
|
||||
<span></span>
|
||||
</button>
|
||||
|
||||
<div className={`nav-links ${menuOpen ? 'nav-links--open' : ''}`} role="menu">
|
||||
<a href="#" className="active" aria-current="page" role="menuitem">Wiadomości</a>
|
||||
<a href="#" role="menuitem">Dla zaawansowanych</a>
|
||||
<a href="#" role="menuitem">Modele AI</a>
|
||||
<a href="#" role="menuitem">Biblioteka Promptów</a>
|
||||
</div>
|
||||
|
||||
<div className="nav-actions">
|
||||
<button className="nav-button">Subskrybuj PRO</button>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
);
|
||||
};
|
||||
|
||||
export default Nav;
|
||||
Reference in New Issue
Block a user