Skip to content

Commit eb590ca

Browse files
committed
refactor: review
1 parent ef0a681 commit eb590ca

10 files changed

Lines changed: 94 additions & 75 deletions

File tree

packages/components/src/components/CodeBlock/CodeBlock.mdx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ npm install highlight.js@^11
2828
### Configuring highlight.js
2929

3030
By default, `CodeBlock` lazily loads the full `highlight.js` bundle with all languages (~1 MB). To
31-
reduce bundle size, wrap the app (or a part of it) with `CodeBlockHighlightConfigProvider` and specify
31+
reduce bundle size, wrap the app (or a part of it) with `CodeBlock.HighlightConfigProvider` and specify
3232
only the languages you need:
3333

3434
```tsx
@@ -44,9 +44,9 @@ const highlightConfig = {
4444

4545
function App() {
4646
return (
47-
<CodeBlockHighlightConfigProvider config={highlightConfig}>
47+
<CodeBlock.HighlightConfigProvider config={highlightConfig}>
4848
<CodeBlock files={files} />
49-
</CodeBlockHighlightConfigProvider>
49+
</CodeBlock.HighlightConfigProvider>
5050
);
5151
}
5252
```

packages/components/src/components/CodeBlock/CodeBlock.module.css

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@
9595
}
9696

9797
.actionbar {
98-
visibility: hidden;
98+
opacity: 0;
9999
pointer-events: none;
100100
position: absolute;
101101
inset-block-start: 0;
@@ -126,14 +126,15 @@
126126
*/
127127
&:hover .actionbar,
128128
&:focus-within .actionbar,
129+
&[data-action-bar-tooltip-open] .actionbar,
129130
&[data-always-show-action-bar] .actionbar {
130-
visibility: visible;
131+
opacity: 1;
131132
pointer-events: auto;
132133
}
133134

134135
@media (hover: none) {
135136
.actionbar {
136-
visibility: visible;
137+
opacity: 1;
137138
pointer-events: auto;
138139
}
139140
}

packages/components/src/components/CodeBlock/CodeBlock.stories.tsx

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import { Typography } from '../Typography';
1010

1111
import {
1212
CodeBlock,
13-
CodeBlockHighlightConfigProvider,
1413
type CodeBlockFile,
1514
type CodeBlockProps,
1615
type CodeBlockRef,
@@ -19,6 +18,9 @@ import {
1918
const meta = {
2019
title: 'Components/CodeBlock',
2120
component: CodeBlock,
21+
subcomponents: {
22+
HighlightConfigProvider: CodeBlock.HighlightConfigProvider,
23+
},
2224
parameters: {
2325
layout: 'padded',
2426
},
@@ -51,7 +53,7 @@ export const Overview: Story = {
5153
];
5254

5355
return (
54-
<CodeBlockHighlightConfigProvider config={highlightConfig}>
56+
<CodeBlock.HighlightConfigProvider config={highlightConfig}>
5557
<Toggle
5658
isSelected={hasLineNumbers}
5759
onChange={setHasLineNumbers}
@@ -65,7 +67,7 @@ export const Overview: Story = {
6567
files={files}
6668
hasLineNumbers={hasLineNumbers}
6769
/>
68-
</CodeBlockHighlightConfigProvider>
70+
</CodeBlock.HighlightConfigProvider>
6971
);
7072
},
7173
};
@@ -112,7 +114,7 @@ export const HeaderPinned: Story = {
112114
];
113115

114116
return (
115-
<CodeBlockHighlightConfigProvider config={highlightConfig}>
117+
<CodeBlock.HighlightConfigProvider config={highlightConfig}>
116118
<CodeBlock
117119
{...args}
118120
canToggleSoftWrap
@@ -145,7 +147,7 @@ export const HeaderPinned: Story = {
145147
)}
146148
style={{ blockSize: 350 }}
147149
/>
148-
</CodeBlockHighlightConfigProvider>
150+
</CodeBlock.HighlightConfigProvider>
149151
);
150152
},
151153
};
@@ -173,7 +175,7 @@ export const WithMaxHeight: Story = {
173175
];
174176

175177
return (
176-
<CodeBlockHighlightConfigProvider config={highlightConfig}>
178+
<CodeBlock.HighlightConfigProvider config={highlightConfig}>
177179
<Toggle
178180
isSelected={viewAll}
179181
onChange={setViewAll}
@@ -197,7 +199,7 @@ export const WithMaxHeight: Story = {
197199
onViewAllChange={setViewAll}
198200
viewAll={viewAll}
199201
/>
200-
</CodeBlockHighlightConfigProvider>
202+
</CodeBlock.HighlightConfigProvider>
201203
);
202204
},
203205
};
@@ -224,7 +226,7 @@ export const WithSoftWrap: Story = {
224226
];
225227

