Skip to content
Merged
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
35 changes: 25 additions & 10 deletions src/components/homepage/homeNavBoxes.js
Original file line number Diff line number Diff line change
Expand Up @@ -120,26 +120,41 @@ function FeatureItem({url, text}){


function Feature({title, icon, items }) {
const altTexts = {
'Getting Started': 'Navigate to getting started guides and tutorials',
'Setting up your feed': 'Customize and configure your content feed',
'Key features': 'Explore daily.dev core features and functionality',
'Your profile': 'Manage your profile settings and activity',
'Squads': 'Join and manage developer community squads',
'Plus': 'Discover premium features and subscriptions',
'Monetization (beta)': 'Learn about monetization and earning features',
'Customization': 'Personalize your daily.dev experience',
'For content creators': 'Resources for content creators and publishers',
'For OSS contributors': 'Open source contribution guidelines and resources'
};

return (
<article className={clsx('col col--4')}>
<article className={clsx('col col--4')} role="region" aria-labelledby={`feature-${title.replace(/\s+/g, '-').toLowerCase()}`}>
<div className={styles.homecard}>
<img
src={icon}
className={styles.homeIcon}
loading="eager"
decoding="sync"
alt={`${title} icon`}
alt={altTexts[title] || `${title} icon`}
width="48"
height="48"
style={{ aspectRatio: '1/1' }}
/>
<h2>{title}</h2>
<h2 id={`feature-${title.replace(/\s+/g, '-').toLowerCase()}`}>{title}</h2>
<div className={styles.listContainer}>
<ul>
{items.map((props, idx) => (
<FeatureItem key={idx} {...props} />
))}
</ul>
<nav aria-label={`${title} navigation`}>
<ul>
{items.map((props, idx) => (
<FeatureItem key={idx} {...props} />
))}
</ul>
</nav>
</div>
</div>
</article>
Expand All @@ -158,8 +173,8 @@ export default function HomepageFeatures() {
}, []);

return (
<section className={styles.features}>
<ul className={styles.grid3col}>
<section className={styles.features} aria-label="Daily.dev documentation sections">
<ul className={styles.grid3col} role="list">
{FeatureList.map((props, idx) => (
<Feature key={idx} {...props} />
))}
Expand Down
43 changes: 38 additions & 5 deletions src/components/video-page/navBoxes.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,15 +98,40 @@ function Feature({title, url, type, duration }) {
// Prevent the URL from redirecting users
e.preventDefault();

// Get the video ID
// Get the video ID and title for better accessibility
let id = link.getAttribute('data-youtube');
let videoTitle = title || 'Video';

// Create the player
// Create the player with improved accessibility
let player = document.createElement('div');
player.innerHTML = `<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/${id}?autoplay=1" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>`;
player.innerHTML = `<iframe
width="560"
height="315"
src="https://www.youtube-nocookie.com/embed/${id}"
title="${videoTitle}"
frameborder="0"
allow="accelerometer; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
allowfullscreen
role="application"
aria-label="YouTube video player for ${videoTitle}">
</iframe>`;

// Inject the player into the UI
link.replaceWith(player);

// Focus the iframe after loading for keyboard users
const iframe = player.querySelector('iframe');
if (iframe) {
iframe.focus();
}
}

function handleKeyPress(e) {
// Support Enter and Space key activation
if (e.key === 'Enter' || e.key === ' ') {
e.preventDefault();
replaceVideo(e);
}
}


Expand All @@ -116,9 +141,17 @@ function Feature({title, url, type, duration }) {
<img src="img/logo.png" className={styles.vidIcon}></img>
<h2>{title}</h2>
<div className={styles.iframecontainer}>
<div className={styles.youTubeOverlay} onClick={replaceVideo} data-youtube={url}>
<div
className={styles.youTubeOverlay}
onClick={replaceVideo}
onKeyDown={handleKeyPress}
data-youtube={url}
role="button"
tabIndex="0"
aria-label={`Play video: ${title}`}
>
<div className={styles.youTubeOverlayTime}>{duration}</div>
<img className={styles.imgVid} width="340" height="180" alt="" src={"https://img.youtube.com/vi/" + url + "/0.jpg"}/>
<img className={styles.imgVid} width="340" height="180" alt={`Video thumbnail for ${title}`} src={"https://img.youtube.com/vi/" + url + "/0.jpg"}/>
</div>
</div>
{/* <div className={styles.iframecontainer}>
Expand Down
32 changes: 25 additions & 7 deletions src/css/custom.css
Original file line number Diff line number Diff line change
Expand Up @@ -345,8 +345,8 @@ img[src='/img/logo.png'] {
--burger90: #722f1b;

--ifm-container-width-xl: 1600px;
--ifm-line-height-base: 1.333;
/* a11y - needs upping to at least 1.5 */
--ifm-line-height-base: 1.5;
/* Fixed: Improved line height for better readability and accessibility */

/* these font and margin calculations are a little over complicated,
but allow for us to change the h6 size and keep the ratios set by the design team,
Expand All @@ -359,8 +359,7 @@ img[src='/img/logo.png'] {
--dd-h4-ratio: 1.1333;
--dd-h5-ratio: 1.1333;
--dd-h6-size: 1.0625rem;
--dd-h6-size: 0.9375rem;
/* ally - this needs removing and setting to 1.0625 or higher so headings are at least minimum sizes */
/* Fixed: Increased from 0.9375rem to meet minimum accessibility requirements */

/* font size calculated as ratio relative to h6 */
--dd-h1-font-size: 4rem;
Expand Down Expand Up @@ -412,6 +411,7 @@ img[src='/img/logo.png'] {
--ifm-link-color: var(--water60);
--ifm-link-hover-color: var(--water20);
--ifm-color-warning-dark: var(--cheese90);
--ifm-color-danger: var(--bacon70); /* Improved contrast: 4.89:1 ratio */

/* menu */
--ifm-menu-link-padding-vertical: 0.5rem;
Expand All @@ -433,9 +433,9 @@ html[data-theme='dark'] *:focus-visible {
}

html *:focus-visible {
outline: 2px solid var(--bluecheese60) !important;
/* A11y contrast not high enough, suggest Blue Cheese 90
#009FB3 but needs discussion with Tsahi */
outline: 2px solid var(--bluecheese90) !important;
outline-offset: 2px;
/* Fixed: Using bluecheese90 for better contrast (3.27:1) */
}

article {
Expand Down Expand Up @@ -632,6 +632,24 @@ div[class^='announcementBar_'] {
}
}

/* Reduced motion preferences for accessibility */
@media (prefers-reduced-motion: reduce) {
.hero__title,
.navbar__link,
.menu__link--sublist:after,
.menu__link--sublist[aria-expanded="true"]:after,
.menu__link--sublist[aria-expanded="false"]:after,
summary:before,
*,
*::before,
*::after {
animation-duration: 0.01ms !important;
animation-iteration-count: 1 !important;
transition-duration: 0.01ms !important;
scroll-behavior: auto !important;
}
}


/* typography */

Expand Down
72 changes: 68 additions & 4 deletions src/registerSW.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,69 @@
// Create accessible update notification
function showUpdateNotification() {
const notification = document.createElement('div');
notification.setAttribute('role', 'alert');
notification.setAttribute('aria-live', 'polite');
notification.style.cssText = `
position: fixed;
top: 20px;
right: 20px;
background: var(--ifm-color-primary);
color: white;
padding: 1rem;
border-radius: 8px;
box-shadow: 0 4px 12px rgba(0,0,0,0.15);
z-index: 9999;
font-family: inherit;
max-width: 300px;
`;

notification.innerHTML = `
<div>
<p style="margin: 0 0 1rem 0; font-size: 0.9rem;">New version available. Would you like to reload to get the latest features?</p>
<div style="display: flex; gap: 0.5rem;">
<button id="sw-reload-btn" style="
background: white;
color: var(--ifm-color-primary);
border: none;
padding: 0.5rem 1rem;
border-radius: 4px;
cursor: pointer;
font-size: 0.8rem;
font-weight: 500;
">Reload</button>
<button id="sw-dismiss-btn" style="
background: transparent;
color: white;
border: 1px solid white;
padding: 0.5rem 1rem;
border-radius: 4px;
cursor: pointer;
font-size: 0.8rem;
font-weight: 500;
">Later</button>
</div>
</div>
`;

document.body.appendChild(notification);

// Add event listeners
document.getElementById('sw-reload-btn').addEventListener('click', () => {
window.location.reload();
});

document.getElementById('sw-dismiss-btn').addEventListener('click', () => {
notification.remove();
});

// Auto-dismiss after 10 seconds
setTimeout(() => {
if (notification.parentNode) {
notification.remove();
}
}, 10000);
}

// Register service worker with optimal timing
export default function registerSW() {
if ('serviceWorker' in navigator) {
Expand All @@ -13,10 +79,8 @@ export default function registerSW() {
if (newWorker) {
newWorker.addEventListener('statechange', () => {
if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
// New update available
if (confirm('New version available. Reload to get the latest features?')) {
window.location.reload();
}
// New update available - show accessible notification
showUpdateNotification();
}
});
}
Expand Down
4 changes: 2 additions & 2 deletions static/img/icons/community.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions static/img/icons/content-creator.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion static/img/icons/cores.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading