Skip to content
Merged
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/design.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@
- Connectionsの基本、踏み台・転送・その他、表示とターミナル、最終的な値の各タブは、tablistと選択中tabpanelを同じ外枠へ入れます。tabpanelを内側へpaddingし、タブから離れた別ブロックに見せません。各tabの`aria-controls`とtabpanelの`aria-labelledby`を対にします。踏み台・転送・その他のタブは、踏み台・ポート転送・その他の設定を節に分けて1画面に並べ、タブの中にさらにタブを置きません。Hostブロックの文をそのまま編集する欄は、見出しの「…」の[テキストで編集]で開き、URLでは`advanced=raw`で表します。
- 主要操作は対象と動作を明確にし、説明や未設定状態よりも目立たせます。Homeは検索・必要なグループ・接続先を主役にし、未所属や未接続の繰り返しを省きます。PCではカードのクリックで選択、ダブルクリックで接続します。タッチは1タップ、キーボードはEnter/Spaceで接続します。Homeには常設Connectボタンと操作方法の案内文を置かず、開始中の表示とカードの操作メニューを残します。Connectionsの設定画面にはConnectボタンを置きます。
- フォーカスリングとチェック済みの印にも同じaccentを使います。ターミナルとコードエディタは各自のフォーカス/選択描画を維持します。フォーカスの枠は、`web/src/index.css`の決まりが付ける2pxのアウトライン(要素から2px離す)の1つの形だけです。ボタン・リンク・入力欄には決まりが自動で付けるので、部品の側でリングや枠線の色を重ねません。親がはみ出しを切っていて外側の枠が欠ける要素には`sshc-focus-inset`を付け、枠を内側に描きます。PCの大きさの画面で枠が欠ける部品は、全ページを巡回する`web/e2e/layout-audit.spec.ts`が`cut-focus-outline`として報告します。押せないボタンの不透明度も同じファイルの決まりが50%にそろえるので、部品の側に`disabled:opacity-*`を書きません(書いても効きません)。明暗それぞれで小さな文字・選択中の文字・主要ボタンの文字のコントラストを確認します。
- ページ・ペイン・ダイアログの中の節見出しは、14pxの太字(`text-sm font-semibold`)にそろえます。`PageSection`とSettingsの節がこの形で、ほかの場所は`web/src/ui/form.tsx`の`sectionHeading`を使います。ファイル名を見出しにする場所(プレビュー、比較、変更の確認)は中太のままです。
- 文字の大きさは、Tailwindの`text-xs`(12px)・`text-sm`(14px)・`text-base`(16px)・`text-lg`・`text-xl`・`text-2xl`と、`web/src/index.css`の`@theme`が足す`text-3xs`(10px、札やキーの印)・`text-2xs`(11px、小さなラベルとセッションの行の2行目)・`text-ui`(13px、入力欄・ボタン・エディタ)だけを使います。名前は14px、補助の文は12pxです。`text-[12.5px]`のような直書きと0.5px刻みは使いません(`web/src/ui/fontSize.test.ts`が検査します。丸い印の中の記号の8px以下は対象外です)。足した3つは行の高さを持たないので、行の高さは置く場所の`leading-*`で決めます。共有の入力欄(`control`)に`text-xs`などを重ねても、CSSの並び順で`text-ui`が勝つので効きません。
- 重なりの順番は、ページの中(上に貼り付く見出し、スマホの下のナビゲーション、引き出し、メニュー、ダイアログ)を`z-50`までの数で書きます。それより手前に出す層は`web/src/index.css`が名前を付けます。コマンドパレットは`z-palette`(70)、ダイアログを開いていても見せる知らせ・リンクの行き先・コマンドのカードは`z-above-dialog`(80)、エンジンに届かないときの画面は`z-fallback`(100)です。`z-[70]`のような直書きは`web/src/ui/layers.test.ts`が検査します。
- パレットの規則は `web/src/ui/palette.test.ts` で検査します。Tailwind のパレット名(`text-red-400` など)、任意値(`text-[#ff0000]`)、inline style の hex 値を走査し、違反箇所をファイル名と行番号付きで報告します。例外は `palette-exempt` を記載した行だけで、現在は native の色入力が独自の既定値を必要とする 2 行に使用しています。
Expand Down
2 changes: 1 addition & 1 deletion web/src/connections/OrphanPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export function OrphanPanel({ metadata, hosts, onSave }: OrphanPanelProps) {

return (
<section aria-labelledby="orphan-heading" className="flex flex-col gap-3 rounded-inset border border-notice-line bg-notice p-4">
<h3 id="orphan-heading" className="text-sm font-medium text-notice-ink">
<h3 id="orphan-heading" className="text-sm font-semibold text-notice-ink">
{t("orphan.heading")}
</h3>
<p className="text-xs text-ink-muted">{t("orphan.explain")}</p>
Expand Down
2 changes: 1 addition & 1 deletion web/src/connections/SavePreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export function SavePreviewPanel({
return (
<section aria-labelledby="preview-heading" className="flex flex-col gap-3 border-t border-line pt-5">
<div className="flex items-center justify-between gap-3">
<h3 id="preview-heading" className="text-sm font-medium text-ink">{t("preview.heading")}</h3>
<h3 id="preview-heading" className="text-sm font-semibold text-ink">{t("preview.heading")}</h3>
{preview === null ? null : (
<span className={tagClass("neutral")}>
{preview.diffs.length}
Expand Down
4 changes: 2 additions & 2 deletions web/src/snippets/SnippetRunSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export function SnippetRunSection({
</Button>
{preview === null ? null : (
<section className="mt-4 min-w-0 rounded-inset bg-notice p-4">
<h4 className="text-sm font-medium">{t("snippets.confirm")}</h4>
<h4 className="text-sm font-semibold">{t("snippets.confirm")}</h4>
{preview.targets.map((target) => (
<div key={target.targetId} className="mt-2">
<p className="text-xs font-medium">
Expand All @@ -81,7 +81,7 @@ export function SnippetRunSection({
{job === null ? null : (
<section className="mt-4 border-t border-line pt-4">
<div className="flex items-center">
<h4 className="grow text-sm font-medium">
<h4 className="grow text-sm font-semibold">
{t("snippets.results")} · {t(snippetStatusLabelKey(job.status))}
</h4>
{job.status === "running" ? (
Expand Down
2 changes: 1 addition & 1 deletion web/src/terminal/RunTargetConnectingPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export function RunTargetConnectingPanel({ alias, awaitingEngine, onUseThisMachi
<Spinner className="mt-0.5 size-[18px] shrink-0 text-ink-muted" />
<div className="flex min-w-0 grow flex-col gap-1">
<div role="status" className="flex min-w-0 flex-col gap-1">
<h2 className="break-words text-sm font-medium text-ink">{text.heading}</h2>
<h2 className="break-words text-sm font-semibold text-ink">{text.heading}</h2>
{text.detail === "" ? null : <p className="break-words text-sm leading-6 text-ink-muted">{text.detail}</p>}
</div>
{/* Outside the status: a screen reader would otherwise read it out every second. */}
Expand Down
2 changes: 1 addition & 1 deletion web/src/terminal/RunTargetRefusalPanel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ export function RunTargetRefusalPanel({
<Icon name={refusalIcon(refusal.code)} className="size-[18px]" />
</span>
<div className="flex min-w-0 flex-col gap-1">
<h2 id={headingId} className="break-words text-sm font-medium text-ink">{heading}</h2>
<h2 id={headingId} className="break-words text-sm font-semibold text-ink">{heading}</h2>
{reason === "" ? null : <p className="break-words text-sm leading-6 text-ink-muted">{reason}</p>}
</div>
</div>
Expand Down
4 changes: 2 additions & 2 deletions web/src/terminal/TerminalPortForwards.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ export function TerminalPortForwards({
{session.state === "reconnecting" ? <Notice>{t("terminal.forwardPausedReconnect")}</Notice> : null}

<section aria-labelledby="terminal-forward-active" className="flex flex-col gap-2">
<h3 id="terminal-forward-active" className="text-sm font-medium text-ink">{t("terminal.forwardActive")}</h3>
<h3 id="terminal-forward-active" className="text-sm font-semibold text-ink">{t("terminal.forwardActive")}</h3>
{forwards.length === 0 ? <p className={hintText}>{t("terminal.forwardNone")}</p> : (
<Card tone="subtle">
{forwards.map((forward) => (
Expand Down Expand Up @@ -160,7 +160,7 @@ export function TerminalPortForwards({
</section>

<section aria-labelledby="terminal-forward-new" className="flex flex-col gap-3 border-t border-line pt-4">
<h3 id="terminal-forward-new" className="text-sm font-medium text-ink">{t("terminal.forwardNew")}</h3>
<h3 id="terminal-forward-new" className="text-sm font-semibold text-ink">{t("terminal.forwardNew")}</h3>
<Notice>{t("conn.forwardLoopbackOnly")}</Notice>
<div className="grid gap-3 sm:grid-cols-2">
<Field label={t("conn.forwardType")}>
Expand Down
4 changes: 2 additions & 2 deletions web/src/terminal/commands/WorkspaceCommandCenter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ export function WorkspaceCommandCenter({
</div>
{prepared === null ? null : (
<section className="rounded-inset border border-notice-line bg-notice p-3">
<h3 className="text-sm font-medium">
<h3 className="text-sm font-semibold">
{t("workspace.previewHeading")}
</h3>
<div className="mt-2 grid max-h-48 gap-2 overflow-auto md:grid-cols-2">
Expand Down Expand Up @@ -349,7 +349,7 @@ export function WorkspaceCommandCenter({
)}
{dispatch === null ? null : (
<section className="rounded-lg border border-line bg-card p-3">
<h3 className="text-sm font-medium">
<h3 className="text-sm font-semibold">
{t("workspace.deliveryResults")}
</h3>
<p className="mt-1 text-xs text-ink-muted">
Expand Down
2 changes: 1 addition & 1 deletion web/src/terminal/splitView/SplitSessionPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export function SplitSessionPicker({ sessions, onSelect, onOpenNew, onClose }: {
const t = useTranslate();
return (
<ModalShell labelledBy="split-session-heading" onDismiss={onClose} panelClassName="flex w-full max-w-sm flex-col gap-3 p-4">
<h2 id="split-session-heading" className="text-sm font-medium text-ink">{t("splitView.chooseSession")}</h2>
<h2 id="split-session-heading" className="text-sm font-semibold text-ink">{t("splitView.chooseSession")}</h2>
<ul className="flex max-h-72 flex-col gap-1 overflow-y-auto">
{sessions.map((session) => (
<li key={session.id}><button type="button" className="w-full rounded-md px-2 py-2 text-left text-sm hover:bg-hover focus:bg-select-fill" onClick={() => onSelect(session.id)}>{terminalDisplayTitle(session)}</button></li>
Expand Down
4 changes: 3 additions & 1 deletion web/src/ui/form.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,9 @@ export const dialogHeading = "text-base font-semibold text-ink";

export const fieldLabel = "text-xs text-ink-muted";
export const hintText = "text-xs text-ink-muted";
export const sectionHeading = "text-sm font-medium text-ink";
// sectionHeading is the heading of a section inside a page, a pane or a dialog: as heavy as the headings of
// PageSection and the settings, so that every section of the application is headed alike.
export const sectionHeading = "text-sm font-semibold text-ink";

export const tableHeadRow =
"border-b border-line text-xs text-ink-faint";
Expand Down
Loading