デザイン調整

This commit is contained in:
Xeltica 2022-01-27 21:12:58 +09:00
parent 7c833c3568
commit bc0eeb5461
12 changed files with 193 additions and 160 deletions

View File

@ -15,7 +15,7 @@ html
meta(name='twitter:site' content='@Xeltica') meta(name='twitter:site' content='@Xeltica')
meta(name='twitter:creator' content='@Xeltica') meta(name='twitter:creator' content='@Xeltica')
link(rel="stylesheet" href="https://koruri.chillout.chat/koruri.css") link(rel="stylesheet" href="https://koruri.chillout.chat/koruri.css")
link(rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css") link(rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.2/font/bootstrap-icons.css")
style. style.
.loading { .loading {
display: flex; display: flex;

View File

@ -59,7 +59,7 @@ const AppInner : React.VFC = () => {
</div> </div>
) : ( ) : (
<div className="container"> <div className="container">
{$location.pathname !== '/' && <Header hasTopLink />} {$location.pathname !== '/' && <Header hasTopLink className="xarticle mb-2" />}
<Switch> <Switch>
<Route exact path="/" component={IndexPage} /> <Route exact path="/" component={IndexPage} />
<Route exact path="/ranking" component={RankingPage} /> <Route exact path="/ranking" component={RankingPage} />

View File

@ -30,7 +30,8 @@ export const AccountsPage: React.VFC = () => {
<Skeleton /> <Skeleton />
</div> </div>
) : ( ) : (
<article className="fade"> <article className="card fade">
<div className="body">
<div> <div>
<strong>{t('_accounts.switchAccount')}</strong> <strong>{t('_accounts.switchAccount')}</strong>
</div> </div>
@ -56,6 +57,7 @@ export const AccountsPage: React.VFC = () => {
} }
</div> </div>
<LoginForm /> <LoginForm />
</div>
</article> </article>
); );
}; };

View File

