From 9be70c86529f0198203dc8a9751c05f7d50f5f9f Mon Sep 17 00:00:00 2001 From: Vitalii Perehonchuk Date: Fri, 26 Jan 2024 11:44:47 +0200 Subject: [PATCH] feat: baseline indicator --- .../assets/baseline-high.svg | 6 + .../assets/baseline-limited.svg | 7 + .../baselineIndicator/assets/baseline-low.svg | 6 + .../assets/browser-chrome.svg | 19 ++ .../baselineIndicator/assets/browser-edge.svg | 65 ++++++ .../assets/browser-firefox.svg | 146 ++++++++++++ .../assets/browser-safari.svg | 44 ++++ components/baselineIndicator/assets/check.svg | 8 + components/baselineIndicator/assets/cross.svg | 9 + .../baselineIndicator.module.scss | 217 ++++++++++++++++++ .../baselineIndicator/baselineIndicator.tsx | 190 +++++++++++++++ content/wdContentLoader.ts | 8 + pages/uk/docs/[...slug].tsx | 7 +- 13 files changed, 731 insertions(+), 1 deletion(-) create mode 100644 components/baselineIndicator/assets/baseline-high.svg create mode 100644 components/baselineIndicator/assets/baseline-limited.svg create mode 100644 components/baselineIndicator/assets/baseline-low.svg create mode 100644 components/baselineIndicator/assets/browser-chrome.svg create mode 100644 components/baselineIndicator/assets/browser-edge.svg create mode 100644 components/baselineIndicator/assets/browser-firefox.svg create mode 100644 components/baselineIndicator/assets/browser-safari.svg create mode 100644 components/baselineIndicator/assets/check.svg create mode 100644 components/baselineIndicator/assets/cross.svg create mode 100644 components/baselineIndicator/baselineIndicator.module.scss create mode 100644 components/baselineIndicator/baselineIndicator.tsx diff --git a/components/baselineIndicator/assets/baseline-high.svg b/components/baselineIndicator/assets/baseline-high.svg new file mode 100644 index 0000000..f6ac12e --- /dev/null +++ b/components/baselineIndicator/assets/baseline-high.svg @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/components/baselineIndicator/assets/baseline-limited.svg b/components/baselineIndicator/assets/baseline-limited.svg new file mode 100644 index 0000000..8930b8c --- /dev/null +++ b/components/baselineIndicator/assets/baseline-limited.svg @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/components/baselineIndicator/assets/baseline-low.svg b/components/baselineIndicator/assets/baseline-low.svg new file mode 100644 index 0000000..83264e6 --- /dev/null +++ b/components/baselineIndicator/assets/baseline-low.svg @@ -0,0 +1,6 @@ + + + + \ No newline at end of file diff --git a/components/baselineIndicator/assets/browser-chrome.svg b/components/baselineIndicator/assets/browser-chrome.svg new file mode 100644 index 0000000..c401678 --- /dev/null +++ b/components/baselineIndicator/assets/browser-chrome.svg @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/components/baselineIndicator/assets/browser-edge.svg b/components/baselineIndicator/assets/browser-edge.svg new file mode 100644 index 0000000..85d0dfc --- /dev/null +++ b/components/baselineIndicator/assets/browser-edge.svg @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/components/baselineIndicator/assets/browser-firefox.svg b/components/baselineIndicator/assets/browser-firefox.svg new file mode 100644 index 0000000..78c1f4d --- /dev/null +++ b/components/baselineIndicator/assets/browser-firefox.svg @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/components/baselineIndicator/assets/browser-safari.svg b/components/baselineIndicator/assets/browser-safari.svg new file mode 100644 index 0000000..778a265 --- /dev/null +++ b/components/baselineIndicator/assets/browser-safari.svg @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/components/baselineIndicator/assets/check.svg b/components/baselineIndicator/assets/check.svg new file mode 100644 index 0000000..8466c8f --- /dev/null +++ b/components/baselineIndicator/assets/check.svg @@ -0,0 +1,8 @@ + + + + + + \ No newline at end of file diff --git a/components/baselineIndicator/assets/cross.svg b/components/baselineIndicator/assets/cross.svg new file mode 100644 index 0000000..9b02b2e --- /dev/null +++ b/components/baselineIndicator/assets/cross.svg @@ -0,0 +1,9 @@ + + + + + + \ No newline at end of file diff --git a/components/baselineIndicator/baselineIndicator.module.scss b/components/baselineIndicator/baselineIndicator.module.scss new file mode 100644 index 0000000..2b5e729 --- /dev/null +++ b/components/baselineIndicator/baselineIndicator.module.scss @@ -0,0 +1,217 @@ +$browsers: "chrome", "edge", "firefox", "safari"; + +.baselineIndicator { + --baseline-high-bg: #e6f4ea; + --baseline-high-engine-bg: #ceead6; + --baseline-high-img: url(./assets/baseline-high.svg); + --baseline-high-check: #099949; + --baseline-low-bg: #e8f0fe; + --baseline-low-engine-bg: #d2e3fc; + --baseline-low-check: #1a73e8; + --baseline-low-img: url(./assets/baseline-low.svg); + --baseline-low-pill-bg: #3367d6; + --baseline-low-pill-color: #f1f3f4; + --baseline-limited-bg: #f1f3f4; + --baseline-limited-engine-bg: #e3e6e8; + --baseline-limited-img: url(./assets/baseline-limited.svg); + --baseline-limited-check: #1e8e3e; + --baseline-limited-cross: #ea8600; + --baseline-bg: var(--baseline-limited-bg); + --baseline-img: var(--baseline-limited-img); + --baseline-cross: var(--baseline-limited-cross); + --baseline-img: var(--baseline-limited-img); + --baseline-pill-bg: var(--baseline-limited-pill-bg); + --baseline-check: var(--baseline-limited-check); + --baseline-engine-bg: var(--baseline-limited-engine-bg); + + background: var(--baseline-bg); + border-radius: 0.25rem; + margin: 1rem 0; + padding-left: 3.8125rem; + + &.high { + --baseline-bg: var(--baseline-high-bg); + --baseline-engine-bg: var(--baseline-high-engine-bg); + --baseline-img: var(--baseline-high-img); + --baseline-check: var(--baseline-high-check); + } + + &.low { + --baseline-bg: var(--baseline-low-bg); + --baseline-engine-bg: var(--baseline-low-engine-bg); + --baseline-img: var(--baseline-low-img); + --baseline-check: var(--baseline-low-check); + --baseline-pill-bg: var(--baseline-low-pill-bg); + --baseline-pill-color: var(--baseline-low-pill-color); + } + + &[open] { + summary .iconChevron { + transform: rotate(180deg); + } + } + + summary { + --chevron-size: 0.6875rem; + --chevron-padding-left: 0.75rem; + --chevron-padding-right: 1.25rem; + + align-items: center; + cursor: pointer; + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + justify-content: space-between; + padding: 1rem 0; + padding-right: calc( + var(--chevron-padding-left) + var(--chevron-size) + + var(--chevron-padding-right) + ); + position: relative; + + &::-webkit-details-marker { + // Remove arrow from older versions of Safari. + display: none; + } + + .indicator { + --width: 2.3125rem; + + background-image: var(--baseline-img); + background-position: center; + background-repeat: no-repeat; + background-size: contain; + display: block; + height: 2.25rem; + left: calc(-0.5rem - var(--width)); + position: absolute; + top: 1rem; + width: var(--width); + } + + h2 { + font-size: 1rem; + font-weight: 600; + letter-spacing: 0; + line-height: 1.5; + margin: 0; + padding: 0.375rem 0; + border-bottom-style: none; + + .notBold { + font-weight: normal; + } + } + + .pill { + background: var(--baseline-pill-bg); + border-radius: 0.125rem; + color: var(--baseline-pill-color); + font-size: 0.75rem; + font-weight: 600; + margin-right: auto; + padding: 0 0.25rem; + text-transform: uppercase; + } + + .browsers { + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + + .engine { + background: var(--baseline-engine-bg); + border-radius: 2rem; + display: flex; + flex-wrap: wrap; + gap: 0.5rem; + padding: 0.5rem 0.625rem; + + .browser { + display: flex; + + &::before { + background-repeat: no-repeat; + background-size: contain; + content: ""; + display: block; + height: 1.25rem; + width: 1.25rem; + } + + @each $name in $browsers { + &.#{$name}::before { + background-image: url("./assets/browser-" + $name + ".svg"); + } + } + + &::after { + background-color: var(--baseline-cross); + content: ""; + display: block; + height: 1.25rem; + mask-image: url("./assets/cross.svg"); + mask-repeat: no-repeat; + mask-size: contain; + width: 1rem; + } + + &.supported::after { + background-color: var(--baseline-check); + mask-image: url("./assets/check.svg"); + } + } + } + } + + .iconChevron { + --icon-size: var(--chevron-size); + --icon-primary: var(--text-primary); + position: absolute; + right: var(--chevron-padding-right); + } + } + + .extra { + padding-bottom: 1.5rem; + padding-right: 1rem; + + p { + margin-bottom: 1rem; + margin-top: 0; + } + + ul { + column-gap: 1.5rem; + display: flex; + flex-wrap: wrap; + margin: 0; + padding: 0; + row-gap: 1rem; + + li { + font-weight: 500; + list-style: none; + margin: 0; + + a.learnMore { + &, + &:active, + &:visited { + background: none; + color: var(--color-ui-primary); + } + } + + a:not(.learnMore) { + &, + &:active, + &:visited { + background: none; + color: var(--color-ui-typo); + } + } + } + } + } +} diff --git a/components/baselineIndicator/baselineIndicator.tsx b/components/baselineIndicator/baselineIndicator.tsx new file mode 100644 index 0000000..90cd868 --- /dev/null +++ b/components/baselineIndicator/baselineIndicator.tsx @@ -0,0 +1,190 @@ +import classNames from 'classnames'; +import { useRouter } from 'next/router'; +import { useCallback, useMemo } from 'react'; + +import type { BaselineItem } from '../../content/wdContentLoader'; + +import { ChevronDownIcon } from '../icons'; + +import classes from './baselineIndicator.module.scss'; + +const ENGINES = [ + { name: 'Blink', browsers: ['Chrome', 'Edge'] }, + { name: 'Gecko', browsers: ['Firefox'] }, + { name: 'WebKit', browsers: ['Safari'] }, +]; +const SURVEY_URL = + 'https://survey.alchemer.com/s3/7634825/MDN-baseline-feedback'; +const BCD_LINK = `#sumisnist-iz-brauzeramy`; + +export default function BaselineIndicator({ + status, +}: { + status?: BaselineItem; +}) { + const { pathname } = useRouter(); + + const low_date = useMemo( + () => + status?.baseline_low_date + ? new Date(status.baseline_low_date) + : undefined, + [status?.baseline_low_date] + ); + const level = status?.baseline + ? status.baseline + : status?.baseline === false + ? 'not' + : undefined; + + const feedbackLink = `${SURVEY_URL}?page=${encodeURIComponent( + pathname + )}&level=${level}`; + + const supported = useCallback( + (browser: string) => { + if (!status) { + return false; + } + const version: string | undefined = + status.support?.[browser.toLowerCase()]; + return Boolean(status.baseline || version); + }, + [status] + ); + + const engineTitle = useCallback( + (browsers: string[]) => + browsers + .map((browser, index, array) => { + const previous = index > 0 ? supported(array[index - 1]) : undefined; + const current = supported(browser); + return typeof previous === 'undefined' + ? current + ? `Підтримується в ${browser}` + : `Не має широкої підтримки в ${browser}` + : current === previous + ? ` і ${browser}` + : current + ? `, а також підтримується в ${browser}` + : `, але не має широкої підтримки в ${browser}`; + }) + .join(''), + [supported] + ); + // const [isExpanded, setIsExpanded] = useState(false); + // const toggleIsExpanded = useCallback( + // () => setIsExpanded((oldValue) => !oldValue), + // [] + // ); + if (!status) return null; + + return level ? ( +
+ + +

+ {level !== 'not' ? ( + <> + База{' '} + + {level === 'high' + ? 'Широка доступність' + : low_date?.getFullYear()} + + + ) : ( + Обмежена доступність + )} +

+ {level === 'low' && ( +
Доступне віднедавна
+ )} +
+ {ENGINES.map(({ name, browsers }) => ( + + {browsers.map((browser) => ( + + ))} + + ))} +
+ +
+
+ {level === 'high' && low_date ? ( +

+ Ця можливість є добре вкоріненою та працює на багатьох пристроях та + версіях браузерів. Вона доступна у браузерах від:{' '} + {low_date.toLocaleDateString('uk-UA', { + year: 'numeric', + month: 'long', + })} + . +

+ ) : level === 'low' && low_date ? ( +

+ Ця можливість працює в найновіших пристроях і версіях браузерів від:{' '} + {low_date.toLocaleDateString('uk-UA', { + year: 'numeric', + month: 'long', + })} + . Вона може не працювати в старих пристроях або браузерах. +

+ ) : ( +

+ Ця можливість не належить до Бази, оскільки вона не працює в частині + найбільш поширених браузерів. +

+ )} + +
+
+ ) : null; +} diff --git a/content/wdContentLoader.ts b/content/wdContentLoader.ts index 3fb6e54..712a730 100644 --- a/content/wdContentLoader.ts +++ b/content/wdContentLoader.ts @@ -17,6 +17,12 @@ export interface MacroData { result: string; } +export interface BaselineItem { + baseline: false | 'high' | 'low'; + baseline_low_date?: string; + support: Record; +} + export interface ContentItem { id?: string; // TODO??? title: string; @@ -37,6 +43,7 @@ export interface ContentItem { browser_compat: unknown; // TODO:: prev?: string; next?: string; + baseline: BaselineItem; } // TODO: merge types @@ -82,6 +89,7 @@ export interface PageData { slug: string; tags: string[]; browserCompat: string; + baseline: BaselineItem; } const readIndex = async (): Promise => { diff --git a/pages/uk/docs/[...slug].tsx b/pages/uk/docs/[...slug].tsx index 883330d..1601fa7 100644 --- a/pages/uk/docs/[...slug].tsx +++ b/pages/uk/docs/[...slug].tsx @@ -11,6 +11,7 @@ import LayoutFooter from '../../../components/layoutFooter'; import MetaHead from '../../../components/metaHead'; import { normalizeUrl } from '../../../utils/url'; import CtaTranslate from '../../../components/ctaTranslate'; +import BaselineIndicator from '../../../components/baselineIndicator/baselineIndicator'; const mdnUrlPrefix = 'https://developer.mozilla.org/en-US/docs/'; @@ -59,6 +60,7 @@ export default function DocEntry({ originalPath, path, section, + baseline, } = page; const robots = hasContent ? 'all' : 'noindex,nofollow'; const hasSidebar = !!macros?.length; @@ -125,7 +127,10 @@ export default function DocEntry({

{title}

{hasContent ? ( -
+ <> + +
+ ) : (