Skip to content

Conversation

@aadeina
Copy link
Contributor

@aadeina aadeina commented Jan 5, 2026

Summary

Adds a copy-to-clipboard button to console tab code blocks (Unix / Windows installation commands).

Fixes: #1276, #2399
Builds on feedback from @sabderemane in PR #1434.

Changes

JavaScript

djangoproject/static/js/djangoproject.js

  • Extends existing clipboard functionality to support console tabs
  • Adds smart command text extraction that excludes:
    • Shell prompts (.gp — e.g. $, ...>)
    • Command output (.go)
  • Minimal change set (~20 lines added), reusing existing patterns and logic

SCSS

djangoproject/scss/_console-tabs.scss

  • Adds position: relative to console tab sections
  • Introduces .btn-clipboard styling using absolute positioning (no float)
  • Includes hover states and “Copied!” success feedback animation
  • Uses existing CSS variables for light/dark mode compatibility

Visual Comparison

Before

Before: console tabs without copy button

After

Video.Project.mp4

@ulgens
Copy link
Member

ulgens commented Jan 5, 2026

This looks nice 🌻 I'd recommend installing git hooks (you can follow the last section of the readme) and rebasing the PR to have a bit more clear history.

@aadeina aadeina force-pushed the docs-copy-to-clipboard branch from ad9d2d6 to 24e3b21 Compare January 5, 2026 19:16
@aadeina aadeina closed this Jan 5, 2026
@aadeina aadeina force-pushed the docs-copy-to-clipboard branch from bb03309 to 07c155d Compare January 5, 2026 19:39
@aadeina aadeina reopened this Jan 5, 2026
@aadeina aadeina force-pushed the docs-copy-to-clipboard branch from c22de90 to cd6cf4c Compare January 5, 2026 20:04
@aadeina
Copy link
Contributor Author

aadeina commented Jan 5, 2026

Hi @ulgens ,
I’ve cleaned up the branch and ensured the PR now contains only the intended commit.
Please let me know if anything else is needed.

Copy link
Member

@adamzap adamzap left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here are some initial thoughts. Thanks for attempting this!

});

function on_success(el) {
function on_success() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why add an unused argument here and on line 145?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch! Just to clarify — I actually removed the unused el parameter here, since it wasn't being used (the functions access success_el via closure instead). Happy to keep it if you prefer consistency with other patterns in the codebase.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, thanks! Sorry for my misunderstanding here.

// Console tabs: extract text excluding prompts (.gp) and output (.go)
const pre_el = console_section.querySelector('.highlight pre');
text = '';
if (pre_el) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In what case is there not a <pre> element?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right — since Pygments always generates the <pre> element, this check isn't strictly necessary.
I'll remove it to keep the code cleaner. Thanks for pointing this out!

const pre_el = console_section.querySelector('.highlight pre');
text = '';
if (pre_el) {
pre_el.childNodes.forEach(function (node) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think it would be more elegant to grab the text content like the old code was doing and just left trim the prompt?

(...).textContent.trim().replace(/^\$ /, '')

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great question! I went with the node-based approach mainly because:

  1. It also handles the Windows tab (which uses ...> prompts)
  2. It excludes command output marked with .go (in case any examples show output)

That said, if the console blocks only ever show simple $ prompts without output, a regex would definitely be simpler. I'm happy to switch to:

text = pre_el.textContent.trim().replace(/^(\$ |\.\.\.>)/gm, '');

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me know which approach you'd prefer!

@aadeina aadeina force-pushed the docs-copy-to-clipboard branch from cd6cf4c to b3cf678 Compare January 25, 2026 19:44
@aadeina
Copy link
Contributor Author

aadeina commented Jan 25, 2026

Updated per feedback — removed the if check. Thanks! Ready for another look when you have time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants