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
5 changes: 5 additions & 0 deletions components/Home/NodeFeatures/NodeFeature/index.module.scss
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
.container {
margin: 0 2em;
max-width: 248px;
text-align: center;
}
18 changes: 18 additions & 0 deletions components/Home/NodeFeatures/NodeFeature/index.tsx
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
import styles from './index.module.scss';
import type { ReactElement, FC } from 'react';

type NodeFeatureProps = {
icon: ReactElement;
heading: ReactElement;
description: ReactElement;
};

const NodeFeature: FC<NodeFeatureProps> = ({ icon, heading, description }) => (
<div className={styles.container}>
{icon}
<h2 className="t-subheading2">{heading}</h2>
<p>{description}</p>
</div>
);

export default NodeFeature;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`NodeFeatures should render 1`] = `
<div>
<section
class="nodeFeatures"
>
<div
class="container"
>
<svg
alt="Node Feature"
class="featureIcon"
fill="currentColor"
height="1em"
stroke="currentColor"
stroke-width="0"
viewBox="0 0 512 512"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M255.917 480a32.536 32.536 0 0 1-16.633-4.599l-52.985-32.44c-7.914-4.562-4.023-6.203-1.443-7.141 10.565-3.781 13.713-5.657 24.947-12.285 1.206-.667 2.747-.424 3.955.322l39.71 23.504c1.476.85 3.557.85 4.931 0l155.188-92.246c1.475-.877 2.415-2.646 2.415-4.441V163.869c0-1.85-.94-3.592-2.449-4.528l-155.12-94.672c-1.478-.894-3.421-.894-4.898 0L98.516 159.374c-1.544.903-2.516 2.698-2.516 4.495v186.805c0 1.813.972 3.513 2.481 4.389l39.929 23.972c23.61 12.204 37.59-.17 37.59-14.611V180.725c0-2.652 2.047-4.727 4.596-4.727h22.809c2.515 0 4.597 2.072 4.597 4.727v183.698c0 32.563-19.353 51.248-49.199 51.248-9.156 0-16.397 0-36.552-10.279l-41.584-24.781C70.371 374.459 64 362.965 64 350.656V161.191c0-12.316 6.371-23.784 16.665-29.917L239.35 36.41c10.027-5.88 23.374-5.88 33.332 0l158.65 94.864C441.63 137.423 448 148.899 448 161.191v189.465c0 12.309-6.37 23.75-16.668 29.953l-158.65 94.774a32.52 32.52 0 0 1-16.698 4.599l-.067.018z"
/>
<path
d="M304.943 351.998c-64.61 0-84.006-31.61-84.006-59.271 0-2.629 2.048-4.729 4.562-4.729h20.521c2.282 0 4.227 1.7 4.562 4.016 3.084 21.602 16.748 31.15 54.324 31.15 33.399 0 47.091-10.346 47.091-28.684 0-10.592-3.463-18.424-55.407-23.697-43.427-4.441-70.288-14.373-70.288-50.295 0-33.135 26.996-52.49 72.234-52.49 46.128 0 76.462 14 79.173 50.829.102 1.337-.368 2.629-1.241 3.644-.871.965-2.078 1.527-3.353 1.527h-20.591c-2.146 0-4.024-1.562-4.459-3.713-4.401-16.953-16.97-23.402-49.563-23.402-36.486 0-40.746 12.753-40.746 22.607 0 11.963 5.031 15.441 54.294 22.172 48.761 6.663 71.933 16.117 71.933 51.552 0 35.781-28.808 58.783-79.075 58.783l.035.001z"
/>
</svg>
<h2
class="t-subheading2"
>
pages.index.features.javascript.title
</h2>
<p>
pages.index.features.javascript.description
</p>
</div>
<div
class="container"
>
<svg
alt="Node Feature"
class="featureIcon"
fill="currentColor"
height="1em"
stroke="currentColor"
stroke-width="0"
viewBox="0 0 512 512"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M416 376.6V206.8c0-46.4-3.7-70.8-22.1-94C374 87.7 348.9 77 310 77h-22V16l-96 96 96 96v-65h22c24.6 0 29 3.6 33.8 9.6 5.5 6.9 8.2 19.1 8.2 54.2v169.8c-19.1 11.1-32 31.7-32 55.4 0 35.3 28.7 64 64 64s64-28.7 64-64c0-23.7-12.9-44.3-32-55.4zM384 472c-22.1 0-40-17.9-40-40s17.9-40 40-40 40 17.9 40 40-17.9 40-40 40zM128 48c-35.3 0-64 28.7-64 64 0 23.7 12.9 44.3 32 55.4v209.2c-19.1 11.1-32 31.7-32 55.4 0 35.3 28.7 64 64 64s64-28.7 64-64c0-23.7-12.9-44.3-32-55.4V167.4c19.1-11.1 32-31.7 32-55.4 0-35.3-28.7-64-64-64zm0 424c-22.1 0-40-17.9-40-40s17.9-40 40-40 40 17.9 40 40-17.9 40-40 40zm0-320c-22.1 0-40-17.9-40-40s17.9-40 40-40 40 17.9 40 40-17.9 40-40 40z"
/>
</svg>
<h2
class="t-subheading2"
>
pages.index.features.openSource.title
</h2>
<p>
pages.index.features.openSource.description
</p>
</div>
<div
class="container"
>
<svg
alt="Node Feature"
class="featureIcon"
fill="currentColor"
height="1em"
stroke="currentColor"
stroke-width="0"
viewBox="0 0 512 512"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M256 421.6c-18.1 0-33.2-6.8-42.9-10.9-5.4-2.3-11.3 1.8-10.9 7.6l3.5 51c.2 3.1 3.8 4.7 6.3 2.8l14.5-11c1.8-1.4 4.5-.9 5.7 1l20.5 32.1c1.5 2.4 5.1 2.4 6.6 0l20.5-32.1c1.2-1.9 3.9-2.4 5.7-1l14.5 11c2.5 1.9 6.1.3 6.3-2.8l3.5-51c.4-5.8-5.5-10-10.9-7.6-9.8 4.1-24.8 10.9-42.9 10.9z"
/>
<path
d="M397.7 293.1l-48-49.1c0-158-93.2-228-93.2-228s-94.1 70-94.1 228l-48 49.1c-1.8 1.8-2.6 4.5-2.2 7.1L130.6 412c.9 5.7 7.1 8.5 11.8 5.4l67.1-45.4s20.7 20 47.1 20c26.4 0 46.1-20 46.1-20l67.1 45.4c4.6 3.1 10.8.3 11.8-5.4l18.5-111.9c.2-2.6-.6-5.2-2.4-7zM256.5 192c-17 0-30.7-14.3-30.7-32s13.8-32 30.7-32c17 0 30.7 14.3 30.7 32s-13.7 32-30.7 32z"
/>
</svg>
<h2
class="t-subheading2"
>
pages.index.features.everywhere.title
</h2>
<p>
pages.index.features.everywhere.description
</p>
</div>
</section>
</div>
`;
14 changes: 14 additions & 0 deletions components/Home/NodeFeatures/__test__/index.test.tsx
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
import { render } from '@testing-library/react';
import { IntlProvider } from 'react-intl';
import NodeFeatures from '../index';

