summaryrefslogtreecommitdiffhomepage
path: root/packages/web/src/components
diff options
context:
space:
mode:
authorJay V <[email protected]>2025-06-26 13:06:37 -0400
committerJay V <[email protected]>2025-06-26 13:06:41 -0400
commite6bfa95758d242e9ecb332f1e0e8fd3b8c5f83f9 (patch)
treea18130900073f51a476b3a68956ac9f04798c9c3 /packages/web/src/components
parente4120b628799288419fec9606604066011b649a4 (diff)
downloadopencode-e6bfa95758d242e9ecb332f1e0e8fd3b8c5f83f9.tar.gz
opencode-e6bfa95758d242e9ecb332f1e0e8fd3b8c5f83f9.zip
docs: share page responsive diff
Diffstat (limited to 'packages/web/src/components')
-rw-r--r--packages/web/src/components/DiffView.tsx191
-rw-r--r--packages/web/src/components/diffview.module.css33
-rw-r--r--packages/web/src/components/markdownview.module.css2
3 files changed, 139 insertions, 87 deletions
diff --git a/packages/web/src/components/DiffView.tsx b/packages/web/src/components/DiffView.tsx
index 237f25bdf..66dd7f0fc 100644
--- a/packages/web/src/components/DiffView.tsx
+++ b/packages/web/src/components/DiffView.tsx
@@ -54,8 +54,8 @@ const DiffView: Component<DiffViewProps> = (props) => {
// Pair removals with additions
const maxLength = Math.max(removals.length, additions.length)
for (let k = 0; k < maxLength; k++) {
- const hasLeft = !!removals[k]
- const hasRight = !!additions[k]
+ const hasLeft = k < removals.length
+ const hasRight = k < additions.length
if (hasLeft && hasRight) {
// Replacement - left is removed, right is added
@@ -71,8 +71,8 @@ const DiffView: Component<DiffViewProps> = (props) => {
right: "",
type: "removed"
})
- } else {
- // Pure addition
+ } else if (hasRight) {
+ // Pure addition - only create if we actually have content
diffRows.push({
left: "",
right: additions[k],
@@ -111,85 +111,136 @@ const DiffView: Component<DiffViewProps> = (props) => {
return diffRows
})
+ const mobileRows = createMemo(() => {
+ const mobileBlocks: { type: 'removed' | 'added' | 'unchanged', lines: string[] }[] = []
+ const currentRows = rows()
+
+ let i = 0
+ while (i < currentRows.length) {
+ const removedLines: string[] = []
+ const addedLines: string[] = []
+
+ // Collect consecutive modified/removed/added rows
+ while (i < currentRows.length &&
+ (currentRows[i].type === 'modified' ||
+ currentRows[i].type === 'removed' ||
+ currentRows[i].type === 'added')) {
+ const row = currentRows[i]
+ if (row.left && (row.type === 'removed' || row.type === 'modified')) {
+ removedLines.push(row.left)
+ }
+ if (row.right && (row.type === 'added' || row.type === 'modified')) {
+ addedLines.push(row.right)
+ }
+ i++
+ }
+
+ // Add grouped blocks
+ if (removedLines.length > 0) {
+ mobileBlocks.push({ type: 'removed', lines: removedLines })
+ }
+ if (addedLines.length > 0) {
+ mobileBlocks.push({ type: 'added', lines: addedLines })
+ }
+
+ // Add unchanged rows as-is
+ if (i < currentRows.length && currentRows[i].type === 'unchanged') {
+ mobileBlocks.push({
+ type: 'unchanged',
+ lines: [currentRows[i].left]
+ })
+ i++
+ }
+ }
+
+ return mobileBlocks
+ })
+
return (
<div class={`${styles.diff} ${props.class ?? ""}`}>
- {rows().map((r) => (
- <div class={styles.row}>
- <div class={styles.beforeColumn}>
- <CodeBlock
- code={r.left}
- lang={props.lang}
- data-section="cell"
- data-diff-type={r.type === "removed" || r.type === "modified" ? "removed" : ""}
- data-display-mobile={r.type === "added" && !r.left ? "false" : undefined}
- />
- {(r.type === "added" || r.type === "modified") && r.right !== undefined && (
+ <div class={styles.desktopView}>
+ {rows().map((r) => (
+ <div class={styles.row}>
+ <div class={styles.beforeColumn}>
+ <CodeBlock
+ code={r.left}
+ lang={props.lang}
+ data-section="cell"
+ data-diff-type={r.type === "removed" || r.type === "modified" ? "removed" : ""}
+ />
+ </div>
+ <div class={styles.afterColumn}>
<CodeBlock
code={r.right}
lang={props.lang}
data-section="cell"
- data-diff-type="added"
- data-display-mobile="true"
+ data-diff-type={r.type === "added" || r.type === "modified" ? "added" : ""}
/>
- )}
+ </div>
</div>
+ ))}
+ </div>
- <div class={styles.afterColumn}>
- <CodeBlock
- code={r.right}
- lang={props.lang}
- data-section="cell"
- data-diff-type={r.type === "added" || r.type === "modified" ? "added" : ""}
- />
+ <div class={styles.mobileView}>
+ {mobileRows().map((block) => (
+ <div class={styles.mobileBlock}>
+ {block.lines.map((line) => (
+ <CodeBlock
+ code={line}
+ lang={props.lang}
+ data-section="cell"
+ data-diff-type={block.type === 'removed' ? 'removed' :
+ block.type === 'added' ? 'added' : ''}
+ />
+ ))}
</div>
- </div>
- ))}
+ ))}
+ </div>
</div>
)
}
export default DiffView
-// String to test diff viewer with
-const testDiff = `--- combined_before.txt 2025-06-24 16:38:08
-+++ combined_after.txt 2025-06-24 16:38:12
-@@ -1,21 +1,25 @@
- unchanged line
--deleted line
--old content
-+added line
-+new content
-
--removed empty line below
-+added empty line above
-
-- tab indented
--trailing spaces
--very long line that will definitely wrap in most editors and cause potential alignment issues when displayed in a two column diff view
--unicode content: πŸš€ ✨ δΈ­ζ–‡
--mixed content with tabs and spaces
-+ space indented
-+no trailing spaces
-+short line
-+very long replacement line that will also wrap and test how the diff viewer handles long line additions after short line removals
-+different unicode: πŸŽ‰ πŸ’» ζ—₯本θͺž
-+normalized content with consistent spacing
-+newline to content
-
--content to remove
--whitespace only:
--multiple
--consecutive
--deletions
--single deletion
-+
-+single addition
-+first addition
-+second addition
-+third addition
- line before addition
-+first added line
-+
-+third added line
- line after addition
- final unchanged line`
+// const testDiff = `--- combined_before.txt 2025-06-24 16:38:08
+// +++ combined_after.txt 2025-06-24 16:38:12
+// @@ -1,21 +1,25 @@
+// unchanged line
+// -deleted line
+// -old content
+// +added line
+// +new content
+//
+// -removed empty line below
+// +added empty line above
+//
+// - tab indented
+// -trailing spaces
+// -very long line that will definitely wrap in most editors and cause potential alignment issues when displayed in a two column diff view
+// -unicode content: πŸš€ ✨ δΈ­ζ–‡
+// -mixed content with tabs and spaces
+// + space indented
+// +no trailing spaces
+// +short line
+// +very long replacement line that will also wrap and test how the diff viewer handles long line additions after short line removals
+// +different unicode: πŸŽ‰ πŸ’» ζ—₯本θͺž
+// +normalized content with consistent spacing
+// +newline to content
+//
+// -content to remove
+// -whitespace only:
+// -multiple
+// -consecutive
+// -deletions
+// -single deletion
+// +
+// +single addition
+// +first addition
+// +second addition
+// +third addition
+// line before addition
+// +first added line
+// +
+// +third added line
+// line after addition
+// final unchanged line`
diff --git a/packages/web/src/components/diffview.module.css b/packages/web/src/components/diffview.module.css
index b3f61ac02..a748c5d02 100644
--- a/packages/web/src/components/diffview.module.css
+++ b/packages/web/src/components/diffview.module.css
@@ -6,6 +6,19 @@
border-radius: 0.25rem;
}
+.desktopView {
+ display: block;
+}
+
+.mobileView {
+ display: none;
+}
+
+.mobileBlock {
+ display: flex;
+ flex-direction: column;
+}
+
.row {
display: grid;
grid-template-columns: 1fr 1fr;
@@ -98,25 +111,11 @@
}
@media (max-width: 40rem) {
- .row {
- grid-template-columns: 1fr;
- }
-
- .afterColumn {
+ .desktopView {
display: none;
}
- .beforeColumn {
- border-right: none;
- }
-
- [data-section="cell"] {
- &[data-display-mobile="true"] {
- display: flex;
- }
-
- &[data-display-mobile="false"] {
- display: none;
- }
+ .mobileView {
+ display: block;
}
}
diff --git a/packages/web/src/components/markdownview.module.css b/packages/web/src/components/markdownview.module.css
index 37a10dfa9..a4360bde9 100644
--- a/packages/web/src/components/markdownview.module.css
+++ b/packages/web/src/components/markdownview.module.css
@@ -30,6 +30,8 @@
h4,
h5,
h6 {
+ font-size: 0.875rem;
+ font-weight: 600;
margin-bottom: 0.5rem;
}