diff --git a/apps/site/.storybook/preview.tsx b/apps/site/.storybook/preview.tsx index 1cc9e387dce32..5a0ee0e826748 100644 --- a/apps/site/.storybook/preview.tsx +++ b/apps/site/.storybook/preview.tsx @@ -6,7 +6,7 @@ import { NextIntlClientProvider } from 'next-intl'; import { STORYBOOK_MODES, STORYBOOK_SIZES } from '@/.storybook/constants'; import { NotificationProvider } from '@/providers/notificationProvider'; -import '../styles/index.css'; +import '@node-core/ui-components/styles/index.css'; const preview: Preview = { parameters: { diff --git a/apps/site/app/[locale]/error.tsx b/apps/site/app/[locale]/error.tsx index 79feae5ccf4c0..3955385481bd5 100644 --- a/apps/site/app/[locale]/error.tsx +++ b/apps/site/app/[locale]/error.tsx @@ -4,7 +4,7 @@ import { ArrowRightIcon } from '@heroicons/react/24/solid'; import { useTranslations } from 'next-intl'; import type { FC } from 'react'; -import Button from '@/components/Common/Button'; +import Button from '@/components/withButton'; import GlowingBackdropLayout from '@/layouts/GlowingBackdrop'; const ErrorPage: FC<{ error: Error }> = () => { diff --git a/apps/site/app/[locale]/layout.tsx b/apps/site/app/[locale]/layout.tsx index b1887eea5c80e..451521fa975ba 100644 --- a/apps/site/app/[locale]/layout.tsx +++ b/apps/site/app/[locale]/layout.tsx @@ -10,7 +10,7 @@ import { availableLocalesMap, defaultLocale } from '@/next.locales.mjs'; import { LocaleProvider } from '@/providers/localeProvider'; import { ThemeProvider } from '@/providers/themeProvider'; -import '@/styles/index.css'; +import '@node-core/ui-components/styles/index.css'; const fontClasses = classNames(IBM_PLEX_MONO.variable, OPEN_SANS.variable); diff --git a/apps/site/app/[locale]/next-data/og/[category]/[title]/route.tsx b/apps/site/app/[locale]/next-data/og/[category]/[title]/route.tsx index 844c9fa6753f5..54931556d5829 100644 --- a/apps/site/app/[locale]/next-data/og/[category]/[title]/route.tsx +++ b/apps/site/app/[locale]/next-data/og/[category]/[title]/route.tsx @@ -1,7 +1,7 @@ +import HexagonGridIcon from '@node-core/ui-components/Icons/HexagonGrid'; +import JsWhiteIcon from '@node-core/ui-components/Icons/Logos/JsWhite'; import { ImageResponse } from 'next/og'; -import HexagonGrid from '@/components/Icons/HexagonGrid'; -import JsIconWhite from '@/components/Icons/Logos/JsIconWhite'; import { DEFAULT_CATEGORY_OG_TYPE } from '@/next.constants.mjs'; import { defaultLocale } from '@/next.locales.mjs'; import tailwindConfig from '@/tailwind.config'; @@ -34,10 +34,10 @@ export const GET = async (_: Request, props: StaticParams) => { return new ImageResponse( (
- +
- +

{params.title.slice(0, 100)}

diff --git a/apps/site/app/[locale]/not-found.tsx b/apps/site/app/[locale]/not-found.tsx index 9ab34ca5bbf2e..f5c29af871ca2 100644 --- a/apps/site/app/[locale]/not-found.tsx +++ b/apps/site/app/[locale]/not-found.tsx @@ -5,7 +5,7 @@ import Image from 'next/image'; import { useTranslations } from 'next-intl'; import type { FC } from 'react'; -import Button from '@/components/Common/Button'; +import Button from '@/components/withButton'; import GlowingBackdropLayout from '@/layouts/GlowingBackdrop'; const NotFoundPage: FC = () => { diff --git a/apps/site/app/global-error.tsx b/apps/site/app/global-error.tsx index 53238830c7a2c..d705914a88d08 100644 --- a/apps/site/app/global-error.tsx +++ b/apps/site/app/global-error.tsx @@ -3,7 +3,7 @@ import { ArrowRightIcon } from '@heroicons/react/24/solid'; import type { FC } from 'react'; -import Button from '@/components/Common/Button'; +import Button from '@/components/withButton'; import BaseLayout from '@/layouts/Base'; import GlowingBackdropLayout from '@/layouts/GlowingBackdrop'; diff --git a/apps/site/components/Common/AvatarGroup/index.tsx b/apps/site/components/Common/AvatarGroup/index.tsx index 2bacc71b8ab7b..fb000ba935068 100644 --- a/apps/site/components/Common/AvatarGroup/index.tsx +++ b/apps/site/components/Common/AvatarGroup/index.tsx @@ -1,5 +1,6 @@ 'use client'; +import Tooltip from '@node-core/ui-components/Common/Tooltip'; import classNames from 'classnames'; import type { FC } from 'react'; import { useState, useMemo, Fragment } from 'react'; @@ -8,7 +9,6 @@ import type { AvatarProps } from '@/components/Common/AvatarGroup/Avatar'; import Avatar from '@/components/Common/AvatarGroup/Avatar'; import avatarstyles from '@/components/Common/AvatarGroup/Avatar/index.module.css'; import AvatarOverlay from '@/components/Common/AvatarGroup/Overlay'; -import Tooltip from '@/components/Common/Tooltip'; import styles from './index.module.css'; diff --git a/apps/site/components/Common/BlogPostCard/index.tsx b/apps/site/components/Common/BlogPostCard/index.tsx index 30815ad9ed62c..b99c1ac13a465 100644 --- a/apps/site/components/Common/BlogPostCard/index.tsx +++ b/apps/site/components/Common/BlogPostCard/index.tsx @@ -1,8 +1,8 @@ +import Preview from '@node-core/ui-components/Common/Preview'; import { useTranslations } from 'next-intl'; import type { FC } from 'react'; import FormattedTime from '@/components/Common/FormattedTime'; -import Preview from '@/components/Common/Preview'; import Link from '@/components/Link'; import WithAvatarGroup from '@/components/withAvatarGroup'; import type { BlogCategory } from '@/types'; diff --git a/apps/site/components/Common/Breadcrumbs/BreadcrumbLink/index.module.css b/apps/site/components/Common/Breadcrumbs/BreadcrumbLink/index.module.css deleted file mode 100644 index ea0d6b9db96b5..0000000000000 --- a/apps/site/components/Common/Breadcrumbs/BreadcrumbLink/index.module.css +++ /dev/null @@ -1,20 +0,0 @@ -.link { - @apply max-w-fit - truncate; - - &.active { - @apply rounded - bg-green-600 - px-2 - py-1 - font-semibold - text-white - motion-safe:transition-colors - dark:text-white; - - &:hover { - @apply bg-green-700 - text-white; - } - } -} diff --git a/apps/site/components/Common/Breadcrumbs/BreadcrumbRoot/index.module.css b/apps/site/components/Common/Breadcrumbs/BreadcrumbRoot/index.module.css deleted file mode 100644 index 51043398d4657..0000000000000 --- a/apps/site/components/Common/Breadcrumbs/BreadcrumbRoot/index.module.css +++ /dev/null @@ -1,7 +0,0 @@ -.list { - @apply xs:w-full - flex - w-screen - gap-5 - px-6; -} diff --git a/apps/site/components/Common/Button/index.module.css b/apps/site/components/Common/Button/index.module.css deleted file mode 100644 index 6f2d69b8e9bef..0000000000000 --- a/apps/site/components/Common/Button/index.module.css +++ /dev/null @@ -1,146 +0,0 @@ -.button { - @apply px-4.5 - relative - inline-flex - items-center - justify-center - gap-2 - py-2.5 - text-center - font-semibold - motion-safe:transition-colors; - - svg { - @apply size-5; - } - - &[aria-disabled='true'] { - @apply cursor-not-allowed; - } - - &.small { - @apply px-3 - py-2 - text-sm; - } - - &.neutral { - @apply rounded - bg-neutral-900 - text-white - dark:text-neutral-200; - - &:hover:not([aria-disabled='true']) { - @apply bg-neutral-800; - } - - &[aria-disabled='true'] { - @apply bg-neutral-900 - opacity-50; - } - - &:focus { - @apply bg-neutral-800; - } - } - - &.primary { - @apply rounded - border - border-green-600 - bg-green-600 - text-white - shadow-sm; - - &:hover:not([aria-disabled='true']) { - @apply border-green-700 - bg-green-700 - text-white; - } - - &:focus { - @apply border-green-700 - bg-green-700; - } - - &[aria-disabled='true'] { - @apply bg-green-600 - opacity-50; - } - } - - &.secondary { - @apply rounded-lg - text-neutral-800 - dark:text-neutral-200; - - &:hover:not([aria-disabled='true']) { - @apply bg-neutral-100 - text-neutral-800 - dark:bg-neutral-900 - dark:text-neutral-200; - } - - &[aria-disabled='true'] { - @apply bg-transparent - opacity-50; - } - - &:focus { - @apply bg-neutral-100 - text-neutral-800 - dark:bg-neutral-900 - dark:text-neutral-200; - } - } - - &.special { - @apply rounded-lg - border - border-green-600/30 - bg-green-600/10 - text-white - shadow-sm; - - &::before { - @apply bg-gradient-glow-backdrop - absolute - left-0 - right-0 - top-0 - -z-10 - mx-auto - h-full - w-full - opacity-30 - content-['']; - } - - &::after { - @apply absolute - -top-px - left-0 - right-0 - mx-auto - h-px - w-2/5 - bg-gradient-to-r - from-green-600/0 - via-green-600 - to-green-600/0 - content-['']; - } - - &[aria-disabled='true'] { - @apply opacity-50; - } - - &:hover:not([aria-disabled='true']) { - @apply bg-green-600/20; - } - - &:focus { - @apply bg-green-600/20; - } - } -} diff --git a/apps/site/components/Common/Button/index.tsx b/apps/site/components/Common/Button/index.tsx deleted file mode 100644 index bf19cfc5cffd3..0000000000000 --- a/apps/site/components/Common/Button/index.tsx +++ /dev/null @@ -1,77 +0,0 @@ -'use client'; - -import classNames from 'classnames'; -import type { - FC, - AnchorHTMLAttributes, - KeyboardEvent, - MouseEvent, -} from 'react'; - -import Link from '@/components/Link'; - -import styles from './index.module.css'; - -type ButtonProps = AnchorHTMLAttributes & { - kind?: 'neutral' | 'primary' | 'secondary' | 'special'; - size?: 'default' | 'small'; - disabled?: boolean; -}; - -const Button: FC = ({ - kind = 'primary', - size = 'default', - disabled = false, - href = undefined, - children, - className, - onClick, - ...props -}) => { - const onKeyDownHandler = (e: KeyboardEvent) => { - if (disabled) { - e.preventDefault(); - return; - } - - if (e.key === 'Enter' || e.key === ' ') { - e.preventDefault(); - if (typeof onClick === 'function') { - onClick(e as unknown as MouseEvent); - } - } - }; - - const onClickHandler = (e: MouseEvent) => { - if (disabled) { - e.preventDefault(); - return; - } - - if (typeof onClick === 'function') { - onClick(e); - } - }; - - return ( - - {children} - - ); -}; - -export default Button; diff --git a/apps/site/components/Common/CodeTabs/index.module.css b/apps/site/components/Common/CodeTabs/index.module.css deleted file mode 100644 index 5c79f7ecd4fd4..0000000000000 --- a/apps/site/components/Common/CodeTabs/index.module.css +++ /dev/null @@ -1,54 +0,0 @@ -.root { - > [role='tabpanel'] > :first-child { - @apply rounded-t-none; - } - - > div:nth-of-type(1) { - @apply flex - rounded-t - border-x - border-t - border-neutral-900 - bg-neutral-950 - px-2 - pt-3 - md:px-4; - - .trigger { - @apply border-b - border-b-transparent - px-1 - text-neutral-200; - - &[data-state='active'] { - @apply border-b-green-400 - text-green-400; - } - } - - .link { - @apply hidden - items-center - gap-2 - text-center - text-neutral-200 - motion-safe:transition-colors - lg:flex; - - & > .icon { - @apply size-4 - text-neutral-300; - } - - &:is(:link, :visited) { - &:hover { - @apply text-neutral-400; - - & > .icon { - @apply text-neutral-600; - } - } - } - } - } -} diff --git a/apps/site/components/Common/CodeTabs/index.tsx b/apps/site/components/Common/CodeTabs/index.tsx deleted file mode 100644 index 614db0017079b..0000000000000 --- a/apps/site/components/Common/CodeTabs/index.tsx +++ /dev/null @@ -1,41 +0,0 @@ -import { ArrowUpRightIcon } from '@heroicons/react/24/solid'; -import type { ComponentProps, FC, PropsWithChildren } from 'react'; - -import Tabs from '@/components/Common/Tabs'; -import { Link } from '@/navigation.mjs'; - -import styles from './index.module.css'; - -type CodeTabsProps = Pick< - ComponentProps, - 'tabs' | 'defaultValue' -> & { - linkUrl?: string; - linkText?: string; -}; - -const CodeTabs: FC> = ({ - children, - linkUrl, - linkText, - ...props -}) => ( - - {linkText} - - - ) - } - > - {children} - -); - -export default CodeTabs; diff --git a/apps/site/components/Common/CopyButton.tsx b/apps/site/components/Common/CopyButton.tsx new file mode 100644 index 0000000000000..84343a3c1d32b --- /dev/null +++ b/apps/site/components/Common/CopyButton.tsx @@ -0,0 +1,43 @@ +'use client'; + +import { + DocumentDuplicateIcon, + CodeBracketIcon, +} from '@heroicons/react/24/outline'; +import type { CopyButtonProps } from '@node-core/ui-components/Common/CodeBox'; +import { useTranslations } from 'next-intl'; +import type { FC } from 'react'; + +import WithButton from '@/components/withButton'; +import { useCopyToClipboard, useNotification } from '@/hooks'; + +const CopyButton: FC = ({ styles, ref }) => { + const notify = useNotification(); + const [, copyToClipboard] = useCopyToClipboard(); + const t = useTranslations(); + + const onCopy = async () => { + if (ref.current?.textContent) { + copyToClipboard(ref.current.textContent); + + notify({ + duration: 3000, + message: ( +
+ + {t('components.common.codebox.copied')} +
+ ), + }); + } + }; + + return ( + + + {t('components.common.codebox.copy')} + + ); +}; + +export default CopyButton; diff --git a/apps/site/components/Common/LanguageDropDown/index.module.css b/apps/site/components/Common/LanguageDropDown/index.module.css deleted file mode 100644 index 7f1a0d1052106..0000000000000 --- a/apps/site/components/Common/LanguageDropDown/index.module.css +++ /dev/null @@ -1,49 +0,0 @@ -.languageDropdown { - @apply h-9 - w-9 - rounded-md - p-2 - text-neutral-700 - motion-safe:transition-colors - dark:text-neutral-300; - - &:hover { - @apply bg-neutral-100 - dark:bg-neutral-900; - } -} - -.dropDownContent { - @apply max-h-80 - w-48 - overflow-hidden - rounded - border - border-neutral-200 - bg-white - shadow-lg - dark:border-neutral-900 - dark:bg-neutral-950; - - > div { - @apply max-h-80 - w-48 overflow-y-auto; - } -} - -.dropDownItem { - @apply cursor-pointer - 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; -} diff --git a/apps/site/components/Common/Pagination/index.tsx b/apps/site/components/Common/Pagination/index.tsx index 969cf4dc86fc3..994ff30b00210 100644 --- a/apps/site/components/Common/Pagination/index.tsx +++ b/apps/site/components/Common/Pagination/index.tsx @@ -2,8 +2,8 @@ import { ArrowRightIcon, ArrowLeftIcon } from '@heroicons/react/20/solid'; import { useTranslations } from 'next-intl'; import type { FC } from 'react'; -import Button from '@/components/Common/Button'; import { useGetPageElements } from '@/components/Common/Pagination/useGetPageElements'; +import Button from '@/components/withButton'; import styles from './index.module.css'; diff --git a/apps/site/components/Common/ProgressionSidebar/ProgressionSidebarItem/index.tsx b/apps/site/components/Common/ProgressionSidebar/ProgressionSidebarItem/index.tsx index 047beac8d7326..67bb7ef97282a 100644 --- a/apps/site/components/Common/ProgressionSidebar/ProgressionSidebarItem/index.tsx +++ b/apps/site/components/Common/ProgressionSidebar/ProgressionSidebarItem/index.tsx @@ -1,7 +1,7 @@ import type { FC } from 'react'; -import ActiveLink from '@/components/Common/ActiveLink'; import ProgressionSidebarIcon from '@/components/Common/ProgressionSidebar/ProgressionSidebarIcon'; +import WithActiveLink from '@/components/withActiveLink'; import type { FormattedMessage } from '@/types'; import styles from './index.module.css'; @@ -15,14 +15,14 @@ const ProgressionSidebarItem: FC = ({ label, link, }) => ( - {label} - + ); export default ProgressionSidebarItem; diff --git a/apps/site/components/Common/Select/index.module.css b/apps/site/components/Common/Select/index.module.css deleted file mode 100644 index 1e13248039a83..0000000000000 --- a/apps/site/components/Common/Select/index.module.css +++ /dev/null @@ -1,151 +0,0 @@ -.select { - @apply inline-flex - flex-col - gap-1.5; - - .label { - @apply block - w-full - text-sm - font-medium - text-neutral-800 - dark:text-neutral-200; - } - - .trigger { - @apply shadow-xs - inline-flex - h-11 - w-full - min-w-[17rem] - items-center - justify-between - gap-2 - rounded - border - border-neutral-300 - bg-white - px-3.5 - py-2.5 - text-left - text-base - font-medium - text-neutral-900 - outline-none - focus:border-neutral-500 - focus:ring-1 - focus:ring-neutral-500 - data-[placeholder]:text-neutral-800 - dark:border-neutral-800 - dark:bg-neutral-950 - dark:text-white - dark:focus:border-neutral-600 - dark:focus:ring-neutral-600 - dark:data-[placeholder]:text-neutral-200; - } - - .trigger span { - @apply flex - h-5 - items-center - gap-2; - } - - .icon { - @apply size-5 - text-neutral-600 - dark:text-neutral-400; - } -} - -.dropdown { - @apply max-h-48 - max-w-xs - overflow-hidden - overflow-y-auto - rounded-md - border - border-neutral-200 - bg-white - shadow-lg - dark:border-neutral-800 - dark:bg-neutral-950; - - .item { - @apply select-none - truncate - px-2.5 - py-1.5 - text-sm - font-medium; - } - - .text { - @apply text-neutral-800 - data-[highlighted]:bg-green-500 - data-[highlighted]:text-white - data-[highlighted]:outline-none - dark:text-neutral-200 - dark:data-[highlighted]:bg-green-600 - dark:data-[highlighted]:text-white; - } - - .text > span { - @apply flex - items-center - gap-2; - } - - .text > span > span { - @apply max-w-64 - truncate - text-wrap; - } - - .label { - @apply text-neutral-600 - dark:text-neutral-400; - } -} - -.dropdown:has(.label) .text > span { - &:has(svg) > svg { - @apply ml-3; - } - - &:not(&:has(svg)) > span { - @apply ml-3; - } -} - -.inline { - .trigger { - @apply h-auto - min-w-fit - px-2.5 - py-2 - text-sm - font-medium; - } - - .icon { - @apply size-4; - } - - .text { - @apply text-neutral-900 - data-[highlighted]:bg-neutral-100 - data-[disabled]:text-neutral-600 - data-[highlighted]:text-neutral-900 - dark:text-white - dark:data-[highlighted]:bg-neutral-900 - dark:data-[disabled]:text-neutral-700 - dark:data-[highlighted]:text-white; - } - - &.dropdown { - @apply mt-1 - w-[calc(100%+1.5rem)] - rounded; - } -} diff --git a/apps/site/components/Common/Skeleton/index.module.css b/apps/site/components/Common/Skeleton/index.module.css deleted file mode 100644 index 389dc00ca4499..0000000000000 --- a/apps/site/components/Common/Skeleton/index.module.css +++ /dev/null @@ -1,28 +0,0 @@ -.skeleton { - @apply dark:animate-pulse-dark - pointer-events-none - animate-pulse - cursor-default - select-none - rounded-md - border-none - bg-clip-border - text-transparent - shadow-none - outline-none; -} - -.skeleton[data-inline-skeleton] { - @apply leading-none; -} - -.skeleton:empty { - @apply block - h-3; -} - -.skeleton > *, -.skeleton::after, -.skeleton::before { - @apply invisible; -} diff --git a/apps/site/components/Common/ThemeToggle/index.module.css b/apps/site/components/Common/ThemeToggle/index.module.css deleted file mode 100644 index c2cd6bb230a91..0000000000000 --- a/apps/site/components/Common/ThemeToggle/index.module.css +++ /dev/null @@ -1,13 +0,0 @@ -.themeToggle { - @apply size-9 - rounded-md - p-2 - text-neutral-700 - motion-safe:transition-colors - dark:text-neutral-300; - - &:hover { - @apply bg-neutral-100 - dark:bg-neutral-900; - } -} diff --git a/apps/site/components/Containers/Footer/index.tsx b/apps/site/components/Containers/Footer/index.tsx index e2d2411db1098..63bb11c730da4 100644 --- a/apps/site/components/Containers/Footer/index.tsx +++ b/apps/site/components/Containers/Footer/index.tsx @@ -1,28 +1,33 @@ +'use client'; + +import NavItem from '@node-core/ui-components/Containers/NavBar/NavItem'; +import BlueskyIcon from '@node-core/ui-components/Icons/Social/Bluesky'; +import GitHubIcon from '@node-core/ui-components/Icons/Social/GitHub'; +import LinkedInIcon from '@node-core/ui-components/Icons/Social/LinkedIn'; +import MastodonIcon from '@node-core/ui-components/Icons/Social/Mastodon'; +import SlackIcon from '@node-core/ui-components/Icons/Social/Slack'; +import XIcon from '@node-core/ui-components/Icons/Social/X'; import { useTranslations } from 'next-intl'; import type { FC, SVGProps } from 'react'; -import NavItem from '@/components/Containers/NavBar/NavItem'; -import Bluesky from '@/components/Icons/Social/Bluesky'; -import GitHub from '@/components/Icons/Social/GitHub'; -import LinkedIn from '@/components/Icons/Social/LinkedIn'; -import Mastodon from '@/components/Icons/Social/Mastodon'; -import Slack from '@/components/Icons/Social/Slack'; -import Twitter from '@/components/Icons/Social/Twitter'; +import Link from '@/components/Link'; +import { usePathname } from '@/navigation.mjs'; import { siteNavigation } from '@/next.json.mjs'; import styles from './index.module.css'; const footerSocialIcons: Record>> = { - github: GitHub, - mastodon: Mastodon, - twitter: Twitter, - slack: Slack, - linkedin: LinkedIn, - bluesky: Bluesky, + github: GitHubIcon, + mastodon: MastodonIcon, + twitter: XIcon, + slack: SlackIcon, + linkedin: LinkedInIcon, + bluesky: BlueskyIcon, }; const Footer: FC = () => { const t = useTranslations(); + const pathname = usePathname()!; const openJSlink = siteNavigation.footerLinks.at(-1)!; @@ -30,14 +35,25 @@ const Footer: FC = () => {