226228
return (
227-
<CodeBlockHighlightConfigProvider config={highlightConfig}>
229+
<CodeBlock.HighlightConfigProvider config={highlightConfig}>
228230
<Toggle
229231
isSelected={softWrap}
230232
onChange={setSoftWrap}
@@ -240,7 +242,7 @@ export const WithSoftWrap: Story = {
240242
onSoftWrapChange={setSoftWrap}
241243
softWrap={softWrap}
242244
/>
243-
</CodeBlockHighlightConfigProvider>
245+
</CodeBlock.HighlightConfigProvider>
244246
);
245247
},
246248
};
@@ -283,7 +285,7 @@ export const WithTabs: Story = {
283285
];
284286

285287
return (
286-
<CodeBlockHighlightConfigProvider config={highlightConfig}>
288+
<CodeBlock.HighlightConfigProvider config={highlightConfig}>
287289
<Toggle
288290
isSelected={hideTabs}
289291
onChange={setHideTabs}
@@ -314,7 +316,7 @@ export const WithTabs: Story = {
314316
hideTabs={hideTabs}
315317
isFilled={isFilled}
316318
/>
317-
</CodeBlockHighlightConfigProvider>
319+
</CodeBlock.HighlightConfigProvider>
318320
);
319321
},
320322
};
@@ -359,7 +361,7 @@ export const WithTabsAndShadow: Story = {
359361
}, []);
360362

361363
return (
362-
<CodeBlockHighlightConfigProvider config={highlightConfig}>
364+
<CodeBlock.HighlightConfigProvider config={highlightConfig}>
363365
<CodeBlock
364366
{...args}
365367
ref={codeBlockRef}
@@ -370,7 +372,7 @@ export const WithTabsAndShadow: Story = {
370372
hasLineNumbers
371373
style={{ blockSize: 350 }}
372374
/>
373-
</CodeBlockHighlightConfigProvider>
375+
</CodeBlock.HighlightConfigProvider>
374376
);
375377
},
376378
};
@@ -398,7 +400,7 @@ export const WithFilled: Story = {
398400
];
399401

400402
return (
401-
<CodeBlockHighlightConfigProvider config={highlightConfig}>
403+
<CodeBlock.HighlightConfigProvider config={highlightConfig}>
402404
<Toggle
403405
isSelected={isFilled}
404406
onChange={setIsFilled}
@@ -421,7 +423,7 @@ export const WithFilled: Story = {
421423
files={files}
422424
isFilled={isFilled}
423425
/>
424-
</CodeBlockHighlightConfigProvider>
426+
</CodeBlock.HighlightConfigProvider>
425427
);
426428
},
427429
};
@@ -454,7 +456,7 @@ export const WithNoBorder: Story = {
454456
];
455457

456458
return (
457-
<CodeBlockHighlightConfigProvider config={highlightConfig}>
459+
<CodeBlock.HighlightConfigProvider config={highlightConfig}>
458460
<SidePanel
459461
size="small"
460462
control={(props) => <Button {...props}>Open sidepanel</Button>}
@@ -480,7 +482,7 @@ export const WithNoBorder: Story = {
480482
</SidePanel.Body>
481483
)}
482484
</SidePanel>
483-
</CodeBlockHighlightConfigProvider>
485+
</CodeBlock.HighlightConfigProvider>
484486
);
485487
},
486488
};
@@ -507,9 +509,9 @@ export const WithLink: Story = {
507509
];
508510

509511
return (
510-
<CodeBlockHighlightConfigProvider config={highlightConfig}>
512+
<CodeBlock.HighlightConfigProvider config={highlightConfig}>
511513
<CodeBlock {...args} files={files} hasLineNumbers hideCopyButton />
512-
</CodeBlockHighlightConfigProvider>
514+
</CodeBlock.HighlightConfigProvider>
513515
);
514516
},
515517
};

packages/components/src/components/CodeBlock/CodeBlock.test.tsx

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import type { HLJSApi } from 'highlight.js';
1313
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
1414

1515
import { CodeBlock } from './CodeBlock';
16-
import { CodeBlockHighlightConfigProvider } from './context';
1716
import type { CodeBlockHighlightConfig } from './context';
1817
import type { CodeBlockFile, CodeBlockRef } from './types';
1918

@@ -91,6 +90,16 @@ describe('CodeBlock', () => {
9190
expect(onHideTabsChange).toHaveBeenCalledWith(true);
9291
});
9392

