Skip to content
Draft
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"html-to-image": "^1.11.11",
"lightense-images": "^1.0.17",
"next": "13.4.7",
"next-intl": "^4.3.5",
"postcss-focus-visible": "^6.0.4",
"postcss-import": "^14.1.0",
"prism-react-renderer": "^1.3.5",
Expand Down
212 changes: 164 additions & 48 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions src/components/Header.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import clsx from 'clsx'
import Link from 'next/link'
import React, { useEffect, useState } from 'react'

import { LanguageSwitcher } from '@/components/LanguageSwitcher'
import { MobileNavigation } from '@/components/MobileNavigation'
import { Search } from '@/components/Search'
import { ThemeSelector } from '@/components/ThemeSelector'
Expand Down Expand Up @@ -75,6 +76,9 @@ export function Header({ page }) {
<div className="-my-5">
<Search />
</div>
<div className="hidden sm:block">
<LanguageSwitcher />
</div>
<ThemeSelector className="relative z-10" />
<Link
href={page.product.github}
Expand Down
93 changes: 93 additions & 0 deletions src/components/LanguageSwitcher.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { useState, useRef, useEffect } from 'react'
import { useRouter } from 'next/router'
import Link from 'next/link'
import { useLocale } from '@/contexts/LocaleContext'

const languages = [
{ code: 'en', name: 'English', flag: '🇺🇸' },
{ code: 'jp', name: '日本語', flag: '🇯🇵' },
{ code: 'kr', name: '한국어', flag: '🇰🇷' },
]

export function LanguageSwitcher() {
const { locale } = useLocale()
const { pathname } = useRouter()
const [isOpen, setIsOpen] = useState(false)
const dropdownRef = useRef(null)

// Close dropdown when clicking outside
useEffect(() => {
const handleClickOutside = (event) => {
if (dropdownRef.current && !dropdownRef.current.contains(event.target)) {
setIsOpen(false)
}
}

document.addEventListener('mousedown', handleClickOutside)
return () => document.removeEventListener('mousedown', handleClickOutside)
}, [])

const getLocalizedPath = (targetLocale) => {
if (targetLocale === 'en') {
// For English, remove any locale prefix and return root path
if (pathname.startsWith('/jp')) {
return pathname.replace(/^\/jp/, '') || '/'
}
if (pathname.startsWith('/kr')) {
return pathname.replace(/^\/kr/, '') || '/'
}
return pathname
} else {
// For other locales, add the locale prefix
if (pathname.startsWith('/jp') || pathname.startsWith('/kr')) {
// Replace existing locale prefix
return pathname.replace(/^\/[a-z]{2}/, `/${targetLocale}`)
} else {
// Add locale prefix to English path
return `/${targetLocale}${pathname === '/' ? '' : pathname}`
}
}
}

const currentLanguage = languages.find(lang => lang.code === locale)

return (
<div className="relative" ref={dropdownRef}>
<button
onClick={() => setIsOpen(!isOpen)}
className="flex items-center space-x-1 px-2 py-1 text-sm text-slate-600 hover:text-slate-900 dark:text-slate-400 dark:hover:text-slate-300 transition-colors"
aria-label="Select language"
>
<span className="text-base">{currentLanguage?.flag}</span>
<svg
className={`w-3 h-3 transition-transform duration-200 ${isOpen ? 'rotate-180' : ''}`}
fill="none"
stroke="currentColor"
viewBox="0 0 24 24"
>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
</svg>
</button>

{isOpen && (
<div className="absolute right-0 top-full mt-1 w-32 bg-white dark:bg-slate-800 rounded-md shadow-lg border border-slate-200 dark:border-slate-700 py-1 z-50">
{languages.map((lang) => (
<Link
key={lang.code}
href={getLocalizedPath(lang.code)}
onClick={() => setIsOpen(false)}
className={`flex items-center space-x-2 px-3 py-2 text-sm hover:bg-slate-50 dark:hover:bg-slate-700 transition-colors ${
locale === lang.code
? 'text-blue-600 dark:text-blue-400 font-medium'
: 'text-slate-700 dark:text-slate-300'
}`}
>
<span>{lang.flag}</span>
<span>{lang.name}</span>
</Link>
))}
</div>
)}
</div>
)
}
28 changes: 23 additions & 5 deletions src/components/NavList.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,34 @@ import { Popover } from '@headlessui/react'
import Link from 'next/link'
import { SwitcherPopover } from './products/SwitcherPopover'
import { productCategories } from './products/index'
import { useTranslations, useLocale } from '@/contexts/LocaleContext'

const NavList = () => {
const t = useTranslations('header')
const { locale } = useLocale()

const getLocalizedHref = (path) => {
if (locale === 'en') return path
return `/${locale}${path}`
}

const getTranslatedCategory = (category) => {
const categoryMap = {
'MPL': t('mpl', 'MPL'),
'Dev Tools': t('devTools', 'Dev Tools'),
'Aura': t('aura', 'Aura')
}
return categoryMap[category] || category
}

return (
<div className="hidden cursor-pointer gap-8 lg:flex">
{productCategories.map((item, index) => {
if (item === 'Aura') {
return (
<Link href="/aura" key={index}>
<Link href={getLocalizedHref("/aura")} key={index}>
<div className="-mx-4 -my-2 rounded-lg px-4 py-2 text-black dark:text-white">
Aura
{getTranslatedCategory(item)}
</div>
</Link>
)
Expand All @@ -23,16 +41,16 @@ const NavList = () => {
<div className="hidden flex-col lg:flex" key={index}>
<SwitcherPopover menuItem={productCategories[index]}>
<Popover.Button className="-mx-4 -my-2 rounded-lg px-4 py-2 text-black dark:text-white">
{item}
{getTranslatedCategory(item)}
</Popover.Button>
</SwitcherPopover>
</div>
)
})}
<div className="hidden flex-col lg:flex">
<Link href="/guides">
<Link href={getLocalizedHref("/guides")}>
<div className="-mx-4 -my-2 rounded-lg px-4 py-2 text-black dark:text-white">
Guides
{t('guides', 'Guides')}
</div>
</Link>
</div>
Expand Down
7 changes: 4 additions & 3 deletions src/components/TableOfContent.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,25 @@ function useTableOfContents(tableOfContents) {
.flatMap((node) => [node.id, ...node.children.map((child) => child.id)])
.map((id) => {
let el = document.getElementById(id)
if (!el) return
if (!el) return null

let style = window.getComputedStyle(el)
let scrollMt = parseFloat(style.scrollMarginTop)

let top = window.scrollY + el.getBoundingClientRect().top - scrollMt
return { id, top }
})
.filter(Boolean) // Remove null/undefined entries
}, [])

useEffect(() => {
if (tableOfContents.length === 0) return
let headings = getHeadings(tableOfContents)
function onScroll() {
let top = window.scrollY
let current = headings[0].id
let current = headings[0]?.id
for (let heading of headings) {
if (top >= heading.top) {
if (heading && top >= heading.top) {
current = heading.id
} else {
break
Expand Down
Loading