Copy Button

Button that copies text to the clipboard — the element it sits in, another element by id, or a literal string.

c2-copy-button puts text on the clipboard. Drop it inside the element you want to copy and that is all the configuration it needs: it copies its parent, and leaves its own label out of the result. Point it at something else with for (the id of the source), or hand it the exact string with value. It reads each source the way that source stores its text — the code of a c2-code-viewer, the value of an input or c2-text-field, the rendered text of anything else — so copying a highlighted snippet gives you the code, not a wall of token spans. By default the button stays out of the way until you hover its source, and pin parks it in a corner where it stays put even while the source scrolls.

Installation

npm install @c2n/copy-button

Usage

npx -y @c2n/mcp
git remote add origin git@github.com:code2nguyen/web-components.git && git fetch --all --tags --prune && git checkout -b feature/copy-button origin/develop && npm install && npm run build && npm run ui:build — scroll this box: the pinned button holds its corner in both directions
CopyCopy order
Anthropic, 548 Market St, San Francisco, CA 94104
Copy token
Copy code
DisabledLong feedbackCopy Got it

Reveal. reveal="hover" is the default: the button is transparent until the pointer enters its source, which keeps a corner button from sitting on top of the content it copies. It is only the opacity that changes, so the button keeps its box and stays reachable — it also appears when focus lands anywhere inside the source (so it is keyboard-operable), on devices with no hover at all (a hover-only button would be unreachable on touch), and for as long as the copied confirmation is showing, so the check mark does not flash invisibly after the pointer leaves. While hidden it takes no pointer events, so there is never an invisible click target. Use reveal="always" when the button should be permanently visible — which is also what the previews and gallery cards on this site do, since nothing hovers them.

Pin. pin absolutely positions the button in a corner of its containing block — pin alone means top right, or name one of top-right, top-left, bottom-right, bottom-left — inset by --c2-copy-button__pin--offset-x / -y. Give the element it sits in position: relative, as with any absolutely positioned child.

The reason pin exists rather than leaving you to write the CSS: an absolutely positioned child of a scrolling box lives in that box’s scrollable overflow, so it scrolls away with the content — exactly when you need it, because long or wide text is why there is a scrollbar in the first place. A pinned button finds the nearest ancestor that can scroll and cancels out its scroll offset, so it holds its corner no matter where the content is scrolled, in either direction. Scroll the second example above to see it.

Sources. Resolution is value, then for, then the light-DOM parent. parentElement is deliberate: a button slotted into another custom element copies the element it was authored inside, not the shadow-DOM node it happens to render in. Whitespace inside the source is preserved (newlines in a <pre> survive) and only the leading and trailing whitespace is trimmed.

Feedback and slots. With no slotted content the button is icon-only and square (--c2-copy-button__container--min-width matches its height); slot text and it grows into an icon-and-label button. The copy-icon and copied-icon slots replace the two default glyphs, and copied-label replaces the text while the copied state is showing. copied is reflected, so c2-copy-button[copied] is styleable from outside, and the __container__copied--* variables cover the state from within. Because an icon swap alone is not announced, the element renders a visually hidden role="status" region carrying copied-label (or Copy failed), and the button’s aria-label follows the same text — set label and copied-label when the defaults (“Copy” / “Copied”) do not fit. A refused clipboard write turns the button red and fires copy-error rather than failing silently, and where navigator.clipboard is unavailable — any non-secure context, which includes a plain-http dev server — it falls back to an off-screen <textarea> and document.execCommand('copy').

escAccordionConnected, animated panels with shared borders and single or multiple expansion.LayoutAvatarImage, initials or icon for a person, with status dot and badge.Data displayBadgeTinted pill for status text, counts and dots, optionally pinned to a corner of another element.Data displayBreadcrumbNavigation trail of link buttons with separators, a current page and optional collapsing.NavigationButtonThemeable button with slots for text, prefix, suffix and running icons.ButtonsButton GroupAttached buttons with shared borders, optionally a segmented control with single or multiple selection.ButtonsCardGroups related content and actions on a single bordered surface.LayoutChat InputAuto-growing message box with a send button for chat interfaces.ChatChat MessageOne chat bubble with avatar, title, timestamp and message body.ChatCheckboxNative checkbox behaviour in a quiet, themeable box with an opt-in hover layer.InputsCode ViewerSyntax-highlighted code with line numbers, copy button and dark mode, powered by shiki.Data displayColor AreaTwo-dimensional area for picking saturation and value of a colour.InputsColor SelectColour swatch that opens a full picker built from area and slider.InputsColor SliderHorizontal slider for choosing a hue from 0 to 360.InputsCopy ButtonButton that copies text to the clipboard — the element it sits in, another element by id, or a literal string.ButtonsDetailsCollapsible disclosure built on native details and summary.LayoutIcon ButtonRound, hoverable button wrapping a slotted SVG icon.ButtonsKbdKeyboard key label for shortcuts and command hints, with the semantics of the native kbd element.Data displayLabelCaption that names and activates the control referenced by its for attribute, with a required marker.InputsLink ButtonText-styled control for link and navigation actions, rendered as a real anchor or a button.NavigationListVertical list container with single or multiple selection.Data displayList ItemSelectable row with icon slots, used on its own or as the option of list and select.Data displayMenuCommands, links, checkboxes and submenus in a popover anchored to a trigger.NavigationModalDialog built on the native dialog element: focus trap, backdrop, Escape, title, body and footer.FeedbackNavigation MenuSite navigation bar whose triggers open panels of links below the header.NavigationOverlayAnchored popup built on the browser Popover API, positioned with floating-ui.FeedbackPaginationPage navigation in three layouts: numbered pages, a simple page status, or a table-footer row with rows-per-page.NavigationProgressLinear progress bar, indeterminate or filling to a value, with an optional label and count.FeedbackRadioRadio options built on native inputs, grouped into one value with keyboard navigation.InputsSelectDropdown that pairs a themeable trigger with an anchored list of c2-list-item options.InputsSeperatorHorizontal or vertical rule with an optional label, for dividing content and toolbars.LayoutSheetDialog pinned to an edge of the screen, for content that complements the page rather than interrupting it.FeedbackSide NavResponsive navigation drawer beside the page: pushes the content on large screens, slides over it with a backdrop on small ones.NavigationSkeletonPlaceholder block standing in for content that has not arrived, in three shapes and three animations.FeedbackSliderRange input with a themeable track, thumb, step ticks and value bubble.InputsSpinnerCircular progress indicator, indeterminate or showing a value, with optional text.FeedbackSwitchOn/off toggle on a native switch input, with label, description and thumb icons.InputsTableVirtualized data grid with declarative columns, sorting, selection, pinning and resizing.Data displayTabsTab strip that shows one content panel at a time.NavigationText FieldSingle-line input with icon slots, clear button, helper and error text, and a character counter.InputsTextareaMultiline text input with resizing, helper and error text, and a character counter.InputsToastNotification cards and a manager for stacked, queued notifications with independent lifetimes.FeedbackTooltipContextual hint shown when its target is hovered or focused, rendered in the top layer.FeedbackFeather Icons287 open-source Feather icons, one web component each.IconsMat Icon2,234 Material Icons ligatures rendered through a single element.IconsPhosphor Icons1,512 flexible icons in six weights, one web component each.IconsThemingTheme every c2n component from a handful of design tokens with @c2n/theme, or reach for any component variable directly.GuideUsing c2n in an applicationThe workflow behind every c2n app: load the theme once, use c2-* tags directly, and turn every repeated pattern into a small variant or composed component.Guide