93+
it('keeps action bar controls in sequential keyboard navigation when tabs are hidden', async () => {
94+
render(<CodeBlock files={jsFile} />);
95+
96+
const copyButton = await screen.findByRole('button', { name: 'Copy' });
97+
98+
await user.tab();
99+
100+
expect(copyButton).toHaveFocus();
101+
});
102+
94103
it('shows tabs again when files no longer require automatic hiding', async () => {
95104
const onHideTabsChange = vi.fn();
96105

@@ -322,10 +331,10 @@ describe('CodeBlock', () => {
322331
};
323332

324333
render(
325-
<CodeBlockHighlightConfigProvider config={config}>
334+
<CodeBlock.HighlightConfigProvider config={config}>
326335
<CodeBlock files={jsFile} />
327336
<CodeBlock files={jsFile} />
328-
</CodeBlockHighlightConfigProvider>
337+
</CodeBlock.HighlightConfigProvider>
329338
);
330339

331340
await waitFor(() =>
@@ -360,9 +369,9 @@ describe('CodeBlock', () => {
360369
const file = { content, language: 'unknown' };
361370

362371
render(
363-
<CodeBlockHighlightConfigProvider config={config}>
372+
<CodeBlock.HighlightConfigProvider config={config}>
364373
<CodeBlock files={[file]} />
365-
</CodeBlockHighlightConfigProvider>
374+
</CodeBlock.HighlightConfigProvider>
366375
);
367376

368377
await waitFor(() =>
@@ -403,9 +412,9 @@ describe('CodeBlock', () => {
403412
const file = { content: 'plain text' };
404413

405414
render(
406-
<CodeBlockHighlightConfigProvider config={config}>
415+
<CodeBlock.HighlightConfigProvider config={config}>
407416
<CodeBlock files={[file]} />
408-
</CodeBlockHighlightConfigProvider>
417+
</CodeBlock.HighlightConfigProvider>
409418
);
410419

411420
await waitFor(() =>
@@ -427,9 +436,9 @@ describe('CodeBlock', () => {
427436
};
428437

429438
render(
430-
<CodeBlockHighlightConfigProvider config={config}>
439+
<CodeBlock.HighlightConfigProvider config={config}>
431440
<CodeBlock files={jsFile} />
432-
</CodeBlockHighlightConfigProvider>
441+
</CodeBlock.HighlightConfigProvider>
433442
);
434443

435444
await waitFor(() =>
@@ -500,9 +509,10 @@ describe('CodeBlock', () => {
500509
vi.unstubAllGlobals();
501510
});
502511

503-
it('closes an open tooltip when pointer enters its portal', async () => {
512+
it('keeps the action bar visible while pointer is over its tooltip', async () => {
504513
render(<CodeBlock files={jsFile} data-testid="root" />);
505514

515+
const root = screen.getByTestId('root');
506516
const copyButton = await screen.findByRole('button', { name: 'Copy' });
507517

508518
await user.hover(copyButton);
@@ -514,9 +524,21 @@ describe('CodeBlock', () => {
514524
)
515525
);
516526

517-
await user.hover(screen.getByRole('tooltip'));
527+
expect(root).toHaveAttribute('data-action-bar-tooltip-open');
528+
529+
const tooltip = screen.getByRole('tooltip');
530+
531+
await user.hover(tooltip);
518532

519-
expect(screen.queryByRole('tooltip')).not.toBeInTheDocument();
533+
expect(tooltip).toBeVisible();
534+
expect(root).toHaveAttribute('data-action-bar-tooltip-open');
535+
536+
await user.unhover(tooltip);
537+
538+
await waitFor(() => {
539+
expect(screen.queryByRole('tooltip')).not.toBeInTheDocument();
540+
expect(root).not.toHaveAttribute('data-action-bar-tooltip-open');
541+
});
520542
});
521543

522544
it('toggles an uncontrolled defaultSoftWrap value and reports the change', async () => {
@@ -791,9 +813,9 @@ describe('CodeBlock', () => {
791813
.mockImplementation(() => {});
792814

793815
render(
794-
<CodeBlockHighlightConfigProvider config={config}>
816+
<CodeBlock.HighlightConfigProvider config={config}>
795817
<CodeBlock files={jsFile} ref={ref} />
796-
</CodeBlockHighlightConfigProvider>
818+
</CodeBlock.HighlightConfigProvider>
797819
);
798820

799821
ref.current?.scrollTo({ top: 24, behavior: 'instant' });

0 commit comments

Comments
 (0)