From bbdedb30021ee50056edfbcf854814b4ee71ea4a Mon Sep 17 00:00:00 2001
From: Zach Shilton <4624598+zchsh@users.noreply.github.com>
Date: Tue, 8 Aug 2023 20:03:14 -0400
Subject: [PATCH] refactor: make it composable
---
packages/code-block/docs.mdx | 40 ++-
.../code-block/partials/code-lines/index.js | 271 ++++++++++--------
.../partials/code-lines/style.module.css | 170 +++++------
3 files changed, 264 insertions(+), 217 deletions(-)
diff --git a/packages/code-block/docs.mdx b/packages/code-block/docs.mdx
index 73676dd91..6fbf2b870 100644
--- a/packages/code-block/docs.mdx
+++ b/packages/code-block/docs.mdx
@@ -35,6 +35,8 @@ Longer lines of code may take up more space than the available content width. In
```
A line that goes on for a very long time so that it overflows the container in which it is located, which might be a pretty wide container.
This is a second line of code.
+And a third line.
+And another line, this is the fourth line.
```
````
@@ -42,14 +44,16 @@ This is a second line of code.
-
- {lineNumbers && !wrapCode ? (
+ // When the floating copy button is present, we add padding to many lines
+ const padRight = hasFloatingCopyButton
+
+ if (wrapCode) {
+ /**
+ * For wrapped code, we use a single-column flex layout.
+ * Lines of code are stacked in a single container, and each line row renders
+ * its own line number, which ensures that when lines wrap, the line numbers
+ * are aligned as expected
+ */
+ return (
+
+
+
+ {linesOfCode.map(({ number, children, highlight, dim }, idx) => (
+
+ {lineNumbers ? (
+
+ ) : null}
+
+ {children}
+ {'\n'}
+
+
+ ))}
+
+
+
+ )
+ } else {
+ /**
+ * For overflowing code, we use a two-column layout.
+ * The first column contains line numbers, and is effectively fixed.
+ * The second column contains the lines themselves, and is an overflow
+ * container to allow extra long lines to scroll as needed.
+ */
+ return (
+
+ {lineNumbers ? (
- {linesOfCode.map((_lineChildren, stableIdx) => {
- const number = stableIdx + 1
- const isHighlighted = highlightedLines.indexOf(number) !== -1
- const isNotHighlighted =
- highlightedLines.length > 0 && !isHighlighted
- return (
-
- )
- })}
+ {linesOfCode.map(({ number, highlight, dim }, idx) => (
+
+ ))}
) : null}
-
- {wrapCode ? (
-
- ) : null}
-
- {linesOfCode.map((lineChildren, stableIdx) => {
- const number = stableIdx + 1
- const isHighlighted = highlightedLines.indexOf(number) !== -1
- const isNotHighlighted = highlightedLines.length && !isHighlighted
- return (
- // This array is stable, so we can use index as key
- // eslint-disable-next-line react/no-array-index-key
-
- {lineNumbers && wrapCode ? (
-
- ) : null}
-
- {lineChildren}
- {'\n'}
-
-
- )
- })}
+
+
+ {linesOfCode.map(({ children, highlight, dim }, idx) => (
+
+ {children}
+ {'\n'}
+
+ ))}
- {wrapCode ? (
-
- ) : null}
+
+ )
+ }
+}
+
+/**
+ * Set up the `` + `` container
+ * which is necessary for language-specific syntax highlighting styles
+ */
+function PreCode({ children, language }) {
+ return (
+
+
+ {children}
)
}
-function LineSpacer({ lineCount, hasFloatingCopyButton }) {
+/**
+ * Provides "padding" at the top and bottom of a code block with wrapping lines
+ * while retaining the "numbers" and "lines" separation border.
+ *
+ * For context, with wrapped code, we don't have separate "numbers" and "lines"
+ * columns as we would with overflowing code. So, we can't add padding
+ * to those columns as we do with overflowing code.
+ *
+ * To create padding-equivalent space, while also rendering a continuous border
+ * between the "numbers" and "lines" columns, we use this component,
+ * which is essentially and empty line of code that's been shortened a bit.
+ */
+function WrappedLinesSpacer({ number, padRight }) {
return (
-
-
-
- {''}
- {'\n'}
-
+
+ {number ? : null}
+ {'\n'}
)
}
-function LineNumber({
- number,
- isHighlighted,
- isNotHighlighted,
- lineCount,
- wrapCode,
-}) {
- const padLevel = Math.max(lineCount.toString().length, 1)
- const paddedNumber = number.toString().padEnd(padLevel)
+/**
+ * Renders a line number.
+ *
+ * Note the `number` is rendered in monospace in a whitespace-sensitive way,
+ * so that if a padded string is passed, we can allow for table-like alignment
+ * of line numbers, and consistent horizontal width of numbers across all lines.
+ */
+function LineNumber({ number, highlight, dim, wrap }) {
return (
+ >
+ {number}
+
)
}
-function LineOfCode({
- children,
- isHighlighted,
- isNotHighlighted,
- hasFloatingCopyButton,
- wrapCode,
-}) {
+/**
+ * Renders a line of code
+ */
+function LineOfCode({ children, highlight, dim, padRight, wrap }) {
return (
{children}
diff --git a/packages/code-block/partials/code-lines/style.module.css b/packages/code-block/partials/code-lines/style.module.css
index 0b81a6526..a3611cc08 100644
--- a/packages/code-block/partials/code-lines/style.module.css
+++ b/packages/code-block/partials/code-lines/style.module.css
@@ -9,6 +9,12 @@ code-block/theme-(dark|light).module.css
to be present.
*/
+/*
+
+SHARED
+
+*/
+
pre.pre {
--code-padding: 16px;
--code-font-size: 0.84375rem; /* 13.5 px at default text size */
@@ -32,73 +38,6 @@ pre.pre {
overflow: hidden;
}
-.linesColumn {
- display: block;
- flex-grow: 1;
- padding: var(--code-padding) 0;
-
- /*
-
- Ran into weird issues in Safari with overflow here.
- Sometimes overflow-y appears... but toggling LITERALLY ANY
- CSS property in dev tools, ANYWHERE IN THE DOCUMENT,
- immediately resolves the issue 😳
-
- Should note as well this does NOT seem to be related to
- the custom scrollbar styles below... I've tried disabling them,
- but I still wind up with the same issue.
-
- TLDR;, would love if this could just be "overflow: auto;",
- but Safari-specific issues when macOS's "Always show scrollbars" pref is enabled
- means I have to set overflow-y to "hidden" to reduce the impact of the bug
- */
- overflow-x: auto;
- overflow-y: hidden;
-
- &.wrapCode {
- padding: 0;
- }
-}
-
-.styledScrollbars {
- /* web standard Firefox */
- scrollbar-width: thin;
- scrollbar-color: var(--scrollbar-foreground) transparent;
-
- /* webkit prefixed Safari, Chrome, chromium-based browsers */
- &::-webkit-scrollbar {
- width: 11px;
- height: 11px;
- }
- &::-webkit-scrollbar-track {
- background: transparent;
- }
- &::-webkit-scrollbar-thumb {
- background-color: var(--scrollbar-foreground);
- border-radius: 6px;
- border: 3px solid var(--scrollbar-background);
- }
-}
-
-.linesWrapper {
- display: flex;
- width: max-content;
- min-width: 100%;
- flex-direction: column;
- flex-shrink: 0;
-
- &.wrapCode {
- width: 100%;
- }
-}
-
-.numbersColumn {
- display: block;
- border-right: 1px solid var(--divider-line-color);
- flex-shrink: 0;
- padding: var(--code-padding) 0;
-}
-
.LineNumber {
composes: g-type-code from global;
display: block;
@@ -108,16 +47,16 @@ pre.pre {
padding: 0 var(--code-padding);
color: var(--text-color-faded);
- &.wrapCode {
+ &.wrap {
border-right: 1px solid var(--divider-line-color);
}
- &.isHighlighted {
+ &.highlight {
background: var(--background-highlighted-line);
color: var(--text-color-base);
}
- &.isNotHighlighted > * {
+ &.dim > * {
color: var(--text-color-faded);
}
}
@@ -133,23 +72,24 @@ pre.pre {
min-width: max-content;
white-space: pre;
- &.wrapCode {
+ &.wrap {
white-space: pre-wrap;
overflow-wrap: break-word;
min-width: 0;
+ width: 100%;
}
- &.hasFloatingCopyButton {
+ &.padRight {
/* Adds right padding so that the floating copy button
does not obscure content at the end of the line */
padding-right: 96px;
}
- &.isHighlighted {
+ &.highlight {
background: var(--background-highlighted-line);
}
- &.isNotHighlighted {
+ &.dim {
opacity: 0.7;
&,
@@ -164,25 +104,91 @@ pre.pre {
/*
-Additions to make code-wrap work as expected
+SCROLL OVERFLOW LAYOUT
-TODO: refactor this whole component so there's less conditional stuff going on.
+*/
+
+.numbersColumn {
+ display: block;
+ border-right: 1px solid var(--divider-line-color);
+ flex-shrink: 0;
+ padding: var(--code-padding) 0;
+}
+
+.linesColumn {
+ display: block;
+ flex-grow: 1;
+ padding: var(--code-padding) 0;
+
+ /*
+
+ Ran into weird issues in Safari with overflow here.
+ Sometimes overflow-y appears... but toggling LITERALLY ANY
+ CSS property in dev tools, ANYWHERE IN THE DOCUMENT,
+ immediately resolves the issue 😳
+
+ Should note as well this does NOT seem to be related to
+ the custom scrollbar styles below... I've tried disabling them,
+ but I still wind up with the same issue.
+
+ TLDR;, would love if this could just be "overflow: auto;",
+ but Safari-specific issues when macOS's "Always show scrollbars" pref is enabled
+ means I have to set overflow-y to "hidden" to reduce the impact of the bug
+ */
+ overflow-x: auto;
+ overflow-y: hidden;
+}
+
+.styledScrollbars {
+ /* web standard Firefox */
+ scrollbar-width: thin;
+ scrollbar-color: var(--scrollbar-foreground) transparent;
+
+ /* webkit prefixed Safari, Chrome, chromium-based browsers */
+ &::-webkit-scrollbar {
+ width: 11px;
+ height: 11px;
+ }
+ &::-webkit-scrollbar-track {
+ background: transparent;
+ }
+ &::-webkit-scrollbar-thumb {
+ background-color: var(--scrollbar-foreground);
+ border-radius: 6px;
+ border: 3px solid var(--scrollbar-background);
+ }
+}
+
+.linesScrollContainer {
+ display: flex;
+ width: max-content;
+ min-width: 100%;
+ flex-direction: column;
+ flex-shrink: 0;
+}
+
+/*
+
+WRAP LAYOUT
*/
-.lineWrapper {
+.wrappedLinesContainer {
+ display: flex;
+ width: 100%;
+ flex-direction: column;
+ flex-shrink: 0;
+}
+
+.wrappedLine {
display: flex;
flex-wrap: nowrap;
}
/* adds space at the top and bottom of the block,
while supporting a continuous border for line numbers */
-.linesSpacer {
+.wrappedLinesSpacer {
display: flex;
flex-wrap: nowrap;
height: var(--code-padding);
-
- &.wrapCode {
- display: flex;
- }
}