このコミットが含まれているのは:
2026-07-05 20:00:58 +09:00
コミット 021d13a262
10個のファイルの変更647行の追加480行の削除
+27 -28
ファイルの表示
@@ -208,12 +208,12 @@ const TopNav: FC<Props> = ({ user }) => {
return (
<>
<nav className="px-3 flex justify-between items-center w-full
border-b top-nav-themed">
<nav className="top-nav-root px-3 flex justify-between items-center w-full
border-b">
<div className="flex items-center gap-2 h-12">
<PrefetchLink
to="/posts"
className="mx-4 text-xl font-bold"
className="top-nav-link mx-4 text-xl font-bold"
onClick={() => {
scroll (0, 0)
}}>
@@ -223,7 +223,7 @@ const TopNav: FC<Props> = ({ user }) => {
<div ref={navRef} className="relative hidden md:flex h-12 items-center">
<div aria-hidden
className={cn ('absolute inset-y-0 h-12',
'top-nav-themed-active',
'top-nav-highlight',
highlightTransitionClass)}
style={{ width: hl.width,
transform: `translateX(${ hl.left }px)`,
@@ -245,8 +245,8 @@ const TopNav: FC<Props> = ({ user }) => {
ref={(el: (HTMLAnchorElement | null)) => {
itemsRef.current[i] = el
}}
className={cn ('relative z-10 flex h-full items-center px-5',
(i === openItemIdx) && 'top-nav-themed-active font-bold')}>
className={cn ('top-nav-link relative z-10 flex h-full items-center px-5',
(i === openItemIdx) && 'font-bold')}>
{item.name}
</PrefetchLink>
</motion.div>))}
@@ -260,8 +260,8 @@ const TopNav: FC<Props> = ({ user }) => {
setMoreVsbl (true)
measure (-1)
}}
className={cn ('relative z-10 flex h-full items-center px-5',
(openItemIdx < 0 || moreVsbl) && 'top-nav-themed-active font-bold')}>
className={cn ('top-nav-link relative z-10 flex h-full items-center px-5',
(openItemIdx < 0 || moreVsbl) && 'font-bold')}>
&raquo;
</PrefetchLink>
</div>
@@ -271,7 +271,7 @@ const TopNav: FC<Props> = ({ user }) => {
<button
type="button"
className="md:hidden ml-auto border-0 bg-transparent pr-4"
className="top-nav-link md:hidden ml-auto border-0 bg-transparent pr-4"
onClick={() => {
setMenuOpen (!(menuOpen))
}}>
@@ -284,8 +284,7 @@ const TopNav: FC<Props> = ({ user }) => {
key="submenu-shell"
{...(animationsOff ? { }
: { layout: true })}
className="relative z-20 hidden md:block overflow-hidden
top-nav-themed-submenu"
className="relative z-20 hidden md:block overflow-hidden top-nav-submenu"
animate={{ height: submenuHeight }}
onMouseLeave={() => {
if (moreVsbl)
@@ -346,7 +345,7 @@ const TopNav: FC<Props> = ({ user }) => {
to={subItem.to}
target={subItem.to.slice (0, 2) === '//' ? '_blank' : undefined}
onClick={() => setMoreVsbl (false)}
className="h-full flex items-center px-3">
className="top-nav-link h-full flex items-center px-3">
{subItem.name}
</PrefetchLink>
</motion.div>)))}
@@ -373,7 +372,7 @@ const TopNav: FC<Props> = ({ user }) => {
target={item.to.slice (0, 2) === '//'
? '_blank'
: undefined}
className="h-full flex items-center px-3">
className="top-nav-link h-full flex items-center px-3">
{item.name}
</PrefetchLink>
</div>)))}
@@ -412,7 +411,7 @@ const TopNav: FC<Props> = ({ user }) => {
target={item.to.slice (0, 2) === '//'
? '_blank'
: undefined}
className="h-full flex items-center px-3">
className="top-nav-link h-full flex items-center px-3">
{item.name}
</PrefetchLink>
</motion.div>)))}
@@ -426,16 +425,16 @@ const TopNav: FC<Props> = ({ user }) => {
? (
menuOpen && (
<div
className={cn ('top-nav-themed top-nav-themed-submenu flex flex-col md:hidden',
className={cn ('top-nav-root top-nav-mobile-menu flex flex-col md:hidden',
'items-start')}>
<Separator/>
{visibleMenu.map ((item, i) => (
<Fragment key={i}>
<PrefetchLink
to={i === openItemIdx ? item.to : '#'}
className={cn ('w-full min-h-[40px] flex items-center pl-8',
className={cn ('top-nav-link w-full min-h-[40px] flex items-center pl-8',
((i === openItemIdx)
&& 'top-nav-themed-active font-bold'))}
&& 'top-nav-mobile-active font-bold'))}
onClick={(ev: MouseEvent<HTMLAnchorElement>) => {
if (i !== openItemIdx)
{
@@ -447,7 +446,7 @@ const TopNav: FC<Props> = ({ user }) => {
</PrefetchLink>
{i === openItemIdx && (
<div className="top-nav-themed-submenu w-full">
<div className="top-nav-submenu w-full">
{item.subMenu
.filter (subItem => subItem.visible ?? true)
.map ((subItem, j) => (
@@ -463,7 +462,7 @@ const TopNav: FC<Props> = ({ user }) => {
target={subItem.to.slice (0, 2) === '//'
? '_blank'
: undefined}
className="w-full min-h-[36px] flex items-center pl-12">
className="top-nav-link w-full min-h-[36px] flex items-center pl-12">
{subItem.name}
</PrefetchLink>)))}
</div>)}
@@ -473,9 +472,9 @@ const TopNav: FC<Props> = ({ user }) => {
ref={(el: (HTMLAnchorElement | null)) => {
itemsRef.current[visibleMenu.length] = el
}}
className={cn ('w-full min-h-[40px] flex items-center pl-8',
className={cn ('top-nav-link w-full min-h-[40px] flex items-center pl-8',
((openItemIdx < 0)
&& 'top-nav-themed-active font-bold'))}>
&& 'top-nav-mobile-active font-bold'))}>
&raquo;
</PrefetchLink>
<TopNavUser user={user} sp/>
@@ -486,7 +485,7 @@ const TopNav: FC<Props> = ({ user }) => {
{menuOpen && (
<motion.div
key="spmenu"
className={cn ('top-nav-themed top-nav-themed-submenu flex flex-col md:hidden',
className={cn ('top-nav-root top-nav-mobile-menu flex flex-col md:hidden',
'items-start')}
variants={{ closed: { clipPath: 'inset(0 0 100% 0)',
height: 0 },
@@ -501,9 +500,9 @@ const TopNav: FC<Props> = ({ user }) => {
<Fragment key={i}>
<PrefetchLink
to={i === openItemIdx ? item.to : '#'}
className={cn ('w-full min-h-[40px] flex items-center pl-8',
className={cn ('top-nav-link w-full min-h-[40px] flex items-center pl-8',
((i === openItemIdx)
&& 'top-nav-themed-active font-bold'))}
&& 'top-nav-mobile-active font-bold'))}
onClick={(ev: MouseEvent<HTMLAnchorElement>) => {
if (i !== openItemIdx)
{
@@ -518,7 +517,7 @@ const TopNav: FC<Props> = ({ user }) => {
{i === openItemIdx && (
<motion.div
key={`sp-sub-${ i }`}
className="top-nav-themed-submenu w-full"
className="top-nav-submenu w-full"
variants={{ closed: { clipPath: 'inset(0 0 100% 0)',
height: 0,
opacity: 0 },
@@ -544,7 +543,7 @@ const TopNav: FC<Props> = ({ user }) => {
target={subItem.to.slice (0, 2) === '//'
? '_blank'
: undefined}
className="w-full min-h-[36px] flex items-center pl-12">
className="top-nav-link w-full min-h-[36px] flex items-center pl-12">
{subItem.name}
</PrefetchLink>)))}
</motion.div>)}
@@ -555,9 +554,9 @@ const TopNav: FC<Props> = ({ user }) => {
ref={(el: (HTMLAnchorElement | null)) => {
itemsRef.current[visibleMenu.length] = el
}}
className={cn ('w-full min-h-[40px] flex items-center pl-8',
className={cn ('top-nav-link w-full min-h-[40px] flex items-center pl-8',
((openItemIdx < 0)
&& 'top-nav-themed-active font-bold'))}>
&& 'top-nav-mobile-active font-bold'))}>
&raquo;
</PrefetchLink>
<TopNavUser user={user} sp/>
+17 -2
ファイルの表示
@@ -15,7 +15,11 @@ import type { ClientAnimationMode,
ClientThumbnailMode } from '@/lib/settings'
type Props = {
sectionClassName: string }
sectionClassName: string
onDirtyStateChange?: (
dirty: boolean,
discard: () => void,
) => void }
type SegmentedOption<T extends string> = {
value: T
@@ -95,7 +99,10 @@ const SettingBlock: FC<SettingBlockProps> = (
</div>)
const BehaviourSettingsSection: FC<Props> = ({ sectionClassName }) => {
const BehaviourSettingsSection: FC<Props> = (
{ sectionClassName,
onDirtyStateChange },
) => {
const [savedSettings, setSavedSettings] =
useState<ClientBehaviorSettings> (() => getClientBehaviorSettings ())
const [draftSettings, setDraftSettings] =
@@ -129,6 +136,14 @@ const BehaviourSettingsSection: FC<Props> = ({ sectionClassName }) => {
setDraftSettings (savedSettings)
}
useEffect (() => {
onDirtyStateChange?.(hasUnsavedChanges, handleDiscard)
return () => {
onDirtyStateChange?.(false, () => { })
}
}, [handleDiscard, hasUnsavedChanges, onDirtyStateChange])
return (
<section className={sectionClassName}>
<div className="flex flex-wrap items-start justify-between gap-3">
+16 -1
ファイルの表示
@@ -19,10 +19,17 @@ import type { FC } from 'react'
type Props = {
sectionClassName: string
onDirtyStateChange?: (
dirty: boolean,
discard: () => void,
) => void
}
const KeyboardSettingsSection: FC<Props> = ({ sectionClassName }) => {
const KeyboardSettingsSection: FC<Props> = (
{ sectionClassName,
onDirtyStateChange },
) => {
const {
keyboardSettings,
saveKeyboardSettings,
@@ -127,6 +134,14 @@ const KeyboardSettingsSection: FC<Props> = ({ sectionClassName }) => {
setCapturingActionId (null)
}
useEffect (() => {
onDirtyStateChange?.(hasUnsavedChanges, handleDiscard)
return () => {
onDirtyStateChange?.(false, () => { })
}
}, [handleDiscard, hasUnsavedChanges, onDirtyStateChange])
return (
<section className={sectionClassName}>
<div className="flex flex-wrap items-start justify-between gap-3">