Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pull] main from nodejs:main #285

Merged
merged 9 commits into from
Oct 18, 2023
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
1 change: 1 addition & 0 deletions components/Common/AvatarGroup/index.module.css
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
.avatarGroup {
@apply flex
h-8
items-center;
}
39 changes: 39 additions & 0 deletions components/Common/LanguageDropDown/index.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
.iconWrapper {
@apply h-9
w-9
rounded-md
bg-neutral-100
p-2
text-neutral-700
dark:bg-neutral-900
dark:text-neutral-300;
}

.dropDownContent {
@apply max-h-80
w-48
overflow-y-scroll
rounded
border
border-neutral-200
py-[1px]
shadow-lg
dark:border-neutral-900;
}

.dropDownItem {
@apply cursor-default
px-2.5
py-1.5
text-sm
font-medium
text-neutral-800
outline-none
data-[highlighted]:bg-green-600
data-[highlighted]:text-white
dark:text-white;
}

.currentDropDown {
@apply bg-green-600 text-white;
}
10 changes: 10 additions & 0 deletions components/Common/LanguageDropDown/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import type { Meta as MetaObj, StoryObj } from '@storybook/react';

import LanguageDropDown from './index';

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

export const Default: Story = {};

export default { component: LanguageDropDown } as Meta;
56 changes: 56 additions & 0 deletions components/Common/LanguageDropDown/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { LanguageIcon } from '@heroicons/react/24/outline';
import * as DropdownMenu from '@radix-ui/react-dropdown-menu';
import classNames from 'classnames';
import type { FC } from 'react';
import { useIntl } from 'react-intl';

import { useLocale } from '@/hooks/useLocale';

import styles from './index.module.css';

export type LanguageDropDownProps = {
onClick?: () => void;
};

const LanguageDropdown: FC<LanguageDropDownProps> = ({
onClick = () => {},
}) => {
const { availableLocales, currentLocale } = useLocale();
const intl = useIntl();

const ariaLabel = intl.formatMessage({
id: 'components.common.languageDropdown.label',
});

return (
<DropdownMenu.Root>
<DropdownMenu.Trigger asChild>
<button className={styles.iconWrapper} aria-label={ariaLabel}>
<LanguageIcon height="20" />
</button>
</DropdownMenu.Trigger>

<DropdownMenu.Portal>
<DropdownMenu.Content
align="start"
className={styles.dropDownContent}
sideOffset={5}
>
{availableLocales.map(({ name, code }) => (
<DropdownMenu.Item
key={code}
onClick={onClick}
className={classNames(styles.dropDownItem, {
[styles.currentDropDown]: code === currentLocale.code,
})}
>
{name}
</DropdownMenu.Item>
))}
</DropdownMenu.Content>
</DropdownMenu.Portal>
</DropdownMenu.Root>
);
};

export default LanguageDropdown;
67 changes: 67 additions & 0 deletions components/Common/MetaBar/index.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
.wrapper {
@apply flex
w-80
flex-col
items-start
gap-8
border-l
border-neutral-200
p-6
dark:border-neutral-900;

dt {
@apply mb-2
text-sm
font-medium
text-neutral-800
dark:text-neutral-200;
}

dd {
@apply mb-8
flex
items-center
gap-2
text-sm
text-neutral-900
dark:text-white;

a {
@apply font-semibold
text-neutral-900
underline
hover:text-neutral-800
dark:text-white
dark:hover:text-neutral-200;
}

ol {
@apply flex
list-none
flex-col
gap-1.5
p-0;
}

svg {
@apply h-4
w-4
text-neutral-600
dark:text-neutral-400;
}

&:last-child {
@apply mb-0;
}
}

[data-on-dark] {
@apply hidden
dark:block;
}

[data-on-light] {
@apply block
dark:hidden;
}
}
101 changes: 101 additions & 0 deletions components/Common/MetaBar/index.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { CodeBracketIcon } from '@heroicons/react/24/outline';
import type { Meta as MetaObj, StoryObj } from '@storybook/react';
import Image from 'next/image';
import { FormattedMessage } from 'react-intl';

import AvatarGroup from '@/components/Common/AvatarGroup';
import LocalizedLink from '@/components/LocalizedLink';

import MetaBar from './index';

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

