Skip to content

Commit

Permalink
feat: improve Code Block
Browse files Browse the repository at this point in the history
- add `nowrap` and `overflow` modifiers to `nl-code-block` CSS
- add `overflow` property to `CodeBlock` in React
- update Code Block stories for overflow
- update Code Block tests
- add changeset
  • Loading branch information
Robbert authored and matijs committed Dec 18, 2024
1 parent 385fc70 commit d2d520f
Show file tree
Hide file tree
Showing 8 changed files with 232 additions and 71 deletions.
8 changes: 8 additions & 0 deletions .changeset/lucky-apricots-accept.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@nl-design-system-candidate/code-block-react': minor
---

Add `overflow` property to `CodeBlock`, with new options:

- `overflow="nowrap"`: fit content, even for very long lines.
- `overflow="overflow"`: provide scrollbars to see very long lines.
8 changes: 8 additions & 0 deletions .changeset/strong-pants-train.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
'@nl-design-system-candidate/code-block-css': minor
---

Add new class names and mixins:

- `nl-code-block--nowrap`: fit content, even for very long lines.
- `nl-code-block--overflow`: provide scrollbars to see very long lines.
14 changes: 11 additions & 3 deletions packages/components-css/code-block-css/src/_mixin.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,26 @@
display: block;
font-family: var(--nl-code-block-font-family, monospace), monospace;
font-size: var(--nl-code-block-font-size);
hyphens: none;
line-height: var(--nl-code-block-line-height);
padding-block: var(--nl-code-block-padding-block);
padding-inline: var(--nl-code-block-padding-inline);
white-space: pre-wrap;
}

@mixin nl-code-block--nowrap {
inline-size: fit-content;
white-space: pre;
}

@mixin nl-code-block--overflow {
/* stylelint-disable order/properties-alphabetical-order */

/* `overflow-inline` must come after `overflow-x` */
overflow-x: auto;
overflow-inline: auto;

/* stylelint-enable order/properties-alphabetical-order */

padding-block: var(--nl-code-block-padding-block);
padding-inline: var(--nl-code-block-padding-inline);
white-space: pre;
}

Expand Down
8 changes: 8 additions & 0 deletions packages/components-css/code-block-css/src/code-block.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@
@include mixin.nl-code-block;
}

.nl-code-block--nowrap {
@include mixin.nl-code-block--nowrap;
}

.nl-code-block--overflow {
@include mixin.nl-code-block--overflow;
}

.nl-code-block__code {
@include mixin.nl-code-block__code;
}
18 changes: 15 additions & 3 deletions packages/components-react/code-block-react/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,21 @@ Blok met 1 of meerdere regels computercode.

## Features

