Skip to content

Commit

Permalink
Fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
lex111 committed Apr 16, 2022
1 parent 6d57368 commit 97e6922
Show file tree
Hide file tree
Showing 7 changed files with 95 additions and 58 deletions.
10 changes: 10 additions & 0 deletions packages/docusaurus-theme-classic/src/theme-classic.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,16 @@ declare module '@theme/CodeBlock/Line' {
export default function CodeBlockLine(props: Props): JSX.Element;
}

declare module '@theme/CodeBlock/WordWrapButton' {
export interface Props {
readonly className?: string;
readonly onClick: React.MouseEventHandler;
readonly isEnabled: boolean;
}

export default function WordWrapButton(props: Props): JSX.Element;
}

declare module '@theme/DocCard' {
import type {PropSidebarItem} from '@docusaurus/plugin-content-docs';

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,21 @@
* LICENSE file in the root directory of this source tree.
*/

import React from 'react';
import React, {useRef} from 'react';
import {
useThemeConfig,
parseCodeBlockTitle,
parseLanguage,
parseLines,
containsLineNumbers,
usePrismTheme,
useCodeWordWrap,
} from '@docusaurus/theme-common';
import clsx from 'clsx';
import Highlight, {defaultProps, type Language} from 'prism-react-renderer';
import Line from '@theme/CodeBlock/Line';
import CopyButton from '@theme/CodeBlock/CopyButton';
import WordWrapButton from '@theme/CodeBlock/WordWrapButton';
import Container from '@theme/CodeBlock/Container';
import type {Props} from '@theme/CodeBlock/Content/String';

Expand All @@ -37,6 +39,8 @@ export default function CodeBlockString({
const language =
languageProp ?? parseLanguage(blockClassName) ?? defaultLanguage;
const prismTheme = usePrismTheme();
const codeBlockRef = useRef<HTMLPreElement>(null);
const wordWrap = useCodeWordWrap(codeBlockRef);

// We still parse the metastring in case we want to support more syntax in the
// future. Note that MDX doesn't strip quotes when parsing metastring:
Expand Down Expand Up @@ -67,6 +71,7 @@ export default function CodeBlockString({
<pre
/* eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex */
tabIndex={0}
ref={codeBlockRef}
className={clsx(className, styles.codeBlock, 'thin-scrollbar')}>
<code
className={clsx(
Expand All @@ -87,7 +92,16 @@ export default function CodeBlockString({
</pre>
)}
</Highlight>
<CopyButton code={code} />
<div className={styles.buttonGroup}>
{(wordWrap.isEnabled || wordWrap.isCodeScrollable) && (
<WordWrapButton
className={styles.codeButton}
onClick={() => wordWrap.toggle()}
isEnabled={wordWrap.isEnabled}
/>
)}
<CopyButton className={styles.codeButton} code={code} />
</div>
</div>
</Container>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,28 +55,35 @@
}
}

.codeButton {
--docusaurus-code-button-size: 2rem;
.buttonGroup {
display: flex;
position: absolute;
right: calc(var(--ifm-pre-padding) / 2);
top: calc(var(--ifm-pre-padding) / 2);
width: var(--docusaurus-code-button-size);
height: var(--docusaurus-code-button-size);
}

.buttonGroup button {
display: flex;
justify-content: center;
align-items: center;
background: inherit;
background: var(--prism-background-color);
color: var(--prism-color);
border: 1px solid var(--ifm-color-emphasis-300);
border-radius: var(--ifm-global-radius);
padding: 0.4rem;
line-height: 0;
transition: opacity 200ms ease-in-out;
opacity: 0;
}

.codeButton:focus-visible,
.codeButton:hover {
.buttonGroup button:not(:first-child) {
margin-left: 0.5rem;
}

.buttonGroup button:focus-visible,
.buttonGroup button:hover {
opacity: 1 !important;
}

:global(.theme-code-block:hover) .codeButton {
:global(.theme-code-block:hover) .buttonGroup button {
opacity: 0.4;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,6 @@
* LICENSE file in the root directory of this source tree.
*/

.copyButton {
display: flex;
/* TODO: move to base button styling */
background: var(--prism-background-color);
color: var(--prism-color);
border: 1px solid var(--ifm-color-emphasis-300);
border-radius: var(--ifm-global-radius);
padding: 0.4rem;
position: absolute;
right: calc(var(--ifm-pre-padding) / 2);
top: calc(var(--ifm-pre-padding) / 2);
transition: opacity 200ms ease-in-out;
opacity: 0;
}

.copyButton:focus-visible,
.copyButton:hover,
:global(.theme-code-block:hover) .copyButtonCopied {
opacity: 1 !important;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,55 +5,29 @@
* LICENSE file in the root directory of this source tree.
*/

import React, {useCallback, useState, useEffect} from 'react';
import React from 'react';
import clsx from 'clsx';
import {translate} from '@docusaurus/Translate';
import type {Props} from '@theme/CodeBlock/WordWrapButton';

import styles from './styles.module.css';

export default function WordWrapButton({
codeBlockRef,
className,
onClick,
isEnabled,
}: Props): JSX.Element | null {
const [isEnabled, setIsEnabled] = useState(false);
const [isCodeScrollable, setIsCodeScrollable] = useState<boolean>(false);
const toggleWordWrapCode = useCallback(() => {
setIsEnabled((value) => !value);

const codeElement = codeBlockRef.current!.querySelector('code');
codeElement?.classList.toggle(styles.codeWithWordWrap!);
}, [codeBlockRef]);
const updateCodeIsScrollable = useCallback(() => {
const {scrollWidth, clientWidth} = codeBlockRef.current!;
setIsCodeScrollable(scrollWidth > clientWidth);
}, [codeBlockRef]);
const title = translate({
id: 'theme.CodeBlock.wordWrapToggle',
message: 'Toggle word wrap',
description:
'The title attribute for toggle word wrapping button of code block lines',
});

useEffect(() => {
updateCodeIsScrollable();

window.addEventListener('resize', updateCodeIsScrollable);

return () => {
window.removeEventListener('resize', updateCodeIsScrollable);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

if (!isCodeScrollable) {
return null;
}

return (
<button
type="button"
onClick={toggleWordWrapCode}
onClick={onClick}
className={clsx(
'clean-btn',
className,
Expand Down
48 changes: 48 additions & 0 deletions packages/docusaurus-theme-common/src/hooks/useCodeWordWrap.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

import {useState, useCallback, useEffect} from 'react';

export function useCodeWordWrap(codeBlockRef: React.RefObject<HTMLPreElement>) {
const [isEnabled, setIsEnabled] = useState(false);
const [isCodeScrollable, setIsCodeScrollable] = useState<boolean>(false);

const toggle = useCallback(() => {
const codeElement = codeBlockRef.current!.querySelector('code')!;

if (isEnabled) {
codeElement.removeAttribute('style');
} else {
codeElement.style.whiteSpace = 'pre-wrap';
}

setIsEnabled((value) => !value);
}, [codeBlockRef, isEnabled]);

const updateCodeIsScrollable = useCallback(() => {
const {scrollWidth, clientWidth} = codeBlockRef.current!;
const isScrollable =
scrollWidth > clientWidth ||
codeBlockRef.current!.querySelector('code')!.hasAttribute('style');
setIsCodeScrollable(isScrollable);
}, [codeBlockRef]);

useEffect(() => {
updateCodeIsScrollable();

window.addEventListener('resize', updateCodeIsScrollable, {
passive: true,
});

return () => {
window.removeEventListener('resize', updateCodeIsScrollable);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return {isEnabled, isCodeScrollable, toggle};
}
1 change: 1 addition & 0 deletions packages/docusaurus-theme-common/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,3 +158,4 @@ export {usePrismTheme} from './hooks/usePrismTheme';
export {useLockBodyScroll} from './hooks/useLockBodyScroll';
export {useWindowSize} from './hooks/useWindowSize';
export {useSearchPage} from './hooks/useSearchPage';
export {useCodeWordWrap} from './hooks/useCodeWordWrap';

0 comments on commit 97e6922

Please sign in to comment.