diff --git a/src/components/code-view.tsx b/src/components/code-view.tsx index 88b2f4c..7447edb 100644 --- a/src/components/code-view.tsx +++ b/src/components/code-view.tsx @@ -658,6 +658,8 @@ export const PullDiffView: Component<{ roundLabel: string; storageKey: string; history: JSX.Element; + mobileDrawerOpen?: boolean; + onMobileDrawerClose?: () => void; }> = (props) => { const files = createMemo(() => parseDiffFiles(props.patch)); const stats = createMemo(() => totalDiffStats(files())); @@ -666,6 +668,26 @@ export const PullDiffView: Component<{ const [filesVisible, setFilesVisible] = createSignal(true); const [historyVisible, setHistoryVisible] = createSignal(true); + const [isDesktop, setIsDesktop] = createSignal(window.matchMedia('(min-width: 768px)').matches); + onMount(() => { + const media = window.matchMedia('(min-width: 768px)'); + const listener = (e: MediaQueryListEvent) => setIsDesktop(e.matches); + media.addEventListener('change', listener); + onCleanup(() => media.removeEventListener('change', listener)); + }); + + createEffect(() => { + if (!isDesktop() && props.mobileDrawerOpen) { + document.body.style.overflow = 'hidden'; + } else { + document.body.style.overflow = ''; + } + }); + + onCleanup(() => { + document.body.style.overflow = ''; + }); + const loadReviewed = (): Set => { try { const data = localStorage.getItem(props.storageKey); @@ -757,6 +779,15 @@ export const PullDiffView: Component<{ return (
+ {/* backdrop overlay - only visible on mobile when open */} +
props.onMobileDrawerClose?.()} + />
- +
diff --git a/src/index.css b/src/index.css index 7a9049d..cc03a7e 100644 --- a/src/index.css +++ b/src/index.css @@ -605,21 +605,99 @@ position: static; } - .untangled-pr-file-tree, + .untangled-pr-file-tree { + position: static; + max-height: none; + display: none; + } +} + +@media (min-width: 768px) and (max-width: 1023px) { .untangled-pr-history { position: static; max-height: none; } +} - .untangled-pr-file-tree { - display: none; +@media (max-width: 767px) { + .untangled-pr-history { + position: fixed; + top: auto; + bottom: 0; + left: 0; + right: 0; + z-index: 50; + width: 100%; + max-height: none; + overflow: visible; + padding: 0; + background: transparent; + border: none; + box-shadow: none; + transform: translateY(calc(100% - 3rem)); + transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1); + } + + .untangled-pr-history.open { + transform: none; + } + + .untangled-pr-history-body { + transform: translateY(4rem); + transition: transform 0.35s cubic-bezier(0.16, 1, 0.3, 1); } + .untangled-pr-history.open .untangled-pr-history-body { + transform: none; + } + + .untangled-pr-history details, + .untangled-pr-history details summary { + border-top-left-radius: 0.625rem !important; + border-top-right-radius: 0.625rem !important; + } + + /* Style the history card skeleton to be a collapsed header at the bottom on mobile */ + .untangled-pr-history-card { + border: none !important; + background: transparent !important; + } + + .untangled-pr-history-card .untangled-pr-history-submission, + .untangled-pr-history-card .px-4, + .untangled-pr-history-card .p-4, + .untangled-pr-history-card .untangled-pr-history-comment { + display: none !important; + } + + .untangled-pr-history-card > header { + background: rgb(229 231 235); + height: 3rem; + border-top-left-radius: 0.625rem !important; + border-top-right-radius: 0.625rem !important; + padding: 0 1rem; + border: 1px solid rgb(209 213 219); + border-bottom: none; + } +} + +@media (max-width: 767px) and (prefers-color-scheme: dark) { + .untangled-pr-history-card > header { + background: rgb(31 41 55); + border-color: rgb(55 65 81); + } +} + +summary::-webkit-details-marker { + display: none; +} +summary { + list-style: none; } @media (max-width: 767px) { .untangled-pr-summary-card { - padding: 1rem; + padding: 0.75rem; } .untangled-thread-meta { diff --git a/src/pages/repo/pulls.tsx b/src/pages/repo/pulls.tsx index af21a77..39f4580 100644 --- a/src/pages/repo/pulls.tsx +++ b/src/pages/repo/pulls.tsx @@ -3,6 +3,8 @@ import { ArrowLeftRight, CircleChevronUp, CirclePlus, + ChevronDown, + ChevronUp, Copy, Diff, Eye, @@ -1028,6 +1030,7 @@ export const PullPage: Component = () => { const [workingAction, setWorkingAction] = createSignal<'comment' | 'state' | 'merge' | null>(null); const working = createMemo(() => workingAction() !== null); const [error, setError] = createSignal(null); + const [mobileDrawerOpen, setMobileDrawerOpen] = createSignal(false); const pullQuery = createQuery(() => { const repo = repoQuery.data; @@ -1391,26 +1394,50 @@ export const PullPage: Component = () => { patch={patchQuery.data!} roundLabel={roundLabel()} storageKey={`reviewed:${repoQuery.data!.owner.handle}/${repoQuery.data!.slug}/pulls/${detail().pull.number || parseAtUri(detail().pull.uri).rkey}/round/${roundIndex()}`} + mobileDrawerOpen={mobileDrawerOpen()} + onMobileDrawerClose={() => setMobileDrawerOpen(false)} history={ -
- {/* History Header */} -
+ { + e.preventDefault(); + setMobileDrawerOpen(!mobileDrawerOpen()); + }} > -

history

- - {detail().pull.value.rounds.length} round{detail().pull.value.rounds.length === 1 ? '' : 's'} - ยท - {detail().comments.length} comment{detail().comments.length === 1 ? '' : 's'} +

history

+ + + {detail().pull.value.rounds.length} round{detail().pull.value.rounds.length === 1 ? '' : 's'} + + + + {detail().comments.length} comment{detail().comments.length === 1 ? '' : 's'} + + + }> + + + -
- - + +
+ {(round, index) => { const isSelected = () => index() === roundIndex(); const isLatest = () => index() === detail().pull.value.rounds.length - 1; @@ -1631,6 +1658,7 @@ export const PullPage: Component = () => { }}
+ } />