Skip to content

Commit

Permalink
[docs] Code block scroll improvements (#1187)
Browse files Browse the repository at this point in the history
  • Loading branch information
vladmoroz authored Dec 20, 2024
1 parent e04f425 commit 5fa5fb4
Show file tree
Hide file tree
Showing 8 changed files with 188 additions and 150 deletions.
68 changes: 28 additions & 40 deletions docs/src/components/Demo/Demo.css
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@

@media (--xs) {
padding: 3rem 1.5rem;
min-height: 11.25rem; /* Match .DemoCodeBlockContainer pre min-height */
min-height: 11.25rem; /* Match .DemoCodeBlockRoot pre min-height */
}
}

Expand Down Expand Up @@ -153,51 +153,13 @@
}
}

.DemoCodeBlockContainer {
.DemoCodeBlockRoot {
display: flex;
flex-direction: column;
position: relative;
outline: 0;

& pre {
@apply text-xs;
padding: 0.5rem 0.75rem;
cursor: text;

/* Scroll */
display: flex;
overflow: auto;
/* Prevent Chrome/Safari page navigation gestures when scrolling horizontally */
overscroll-behavior-x: contain;

/* Scroll containers may be focusable */
&:focus-visible {
position: relative;
outline: 2px solid var(--color-blue);
outline-offset: -1px;
z-index: 1;
}

/* Add a border radius when there is no collapse button */
&:not(.DemoCollapseButton + &) {
border-bottom-left-radius: var(--radius-md);
border-bottom-right-radius: var(--radius-md);
}
}

& code {
/* Different fonts may introduce vertical align issues */
display: block;
/* Make sure selection highlight spans full container width in Safari */
flex-grow: 1;
}

&[data-closed] {
& pre {
overflow: hidden;
max-height: calc(8.6lh + 0.5rem); /* Show 8.6 of code lines and account for top padding */
}

&::before {
content: '';
position: absolute;
Expand All @@ -217,6 +179,32 @@
}
}

.DemoCodeBlockViewport {
/* Prevent Chrome/Safari page navigation gestures when scrolling horizontally */
overscroll-behavior-x: contain;

/* Max height for code blocks, if we ever want to recover this (https://github.com/mui/base-ui/pull/1187) */
/* max-height: clamp(8.75lh + 0.5rem, 80vh, 23.75lh + 0.5rem); */

&[data-closed] {
overflow: hidden;
max-height: calc(8.75lh + 0.5rem); /* Show almost 9 code lines plus top padding */
}
}

.DemoSourceBrowser {
@apply text-xs;
padding: 0.5rem 0.75rem;
cursor: text;

& code {
/* Different fonts may introduce vertical align issues */
display: block;
/* Make sure selection highlight spans full container width in Safari */
flex-grow: 1;
}
}

.DemoCollapseButton {
@apply text-xs;
background-color: var(--color-gray-50);
Expand Down
4 changes: 2 additions & 2 deletions docs/src/components/Demo/Demo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import clsx from 'clsx';
import { CheckIcon } from 'docs/src/icons/CheckIcon';
import { DemoVariantSelector } from './DemoVariantSelector';
import { DemoFileSelector } from './DemoFileSelector';
import { DemoSourceBrowser } from './DemoSourceBrowser';
import { DemoCodeBlock } from './DemoCodeBlock';
import { CodeSandboxLink } from './CodeSandboxLink';
import { GhostButton } from '../GhostButton';
import { DemoPlayground } from './DemoPlayground';
Expand Down Expand Up @@ -62,7 +62,7 @@ export function Demo({
</div>
)}

<DemoSourceBrowser collapsibleOpen={open} compact={compact} />
<DemoCodeBlock collapsibleOpen={open} compact={compact} />
</div>
</Collapsible.Root>
</BaseDemo.Root>
Expand Down
95 changes: 95 additions & 0 deletions docs/src/components/Demo/DemoCodeBlock.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
import * as React from 'react';
import * as BaseDemo from 'docs/src/blocks/Demo';
import { Collapsible } from '@base-ui-components/react/collapsible';
import * as ScrollArea from '../ScrollArea';

interface DemoCodeBlockProps {
collapsibleOpen: boolean;
/** How many lines should the code block have to get collapsed instead of rendering fully */
collapsibleLinesThreshold?: number;
/** When compact, we don't show a preview of the collapse code */
compact: boolean;
}

function Root(props: React.ComponentProps<typeof ScrollArea.Root>) {
return (
<ScrollArea.Root
{...props}
className="DemoCodeBlockRoot"
tabIndex={-1}
onKeyDown={(event: React.KeyboardEvent) => {
if (
event.key === 'a' &&
(event.metaKey || event.ctrlKey) &&
!event.shiftKey &&
!event.altKey
) {
event.preventDefault();
window.getSelection()?.selectAllChildren(event.currentTarget);
}
}}
/>
);
}

export function DemoCodeBlock({
compact,
collapsibleOpen,
collapsibleLinesThreshold = 12,
}: DemoCodeBlockProps) {
const demoContext = React.useContext(BaseDemo.DemoContext);

if (!demoContext) {
throw new Error('Demo.Playground must be used within a Demo.Root');
}

const { selectedFile } = demoContext;
const lineBreaks = selectedFile.content.match(/\n/g) ?? [];

if (lineBreaks.length < collapsibleLinesThreshold) {
return (
<Root>
<ScrollArea.Viewport>
<BaseDemo.SourceBrowser className="DemoSourceBrowser" />
</ScrollArea.Viewport>
<ScrollArea.Corner />
<ScrollArea.Scrollbar orientation="vertical" />
<ScrollArea.Scrollbar orientation="horizontal" />
</Root>
);
}

return (
<React.Fragment>
<Root
render={
<Collapsible.Panel
keepMounted={compact ? undefined : true}
hidden={compact ? undefined : false}
/>
}
>
<ScrollArea.Viewport
aria-hidden={!collapsibleOpen}
data-closed={collapsibleOpen ? undefined : ''}
className="DemoCodeBlockViewport"
{...(!collapsibleOpen && { tabIndex: undefined, style: { overflow: undefined } })}
>
<BaseDemo.SourceBrowser className="DemoSourceBrowser" />
</ScrollArea.Viewport>

{collapsibleOpen && (
<React.Fragment>
<ScrollArea.Corner />
<ScrollArea.Scrollbar orientation="vertical" />
<ScrollArea.Scrollbar orientation="horizontal" />
</React.Fragment>
)}
</Root>

<Collapsible.Trigger className="DemoCollapseButton">
{collapsibleOpen ? 'Hide' : 'Show'} code
</Collapsible.Trigger>
</React.Fragment>
);
}
82 changes: 0 additions & 82 deletions docs/src/components/Demo/DemoSourceBrowser.tsx

This file was deleted.

56 changes: 30 additions & 26 deletions docs/src/components/ScrollArea.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,66 +13,70 @@

.ScrollAreaScrollbar {
display: flex;
background-color: var(--color-gray-200);
border-radius: 0.375rem;
margin: 0.5rem;
pointer-events: none;

opacity: 0;
transition: opacity 150ms 300ms;

&[data-scrolling] {
pointer-events: auto;
opacity: 1;
transition-duration: 75ms;
transition-delay: 0ms;
}

@media (hover: hover) {
&:hover {
/* Once shown, don't hide if hovering (like macOS scrollbar) */
pointer-events: auto;
transition-duration: 75ms;
transition-delay: 25ms;
opacity: 1;
}
}

&[data-orientation='horizontal'] {
height: 0.25rem;
}

&[data-orientation='vertical'] {
width: 0.25rem;
}

&[data-orientation='vertical'] {
width: 0.25rem;
}

&::before {
content: '';
position: absolute;
border-radius: inherit;
}

&[data-orientation='horizontal']::before {
align-self: center;
&[data-orientation='horizontal'] {
align-items: center;
height: 1.25rem;
width: 100%;
margin-inline: 0.5rem;

&::before {
height: 0.25rem;
inset-inline: 0;
background-color: var(--color-gray-200);
}
}

&[data-orientation='vertical']::before {
justify-self: center;
&[data-orientation='vertical'] {
justify-content: center;
width: 1.25rem;
height: 100%;
margin-block: 0.5rem;

&::before {
width: 0.25rem;
inset-block: 0;
background-color: var(--color-gray-200);
}
}
}

.ScrollAreaThumb {
position: relative;
height: 100%;
width: 100%;
border-radius: inherit;
background-color: var(--color-gray-400);

&[data-orientation='horizontal'] {
height: 0.25rem;
}

&[data-orientation='vertical'] {
width: 0.25rem;
}

/* Draggable area */
&::before {
content: '';
position: absolute;
Expand Down
4 changes: 4 additions & 0 deletions docs/src/components/ScrollArea.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,7 @@ export function Scrollbar({ className, ...props }: ScrollArea.Scrollbar.Props) {
</ScrollArea.Scrollbar>
);
}

export function Corner({ className, ...props }: ScrollArea.Corner.Props) {
return <ScrollArea.Corner className={clsx('ScrollAreaCorner', className)} {...props} />;
}
Loading

0 comments on commit 5fa5fb4

Please sign in to comment.