Update static pages

This commit is contained in:
Justin Edmund 2023-06-30 22:12:47 -07:00
parent bd10c93dc8
commit c0392a1bab
12 changed files with 407 additions and 402 deletions

View file

@ -1,4 +1,4 @@
.About.PageContent {
.about {
$width: 520px;
padding-bottom: $unit-12x;
@ -9,7 +9,7 @@
gap: $unit-2x;
z-index: 5;
.Hero {
.hero {
position: absolute;
width: 40vw;
height: 80vh;
@ -55,22 +55,10 @@
z-index: 2;
}
}
.Links {
.links {
display: grid;
gap: $unit;
margin: $unit-2x 0;
}
div.LinkItem {
margin-top: $unit-2x;
}
.LinkItem {
max-width: calc($width / 3 * 2);
@include breakpoint(phone) {
max-width: inherit;
width: 100%;
}
}
}

View file

@ -1,6 +1,9 @@
import React from 'react'
import Link from 'next/link'
import { Trans, useTranslation } from 'next-i18next'
import classNames from 'classnames'
import LinkItem from '../LinkItem'
import ShareIcon from '~public/icons/Share.svg'
import DiscordIcon from '~public/icons/discord.svg'
@ -14,8 +17,10 @@ const AboutPage: React.FC<Props> = (props: Props) => {
const { t: common } = useTranslation('common')
const { t: about } = useTranslation('about')
const classes = classNames(styles.about, 'PageContent')
return (
<div className="About PageContent">
<div className={classes}>
<h1>{common('about.segmented_control.about')}</h1>
<section>
<h2>
@ -33,28 +38,19 @@ const AboutPage: React.FC<Props> = (props: Props) => {
</h2>
<p>{about('about.explanation.0')}</p>
<p>{about('about.explanation.1')}</p>
<div className="Hero" />
<div className={styles.hero} />
</section>
<section>
<h2>{about('about.feedback.title')}</h2>
<p>{about('about.feedback.explanation')}</p>
<p>{about('about.feedback.solicit')}</p>
<div className="Discord LinkItem">
<Link href="https://discord.gg/qyZ5hGdPC8">
<a
href="https://discord.gg/qyZ5hGdPC8"
target="_blank"
rel="noreferrer"
>
<div className="Left">
<DiscordIcon />
<h3>granblue-tools</h3>
</div>
<ShareIcon className="ShareIcon" />
</a>
</Link>
</div>
<LinkItem
className="discord constrained"
title="granblue-tools"
link="https://discord.gg/qyZ5hGdPC8"
icon={<DiscordIcon />}
/>
</section>
<section>
@ -114,38 +110,20 @@ const AboutPage: React.FC<Props> = (props: Props) => {
<h2>{about('about.contributing.title')}</h2>
<p>{about('about.contributing.explanation')}</p>
<ul className="Links">
<li className="Github LinkItem">
<Link href="https://github.com/jedmund/hensei-api">
<a
href="https://github.com/jedmund/hensei-api"
target="_blank"
rel="noreferrer"
>
<div className="Left">
<GithubIcon />
<h3>jedmund/hensei-api</h3>
</div>
<ShareIcon className="ShareIcon" />
</a>
</Link>
</li>
<li className="Github LinkItem">
<Link href="https://github.com/jedmund/hensei-web">
<a
href="https://github.com/jedmund/hensei-web"
target="_blank"
rel="noreferrer"
>
<div className="Left">
<GithubIcon />
<h3>jedmund/hensei-web</h3>
</div>
<ShareIcon className="ShareIcon" />
</a>
</Link>
</li>
</ul>
<div className={styles.links}>
<LinkItem
className="github constrained"
title="jedmund/hensei-api"
link="https://github.com/jedmund/hensei-api"
icon={<GithubIcon />}
/>
<LinkItem
className="github constrained"
title="jedmund/hensei-web"
link="https://github.com/jedmund/hensei-web"
icon={<GithubIcon />}
/>
</div>
</section>
<section>
<h2>{about('about.license.title')}</h2>

View file

@ -1,4 +1,4 @@
.ChangelogUnit {
.unit {
display: flex;
flex-direction: column;
gap: $unit;

View file

@ -82,7 +82,7 @@ const ChangelogUnit = ({ id, type, image }: Props) => {
}
return (
<div className="ChangelogUnit" key={id}>
<div className={styles.unit} key={id}>
<img alt={item ? item.name[locale] : ''} src={imageUrl()} />
<h4>{item ? item.name[locale] : ''}</h4>
</div>

View file

@ -1,11 +1,71 @@
.Content.Version {
.Contents {
margin-bottom: $unit-3x;
.content.version {
display: flex;
flex-direction: column;
gap: $unit-2x;
.header {
align-items: baseline;
display: flex;
gap: $unit-half;
margin-bottom: $unit-2x;
h3 {
color: var(--accent-yellow);
font-weight: $medium;
font-size: $font-large;
}
time {
color: var(--text-secondary);
font-size: $font-small;
font-weight: $medium;
}
}
.Notes h4 {
font-weight: $medium;
font-size: $font-regular;
margin-bottom: $unit-2x;
.contents {
margin-bottom: $unit-3x;
display: grid;
grid-template-columns: 1fr;
gap: $unit-4x;
.characters,
.weapons,
.summons {
display: grid;
grid-template-rows: auto 1fr;
gap: $unit;
& > h4 {
font-weight: $medium;
font-size: $font-regular;
}
.items {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
gap: $unit-4x;
}
}
}
.notes {
h4 {
font-weight: $medium;
font-size: $font-regular;
margin-bottom: $unit-2x;
}
.list {
display: flex;
flex-direction: column;
color: var(--text-primary);
list-style-type: disc;
list-style-position: inside;
gap: $unit-half;
li {
font-size: 14px;
}
}
}
}

View file

@ -1,7 +1,8 @@
import React from 'react'
import { useTranslation } from 'next-i18next'
import ChangelogUnit from '~components/about/ChangelogUnit'
import classNames from 'classnames'
import ChangelogUnit from '~components/about/ChangelogUnit'
import styles from './index.module.scss'
interface UpdateObject {
@ -51,9 +52,9 @@ const ContentUpdate = ({
const items = newItems[key]
section =
items && items.length > 0 ? (
<section className={`${key}s`}>
<section className={styles[`${key}s`]}>
<h4>{updates(`labels.${key}s`)}</h4>
<div className="items">{newItemElements(key)}</div>
<div className={styles.items}>{newItemElements(key)}</div>
</section>
) : (
''
@ -70,9 +71,9 @@ const ContentUpdate = ({
elements = items
? items.map((id) => {
return key === 'character' ? (
<ChangelogUnit id={id} type={key} image="03" />
<ChangelogUnit id={id} type={key} key={id} image="03" />
) : (
<ChangelogUnit id={id} type={key} />
<ChangelogUnit id={id} type={key} key={id} />
)
})
: []
@ -87,9 +88,9 @@ const ContentUpdate = ({
const items = uncappedItems[key]
section =
items && items.length > 0 ? (
<section className={`${key}s`}>
<section className={styles[`${key}s`]}>
<h4>{updates(`labels.uncaps.${key}s`)}</h4>
<div className="items">{uncapItemElements(key)}</div>
<div className={styles.items}>{uncapItemElements(key)}</div>
</section>
) : (
''
@ -100,15 +101,21 @@ const ContentUpdate = ({
}
return (
<section className="Content Version" data-version={version}>
<div className="Header">
<section
className={classNames({
[styles.content]: true,
[styles.version]: true,
})}
data-version={version}
>
<div className={styles.header}>
<h3>{`${updates('events.date', {
year: date.getFullYear(),
month: `${date.getMonth() + 1}`.padStart(2, '0'),
})} ${updates(event)}`}</h3>
<time>{dateString}</time>
</div>
<div className="Contents">
<div className={styles.contents}>
{newItemSection('character')}
{uncapItemSection('character')}
{newItemSection('weapon')}
@ -117,10 +124,10 @@ const ContentUpdate = ({
{uncapItemSection('summon')}
</div>
{numNotes > 0 ? (
<div className="Notes">
<div className={styles.notes}>
<section>
<h4>{updates('labels.updates')}</h4>
<ul className="Bare Contents">
<ul className={styles.list}>
{[...Array(numNotes)].map((e, i) => (
<li key={`${version}-${i}`}>
{updates(`versions.${version}.features.${i}`)}

View file

@ -0,0 +1,77 @@
.item {
$diameter: $unit-6x;
align-items: center;
background: var(--dialog-bg);
border: 1px solid var(--link-item-bg);
border-radius: $card-corner;
display: flex;
min-height: 82px;
transition: background $duration-zoom ease-in,
transform $duration-zoom ease-in;
&:hover {
background: var(--link-item-bg);
color: var(--text-primary);
.shareIcon {
fill: var(--text-primary);
transform: translate($unit-half, calc(($unit * -1) / 2));
}
}
&.constrained {
max-width: 520px;
@include breakpoint(phone) {
max-width: inherit;
width: 100%;
}
}
&.github:hover .left .icon svg {
fill: var(--text-primary);
}
&.discord:hover .left .icon svg {
fill: #5865f2;
}
a {
display: flex;
justify-content: space-between;
padding: $unit-2x;
width: 100%;
&:hover {
text-decoration: none;
}
.left {
align-items: center;
display: flex;
gap: $unit-2x;
flex-grow: 1;
h3 {
font-weight: 600;
max-width: 70%;
line-height: 1.3;
}
}
svg {
fill: var(--link-item-image-color);
width: $diameter;
height: auto;
transition: fill $duration-zoom ease-in;
&.shareIcon {
width: $unit-4x;
}
}
}
h3 {
font-weight: $bold;
}
}

View file

@ -0,0 +1,37 @@
import { ComponentProps } from 'react'
import Link from 'next/link'
import classNames from 'classnames'
import ShareIcon from '~public/icons/Share.svg'
import styles from './index.module.scss'
interface Props extends ComponentProps<'div'> {
title: string
link: string
icon: React.ReactNode
}
const LinkItem = ({ icon, title, link, className, ...props }: Props) => {
const classes = classNames(
{
[styles.item]: true,
},
className?.split(' ').map((c) => styles[c])
)
return (
<div className={classes}>
<Link href={link}>
<a href={link} target="_blank" rel="noreferrer">
<div className={styles.left}>
<i className={styles.icon}>{icon}</i>
<h3>{title}</h3>
</div>
<ShareIcon className={styles.shareIcon} />
</a>
</Link>
</div>
)
}
export default LinkItem

View file

@ -1,5 +1,6 @@
.Roadmap.PageContent {
.roadmap {
padding-bottom: $unit-12x;
h3.priority {
font-weight: $medium;
font-size: $font-large;
@ -32,53 +33,6 @@
margin-bottom: $unit;
font-size: $font-medium;
}
.LinkItem {
$diameter: $unit-6x;
background: var(--dialog-bg);
border: 1px solid var(--link-item-bg);
border-radius: $card-corner;
&:hover {
background-color: var(--link-item-bg);
svg {
fill: var(--link-item-image-color-hover);
}
}
a {
display: flex;
padding: $unit-2x;
&:hover {
text-decoration: none;
}
.Left {
align-items: center;
display: flex;
gap: $unit-2x;
flex-grow: 1;
}
svg {
fill: var(--link-item-image-color);
width: $diameter;
height: auto;
&.ShareIcon {
width: $unit-4x;
}
}
}
h3 {
font-weight: $bold;
max-width: 70%;
line-height: 1.3;
}
}
}
ul {

View file

@ -1,9 +1,10 @@
import React from 'react'
import Link from 'next/link'
import { useRouter } from 'next/router'
import { useTranslation } from 'next-i18next'
import classNames from 'classnames'
import LinkItem from '~components/about/LinkItem'
import ShareIcon from '~public/icons/Share.svg'
import GithubIcon from '~public/icons/github.svg'
@ -15,31 +16,31 @@ const RoadmapPage = () => {
const { t: common } = useTranslation('common')
const { t: about } = useTranslation('about')
const classes = classNames(styles.roadmap, 'PageContent')
return (
<div className="Roadmap PageContent">
<div className={classes}>
<h1>{common('about.segmented_control.roadmap')}</h1>
<section className="notes">
<section className={styles.notes}>
<p>{about('roadmap.blurb')}</p>
<p>{about('roadmap.link.intro')}</p>
<div className="Github LinkItem">
<Link href="https://github.com/users/jedmund/projects/1/views/3">
<a
href="https://github.com/users/jedmund/projects/1/views/3"
target="_blank"
rel="noreferrer"
>
<div className="Left">
<GithubIcon />
<h3>{about('roadmap.link.title')}</h3>
</div>
<ShareIcon className="ShareIcon" />
</a>
</Link>
</div>
<LinkItem
className="github"
title={about('roadmap.link.title')}
link="https://github.com/users/jedmund/projects/1/views/3"
icon={<GithubIcon />}
/>
</section>
<section className="features">
<h3 className="priority in_progress">{about('roadmap.subtitle')}</h3>
<section className={styles.features}>
<h3
className={classNames({
[styles.priority]: true,
[styles.in_progress]: true,
})}
>
{about('roadmap.subtitle')}
</h3>
<ul>
{[...Array(ROADMAP_ITEMS)].map((e, i) => (
<li key={`roadmap-${i}`}>

View file

@ -1,95 +1,23 @@
.Updates.PageContent {
.updates {
padding-bottom: $unit-12x;
.Version {
.version {
display: flex;
flex-direction: column;
gap: $unit-2x;
h3,
li,
p {
}
&.Content {
.Header h3 {
&.content {
.header h3 {
color: var(--accent-yellow);
}
.Contents {
display: grid;
grid-template-columns: 1fr;
gap: $unit-4x;
.characters,
.weapons,
.summons {
display: grid;
grid-template-rows: auto 1fr;
gap: $unit;
& > h4 {
font-weight: $medium;
font-size: $font-regular;
}
.items {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
gap: $unit-4x;
}
}
}
}
.Header {
align-items: baseline;
display: flex;
gap: $unit-half;
margin-bottom: $unit-2x;
h3 {
color: var(--accent-blue);
font-weight: $medium;
font-size: $font-large;
}
time {
color: var(--text-secondary);
font-size: $font-small;
font-weight: $medium;
}
}
.Contents {
.contents {
display: flex;
flex-direction: column;
gap: $unit-4x;
&.Bare {
display: flex;
flex-direction: column;
color: var(--text-primary);
list-style-type: disc;
list-style-position: inside;
gap: $unit-half;
li {
font-size: 14px;
}
}
section {
display: flex;
flex-direction: column;
gap: $unit-2x;
h2 {
margin: 0;
}
}
.Notes {
.features {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
gap: $unit-2x;
@ -122,6 +50,67 @@
}
}
}
}
.header {
align-items: baseline;
display: flex;
gap: $unit-half;
margin-bottom: $unit-2x;
h3 {
color: var(--accent-blue);
font-weight: $medium;
font-size: $font-large;
}
time {
color: var(--text-secondary);
font-size: $font-small;
font-weight: $medium;
}
}
.list {
display: flex;
flex-direction: column;
color: var(--text-primary);
list-style-type: disc;
list-style-position: inside;
gap: $unit-half;
li {
font-size: 14px;
}
}
.Contents {
display: flex;
flex-direction: column;
gap: $unit-4x;
&.Bare {
display: flex;
flex-direction: column;
color: var(--text-primary);
list-style-type: disc;
list-style-position: inside;
gap: $unit-half;
li {
font-size: 14px;
}
}
section {
display: flex;
flex-direction: column;
gap: $unit-2x;
h2 {
margin: 0;
}
}
.Bugs {
display: flex;

View file

@ -1,6 +1,6 @@
import React from 'react'
import { useTranslation } from 'next-i18next'
import classNames from 'classnames'
import ContentUpdate from '~components/about/ContentUpdate'
import ChangelogUnit from '~components/about/ChangelogUnit'
@ -11,6 +11,8 @@ const UpdatesPage = () => {
const { t: common } = useTranslation('common')
const { t: updates } = useTranslation('updates')
const classes = classNames(styles.updates, 'PageContent')
const versionUpdates = {
'1.0.0': 5,
'1.0.1': 4,
@ -54,8 +56,17 @@ const UpdatesPage = () => {
}
return (
<div className="Updates PageContent">
<div className={classes}>
<h1>{common('about.segmented_control.updates')}</h1>
<ContentUpdate
version="2023-06L"
dateString="2023/06/29"
event="events.legfest"
newItems={{
character: ['3040468000', '3040469000'],
weapon: ['1040421900', '1040712600', '1040516000', '1030305700'],
}}
/>
<ContentUpdate
version="2023-06F"
dateString="2023/06/19"
@ -241,15 +252,15 @@ const UpdatesPage = () => {
weapon: ['1040617100', '1040016100'],
}}
/>
<section className="Version" data-version="1.1">
<div className="Header">
<section className={styles.version} data-version="1.1">
<div className={styles.header}>
<h3>1.1.0</h3>
<time>2023/02/06</time>
</div>
<div className="Contents">
<div className={styles.contents}>
<section>
<h2>{updates('labels.features')}</h2>
<ul className="Notes">
<ul className={styles.features}>
{[...Array(versionUpdates['1.1.0'].updates)].map((e, i) => (
<li key={`1.1.0-update-${i}`}>
{image(
@ -266,7 +277,7 @@ const UpdatesPage = () => {
</section>
<section>
<h2>Bug fixes</h2>
<ul className="Bugs">
<ul className={styles.bugs}>
{[...Array(versionUpdates['1.1.0'].bugs)].map((e, i) => (
<li key={`1.1.0-bugfix-${i}`}>
{updates(`versions.1.1.0.bugs.${i}`)}
@ -276,113 +287,51 @@ const UpdatesPage = () => {
</section>
</div>
</section>
<section className="Content Version" data-version="2023-02U">
<div className="Header">
<h3>{`${updates('events.date', {
year: 2023,
month: 2,
})} ${updates('events.uncap')}`}</h3>
<time>2023/02/01</time>
</div>
<div className="Contents">
<section className="characters">
<h4>{updates('labels.uncaps.characters')}</h4>
<div className="items">
<ChangelogUnit id="3040136000" type="character" />
<ChangelogUnit id="3040219000" type="character" />
</div>
</section>
<section className="weapons">
<h4>{updates('labels.uncaps.weapons')}</h4>
<div className="items">
<ChangelogUnit id="1040511300" type="weapon" />
<ChangelogUnit id="1040412800" type="weapon" />
</div>
</section>
<section className="summons">
<h4>{updates('labels.uncaps.summons')}</h4>
<div className="items">
<ChangelogUnit id="2040234000" type="summon" />
<ChangelogUnit id="2040331000" type="summon" />
</div>
</section>
</div>
</section>
<section className="Content Version" data-version="2023-01F">
<div className="Header">
<h3>{`${updates('events.date', {
year: 2023,
month: 1,
})} ${updates('events.legfest')}`}</h3>
<time>2023/01/31</time>
</div>
<div className="Contents">
<section className="characters">
<h4>{updates('labels.characters')}</h4>
<div className="items">
<ChangelogUnit id="3040445000" type="character" />
<ChangelogUnit id="3040446000" type="character" />
</div>
</section>
<section className="weapons">
<h4>{updates('labels.weapons')}</h4>
<div className="items">
<ChangelogUnit id="1040116700" type="weapon" />
<ChangelogUnit id="1040421400" type="weapon" />
<ChangelogUnit id="1040316000" type="weapon" />
<ChangelogUnit id="1030208000" type="weapon" />
</div>
</section>
</div>
</section>
<section className="Content Version" data-version="2023-01F">
<div className="Header">
<h3>{`${updates('events.date', {
year: 2023,
month: 1,
})} ${updates('events.flash')}`}</h3>
<time>2023/01/19</time>
</div>
<div className="Contents">
<section className="characters">
<h4>{updates('labels.characters')}</h4>
<div className="items">
<ChangelogUnit id="3040444000" type="character" />
<ChangelogUnit id="3040443000" type="character" />
</div>
</section>
<section className="weapons">
<h4>{updates('labels.weapons')}</h4>
<div className="items">
<ChangelogUnit id="1040218300" type="weapon" />
<ChangelogUnit id="1040116600" type="weapon" />
</div>
</section>
</div>
</section>
<section className="Content Version" data-version="2023-01U">
<div className="Header">
<h3>{`${updates('events.date', {
year: 2023,
month: 1,
})} ${updates('events.uncap')}`}</h3>
<time>2023/01/06</time>
</div>
<div className="Contents">
<section className="characters">
<h4>{updates('labels.uncaps.characters')}</h4>
<div className="items">
<ChangelogUnit id="3040196000" type="character" image="03" />
</div>
</section>
</div>
</section>
<section className="Version" data-version="1.0">
<div className="Header">
<ContentUpdate
version="2023-02-U1"
dateString="2023/02/01"
event="events.uncap"
uncappedItems={{
character: ['3040136000', '3040219000'],
weapon: ['1040412800', '1040511300'],
summon: ['2040234000', '2040331000'],
}}
/>
<ContentUpdate
version="2023-01F"
dateString="2023/01/31"
event={'events.legfest'}
newItems={{
character: ['3040445000', '3040446000'],
weapon: ['1040116700', '1040421400', '1040316000', '1030208000'],
}}
numNotes={0}
/>
<ContentUpdate
version="2023-01F"
dateString="2023/01/19"
event="events.flash"
newItems={{
character: ['3040444000', '3040443000'],
weapon: ['1040218300', '1040116600'],
}}
numNotes={0}
/>
<ContentUpdate
version="2023-01U"
dateString="2023/01/06"
event="events.uncap"
uncappedItems={{
character: ['3040196000'],
}}
numNotes={0}
/>
<section className={styles.version} data-version="1.0">
<div className={styles.header}>
<h3>1.0.1</h3>
<time>2023/01/08</time>
</div>
<ul className="Bare Contents">
<ul className={styles.list}>
{[...Array(versionUpdates['1.0.1'])].map((e, i) => (
<li key={`1.0.1-update-${i}`}>
{updates(`versions.1.0.1.features.${i}`)}
@ -390,68 +339,33 @@ const UpdatesPage = () => {
))}
</ul>
</section>
<section className="Content Version" data-version="2022-12L">
<div className="Header">
<h3>{`${updates('events.date', { year: 2022, month: 12 })} ${updates(
'events.legfest'
)}`}</h3>
<time>2022/12/26</time>
</div>
<div className="Contents">
<section className="characters">
<h4>{updates('labels.characters')}</h4>
<div className="items">
<ChangelogUnit id="3040440000" type="character" />
<ChangelogUnit id="3040441000" type="character" />
<ChangelogUnit id="3040442000" type="character" />
</div>
</section>
<section className="weapons">
<h4>{updates('labels.weapons')}</h4>
<div className="items">
<ChangelogUnit id="1040315900" type="weapon" />
<ChangelogUnit id="1040914500" type="weapon" />
<ChangelogUnit id="1040218200" type="weapon" />
</div>
</section>
<section className="summons">
<h4>{updates('labels.summons')}</h4>
<div className="items">
<ChangelogUnit id="2040417000" type="summon" />
</div>
</section>
</div>
</section>
<section className="Content Version" data-version="2022-12F2">
<div className="Header">
<h3>{`${updates('events.date', { year: 2022, month: 12 })} ${updates(
'events.flash'
)}`}</h3>
<time>2022/12/26</time>
</div>
<div className="Contents">
<section className="characters">
<h4>{updates('labels.characters')}</h4>
<div className="items">
<ChangelogUnit id="3040438000" type="character" />
<ChangelogUnit id="3040439000" type="character" />
</div>
</section>
<section className="weapons">
<h4>{updates('labels.weapons')}</h4>
<div className="items">
<ChangelogUnit id="1040024200" type="weapon" />
<ChangelogUnit id="1040116500" type="weapon" />
</div>
</section>
</div>
</section>
<section className="Version" data-version="1.0">
<div className="Header">
<ContentUpdate
version="2022-12L"
dateString="2022/12/26"
event="events.legfest"
newItems={{
character: ['3040440000', '3040441000', '3040442000'],
weapon: ['1040315900', '1040914500', '1040218200'],
summon: ['2040417000'],
}}
numNotes={0}
/>
<ContentUpdate
version="2022-12F2"
dateString="2022/12/26"
event="events.flash"
newItems={{
character: ['3040438000', '3040439000'],
weapon: ['1040024200', '1040116500'],
}}
numNotes={0}
/>
<section className={styles.version} data-version="1.0">
<div className={styles.header}>
<h3>1.0.0</h3>
<time>2022/12/26</time>
</div>
<ul className="Bare Contents">
<ul className={styles.list}>
{[...Array(versionUpdates['1.0.0'])].map((e, i) => (
<li key={`1.0.0-update-${i}`}>
{updates(`versions.1.0.0.features.${i}`)}