Skip to content

Commit

Permalink
Improved accessibility
Browse files Browse the repository at this point in the history
  • Loading branch information
theoplawinski committed Jul 16, 2024
1 parent 6d39959 commit 49ccd03
Show file tree
Hide file tree
Showing 5 changed files with 111 additions and 39 deletions.
18 changes: 18 additions & 0 deletions apps/front/src/components/lazyImage/LazyImage.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,21 @@
:global(.lazyloaded) {
opacity: 1;
}

.imageWrapper {
position: relative;
width: 100%;
height: 0;
}

.image {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
object-fit: cover;
&:global(.lazyJs) {
opacity: 0;
}
}
74 changes: 55 additions & 19 deletions apps/front/src/components/lazyImage/LazyImage.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,22 @@
import React, { CSSProperties, useEffect, useRef, useState } from "react"
import css from "./LazyImage.module.scss"
import { cls } from "@cher-ami/utils"
import css from "./LazyImage.module.scss"
import { CSSProperties } from "preact/compat"
import { useRef, useState, useEffect } from "preact/hooks"

interface IProps {
src?: string
dataSrc?: string
dataSrcSet?: string
className?: string
alt?: string
aspectRatio?: number
style?: CSSProperties
width: number
height: number
onLoaded?: (img: HTMLImageElement) => void
}

export type Lazy = "lazyload" | "lazyloading" | "lazyloaded"