@ -24,7 +24,7 @@ export const AnnouncementList: React.VFC = () => {
return ( return (
<> <>
<h2 className="mb-0">{t('announcements')}</h2> <h1 className="mb-0">{t('announcements')}</h1>
<div className="large menu fade"> <div className="large menu fade">
{announcements.map(a => ( {announcements.map(a => (
<Link className="item fluid" key={a.id} to={`/announcements/${a.id}`}> <Link className="item fluid" key={a.id} to={`/announcements/${a.id}`}>

View File

@ -0,0 +1,17 @@
.misshaiPageLayout {
display: flex;
flex-wrap: wrap;
gap: var(--margin);
> .misshaiData {
flex: 1 0 300px;
}
> .misshaiRanking {
flex: 5 0 300px;
}
> .alertModeSetting {
flex: 1 0 300px;
}
> .templateSetting {
flex: 5 0 300px;
}
}

View File

@ -10,10 +10,11 @@ import { $post, $put } from '../misc/api';
import { useGetScoreQuery, useGetSessionQuery } from '../services/session'; import { useGetScoreQuery, useGetSessionQuery } from '../services/session';
import { showModal } from '../store/slices/screen'; import { showModal } from '../store/slices/screen';
import { AnnouncementList } from './AnnouncementList'; import { AnnouncementList } from './AnnouncementList';
import { Card } from './Card';
import { Ranking } from './Ranking'; import { Ranking } from './Ranking';
import { Skeleton } from './Skeleton'; import { Skeleton } from './Skeleton';
import './MisshaiPage.scss';
const variables = [ const variables = [
'notesCount', 'notesCount',
'followingCount', 'followingCount',
@ -174,7 +175,7 @@ export const MisshaiPage: React.VFC = () => {
const defaultTemplate = t('_template.default'); const defaultTemplate = t('_template.default');
return session.isLoading || score.isLoading ? ( return session.isLoading || score.isLoading || !session.data || !score.data ? (
<div className="vstack"> <div className="vstack">
<Skeleton width="100%" height="1rem" /> <Skeleton width="100%" height="1rem" />
<Skeleton width="100%" height="1rem" /> <Skeleton width="100%" height="1rem" />
@ -182,23 +183,16 @@ export const MisshaiPage: React.VFC = () => {
<Skeleton width="100%" height="160px" /> <Skeleton width="100%" height="160px" />
</div> </div>
) : ( ) : (
<div className="fade vstack"> <div className="vstack">
{session.data && ( <section className="card announcement">
<section> <div className="body">
<p>{t('welcomeBack', {acct: `@${session.data.username}@${session.data.host}`})}</p>
<p>
<strong>
{t('_missHai.rating')}{': '}
</strong>
{session.data.rating}
</p>
</section>
)}
<AnnouncementList /> <AnnouncementList />
{score.data && ( </div>
<> </section>
<section> <div className="misshaiPageLayout">
<h2>{t('_missHai.data')}</h2> <section className="card misshaiData">
<div className="body">
<h1>{t('_missHai.data')}</h1>
<table className="table fluid"> <table className="table fluid">
<thead> <thead>
<tr> <tr>
@ -225,16 +219,27 @@ export const MisshaiPage: React.VFC = () => {
</tr> </tr>
</tbody> </tbody>
</table> </table>
<p>
<strong>
{t('_missHai.rating')}{': '}
</strong>
{session.data.rating}
</p>
</div>
</section> </section>
<section> <section className="card misshaiRanking">
<h2>{t('_missHai.ranking')}</h2> <div className="body">
<h1>{t('_missHai.ranking')}</h1>
<Ranking limit={limit} /> <Ranking limit={limit} />
{limit && <button className="btn link" onClick={() => setLimit(undefined)}>{t('_missHai.showAll')}</button>} {limit && <button className="btn link" onClick={() => setLimit(undefined)}>{t('_missHai.showAll')}</button>}
</div>
</section> </section>
<section className="vstack mt-2"> </div>
<Card bodyClassName="vstack"> <div className="misshaiPageLayout">
<h1>{t('alertMode')}</h1> <section className="card alertModeSetting">
<div> <div className="body">
<h1 className="mb-2">{t('alertMode')}</h1>
<div className="vstack">
{ {
alertModes.map((mode) => ( alertModes.map((mode) => (
<label key={mode} className="input-check"> <label key={mode} className="input-check">
@ -246,7 +251,6 @@ export const MisshaiPage: React.VFC = () => {
)) ))
} }
</div> </div>
{ draft.alertMode === 'notification' && ( { draft.alertMode === 'notification' && (
<div className="alert bg-danger mt-2"> <div className="alert bg-danger mt-2">
<i className="icon bi bi-exclamation-circle"></i> <i className="icon bi bi-exclamation-circle"></i>
@ -255,8 +259,8 @@ export const MisshaiPage: React.VFC = () => {
)} )}
{ draft.alertMode === 'note' && ( { draft.alertMode === 'note' && (
<> <>
<h2>{t('visibility')}</h2> <h2 className="mt-2 mb-1">{t('visibility')}</h2>
<div> <div className="vstack">
{ {
availableVisibilities.map((visibility) => ( availableVisibilities.map((visibility) => (
<label key={visibility} className="input-check"> <label key={visibility} className="input-check">
@ -276,11 +280,13 @@ export const MisshaiPage: React.VFC = () => {
</label> </label>
</> </>
)} )}
</Card> </div>
<Card bodyClassName="vstack"> </section>
<section className="card templateSetting">
<div className="body">
<h1>{t('template')}</h1> <h1>{t('template')}</h1>
<p>{t('_template.description')}</p> <p>{t('_template.description')}</p>
<div className="hstack dense"> <div className="hstack dense mb-2">
<button className="btn" onClick={onClickInsertVariables}> <button className="btn" onClick={onClickInsertVariables}>
<i className="bi bi-braces" />&nbsp; <i className="bi bi-braces" />&nbsp;
{t('_template.insertVariables')} {t('_template.insertVariables')}
@ -293,20 +299,24 @@ export const MisshaiPage: React.VFC = () => {
dispatchDraft({ template: e.target.value }); dispatchDraft({ template: e.target.value });
}} /> }} />
<small className="text-dimmed">{t('_template.description2')}</small> <small className="text-dimmed">{t('_template.description2')}</small>
<div className="hstack" style={{justifyContent: 'flex-end'}}> <div className="hstack mt-2" style={{justifyContent: 'flex-end'}}>
<button className="btn danger" onClick={() => dispatchDraft({ template: null })}>{t('resetToDefault')}</button> <button className="btn danger" onClick={() => dispatchDraft({ template: null })}>{t('resetToDefault')}</button>
<button className="btn primary" onClick={() => { <button className="btn primary" onClick={() => {
updateSettingWithDialog({ template: draft.template === '' ? null : draft.template }); updateSettingWithDialog({ template: draft.template === '' ? null : draft.template });
}}>{t('save')}</button> }}>{t('save')}</button>
</div> </div>
</Card> </div>
<Card bodyClassName="vstack"> </section>
<button className="btn block" onClick={onClickSendAlert} disabled={draft.alertMode === 'nothing'}>{t('sendAlert')}</button> </div>
<p className="text-dimmed">{t(draft.alertMode === 'nothing' ? 'sendAlertDisabled' : 'sendAlertDescription')}</p> <section className="list-form mt-2">
</Card> <button className="item" onClick={onClickSendAlert} disabled={draft.alertMode === 'nothing'}>
<i className="icon bi bi-send" />
<div className="body">
<h1>{t('sendAlert')}</h1>
<p className="desc">{t(draft.alertMode === 'nothing' ? 'sendAlertDisabled' : 'sendAlertDescription')}</p>
</div>
</button>
</section> </section>
</>
)}
</div> </div>
); );
}; };

View File

@ -1,11 +1,9 @@
import React, { ChangeEventHandler, useEffect, useRef, useState } from 'react'; import React, { ChangeEventHandler, useEffect, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';
import ReactCrop, { Crop } from 'react-image-crop'; import ReactCrop, { Crop } from 'react-image-crop';
import 'react-image-crop/dist/ReactCrop.css'; import 'react-image-crop/dist/ReactCrop.css';
export const NekomimiPage: React.VFC = () => { export const NekomimiPage: React.VFC = () => {
const {t} = useTranslation();
const [blobUrl, setBlobUrl] = useState<string | null>(null); const [blobUrl, setBlobUrl] = useState<string | null>(null);
const [image, setImage] = useState<HTMLImageElement | null>(null); const [image, setImage] = useState<HTMLImageElement | null>(null);
const [crop, setCrop] = useState<Partial<Crop>>({unit: '%', width: 100, aspect: 1 / 1}); const [crop, setCrop] = useState<Partial<Crop>>({unit: '%', width: 100, aspect: 1 / 1});

View File

@ -129,7 +129,7 @@ export const SettingPage: React.VFC = () => {
</div> </div>
</button> </button>
<button className="item text-danger" onClick={onClickDeleteAccount}> <button className="item text-danger" onClick={onClickDeleteAccount}>
<i className="icon bi bi-trash-fill" /> <i className="icon bi bi-trash" />
<div className="body"> <div className="body">
<h1>{t('deleteAccount')}</h1> <h1>{t('deleteAccount')}</h1>
<p className="desc">{t('deleteAccountDescription')}</p> <p className="desc">{t('deleteAccountDescription')}</p>

View File

@ -54,15 +54,17 @@
"title": "プロ仕様のツールキット", "title": "プロ仕様のツールキット",
"description": "Misskey Toolsでは、Misskeyのために設計された、Misskeyをより楽しめるツールを取り揃えています。", "description": "Misskey Toolsでは、Misskeyのために設計された、Misskeyをより楽しめるツールを取り揃えています。",
"misshaiAlertTitle": "ミス廃アラート", "misshaiAlertTitle": "ミス廃アラート",
"misshaiAlertDescription": "Misskeyにのめり込んでいませんかミス廃アラートを使えば、毎日のMisskeyでの活動量を以下のように定期投稿できます。", "misshaiAlertDescription": "Misskeyにのめり込んでいませんかミス廃アラートを使えば、毎日のMisskeyでの活動量を定期投稿できます。",
"misshaiRankingDescription": "ミス廃ランキングでは、Misskeyでの活動を数値化し、ランキング表示します。", "misshaiRankingDescription": "ミス廃ランキングでは、Misskeyでの活動を数値化し、ランキング表示します。",
"catAdjusterDescription": "CATモードの猫耳がアイコンに合わなくてお悩みのあなたへ。かわいいアイコンを猫耳に合わせてトリミングできます。",
"nextFeaturesTitle": "今後も追加予定。", "nextFeaturesTitle": "今後も追加予定。",
"nextFeaturesDescription": "これだけではありません。今後もアップデートで様々な機能を追加します!" "nextFeaturesDescription": "これだけではありません。今後もアップデートで様々な機能を追加します!"
}, },
"_nav": { "_nav": {
"misshai": "ミス廃", "misshai": "ミス廃",
"accounts": "アカウント", "accounts": "アカウント",
"settings": "設定" "settings": "設定",
"catAdjuster": "ねこみみ"
}, },
"_missHai": { "_missHai": {
"ranking": "ミス廃ランキング", "ranking": "ミス廃ランキング",
@ -157,5 +159,8 @@
"no": "キャンセル", "no": "キャンセル",
"success": "アカウントを解除しました。トップ画面に戻ります。", "success": "アカウントを解除しました。トップ画面に戻ります。",
"failure": "アカウントを解除できませんでした。" "failure": "アカウントを解除できませんでした。"
},
"_catAdjuster": {
"title": "ねこみみアジャスター"
} }
} }

View File

@ -14,8 +14,6 @@ import { useGetSessionQuery } from '../services/session';
import { AdminPage } from '../components/AdminPage'; import { AdminPage } from '../components/AdminPage';
import { $get } from '../misc/api'; import { $get } from '../misc/api';
import { NekomimiPage } from '../components/NekomimiPage'; import { NekomimiPage } from '../components/NekomimiPage';
import { CurrentUser } from '../components/CurrentUser';
import { Card } from '../components/Card';
export const IndexSessionPage: React.VFC = () => { export const IndexSessionPage: React.VFC = () => {
const [selectedTab, setSelectedTab] = useState<string>('misshai'); const [selectedTab, setSelectedTab] = useState<string>('misshai');
@ -59,7 +57,7 @@ export const IndexSessionPage: React.VFC = () => {
<Tab items={items} selected={selectedTab} onSelect={setSelectedTab}/> <Tab items={items} selected={selectedTab} onSelect={setSelectedTab}/>
</div> </div>
</div> </div>
<article className="xarticle mt-2"> <article className="xarticle mt-4">
{component} {component}
</article> </article>
</> </>

View File

@ -1,4 +1,4 @@
import React, { useMemo } from 'react'; import React from 'react';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
@ -8,49 +8,42 @@ import { AnnouncementList } from '../components/AnnouncementList';
export const IndexWelcomePage: React.VFC = () => { export const IndexWelcomePage: React.VFC = () => {
const {t} = useTranslation(); const {t} = useTranslation();
const example = useMemo(() => (
t('_template.default')
.replace('{notesCount}', '32000')
.replace('{notesDelta}', '+190')
.replace('{followingCount}', '510')
.replace('{followingDelta}', '+3')
.replace('{followersCount}', '1020')
.replace('{followersDelta}', '-1')
.replace('{url}', 'https://misskey.tools')
), []);
return ( return (
<> <>
<Header> <Header className="xarticle mb-4">
<article className="mt-4"> <article className="mt-4">
<p>{t('description1')}</p> <p>{t('description1')}</p>
<p>{t('description2')}</p> <p>{t('description2')}</p>
</article> </article>
<LoginForm /> <LoginForm />
</Header> </Header>
<article className="xarticle"> <article className="xarticle card">
<div className="body">
<AnnouncementList /> <AnnouncementList />
</div>
</article> </article>
<hr />
<article className="xarticle vstack pa-2"> <article className="xarticle vstack pa-2">
<header> <header>
<h2>{t('_welcome.title')}</h2> <h2>{t('_welcome.title')}</h2>
<p>{t('_welcome.description')}</p> <p>{t('_welcome.description')}</p>
</header> </header>
<article> <div className="row">
<h3>{t('_welcome.misshaiAlertTitle')}</h3> <article className="col-4 col-12-sm">
<h3><i className="bi bi-megaphone-fill"/> {t('_welcome.misshaiAlertTitle')}</h3>
<p>{t('_welcome.misshaiAlertDescription')}</p> <p>{t('_welcome.misshaiAlertDescription')}</p>
<div className="card ma-2 shadow-2" style={{maxWidth: 360}}>
<div className="body">
<pre>{example}</pre>
</div>
</div>
</article> </article>
<article> <article className="col-4 col-12-sm">
<h3 className="mb-1">{t('_missHai.ranking')}</h3> <h3><i className="bi bi-bar-chart-fill"/> {t('_missHai.ranking')}</h3>
<p>{t('_welcome.misshaiRankingDescription')}</p> <p>{t('_welcome.misshaiRankingDescription')}</p>
<Link to="/ranking">{t('_missHai.showRanking')}</Link> <Link to="/ranking">{t('_missHai.showRanking')}</Link>
</article> </article>
<article> <div className="col-4 col-12-sm">
<h3><i className="bi bi-crop"/> {t('_catAdjuster.title')}</h3>
<p>{t('_welcome.catAdjusterDescription')}</p>
</div>
</div>
<article className="mt-5">
<h3>{t('_welcome.nextFeaturesTitle')}</h3> <h3>{t('_welcome.nextFeaturesTitle')}</h3>
<p>{t('_welcome.nextFeaturesDescription')}</p> <p>{t('_welcome.nextFeaturesDescription')}</p>
</article> </article>

View File

@ -1,12 +1,22 @@
body { body {
--primary: rgb(134, 179, 0); --primary: rgb(134, 179, 0);
--max-width: 1024px;
font-family: "Koruri", sans-serif; font-family: "Koruri", sans-serif;
font-feature-settings: "pkna"; font-feature-settings: "pkna";
} }
hr {
height: 4px;
background: var(--dimmed);
border: none;
margin: 64px auto;
width: 50%;
max-width: 400px;
}
.xarticle { .xarticle {
margin: auto; margin: auto;
max-width: 1024px; max-width: var(--max-width);
} }
.fade { .fade {