- Semantisch HTML: een `pre` en een `code` element, [zoals de HTML-specificatie voorschrijft bij het `pre` element](https://html.spec.whatwg.org/multipage/grouping-content.html#the-pre-element).
- De tekstrichting van de code is links-naar-rechts ingesteld met het [HTML `dir` attribuut](https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute), ook in documenten waar de tekstrichting rechts-naar-links is.
- De code is gemarkeerd als niet-vertaalbaar met het [HTML `translate` attribuut](https://html.spec.whatwg.org/multipage/dom.html#the-translate-attribute) voor automatische vertaalsoftware.
- Semantisch HTML: een `pre` en een `code` element,
[zoals de HTML-specificatie voorschrijft bij het `pre` element](https://html.spec.whatwg.org/multipage/grouping-content.html#the-pre-element).
- De tekstrichting van de code is links-naar-rechts ingesteld met het
[HTML `dir` attribuut](https://html.spec.whatwg.org/multipage/dom.html#the-dir-attribute), ook in documenten waar de
tekstrichting rechts-naar-links is.
- De code is gemarkeerd als niet-vertaalbaar met het
[HTML `translate` attribuut](https://html.spec.whatwg.org/multipage/dom.html#the-translate-attribute) voor
automatische vertaalsoftware.
- Met de `overflow` property kan het overflow gedrag worden bepaald:
- `overflow="wrap"`: de component wordt zonder `tabindex` attribuut gerenderd en tekst wrapt automatisch. Dit is de
default, ook als de prop niet expliciet gezet is.
- `overflow="nowrap"`: de component wordt zonder `tabindex` attribuut gerenderd, je moet dit zelf in combinatie met
scroll gedrag op een parent element doen.
- `overflow="overflow"`: de component wordt altijd mét een `tabindex="0"` attribuut gerenderd en heeft ingebouwd scroll
gedrag.
- Het visueel ontwerp is door een monospace lettertype goed te onderscheiden van gewone tekst.
- Het visueel ontwerp blijft onderscheidend wanneer:
- wanneer de CSS niet geladen kan worden;
Expand Down
39 changes: 39 additions & 0 deletions packages/components-react/code-block-react/src/code-block.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,45 @@ describe('Code Block', () => {
expect(codeBlock).toHaveClass('nl-code-block', extraClassName);
});

it('renders an element with class names "nl-code-block" and "nl-code-block--overflow" when told to overflow', () => {
const { container } = render(<CodeBlock overflow="overflow">{testCode}</CodeBlock>);
const codeBlock = container.querySelector('pre:only-child');

expect(codeBlock).toHaveClass('nl-code-block', 'nl-code-block--overflow');
});

it('renders an element with class names "nl-code-block" and "nl-code-block--nowrap" when told not to wrap', () => {
const { container } = render(<CodeBlock overflow="nowrap">{testCode}</CodeBlock>);
const codeBlock = container.querySelector('pre:only-child');

expect(codeBlock).toHaveClass('nl-code-block', 'nl-code-block--nowrap');
});

it('renders an element with `tabindex="0" when passed `overflow="overflow"`', () => {
const { container } = render(<CodeBlock overflow="overflow">{testCode}</CodeBlock>);
const codeBlock = container.querySelector('pre:only-child');

expect(codeBlock).toHaveAttribute('tabindex', '0');
});

it('allows the tabindex to be overriden even when told to overflow', () => {
const { container } = render(
<CodeBlock overflow="overflow" tabIndex={undefined}>
{testCode}
</CodeBlock>,
);
const codeBlock = container.querySelector('pre:only-child');

expect(codeBlock).not.toHaveAttribute('tabindex');
});

it('renders an element with only class name "nl-code-block" when told to wrap and when no extra class name is passed', () => {
const { container } = render(<CodeBlock overflow="wrap">{testCode}</CodeBlock>);
const codeBlock = container.querySelector('pre:only-child');

expect(codeBlock).toHaveClass('nl-code-block', { exact: true });
});

it('renders an HTML pre element that contains an HTML code element', () => {
const { container } = render(<CodeBlock>{testCode}</CodeBlock>);
const codeBlock = container.querySelector('pre:only-child');
Expand Down
23 changes: 20 additions & 3 deletions packages/components-react/code-block-react/src/code-block.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,30 @@ import type { HTMLAttributes } from 'react';
import { clsx } from 'clsx';
import { forwardRef } from 'react';

export type CodeBlockProps = HTMLAttributes<HTMLPreElement>;
export interface CodeBlockProps extends HTMLAttributes<HTMLPreElement> {
overflow?: 'wrap' | 'nowrap' | 'overflow';
}

export const CodeBlock = forwardRef<HTMLPreElement, CodeBlockProps>(function CodeBlock(props, forwardedRef) {
const { children, className, ...restProps } = props;
const { children, className, overflow = 'wrap', ...restProps } = props;
const tabIndex = overflow === 'overflow' ? 0 : undefined;

return (
<pre dir="ltr" translate="no" {...restProps} className={clsx('nl-code-block', className)} ref={forwardedRef}>
<pre
dir="ltr"
translate="no"
tabIndex={tabIndex}
{...restProps}
className={clsx(
'nl-code-block',
{
['nl-code-block--nowrap']: overflow === 'nowrap',
['nl-code-block--overflow']: overflow === 'overflow',
},
className,
)}
ref={forwardedRef}
>
<code className="nl-code-block__code">{children}</code>
</pre>
);
Expand Down
Loading

0 comments on commit d2d520f

Please sign in to comment.