Skip to content

行のコントロールを「⋯」メニューに統一する #44 - #46

Merged
temoki merged 4 commits into
mainfrom
feature/44-if-header-width
Aug 11, 2026
Merged

行のコントロールを「⋯」メニューに統一する #44#46
temoki merged 4 commits into
mainfrom
feature/44-if-header-width

Conversation

@temoki

@temoki temoki commented Aug 10, 2026

Copy link
Copy Markdown
Owner

#44 の折り返し対応。決めてもらった 4 点(なら残す / 2 段ネストの折り返しは許容 / そうでなければ も同じ操作系へ / アイコンは ellipsis)で入れています。

入れたもの

  • 行の可視コントロールを ✕ → ⋯ に。中身は うえへ / したへ / けす、+その行が足すもの(もし の「そうでなければをついか」、そうでなければ 仕切りの「けす」)
  • 長押し(macOS の右クリック)は同じメニューを開いたまま
  • VoiceOver: ⋯ は行の読み上げから隠し、うえへ / したへ / けす / そうでなければ は名前つきアクションとして残す
  • ja 文字列 1 件(More → メニュー)

実測で分かった、報告と違う点 2 つ

1. issue に書いた列幅の変更(min 360 / ideal 400)は効きませんでした。

適用して測ったところ、ワークスペースの内容幅は 236–564pt → 236–566pt でほぼ不変。キャンバス列の ideal(420)が先に取るため、ワークスペースは min に落ちるだけでした。なので #23 の幅(300 / 360 / 440)はそのままにしています。

2. そもそも幅不足ではありませんでした。

スクリーンショットを見ると、折り返している「も/し」の右に 60pt の空白があってメニューボタンを待っている。HStack は柔軟な子(折り返せる Text、伸びる Spacer)に幅を同時に配るので、ラベルが Spacer に負けていただけです。

そこで:

  • BlockLabelStyle.layoutPriority(1) — ラベルが先に幅を取る
  • ただしそれだけだと被害が移るだけで、0.6 が「0.」「6」に割れました。チップは数値・名前・色という分割不可能なものなので、WorkspaceChipButtonStyle.fixedSize(horizontal: true, vertical: false)

結果、**行の圧縮順が「スペーサー → ラベル → チップは絶対に折らない」**に固定されます。ラベルに fixedSize ではなく priority を使ったのは、本当に幅が足りない 2 段ネストではブロックからはみ出すより折り返すほうがマシだからです(そこは許容と決めたとおり)。

確認

  • iPad Pro 13" ポートレート: 「もし [🌟 > 6] なら ⊕ ⋯」が 1 行(なら を残したまま)。2 段ネストの「はこにかける」はラベルのみ 2 行、チップは 1 行
  • macOS: ⋯ に余計なメニュー装飾(chevron 等)が出ないことを確認。両行とも 1 行
  • swift test 118 tests green / 両ビルド green / swift format lint --strict clean

補足

App/Views/CLAUDE.md に「行の可視コントロールはメニュー」「行の圧縮順」の 2 段落を追加しました。特に後者は、症状(折り返し)から素直に手を出す先(列幅)が外れであることが分かる形で残しています。

Fixes #44

temoki added 4 commits August 11, 2026 08:31
The ⋯ replaces the always-visible ✕ (#21) on every block row, and holds
うえへ / したへ / けす plus whatever the row adds — the if block's
そうでなければ, which used to be a button of its own on the header, and
the else divider's own "remove", so けす means the same thing wherever
it is found. Long-press still opens the same menu, so the macOS
right-click is unchanged.

Deleting had three ways in and this was the redundant one. Moving a row
had none a child would find: the menu it lived in only opens on
long-press, and nobody presses a block hoping for a hidden menu. A
visible ⋯ costs けす one tap and buys the reorder commands their first
real affordance — children press what looks pressable.

That is also 52pt of the widest row in the app back, which is where
#44 started: an if header nested one level deep broke onto two lines on
iPad, and a recursive block puts it there by construction.

The wrapping itself turned out not to be about width at all. Widening
the column changed nothing — measured, the content stayed at 236–564pt,
because the canvas column's own ideal outranks it — and the reason is
visible in the screenshot: 60pt of empty space sat beside the label,
waiting for the menu button. An HStack hands space to its flexible
children together, and a wrapping Text loses to a growing Spacer. So the
label takes layoutPriority(1), and the chips are pinned with fixedSize,
because serving the label first made 0.6 break as "0." over "6" instead.
A row now compresses in a fixed order: the spacer, then the label, never
a chip. Two levels deep with a long name the label still wraps, and that
is accepted — each level of nesting costs 18pt, and no column width wins
that race.

The column keeps #23's widths. なら / then stays: it reads as the block
was written, and the row fits with it.

Fixes #44
A `Menu` hit-tests what it was handed to draw, so `touchTarget()` wrapped
around the outside of one grows the layout and leaves the tappable area
the size of the glyph. Every `Button` on a row wore it that way and was
fine — a filled ✕ circle is a large shape by itself — and the ⋯ that
replaced them is three dots on a thin band, which is how it came out as
a control that misses taps.

Painting the target in and measuring it does not catch this: the 44pt
square is there either way, and only the touch is different.

The glyph also takes imageScale(.large). It is the one control on the
row now, so it can afford to be the one thing easiest to hit.
The ⑂ button carried a VoiceOver hint explaining what an "otherwise"
mouth is, and moving the action into the menu left the string with no
call site — Xcode marked it stale on the next build. What it explains is
still worth saying, so the menu entry carries it now.

Xcode goes on marking it stale even so, through a clean build and
whether the hint is written as a literal or as a Text; the string is
referenced, so the flag is bookkeeping rather than truth, and it is
cleared here by hand.
The ⋯ was enlarged along with the touch-target fix, on the theory that a
bigger shape would be easier to hit. The 44pt label turned out to be
enough on device, so the glyph goes back to the default: at `.large` the
dots sat heavier than the words beside them, and a control that is easy
to hit does not also need to be the loudest thing on the row.
@temoki
temoki merged commit 419d503 into main Aug 11, 2026
6 checks passed
@temoki
temoki deleted the feature/44-if-header-width branch August 11, 2026 00:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

iPad でコンテナ内の「もし」ヘッダが折り返す(ワークスペース列が狭い)

1 participant