diff --git a/frontend/src/v2/components/V2PodBoard.tsx b/frontend/src/v2/components/V2PodBoard.tsx index 2fe39706a..03230e452 100644 --- a/frontend/src/v2/components/V2PodBoard.tsx +++ b/frontend/src/v2/components/V2PodBoard.tsx @@ -35,6 +35,7 @@ const FILTERS: Array<{ key: BoardFilter; labelKey: string }> = [ { key: 'p0', labelKey: 'board.filter.p0' }, { key: 'unclaimed', labelKey: 'board.filter.unclaimed' }, ]; +const PHONE_MEDIA_QUERY = '(max-width: 760px)'; const DONE_STATUSES = ['done', 'completed', 'complete']; interface BoardTask { @@ -635,6 +636,18 @@ const V2PodBoard: React.FC = () => { } }, [api, podId, newTitle, newAssignee, newPriority, creating, load, t]); + // The frame puts the filter chips under the tabs on a phone, so they render in one place or the other. + const [isPhone, setIsPhone] = useState( + () => typeof window !== 'undefined' && !!window.matchMedia?.(PHONE_MEDIA_QUERY)?.matches, + ); + useEffect(() => { + const query = window.matchMedia?.(PHONE_MEDIA_QUERY); + if (!query) return undefined; + const onChange = () => setIsPhone(query.matches); + onChange(); + query.addEventListener?.('change', onChange); + return () => query.removeEventListener?.('change', onChange); + }, []); const [filters, setFilters] = useState([]); const [searchOpen, setSearchOpen] = useState(false); const [query, setQuery] = useState(''); @@ -665,6 +678,22 @@ const V2PodBoard: React.FC = () => { return byColumn; }, [visibleTasks]); + const filterChips = ( +
+ {FILTERS.map((f) => ( + + ))} +
+ ); + return (
@@ -682,19 +711,7 @@ const V2PodBoard: React.FC = () => { {t('board.taskCount', { count: tasks.length })}
-
- {FILTERS.map((f) => ( - - ))} -
+ {!isPhone && filterChips} {searchOpen && ( { ))} + {isPhone && filterChips}
{COLUMNS.map((col) => { const items = columnTasks.get(col.key) || []; diff --git a/frontend/src/v2/v2.css b/frontend/src/v2/v2.css index cf50510b4..3764badee 100644 --- a/frontend/src/v2/v2.css +++ b/frontend/src/v2/v2.css @@ -14065,6 +14065,7 @@ details[open] > .v2-settings__summary > .v2-settings__icon:last-child { transfor .v2-board__focus[open] .v2-board__focus-chevron { transform: rotate(180deg); } .v2-board__focus[open] > :not(summary) { margin-left: 12px; margin-right: 12px; } .v2-board__focus[open] { max-height: 40vh; overflow-y: auto; } +.v2-board__focus:not([open]) > :not(summary) { display: none; } .v2-board__tabs { display: none; } .v2-board__columns { @@ -14128,16 +14129,16 @@ details[open] > .v2-settings__summary > .v2-settings__icon:last-child { transfor } @media (max-width: 760px) { - .v2-board__head { padding: 8px 12px; min-height: 52px; gap: 6px; flex-wrap: wrap; } + .v2-board__head { padding: 8px 12px; min-height: 52px; gap: 6px; flex-wrap: nowrap; row-gap: 0; } .v2-board__back-label, .v2-board__subtitle { display: none; } .v2-board__head > .v2-board__back { order: 1; } - .v2-board__title-wrap { order: 2; } + .v2-board__title-wrap { order: 2; flex: 1 1 0; min-width: 0; } .v2-board__head > .v2-board__icon-btn { order: 3; } - .v2-board__search { order: 3; } - .v2-board__head > .v2-board__new { order: 4; } - .v2-board__filters { order: 5; width: 100%; padding-bottom: 6px; } - .v2-board__focus { margin: 10px 12px 0; } - .v2-board__focus-strip .v2-board__focus-eyebrow { display: none; } + .v2-board__search { order: 3; flex: 1 1 0; min-width: 0; width: auto; } + .v2-board__head > .v2-board__new { order: 4; margin-left: 0; } + .v2-board__filters { padding: 8px 12px 0; } + /* The frame's phone board has no focus strip; the goal lives on desktop. */ + .v2-board__focus { display: none; } .v2-board__new-label { display: none; } .v2-board__tabs { display: flex; gap: 4px; padding: 8px 12px 0; overflow-x: auto; } .v2-root button.v2-board__tab { @@ -14158,6 +14159,8 @@ details[open] > .v2-settings__summary > .v2-settings__icon:last-child { transfor } .v2-root button.v2-board__card-main, .v2-root button.v2-board__card-main:hover { background: none; } +/* The card already pads itself; a second 12px on the button doubled the frame's card height (85px vs ~57px). */ +.v2-root button.v2-board__card-main { padding: 0; } /* The action bar sits on the id row, so it never covers the title; the owner line yields to it. */ .v2-board__card:hover .v2-board__owner-line, .v2-board__card:focus-within .v2-board__owner-line { visibility: hidden; } .v2-root button.v2-board__card-main:focus-visible, .v2-root button.v2-board__card-move:focus-visible {