From 87f3f2402ab5f24693921b0b45019cc536b3c0f8 Mon Sep 17 00:00:00 2001 From: thepra Date: Tue, 6 Oct 2026 22:42:20 +0200 Subject: [PATCH] Controls are thumb-sized on touch screens, and labels wrap Under (pointer: coarse) only, so desktop keeps daisyUI's sizes: buttons, tabs, inputs and selects are 44px tall and icon buttons and tabs 44px wide; extra small buttons and the badges that act are 36px with a transparent ::after that gives them a 44px hit area, and the rows of reactions and hashtags leave 8px between them so those areas don't overlap. Checkboxes and radios are 24px, toggles 28, range thumbs 28, and a toggle's or checkbox's label at least 44px tall. At every width, the label of a checkbox, radio or toggle now wraps: daisyUI's .label never does, and long ones (Groups, the profile editor, Settings) ran past a phone's edge. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01LsXgEaXee4GCU1hwYgPJXw --- Components/Content.razor | 4 +-- Styles/touch.css | 77 ++++++++++++++++++++++++++++++++++++++-- 2 files changed, 77 insertions(+), 4 deletions(-) diff --git a/Components/Content.razor b/Components/Content.razor index a29dce8..079976b 100644 --- a/Components/Content.razor +++ b/Components/Content.razor @@ -182,7 +182,7 @@ @* the reactions stand outside the content warning: they are not what it hides *@ @if (status.EmojiReactions.Count > 0) { -
+
@foreach (var reaction in status.EmojiReactions) { 0) { -
+
@foreach (var tag in status.Tags) { diff --git a/Styles/touch.css b/Styles/touch.css index 8289264..56cd157 100644 --- a/Styles/touch.css +++ b/Styles/touch.css @@ -1,14 +1,87 @@ /* Touch screens. A phone's layout uses the width variants (max-md:, md:) at the call site; how big a thing is to a finger uses the - pointer: everything here sits under @media (pointer: coarse), so a mouse matches none of it and desktop keeps + pointer: the sizes here sit under @media (pointer: coarse), so a mouse matches none of them and desktop keeps daisyUI's sizes. The rules are plain CSS in Tailwind's utilities layer: like neo.css's @utility overrides they beat - daisyUI's rules, which sit in sublayers of it, and they set daisyUI's own size variables where it has one. */ + daisyUI's rules, which sit in sublayers of it, and they set daisyUI's own size variables where it has one. + + A target gets a 44px hit area (Apple's guideline, WCAG 2.5.5), which tests/e2e/Mobile measures. Buttons, tabs and + fields are 44px tall; the extra small buttons and the badges that act stay 36px to the eye and reach 44px through a + transparent ::after, so the rows that hold them leave 8px between them on touch (pointer-coarse:gap-2), or two hit + areas would overlap. */ @layer utilities { + /* At every width: a checkbox's, radio's or toggle's label wraps (daisyUI's .label never does, and a long one ran past + a phone's edge), and the control keeps its size beside it. */ + .label:has(> input[type=checkbox], > input[type=radio], > .toggle) { + white-space: normal; + text-align: start; + + & > input { + flex-shrink: 0; + } + } + @media (pointer: coarse) { /* Field text at 16px: iOS zooms into a focused field whose text is smaller, now that zooming is allowed. */ :where(.input, .select, .textarea) { --font-size-min: 1rem; } + + .btn:not(.btn-xs, .btn-lg, .btn-xl) { + --size: 2.75rem; + min-width: 2.75rem; + } + + .btn-sm { + --fontsize: .875rem; + } + + .btn-xs, + :is(button, a).badge { + --size: 2.25rem; + min-width: 2.25rem; + position: relative; + + &::after { + content: ""; + position: absolute; + inset: -4px; + } + } + + :is(button, a).badge { + padding-inline: .75rem; + } + + .tabs { + --tab-height: 2.75rem; + } + + .tab { + min-width: 2.75rem; + } + + .input:not(.input-lg, .input-xl), + .select:not(.select-lg, .select-xl) { + --size: 2.75rem; + } + + .checkbox, + .radio { + --size: 1.5rem; + } + + .toggle { + --size: 1.75rem; + } + + .range { + --range-thumb-size: 1.75rem; + } + + .collapse-title, + .label:has(> input[type=checkbox], > input[type=radio], > .toggle) { + min-height: 2.75rem; + } } }