export const Default: Story = {
args: {
items: {
'components.metabar.lastUpdated': new Date(
'17 October 2023'
).toLocaleDateString(),
'components.metabar.readingTime': '15 minutes',
'components.metabar.addedIn': 'v1.0.0',
'components.metabar.author': 'The Node.js Project',
'components.metabar.authors': (
<AvatarGroup
avatars={[
{
src: 'https://avatars.githubusercontent.com/canerakdas',
alt: 'Caner Akdas',
},
{
src: 'https://avatars.githubusercontent.com/bmuenzenmeyer',
alt: 'Brian Muenzenmeyer',
},
{
src: 'https://avatars.githubusercontent.com/ovflowd',
alt: 'Claudio W',
},
]}
/>
),
'components.metabar.contribute': (
<>
<Image
src="/static/images/logos/social-github-dark.svg"
alt="GitHub Logo"
width={16}
height={16}
data-on-light
/>
<Image
src="/static/images/logos/social-github.svg"
alt="GitHub Logo"
width={16}
height={16}
data-on-dark
/>
<LocalizedLink href="/contribute">
<FormattedMessage id="components.metabar.contributeText" />
</LocalizedLink>
</>
),
'components.metabar.viewAs': (
<>
<CodeBracketIcon />
<LocalizedLink href="/json">JSON</LocalizedLink>
</>
),
},
headings: {
items: [
{
value: 'OpenSSL update assessment, and Node.js project plans',
depth: 1,
data: { id: 'heading-1' },
},
{
value: 'Summary',
depth: 2,
data: { id: 'summary' },
},
{
value: 'Analysis',
depth: 2,
data: { id: 'analysis' },
},
{
value: 'The c_rehash script allows command injection (CVE-2022-2068)',
depth: 3,
data: { id: 'the_c_rehash' },
},
{
value: 'Contact and future updates',
depth: 3,
data: { id: 'contact_and_future_updates' },
},
],
},
},
};

export default { component: MetaBar } as Meta;
61 changes: 61 additions & 0 deletions components/Common/MetaBar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import type { Heading } from '@vcarl/remark-headings';
import { Fragment, useMemo } from 'react';
import type { FC } from 'react';
import { FormattedMessage } from 'react-intl';

import LocalizedLink from '@/components/LocalizedLink';

import styles from './index.module.css';

type MetaBarProps = {
items: Record<string, React.ReactNode>;
headings?: {
items: Heading[];
depth?: number;
};
};

const MetaBar: FC<MetaBarProps> = ({ items, headings }) => {
// The default depth of headings to display in the table of contents.
const { depth = 2, items: headingItems = [] } = headings || {};

const heading = useMemo(
() => headingItems.filter(head => head.depth === depth),
[depth, headingItems]
);

return (
<div className={styles.wrapper}>
<dl>
{Object.entries(items).map(([key, value]) => (
<Fragment key={key}>
<dt>
<FormattedMessage id={key} />
</dt>
<dd>{value}</dd>
</Fragment>
))}
{heading.length > 0 && (
<Fragment key="tableOfContents">
<dt>
<FormattedMessage id="components.metabar.tableOfContents" />
</dt>
<dd>
<ol>
{heading.map(head => (
<li key={head.value}>
<LocalizedLink href={`#${head?.data?.id || head.value}`}>
{head.value}
</LocalizedLink>
</li>
))}
</ol>
</dd>
</Fragment>
)}
</dl>
</div>
);
};

export default MetaBar;
46 changes: 46 additions & 0 deletions components/Common/Preview/index.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
.root {
@apply relative
flex
items-center
bg-neutral-950
bg-[url('/static/images/patterns/hexagon-grid.svg')]
bg-contain
bg-center
after:absolute
after:inset-0
after:m-auto
after:aspect-square
after:w-1/3
after:rounded-full
after:bg-gradient-radial
after:blur-3xl;

&.announcement {
@apply after:from-green-700/90;
}

&.release {
@apply after:from-info-600/90;
}

&.vulnerability {
@apply after:from-warning-600/90;
}

& > .container {
@apply z-10
mx-auto
flex
max-w-xl
flex-col
gap-12
text-center
text-3xl
font-semibold
text-white;

& > .logo {
@apply mx-auto;
}
}
}
Loading
Loading