このコミットが含まれているのは:
@@ -22,6 +22,7 @@ class WikiPagesController < ApplicationController
|
|||||||
|
|
||||||
json = descriptions.map { |description| WikiPageRepr.tag_description(description) }
|
json = descriptions.map { |description| WikiPageRepr.tag_description(description) }
|
||||||
json.concat(tag_groups.map { WikiPageRepr.tag_group(_1) })
|
json.concat(tag_groups.map { WikiPageRepr.tag_group(_1) })
|
||||||
|
json.sort! { |a, b| b['updated_at'] <=> a['updated_at'] }
|
||||||
json = json.first(20) if title.present?
|
json = json.first(20) if title.present?
|
||||||
render json:
|
render json:
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import type { FC, MouseEvent } from 'react'
|
|||||||
import type { Material, Menu, MenuVisibleItem, Tag, User } from '@/types'
|
import type { Material, Menu, MenuVisibleItem, Tag, User } from '@/types'
|
||||||
|
|
||||||
type Props = { user: User | null }
|
type Props = { user: User | null }
|
||||||
|
type NavDensity = 'auto' | 'comfortable' | 'compact'
|
||||||
|
|
||||||
|
|
||||||
export const menuOutline = (
|
export const menuOutline = (
|
||||||
@@ -40,6 +41,9 @@ export const menuOutline = (
|
|||||||
|
|
||||||
const materialFlg = /^\/materials\/\d+/.test (pathName)
|
const materialFlg = /^\/materials\/\d+/.test (pathName)
|
||||||
|
|
||||||
|
const helpVsbl = /\/help\/((?!changes)[^\/?]+)/.test (pathName)
|
||||||
|
const helpIdentifier = pathName.split ('/')[2] ?? ''
|
||||||
|
|
||||||
return [
|
return [
|
||||||
{ name: '広場', to: '/posts', subMenu: [
|
{ name: '広場', to: '/posts', subMenu: [
|
||||||
{ name: '一覧', to: '/posts' },
|
{ name: '一覧', to: '/posts' },
|
||||||
@@ -84,7 +88,9 @@ export const menuOutline = (
|
|||||||
visible: wikiPageFlg && editable }] },
|
visible: wikiPageFlg && editable }] },
|
||||||
{ name: 'ヘルプ', to: '/help/home', base: '/help', subMenu: [
|
{ name: 'ヘルプ', to: '/help/home', base: '/help', subMenu: [
|
||||||
{ name: '検索', to: '/help' },
|
{ name: '検索', to: '/help' },
|
||||||
{ name: '全体履歴', to: '/help/changes' }] },
|
{ name: '全体履歴', to: '/help/changes' },
|
||||||
|
{ component: <Separator/>, visible: helpVsbl },
|
||||||
|
{ name: '履歴', to: `/help/changes?identifier=${ helpIdentifier }`, visible: helpVsbl }] },
|
||||||
{ name: 'おたのしみ', visible: false, subMenu: [
|
{ name: 'おたのしみ', visible: false, subMenu: [
|
||||||
{ name: '上映会 (β)', to: '/theatres/1' },
|
{ name: '上映会 (β)', to: '/theatres/1' },
|
||||||
{ name: 'グカネータ (β)', to: '/gekanator' }] },
|
{ name: 'グカネータ (β)', to: '/gekanator' }] },
|
||||||
@@ -107,6 +113,8 @@ const TopNav: FC<Props> = ({ user }) => {
|
|||||||
const dirRef = useRef<(-1) | 1> (1)
|
const dirRef = useRef<(-1) | 1> (1)
|
||||||
const itemsRef = useRef<(HTMLAnchorElement | null)[]> ([])
|
const itemsRef = useRef<(HTMLAnchorElement | null)[]> ([])
|
||||||
const navRef = useRef<HTMLDivElement | null> (null)
|
const navRef = useRef<HTMLDivElement | null> (null)
|
||||||
|
const layoutRef = useRef<HTMLDivElement | null> (null)
|
||||||
|
const barRef = useRef<HTMLElement | null> (null)
|
||||||
|
|
||||||
const measure = (idx: number) => {
|
const measure = (idx: number) => {
|
||||||
const nav = navRef.current
|
const nav = navRef.current
|
||||||
@@ -131,6 +139,8 @@ const TopNav: FC<Props> = ({ user }) => {
|
|||||||
width: 0,
|
width: 0,
|
||||||
visible: false })
|
visible: false })
|
||||||
const [menuOpen, setMenuOpen] = useState (false)
|
const [menuOpen, setMenuOpen] = useState (false)
|
||||||
|
const [desktop, setDesktop] = useState (false)
|
||||||
|
const [density, setDensity] = useState<NavDensity> ('auto')
|
||||||
const [moreVsbl, setMoreVsbl] = useState (false)
|
const [moreVsbl, setMoreVsbl] = useState (false)
|
||||||
const [openItemIdx, setOpenItemIdx] = useState (-1)
|
const [openItemIdx, setOpenItemIdx] = useState (-1)
|
||||||
const [wikiId, setWikiId] = useState<number | null> (WikiIdBus.get ())
|
const [wikiId, setWikiId] = useState<number | null> (WikiIdBus.get ())
|
||||||
@@ -197,15 +207,81 @@ const TopNav: FC<Props> = ({ user }) => {
|
|||||||
const dir = dirRef.current
|
const dir = dirRef.current
|
||||||
|
|
||||||
useLayoutEffect (() => {
|
useLayoutEffect (() => {
|
||||||
const raf = requestAnimationFrame (() => measure (moreVsbl ? -1 : activeIdx))
|
const layout = layoutRef.current
|
||||||
const onResize = () => requestAnimationFrame (() => measure (moreVsbl ? -1 : activeIdx))
|
const bar = barRef.current
|
||||||
|
const primary = bar?.querySelector<HTMLElement> ('.top-nav-primary')
|
||||||
|
if (layout == null || bar == null || primary == null)
|
||||||
|
return
|
||||||
|
|
||||||
addEventListener ('resize', onResize)
|
const userLink = bar.querySelector<HTMLElement> ('.top-nav-user-desktop')
|
||||||
return () => {
|
let raf = 0
|
||||||
cancelAnimationFrame (raf)
|
let active = true
|
||||||
removeEventListener ('resize', onResize)
|
|
||||||
|
const update = () => {
|
||||||
|
if (!(window.matchMedia ('(min-width: 768px)').matches))
|
||||||
|
{
|
||||||
|
setDesktop (false)
|
||||||
|
setDensity ('auto')
|
||||||
|
return
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
// Measure the same desktop elements while the mobile layout is active.
|
||||||
|
layout.setAttribute ('data-measuring', '')
|
||||||
|
const previousDensity = layout.getAttribute ('data-density') ?? 'auto'
|
||||||
|
const fittingDensity = (() => {
|
||||||
|
try
|
||||||
|
{
|
||||||
|
for (const candidate of ['auto', 'comfortable', 'compact'] as const)
|
||||||
|
{
|
||||||
|
layout.setAttribute ('data-density', candidate)
|
||||||
|
const style = getComputedStyle (bar)
|
||||||
|
const required = primary.getBoundingClientRect ().width
|
||||||
|
+ (userLink?.getBoundingClientRect ().width ?? 0)
|
||||||
|
+ parseFloat (style.paddingLeft) + parseFloat (style.paddingRight)
|
||||||
|
+ (userLink == null ? 0 : parseFloat (style.columnGap))
|
||||||
|
if (required <= bar.clientWidth)
|
||||||
|
return candidate
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
layout.setAttribute ('data-density', previousDensity)
|
||||||
|
layout.removeAttribute ('data-measuring')
|
||||||
|
}
|
||||||
|
}) ()
|
||||||
|
setDensity (fittingDensity ?? 'compact')
|
||||||
|
setDesktop (fittingDensity != null)
|
||||||
|
if (fittingDensity != null)
|
||||||
|
measure (moreVsbl ? -1 : activeIdx)
|
||||||
|
}
|
||||||
|
|
||||||
|
const schedule = () => {
|
||||||
|
if (!(active))
|
||||||
|
return
|
||||||
|
cancelAnimationFrame (raf)
|
||||||
|
raf = requestAnimationFrame (update)
|
||||||
|
}
|
||||||
|
|
||||||
|
const observer =
|
||||||
|
typeof ResizeObserver === 'undefined' ? null : new ResizeObserver (schedule)
|
||||||
|
observer?.observe (bar)
|
||||||
|
observer?.observe (primary)
|
||||||
|
if (userLink != null)
|
||||||
|
observer?.observe (userLink)
|
||||||
|
update ()
|
||||||
|
addEventListener ('resize', schedule)
|
||||||
|
document.fonts?.addEventListener ('loadingdone', schedule)
|
||||||
|
void document.fonts?.ready.then (schedule)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
active = false
|
||||||
|
cancelAnimationFrame (raf)
|
||||||
|
observer?.disconnect ()
|
||||||
|
removeEventListener ('resize', schedule)
|
||||||
|
document.fonts?.removeEventListener ('loadingdone', schedule)
|
||||||
|
}
|
||||||
|
}, [activeIdx, moreVsbl, desktop, density, user?.name])
|
||||||
|
|
||||||
useEffect (() => {
|
useEffect (() => {
|
||||||
const unsubscribe = WikiIdBus.subscribe (setWikiId)
|
const unsubscribe = WikiIdBus.subscribe (setWikiId)
|
||||||
@@ -218,20 +294,22 @@ const TopNav: FC<Props> = ({ user }) => {
|
|||||||
}, [activeIdx, location])
|
}, [activeIdx, location])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<div ref={layoutRef} className="top-nav-layout w-full min-w-0 shrink-0"
|
||||||
<nav className="top-nav-root px-3 flex flex-wrap justify-between items-center w-full">
|
data-desktop={desktop} data-density={density}>
|
||||||
<div className="flex shrink-0 items-center gap-2 h-12">
|
<nav ref={barRef}
|
||||||
|
className="top-nav-root top-nav-bar flex justify-between items-center w-full">
|
||||||
|
<div className="top-nav-primary flex shrink-0 items-center h-12">
|
||||||
<PrefetchLink
|
<PrefetchLink
|
||||||
to="/posts"
|
to="/posts"
|
||||||
className="top-nav-brand-link shrink-0 whitespace-nowrap mx-2 text-base
|
className="top-nav-brand-link shrink-0 whitespace-nowrap font-bold"
|
||||||
xl:mx-4 xl:text-xl font-bold"
|
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
scroll (0, 0)
|
scroll (0, 0)
|
||||||
}}>
|
}}>
|
||||||
ぼざクリ タグ広場
|
ぼざクリ タグ広場
|
||||||
</PrefetchLink>
|
</PrefetchLink>
|
||||||
|
|
||||||
<div ref={navRef} className="relative hidden xl:flex shrink-0 h-12 items-center">
|
<div ref={navRef}
|
||||||
|
className="top-nav-desktop-menu relative shrink-0 h-12 items-center">
|
||||||
<div aria-hidden
|
<div aria-hidden
|
||||||
className={cn ('absolute inset-y-0 h-12',
|
className={cn ('absolute inset-y-0 h-12',
|
||||||
'top-nav-highlight',
|
'top-nav-highlight',
|
||||||
@@ -257,7 +335,7 @@ const TopNav: FC<Props> = ({ user }) => {
|
|||||||
ref={(el: (HTMLAnchorElement | null)) => {
|
ref={(el: (HTMLAnchorElement | null)) => {
|
||||||
itemsRef.current[i] = el
|
itemsRef.current[i] = el
|
||||||
}}
|
}}
|
||||||
className={cn ('top-nav-menu-link relative z-10 flex h-full items-center px-5',
|
className={cn ('top-nav-menu-link relative z-10 flex h-full items-center',
|
||||||
(i === openItemIdx) && 'font-bold')}>
|
(i === openItemIdx) && 'font-bold')}>
|
||||||
{item.name}
|
{item.name}
|
||||||
</PrefetchLink>
|
</PrefetchLink>
|
||||||
@@ -272,7 +350,7 @@ const TopNav: FC<Props> = ({ user }) => {
|
|||||||
setMoreVsbl (true)
|
setMoreVsbl (true)
|
||||||
measure (-1)
|
measure (-1)
|
||||||
}}
|
}}
|
||||||
className={cn ('top-nav-menu-link relative z-10 flex h-full items-center px-5',
|
className={cn ('top-nav-menu-link relative z-10 flex h-full items-center',
|
||||||
'shrink-0 whitespace-nowrap',
|
'shrink-0 whitespace-nowrap',
|
||||||
(openItemIdx < 0 || moreVsbl) && 'font-bold')}>
|
(openItemIdx < 0 || moreVsbl) && 'font-bold')}>
|
||||||
その他 »
|
その他 »
|
||||||
@@ -284,7 +362,7 @@ const TopNav: FC<Props> = ({ user }) => {
|
|||||||
|
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className="top-nav-mobile-toggle xl:hidden shrink-0 whitespace-nowrap
|
className="top-nav-mobile-toggle shrink-0 whitespace-nowrap
|
||||||
ml-auto border-0 bg-transparent pr-4"
|
ml-auto border-0 bg-transparent pr-4"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setMenuOpen (!(menuOpen))
|
setMenuOpen (!(menuOpen))
|
||||||
@@ -298,7 +376,8 @@ const TopNav: FC<Props> = ({ user }) => {
|
|||||||
key="submenu-shell"
|
key="submenu-shell"
|
||||||
{...(animationsOff ? { }
|
{...(animationsOff ? { }
|
||||||
: { layout: true })}
|
: { layout: true })}
|
||||||
className="relative z-20 hidden xl:block shrink-0 overflow-hidden top-nav-submenu"
|
className="top-nav-desktop-submenu relative z-20 shrink-0
|
||||||
|
overflow-hidden top-nav-submenu"
|
||||||
animate={{ height: submenuHeight }}
|
animate={{ height: submenuHeight }}
|
||||||
onMouseLeave={() => {
|
onMouseLeave={() => {
|
||||||
if (moreVsbl)
|
if (moreVsbl)
|
||||||
@@ -442,7 +521,7 @@ const TopNav: FC<Props> = ({ user }) => {
|
|||||||
? (
|
? (
|
||||||
menuOpen && (
|
menuOpen && (
|
||||||
<div
|
<div
|
||||||
className={cn ('top-nav-root top-nav-mobile-menu flex flex-col xl:hidden',
|
className={cn ('top-nav-root top-nav-mobile-menu flex flex-col',
|
||||||
'items-start')}>
|
'items-start')}>
|
||||||
<Separator/>
|
<Separator/>
|
||||||
{visibleMenu.map ((item, i) => (
|
{visibleMenu.map ((item, i) => (
|
||||||
@@ -499,7 +578,7 @@ const TopNav: FC<Props> = ({ user }) => {
|
|||||||
{menuOpen && (
|
{menuOpen && (
|
||||||
<motion.div
|
<motion.div
|
||||||
key="spmenu"
|
key="spmenu"
|
||||||
className={cn ('top-nav-root top-nav-mobile-menu flex flex-col xl:hidden',
|
className={cn ('top-nav-root top-nav-mobile-menu flex flex-col',
|
||||||
'items-start')}
|
'items-start')}
|
||||||
variants={{ closed: { clipPath: 'inset(0 0 100% 0)',
|
variants={{ closed: { clipPath: 'inset(0 0 100% 0)',
|
||||||
height: 0 },
|
height: 0 },
|
||||||
@@ -574,7 +653,7 @@ const TopNav: FC<Props> = ({ user }) => {
|
|||||||
<Separator/>
|
<Separator/>
|
||||||
</motion.div>)}
|
</motion.div>)}
|
||||||
</AnimatePresence>)}
|
</AnimatePresence>)}
|
||||||
</>)
|
</div>)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default TopNav
|
export default TopNav
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ const TopNavUser: FC<Props> = ({ user, sp }) => {
|
|||||||
return
|
return
|
||||||
|
|
||||||
const className = cn ((sp
|
const className = cn ((sp
|
||||||
? 'xl:hidden w-full min-h-[40px] flex items-center pl-8'
|
? 'top-nav-user-mobile w-full min-h-[40px] flex items-center pl-8'
|
||||||
: 'hidden xl:block shrink-0 max-w-full break-words ml-auto pr-4'),
|
: 'top-nav-user-desktop shrink-0 whitespace-nowrap ml-auto'),
|
||||||
'font-bold text-red-600 hover:text-red-400',
|
'font-bold text-red-600 hover:text-red-400',
|
||||||
'dark:text-yellow-400 dark:hover:text-yellow-200')
|
'dark:text-yellow-400 dark:hover:text-yellow-200')
|
||||||
|
|
||||||
|
|||||||
+234
-2
@@ -197,12 +197,244 @@ body
|
|||||||
background: var(--top-nav-root-bg-mobile);
|
background: var(--top-nav-root-bg-mobile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width: 1280px)
|
.top-nav-bar
|
||||||
{
|
{
|
||||||
.top-nav-root
|
padding-inline: 8px;
|
||||||
|
column-gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-primary
|
||||||
|
{
|
||||||
|
column-gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-layout .top-nav-brand-link
|
||||||
|
{
|
||||||
|
margin-inline: 4px;
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-desktop-menu,
|
||||||
|
.top-nav-desktop-submenu,
|
||||||
|
.top-nav-user-desktop
|
||||||
|
{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-desktop-menu
|
||||||
|
{
|
||||||
|
font-size: .875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-desktop-menu .top-nav-menu-link
|
||||||
|
{
|
||||||
|
padding-inline: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-user-desktop
|
||||||
|
{
|
||||||
|
padding-right: 4px;
|
||||||
|
font-size: .875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-user-mobile
|
||||||
|
{
|
||||||
|
overflow-wrap: anywhere;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px)
|
||||||
|
{
|
||||||
|
.top-nav-layout .top-nav-brand-link
|
||||||
|
{
|
||||||
|
font-size: 1.125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-layout[data-desktop='true'] .top-nav-root
|
||||||
{
|
{
|
||||||
background: var(--top-nav-root-bg-desktop);
|
background: var(--top-nav-root-bg-desktop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.top-nav-layout[data-desktop='true'] .top-nav-desktop-menu,
|
||||||
|
.top-nav-layout[data-measuring] .top-nav-desktop-menu
|
||||||
|
{
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-layout[data-desktop='true'] .top-nav-user-desktop,
|
||||||
|
.top-nav-layout[data-measuring] .top-nav-user-desktop,
|
||||||
|
.top-nav-layout[data-desktop='true'] .top-nav-desktop-submenu
|
||||||
|
{
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-layout[data-desktop='true'] .top-nav-mobile-toggle,
|
||||||
|
.top-nav-layout[data-measuring] .top-nav-mobile-toggle,
|
||||||
|
.top-nav-layout[data-desktop='true'] .top-nav-mobile-menu,
|
||||||
|
.top-nav-layout[data-desktop='true'] .top-nav-user-mobile
|
||||||
|
{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-layout[data-measuring]
|
||||||
|
{
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1024px)
|
||||||
|
{
|
||||||
|
.top-nav-bar
|
||||||
|
{
|
||||||
|
padding-inline: 12px;
|
||||||
|
column-gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-primary
|
||||||
|
{
|
||||||
|
column-gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-layout .top-nav-brand-link
|
||||||
|
{
|
||||||
|
margin-inline: 8px;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-desktop-menu
|
||||||
|
{
|
||||||
|
column-gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-desktop-menu,
|
||||||
|
.top-nav-user-desktop
|
||||||
|
{
|
||||||
|
font-size: .9375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-desktop-menu .top-nav-menu-link
|
||||||
|
{
|
||||||
|
padding-inline: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-user-desktop
|
||||||
|
{
|
||||||
|
padding-right: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1280px)
|
||||||
|
{
|
||||||
|
.top-nav-bar
|
||||||
|
{
|
||||||
|
column-gap: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-primary
|
||||||
|
{
|
||||||
|
column-gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-layout .top-nav-brand-link
|
||||||
|
{
|
||||||
|
margin-inline: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-desktop-menu
|
||||||
|
{
|
||||||
|
column-gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-desktop-menu,
|
||||||
|
.top-nav-user-desktop
|
||||||
|
{
|
||||||
|
font-size: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-desktop-menu .top-nav-menu-link
|
||||||
|
{
|
||||||
|
padding-inline: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-user-desktop
|
||||||
|
{
|
||||||
|
padding-right: 16px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-layout[data-density='comfortable'] .top-nav-bar
|
||||||
|
{
|
||||||
|
padding-inline: 12px;
|
||||||
|
column-gap: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-layout[data-density='comfortable'] .top-nav-primary
|
||||||
|
{
|
||||||
|
column-gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-layout[data-density='comfortable'] .top-nav-brand-link
|
||||||
|
{
|
||||||
|
margin-inline: 8px;
|
||||||
|
font-size: 1.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-layout[data-density='comfortable'] .top-nav-desktop-menu
|
||||||
|
{
|
||||||
|
column-gap: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-layout[data-density='comfortable'] .top-nav-desktop-menu,
|
||||||
|
.top-nav-layout[data-density='comfortable'] .top-nav-user-desktop
|
||||||
|
{
|
||||||
|
font-size: .9375rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-layout[data-density='comfortable'] .top-nav-desktop-menu .top-nav-menu-link
|
||||||
|
{
|
||||||
|
padding-inline: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-layout[data-density='comfortable'] .top-nav-user-desktop
|
||||||
|
{
|
||||||
|
padding-right: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-layout[data-density='compact'] .top-nav-bar
|
||||||
|
{
|
||||||
|
padding-inline: 8px;
|
||||||
|
column-gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-layout[data-density='compact'] .top-nav-primary
|
||||||
|
{
|
||||||
|
column-gap: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-layout[data-density='compact'] .top-nav-brand-link
|
||||||
|
{
|
||||||
|
margin-inline: 4px;
|
||||||
|
font-size: 1.125rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-layout[data-density='compact'] .top-nav-desktop-menu
|
||||||
|
{
|
||||||
|
column-gap: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-layout[data-density='compact'] .top-nav-desktop-menu,
|
||||||
|
.top-nav-layout[data-density='compact'] .top-nav-user-desktop
|
||||||
|
{
|
||||||
|
font-size: .875rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-layout[data-density='compact'] .top-nav-desktop-menu .top-nav-menu-link
|
||||||
|
{
|
||||||
|
padding-inline: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.top-nav-layout[data-density='compact'] .top-nav-user-desktop
|
||||||
|
{
|
||||||
|
padding-right: 4px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-nav-brand-link,
|
.top-nav-brand-link,
|
||||||
|
|||||||
@@ -48,10 +48,10 @@ const HelpChangesPage: FC = () => {
|
|||||||
return (
|
return (
|
||||||
<MainArea className="min-w-0 max-w-full">
|
<MainArea className="min-w-0 max-w-full">
|
||||||
<Helmet>
|
<Helmet>
|
||||||
<title>{`ヘルプ 変更履歴 | ${ SITE_TITLE }`}</title>
|
<title>{`ヘルプ改定履歴 | ${ SITE_TITLE }`}</title>
|
||||||
</Helmet>
|
</Helmet>
|
||||||
<div className="flex flex-wrap items-center justify-between gap-3">
|
<div className="flex flex-wrap items-center justify-between gap-3">
|
||||||
<PageTitle>変更履歴</PageTitle>
|
<PageTitle>ヘルプ改定履歴</PageTitle>
|
||||||
<label className="flex items-center gap-2 text-xs text-muted-foreground">
|
<label className="flex items-center gap-2 text-xs text-muted-foreground">
|
||||||
<span>件数</span>
|
<span>件数</span>
|
||||||
<select value={limit} onChange={ev => handleLimit (ev.target.value)}
|
<select value={limit} onChange={ev => handleLimit (ev.target.value)}
|
||||||
@@ -69,7 +69,6 @@ const HelpChangesPage: FC = () => {
|
|||||||
? <p className="mt-4 text-red-600" role="alert">{error.message}</p>
|
? <p className="mt-4 text-red-600" role="alert">{error.message}</p>
|
||||||
: (
|
: (
|
||||||
<div className="mt-4">
|
<div className="mt-4">
|
||||||
<p className="mb-2 text-sm" aria-live="polite">{results.length} 件</p>
|
|
||||||
<div className="min-w-0 max-w-full overflow-x-auto">
|
<div className="min-w-0 max-w-full overflow-x-auto">
|
||||||
<table className="table-auto w-full min-w-[900px] whitespace-nowrap
|
<table className="table-auto w-full min-w-[900px] whitespace-nowrap
|
||||||
border-collapse">
|
border-collapse">
|
||||||
@@ -77,9 +76,7 @@ const HelpChangesPage: FC = () => {
|
|||||||
<tr>
|
<tr>
|
||||||
<th className="p-2 text-left">差分</th>
|
<th className="p-2 text-left">差分</th>
|
||||||
<th className="p-2 text-left">タイトル</th>
|
<th className="p-2 text-left">タイトル</th>
|
||||||
<th className="p-2 text-left">版</th>
|
<th className="p-2 text-left">有効開始年月日</th>
|
||||||
<th className="p-2 text-left">変更</th>
|
|
||||||
<th className="p-2 text-left">更新日時</th>
|
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@@ -105,8 +102,6 @@ const HelpChangesPage: FC = () => {
|
|||||||
{entry.title}
|
{entry.title}
|
||||||
</PrefetchLink>
|
</PrefetchLink>
|
||||||
</td>
|
</td>
|
||||||
<td className="p-2">{entry.edition}</td>
|
|
||||||
<td className="p-2">{entry.change === 'new' ? '新規' : '更新'}</td>
|
|
||||||
<td className="p-2">{dateString (updatedAt, 'hour')}</td>
|
<td className="p-2">{dateString (updatedAt, 'hour')}</td>
|
||||||
</tr>)
|
</tr>)
|
||||||
})}
|
})}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import PrefetchLink from '@/components/PrefetchLink'
|
|||||||
import MainArea from '@/components/layout/MainArea'
|
import MainArea from '@/components/layout/MainArea'
|
||||||
import { SITE_TITLE } from '@/config'
|
import { SITE_TITLE } from '@/config'
|
||||||
import { getHelpArticle, getHelpEditionContent } from '@/lib/help'
|
import { getHelpArticle, getHelpEditionContent } from '@/lib/help'
|
||||||
|
import { dateString } from '@/lib/utils'
|
||||||
import { helpKeys } from '@/lib/queryKeys'
|
import { helpKeys } from '@/lib/queryKeys'
|
||||||
import NotFound from '@/pages/NotFound'
|
import NotFound from '@/pages/NotFound'
|
||||||
|
|
||||||
@@ -75,7 +76,7 @@ const HelpDetailPage: FC = () => {
|
|||||||
</PrefetchLink>)
|
</PrefetchLink>)
|
||||||
: '(最古)'}
|
: '(最古)'}
|
||||||
|
|
||||||
<span>{edition}</span>
|
<span>{dateString (edition, 'hour')}</span>
|
||||||
|
|
||||||
{succ
|
{succ
|
||||||
? (
|
? (
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ const HelpSearchPage: FC = () => {
|
|||||||
|
|
||||||
<div className="max-w-xl">
|
<div className="max-w-xl">
|
||||||
<div className="flex flex-wrap items-center justify-between gap-3">
|
<div className="flex flex-wrap items-center justify-between gap-3">
|
||||||
<PageTitle>ヘルプ</PageTitle>
|
<PageTitle>ヘルプ検索</PageTitle>
|
||||||
<label className="flex items-center gap-2 text-xs text-muted-foreground">
|
<label className="flex items-center gap-2 text-xs text-muted-foreground">
|
||||||
<span>件数</span>
|
<span>件数</span>
|
||||||
<select value={limit} onChange={ev => handleLimit (ev.target.value)}
|
<select value={limit} onChange={ev => handleLimit (ev.target.value)}
|
||||||
|
|||||||
新しいイシューから参照
ユーザーをブロックする