設定画面 (#34) #397
@@ -47,7 +47,7 @@ const embedAutoLoadOptions: SegmentedOption<ClientEmbedAutoLoadMode>[] = [
|
|||||||
|
|
||||||
const linkPreloadOptions: SegmentedOption<ClientLinkPreloadMode>[] = [
|
const linkPreloadOptions: SegmentedOption<ClientLinkPreloadMode>[] = [
|
||||||
{ value: 'off', label: 'しない' },
|
{ value: 'off', label: 'しない' },
|
||||||
{ value: 'intent', label: 'マウスを置いたら' }]
|
{ value: 'intent', label: 'する' }]
|
||||||
|
|
||||||
const tagRelationDisplayOptions: SegmentedOption<ClientTagRelationDisplayMode>[] = [
|
const tagRelationDisplayOptions: SegmentedOption<ClientTagRelationDisplayMode>[] = [
|
||||||
{ value: 'flat', label: 'まとめない' },
|
{ value: 'flat', label: 'まとめない' },
|
||||||
@@ -90,7 +90,7 @@ const SegmentedControl = <T extends string,> (
|
|||||||
const SettingBlock: FC<SettingBlockProps> = (
|
const SettingBlock: FC<SettingBlockProps> = (
|
||||||
{ title, description, children },
|
{ title, description, children },
|
||||||
) => (
|
) => (
|
||||||
<div className="space-y-3 rounded-xl border border-border/70 bg-background/70 p-4">
|
<div className="space-y-3 rounded-xl px-4">
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<h3 className="text-sm font-semibold">{title}</h3>
|
<h3 className="text-sm font-semibold">{title}</h3>
|
||||||
<p className="text-sm text-muted-foreground">{description}</p>
|
<p className="text-sm text-muted-foreground">{description}</p>
|
||||||
@@ -149,10 +149,6 @@ const BehaviourSettingsSection: FC<Props> = (
|
|||||||
<div className="flex flex-wrap items-start justify-between gap-3">
|
<div className="flex flex-wrap items-start justify-between gap-3">
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<h2 className="text-xl font-bold">動作</h2>
|
<h2 className="text-xl font-bold">動作</h2>
|
||||||
{hasUnsavedChanges && (
|
|
||||||
<p className="text-sm text-amber-700 dark:text-amber-300">
|
|
||||||
未保存の変更があります
|
|
||||||
</p>)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-wrap gap-2">
|
<div className="flex flex-wrap gap-2">
|
||||||
@@ -173,50 +169,33 @@ const BehaviourSettingsSection: FC<Props> = (
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
<SettingBlock
|
<SettingBlock title="アニメーション">
|
||||||
title="アニメーション"
|
|
||||||
description="画面遷移やレイアウト移動の動きを調整します。">
|
|
||||||
<SegmentedControl
|
<SegmentedControl
|
||||||
value={draftSettings.animation ?? 'normal'}
|
value={draftSettings.animation ?? 'normal'}
|
||||||
options={animationOptions}
|
options={animationOptions}
|
||||||
onChange={value => updateDraft ('animation', value)}/>
|
onChange={value => updateDraft ('animation', value)}/>
|
||||||
</SettingBlock>
|
</SettingBlock>
|
||||||
|
|
||||||
<SettingBlock
|
<SettingBlock title="リンク先の先読み">
|
||||||
title="リンク先の先読み"
|
|
||||||
description="リンクにマウスを置いた時などに、移動先の情報を先に読みます。通信量や意図しない読込みが気になる場合は「しない」にできます。">
|
|
||||||
<SegmentedControl
|
<SegmentedControl
|
||||||
value={draftSettings.linkPreload ?? 'intent'}
|
value={draftSettings.linkPreload ?? 'intent'}
|
||||||
options={linkPreloadOptions}
|
options={linkPreloadOptions}
|
||||||
onChange={value => updateDraft ('linkPreload', value)}/>
|
onChange={value => updateDraft ('linkPreload', value)}/>
|
||||||
</SettingBlock>
|
</SettingBlock>
|
||||||
|
|
||||||
<SettingBlock
|
<SettingBlock title="タグの親子関係表示">
|
||||||
title="タグの親子関係表示"
|
|
||||||
description="親子関係があるタグを、まとまりとして表示します。見た目を単純にしたい場合は「まとめない」にできます。">
|
|
||||||
<SegmentedControl
|
<SegmentedControl
|
||||||
value={draftSettings.tagRelationDisplay ?? 'grouped'}
|
value={draftSettings.tagRelationDisplay ?? 'grouped'}
|
||||||
options={tagRelationDisplayOptions}
|
options={tagRelationDisplayOptions}
|
||||||
onChange={value => updateDraft ('tagRelationDisplay', value)}/>
|
onChange={value => updateDraft ('tagRelationDisplay', value)}/>
|
||||||
</SettingBlock>
|
</SettingBlock>
|
||||||
|
|
||||||
<SettingBlock
|
<SettingBlock title="埋め込み自動読込">
|
||||||
title="埋め込み自動読込"
|
|
||||||
description="外部埋め込みを自動で読み込むかを切り替えます。">
|
|
||||||
<SegmentedControl
|
<SegmentedControl
|
||||||
value={draftSettings.embedAutoLoad ?? 'auto'}
|
value={draftSettings.embedAutoLoad ?? 'auto'}
|
||||||
options={embedAutoLoadOptions}
|
options={embedAutoLoadOptions}
|
||||||
onChange={value => updateDraft ('embedAutoLoad', value)}/>
|
onChange={value => updateDraft ('embedAutoLoad', value)}/>
|
||||||
</SettingBlock>
|
</SettingBlock>
|
||||||
|
|
||||||
<SettingBlock
|
|
||||||
title="サムネイル表示"
|
|
||||||
description="投稿一覧や詳細の画像表示を軽量化します。">
|
|
||||||
<SegmentedControl
|
|
||||||
value={draftSettings.thumbnailMode ?? 'normal'}
|
|
||||||
options={thumbnailModeOptions}
|
|
||||||
onChange={value => updateDraft ('thumbnailMode', value)}/>
|
|
||||||
</SettingBlock>
|
|
||||||
</div>
|
</div>
|
||||||
</section>)
|
</section>)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -147,10 +147,6 @@ const KeyboardSettingsSection: FC<Props> = (
|
|||||||
<div className="flex flex-wrap items-start justify-between gap-3">
|
<div className="flex flex-wrap items-start justify-between gap-3">
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<h2 className="text-xl font-bold">キーボード</h2>
|
<h2 className="text-xl font-bold">キーボード</h2>
|
||||||
{hasUnsavedChanges && (
|
|
||||||
<p className="text-sm text-amber-700 dark:text-amber-300">
|
|
||||||
未保存の変更があります
|
|
||||||
</p>)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-wrap gap-2">
|
<div className="flex flex-wrap gap-2">
|
||||||
@@ -206,8 +202,8 @@ const KeyboardSettingsSection: FC<Props> = (
|
|||||||
<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>
|
||||||
<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>
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ const themeSlotNoSelections: ThemeSegmentedOption<UserThemeSlotNo>[] = [
|
|||||||
{ value: 3, label: '3' } ]
|
{ value: 3, label: '3' } ]
|
||||||
|
|
||||||
const sectionClassName =
|
const sectionClassName =
|
||||||
'space-y-4 rounded-xl border border-border bg-background/80 p-4'
|
'space-y-4 rounded-xl p-4'
|
||||||
|
|
||||||
const themeSelections: ThemeSelectionItem[] = [
|
const themeSelections: ThemeSelectionItem[] = [
|
||||||
{ id: 'user:light:1', label: 'ライト 1', baseTheme: 'light', slotNo: 1 },
|
{ id: 'user:light:1', label: 'ライト 1', baseTheme: 'light', slotNo: 1 },
|
||||||
@@ -517,16 +517,6 @@ const ThemeSection: FC<ThemeSectionProps> = (
|
|||||||
<div className="flex flex-wrap items-start justify-between gap-3">
|
<div className="flex flex-wrap items-start justify-between gap-3">
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
<h2 className="text-xl font-bold">テーマ</h2>
|
<h2 className="text-xl font-bold">テーマ</h2>
|
||||||
<p className="text-sm text-muted-foreground">
|
|
||||||
現在表示中: {displayedThemeLabel}
|
|
||||||
</p>
|
|
||||||
{draftThemeMode === 'system' && (
|
|
||||||
<p className="text-sm text-muted-foreground">
|
|
||||||
システム設定: {systemThemeLabel}
|
|
||||||
</p>)}
|
|
||||||
<p className="text-sm text-muted-foreground">
|
|
||||||
保存先: {themeLabelBySelection (currentDisplayedThemeSlot)}
|
|
||||||
</p>
|
|
||||||
{hasUnsavedChanges && (
|
{hasUnsavedChanges && (
|
||||||
<p className="text-sm text-amber-700 dark:text-amber-300">
|
<p className="text-sm text-amber-700 dark:text-amber-300">
|
||||||
未保存の変更があります
|
未保存の変更があります
|
||||||
@@ -534,6 +524,13 @@ const ThemeSection: FC<ThemeSectionProps> = (
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-wrap gap-2">
|
<div className="flex flex-wrap gap-2">
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
variant="outline"
|
||||||
|
onClick={onResetThemeSlot}>
|
||||||
|
既定に戻す
|
||||||
|
</Button>
|
||||||
|
|
||||||
<Button
|
<Button
|
||||||
type="button"
|
type="button"
|
||||||
variant="destructive"
|
variant="destructive"
|
||||||
@@ -553,7 +550,7 @@ const ThemeSection: FC<ThemeSectionProps> = (
|
|||||||
<FieldError messages={settingsBaseErrors}/>
|
<FieldError messages={settingsBaseErrors}/>
|
||||||
<FieldError messages={settingsFieldErrors.theme ?? []}/>
|
<FieldError messages={settingsFieldErrors.theme ?? []}/>
|
||||||
|
|
||||||
<div className="space-y-3 rounded-xl border border-border/70 bg-background/70 p-4">
|
<div className="space-y-3 rounded-xl p-4">
|
||||||
<div className="flex flex-wrap items-center gap-x-4 gap-y-2">
|
<div className="flex flex-wrap items-center gap-x-4 gap-y-2">
|
||||||
<div className="shrink-0">
|
<div className="shrink-0">
|
||||||
<Label>表示モード</Label>
|
<Label>表示モード</Label>
|
||||||
@@ -567,14 +564,6 @@ const ThemeSection: FC<ThemeSectionProps> = (
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<div className="space-y-1">
|
|
||||||
<h3 className="text-sm font-semibold">テーマの使い分け</h3>
|
|
||||||
<p className="text-sm text-muted-foreground">
|
|
||||||
表示モードと使用テーマは,このブラウザにすぐ保存されます.
|
|
||||||
色の編輯だけが保存・破棄の対象です.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="grid gap-3 md:grid-cols-2">
|
<div className="grid gap-3 md:grid-cols-2">
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
<Label>ライト時</Label>
|
<Label>ライト時</Label>
|
||||||
@@ -588,9 +577,6 @@ const ThemeSection: FC<ThemeSectionProps> = (
|
|||||||
{`ライト ${ selection.value }`}
|
{`ライト ${ selection.value }`}
|
||||||
</option>))}
|
</option>))}
|
||||||
</select>
|
</select>
|
||||||
<p className="text-sm text-muted-foreground">
|
|
||||||
ライト表示の時に使うテーマを選びます.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-2">
|
<div className="space-y-2">
|
||||||
@@ -605,36 +591,16 @@ const ThemeSection: FC<ThemeSectionProps> = (
|
|||||||
{`ダーク ${ selection.value }`}
|
{`ダーク ${ selection.value }`}
|
||||||
</option>))}
|
</option>))}
|
||||||
</select>
|
</select>
|
||||||
<p className="text-sm text-muted-foreground">
|
|
||||||
ダーク表示の時に使うテーマを選びます.
|
|
||||||
</p>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="flex flex-wrap items-center gap-2">
|
|
||||||
<Button
|
|
||||||
type="button"
|
|
||||||
variant="outline"
|
|
||||||
onClick={onResetThemeSlot}>
|
|
||||||
既定に戻す
|
|
||||||
</Button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div style={themePreviewStyle (selectedTheme.tokens.tagColours)}>
|
|
||||||
<TagLink
|
|
||||||
tag={previewTags.general}
|
|
||||||
linkFlg={false}
|
|
||||||
truncateOnMobile
|
|
||||||
withWiki={false}/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
{themeTokenGroups.map (group => (
|
{themeTokenGroups.map (group => (
|
||||||
<div
|
<div
|
||||||
key={group.title}
|
key={group.title}
|
||||||
className="space-y-3 rounded-xl border border-border/70 bg-background/70 p-4">
|
className="space-y-3 rounded-xl p-4">
|
||||||
<h3 className="text-sm font-semibold">{group.title}</h3>
|
<h3 className="text-sm font-semibold">{group.title}</h3>
|
||||||
<div className="space-y-1">
|
<div className="space-y-1">
|
||||||
{group.fields.map (field => (
|
{group.fields.map (field => (
|
||||||
@@ -657,7 +623,7 @@ const ThemeSection: FC<ThemeSectionProps> = (
|
|||||||
</div>
|
</div>
|
||||||
</div>))}
|
</div>))}
|
||||||
|
|
||||||
<div className="space-y-3 rounded-xl border border-border/70 bg-background/70 p-4">
|
<div className="space-y-3 rounded-xl bg-background/70 p-4">
|
||||||
<div className="flex flex-wrap items-center justify-between gap-2">
|
<div className="flex flex-wrap items-center justify-between gap-2">
|
||||||
<div>
|
<div>
|
||||||
<h3 className="font-medium">タグ</h3>
|
<h3 className="font-medium">タグ</h3>
|
||||||
|
|||||||
新しい課題から参照
ユーザをブロックする