/**
* @name LazyImage
*/
function LazyImage(props: IProps) {
const imageRef = useRef<HTMLImageElement>(null)
const [lazyState, setLazyState] = useState<Lazy>("lazyload")
Expand Down Expand Up @@ -51,6 +50,21 @@ function LazyImage(props: IProps) {
const lazyStateRef = useRef<Lazy>("lazyload")

useEffect(() => {
// if img lazy is supported by the browser we don't need to use IntersectionObserver
if ("loading" in HTMLImageElement.prototype) {
// add src and srcset to image
if (imageRef.current) {
imageRef.current.srcset = props.dataSrcSet ?? ""
imageRef.current.src = props.src && !props.dataSrcSet ? props.src : ""
}
return
}

// add class lazyJs on imageRef
if (imageRef.current) {
imageRef.current.classList.add("lazyJs")
}

const observer = new IntersectionObserver((entries) => {
entries.forEach(async (entry) => {
if (entry.isIntersecting) {
Expand All @@ -62,7 +76,9 @@ function LazyImage(props: IProps) {
// Start preload
await preloadImage(image)

// end!
// Set new src fallback
image.src = props.src ?? "data:,"

setLazyState("lazyloaded")
props.onLoaded?.(image)
observer.disconnect()
Expand All @@ -76,19 +92,39 @@ function LazyImage(props: IProps) {
}
}, [])

const aspectRatioPadding =
props.width && props.height ? (props.height / props.width) * 100 : 0

return (
<img
ref={imageRef}
className={cls(css.root, props.className, lazyState)}
src={props.src ?? "data:,"}
data-src={props?.dataSrc}
data-srcset={props?.dataSrcSet}
alt={props?.alt}
style={{
...(props.aspectRatio ? { aspectRatio: `${props.aspectRatio}` } : {}),
...(props.style || {})
}}
/>
<>
<div
className={cls(css.imageWrapper, props.className)}
style={{ paddingBottom: `${aspectRatioPadding}%` }}
>
<img
ref={imageRef}
className={cls(css.image, lazyState)}
src={"data:,"}
data-src={props.dataSrc}
data-srcset={props.dataSrcSet}
alt={props.alt}
width={props.width}
height={props.height}
style={props.style}
loading={"lazy"}
/>
</div>
<noscript>
<img
className={cls(css.image, props.className)}
src={props.src}
srcSet={props.dataSrcSet}
alt={props.alt}
width={props.width}
height={props.height}
/>
</noscript>
</>
)
}

Expand Down
2 changes: 1 addition & 1 deletion apps/front/src/index-server.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export async function render(
<head>
<meta charSet="UTF-8" />
<meta httpEquiv="x-ua-compatible" content="IE=Edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>{meta?.title || "app"}</title>
<meta name="description" content={meta?.description} />
<link rel="canonical" href={meta?.url || url} />
Expand Down
54 changes: 36 additions & 18 deletions apps/front/src/styles/_ratio.scss
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@
#{$property}: fn.toRem(nth($value1, 1)) fn.toRem(nth($value1, 2));
} @else if length($value1) == 3 {
#{$property}: fn.toRem(nth($value1, 1))
fn.toRem(nth($value1, 2))
fn.toRem(nth($value1, 3));
fn.toRem(nth($value1, 2))
fn.toRem(nth($value1, 3));
} @else if length($value1) == 4 {
#{$property}: fn.toRem(nth($value1, 1))
fn.toRem(nth($value1, 2))
fn.toRem(nth($value1, 3))
fn.toRem(nth($value1, 4));
fn.toRem(nth($value1, 2))
fn.toRem(nth($value1, 3))
fn.toRem(nth($value1, 4));
}
@if $value2 != $value1 {
@media (min-width: breakpoints.$breakpoint-tablet) {
Expand All @@ -59,13 +59,13 @@
#{$property}: fn.toRem(nth($value2, 1)) fn.toRem(nth($value2, 2));
} @else if length($value2) == 3 {
#{$property}: fn.toRem(nth($value2, 1))
fn.toRem(nth($value2, 2))
fn.toRem(nth($value2, 3));
fn.toRem(nth($value2, 2))
fn.toRem(nth($value2, 3));
} @else if length($value2) == 4 {
#{$property}: fn.toRem(nth($value2, 1))
fn.toRem(nth($value2, 2))
fn.toRem(nth($value2, 3))
fn.toRem(nth($value2, 4));
fn.toRem(nth($value2, 2))
fn.toRem(nth($value2, 3))
fn.toRem(nth($value2, 4));
}
}
}
Expand Down Expand Up @@ -97,7 +97,17 @@
@include propertyVW($property, $value2, viewport.$viewport-reference-tablet-width);
}

//Horizontal mobile
// Landscape Tablet
@include tablet-landscape {
@include propertyVH(
$property,
$value2,
$ratioVW: viewport.$viewport-reference-desktop-width,
$ratioVH: viewport.$viewport-reference-desktop-height
);
}

// Landscape mobile
@include mobile-landscape {
@include propertyVH($property, $value2, viewport.$viewport-reference-width, 0);
}
Expand All @@ -110,13 +120,13 @@
#{$property}: fn.toPx(nth($value1, 1)) fn.toPx(nth($value1, 2));
} @else if length($value1) == 3 {
#{$property}: fn.toPx(nth($value1, 1))
fn.toPx(nth($value1, 2))
fn.toPx(nth($value1, 3));
fn.toPx(nth($value1, 2))
fn.toPx(nth($value1, 3));
} @else if length($value1) == 4 {
#{$property}: fn.toPx(nth($value1, 1))
fn.toPx(nth($value1, 2))
fn.toPx(nth($value1, 3))
fn.toPx(nth($value1, 4));
fn.toPx(nth($value1, 2))
fn.toPx(nth($value1, 3))
fn.toPx(nth($value1, 4));
}
}
}
Expand All @@ -142,9 +152,17 @@
}

/// Mobile landscape media query.
/// @param {string} [$breakpoint=breakpoints.$breakpoint-tablet] - Le point de rupture pour les médias queries (par défaut égal à breakpoints.$breakpoint-laptop).
@mixin mobile-landscape($breakpoint: breakpoints.$breakpoint-tablet) {
@media (max-width: #{$breakpoint + 1}) and (orientation: landscape) {
@content;
}
}

/// Tablet landscape media query.
/// @param {string} [$breakpoint=breakpoints.$breakpoint-laptop] - Le point de rupture pour les médias queries (par défaut égal à breakpoints.$breakpoint-laptop).
@mixin mobile-landscape($breakpoint: breakpoints.$breakpoint-laptop) {
@media (max-width: #{$breakpoint - 1}) and (orientation: landscape) {
@mixin tablet-landscape($breakpoint: breakpoints.$breakpoint-laptop) {
@media (max-width: #{$breakpoint + 1}) and (orientation: landscape) {
@content;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ const %%upperComponentName%% = forwardRef((props: IProps, handleRef: ForwardedRe

return (
<div className={css.root} ref={rootRef}>
{componentName}
<h1>{componentName}</h1>
</div>
);
});
Expand Down

0 comments on commit 49ccd03

Please sign in to comment.