describe('NodeFeatures', () => {
it('should render', () => {
const { container } = render(
<IntlProvider locale="en" onError={() => {}}>
<NodeFeatures />
</IntlProvider>
);
expect(container).toMatchSnapshot();
});
});
21 changes: 21 additions & 0 deletions components/Home/NodeFeatures/index.module.scss
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
.nodeFeatures {
display: grid;
grid-gap: 1.5rem;
grid-template-columns: repeat(3, 1fr);
justify-content: center;
margin: 0 auto 5em auto;

@media (max-width: 900px) {
grid-template-columns: 1fr;
}

.featureIcon {
height: auto;
min-width: 120px;
opacity: 0.75;

@media (max-width: 900px) {
min-width: 60px;
}
}
}
9 changes: 9 additions & 0 deletions components/Home/NodeFeatures/index.stories.tsx
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
import NodeFeatures from '.';
import type { Meta as MetaObj, StoryObj } from '@storybook/react';

type Story = StoryObj<typeof NodeFeatures>;
type Meta = MetaObj<typeof NodeFeatures>;

export const Default: Story = {};

export default { component: NodeFeatures } as Meta;
45 changes: 45 additions & 0 deletions components/Home/NodeFeatures/index.tsx
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
import { cloneElement } from 'react';
import { IoLogoNodejs, IoMdGitPullRequest, IoMdRocket } from 'react-icons/io';
import { FormattedMessage } from 'react-intl';
import NodeFeature from './NodeFeature';
import styles from './index.module.scss';
import type { ReactElement, FC } from 'react';

const styled = (icon: ReactElement): ReactElement =>
cloneElement(icon, {
alt: 'Node Feature',
className: styles.featureIcon,
});

const features = [
{
icon: styled(<IoLogoNodejs />),
heading: 'pages.index.features.javascript.title',
description: 'pages.index.features.javascript.description',
},
{
icon: styled(<IoMdGitPullRequest />),
heading: 'pages.index.features.openSource.title',
description: 'pages.index.features.openSource.description',
},
{
icon: styled(<IoMdRocket />),
heading: 'pages.index.features.everywhere.title',
description: 'pages.index.features.everywhere.description',
},
];

const NodeFeatures: FC = () => (
<section className={styles.nodeFeatures}>
{features.map(feature => (
<NodeFeature
key={feature.heading}
icon={feature.icon}
heading={<FormattedMessage id={feature.heading} />}
description={<FormattedMessage id={feature.description} />}
/>
))}
</section>
);

export default NodeFeatures;
4 changes: 2 additions & 2 deletions components/Learn/PreviousNextLink/index.tsx
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
import Link from 'next/link';
import type { FC } from 'react';
import { FaAngleDoubleLeft, FaAngleDoubleRight } from 'react-icons/fa';
import { FormattedMessage } from 'react-intl';
import type { LinkInfo } from '../../../types';
import styles from './index.module.scss';
import type { LinkInfo } from '../../../types';
import type { FC } from 'react';

type PreviousNextLinkProps = {
previous?: LinkInfo;
Expand Down
8 changes: 7 additions & 1 deletion i18n/locales/en.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -51,5 +51,11 @@
"components.footer.links.blog": "Blog",
"components.footer.links.github": "GitHub",
"components.prevnextlink.next": "NEXT",
"components.prevnextlink.previous": "PREV"
"components.prevnextlink.previous": "PREV",
"pages.index.features.javascript.title": "JavaScript",
"pages.index.features.javascript.description": "Node.js provides support for the JavaScript programming language",
"pages.index.features.openSource.title": "Open Source",
"pages.index.features.openSource.description": "Node.js is open source and actively maintained by contributors all over the world",
"pages.index.features.everywhere.title": "Everywhere",
"pages.index.features.everywhere.description": "Node.js has been adapted to work in a wide variety of places"
}
1 change: 1 addition & 0 deletions styles/index.scss
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
@import './tokens';
@import './typography';
@import './base';
89 changes: 89 additions & 0 deletions styles/typography.scss
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
.t-display1,
h1 {
font-size: var(--font-size-display1);
font-weight: var(--font-weight-light);
line-height: var(--line-height-display1);
margin: 0 0 var(--space-80) 0;
}

.t-display2 {
font-size: var(--font-size-display2);
font-weight: var(--font-weight-regular);
line-height: var(--line-height-display2);
}

.t-display3 {
font-size: var(--font-size-display3);
font-weight: var(--font-weight-regular);
line-height: var(--line-height-display3);
}

.t-headline,
h2 {
font-size: var(--font-size-headline);
font-weight: var(--font-weight-semibold);
line-height: var(--line-height-headline);
margin: 0 0 var(--space-24) 0;
}

.t-subheading,
h3 {
font-size: var(--font-size-subheading);
font-weight: var(--font-weight-semibold);
line-height: var(--line-height-subheading);
margin: 0 0 var(--space-08) 0;
}

.t-subheading2,
h4 {
font-size: var(--font-size-body1);
font-weight: var(--font-weight-semibold);
line-height: var(--line-height-subheading);
margin: var(--space-20) 0;
}

.t-body1,
p {
font-size: var(--font-size-body1);
font-weight: var(--font-weight-regular);
line-height: var(--line-height-body1);
margin: 0 0 var(--space-24) 0;
}

.t-body2 {
font-size: var(--font-size-body2);
font-weight: var(--font-weight-regular);
line-height: var(--line-height-body2);
}

.t-caption {
font-size: var(--font-size-caption);
font-weight: var(--font-weight-regular);
line-height: var(--line-height-caption);
}

.t-overline {
color: var(--color-text-primary);
font-size: var(--font-size-overline);
font-weight: var(--font-weight-normal);
letter-spacing: 0.1rem;
line-height: var(--line-height-overline);
margin: 0 0 var(--space-4) 0;
text-transform: uppercase;
}

.t-link,
a {
color: var(--color-text-accent);
cursor: pointer;
text-decoration: underline;
}

.t-link:hover,
a:hover,
.t-link:focus,
a:focus {
color: var(--color-text-accent);
cursor: pointer;
text-decoration: none;
}