Skip to content

Commit

Permalink
Add copy button to code block actions (#62)
Browse files Browse the repository at this point in the history
* Wrap long classNames to the next line

* Add CopyCodeButton

* Override primary button styles

* Remove redundant ternary
  • Loading branch information
BrianUribe6 authored Jan 12, 2024
1 parent cef8151 commit 99472e7
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 16 deletions.
9 changes: 6 additions & 3 deletions apps/front-end/src/components/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,19 @@ import { VariantProps, cva } from "class-variance-authority";
import { ComponentPropsWithoutRef, forwardRef } from "react";

const buttonVariants = cva(
"inline-flex items-center justify-center gap-1 whitespace-nowrap rounded-md text-center shadow-sm ring-cyan-600 ring-offset-2 ring-offset-slate-900 focus-visible:outline-none focus-visible:ring-2 md:px-4 md:py-2",
"inline-flex items-center justify-center gap-1 whitespace-nowrap rounded-md text-center shadow-sm ring-cyan-600 ring-offset-2 " +
"ring-offset-slate-900 focus-visible:outline-none focus-visible:ring-2 md:px-4 md:py-2",
{
variants: {
variant: {
primary:
"bg-cyan-200 text-cyan-900 hover:bg-cyan-300 dark:bg-cyan-900 dark:text-cyan-200 dark:hover:bg-cyan-800",
danger:
" text-red-400 outline outline-1 -outline-offset-1 outline-red-200 hover:outline-red-300 dark:text-red-400 dark:outline-red-400 dark:hover:text-red-300 dark:hover:outline-red-300",
" text-red-400 outline outline-1 -outline-offset-1 outline-red-200 hover:outline-red-300 dark:text-red-400" +
"dark:hover:outline-red-30 0 dark:outline-red-400 dark:hover:text-red-300",
secondary:
"text-cyan-900 outline outline-1 -outline-offset-1 outline-cyan-200 hover:outline-cyan-200 dark:text-cyan-400 dark:outline-cyan-400 hover:dark:text-cyan-200 dark:hover:outline-cyan-200",
"text-cyan-900 outline outline-1 -outline-offset-1 outline-cyan-200 hover:outline-cyan-200 dark:text-cyan-400" +
"dark:outline-cyan-400 hover:dark:text-cyan-200 dark:hover:outline-cyan-200",
link: "text-slate-800 hover:text-cyan-800 dark:text-slate-200 hover:dark:text-cyan-400",
},
size: {
Expand Down
2 changes: 1 addition & 1 deletion apps/front-end/src/components/CopyButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export default function CopyButton(props: ButtonProps) {
};

return (
<Tooltip title={copied ? "Copied" : "Copy"} open={copied}>
<Tooltip title="Copied" open={copied}>
<Button className="py-3" onClick={copyToClipBoard} {...rest}>
{!copied ? (
<CopyIcon className="duration-500 animate-in fade-in" aria-hidden />
Expand Down
29 changes: 21 additions & 8 deletions apps/front-end/src/plugins/CodeActionPlugin/ActionBar.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,32 @@
import { LexicalEditor } from "lexical";
import { forwardRef } from "react";
import LanguageSelector, { LanguageSelectorProps } from "./LanguageSelector";
import CopyCodeButton from "./CopyCodeButton";
import LanguageSelector from "./LanguageSelector";

type ActionBarProps = LanguageSelectorProps & {
type ActionBarProps = WithCodeNode<{
codeDOMNode: HTMLElement;
}>;

export type WithCodeNode<T = unknown> = T & {
editor: LexicalEditor;
codeNodeKey: string;
};

const ActionBar = forwardRef<HTMLDivElement, ActionBarProps>(
function ActionBar(props, ref) {
const { left, top, right } = props.codeDOMNode.getBoundingClientRect();
const { left, top, width } = props.codeDOMNode.getBoundingClientRect();
return (
<div className="fixed px-4 py-2" style={{ left, top, right }} ref={ref}>
<LanguageSelector
editor={props.editor}
codeNodeKey={props.codeNodeKey}
/>
<div className="fixed px-4 py-2" style={{ left, top, width }} ref={ref}>
<div className="flex w-full justify-between">
<LanguageSelector
editor={props.editor}
codeNodeKey={props.codeNodeKey}
/>
<CopyCodeButton
editor={props.editor}
codeNodeKey={props.codeNodeKey}
/>
</div>
</div>
);
},
Expand Down
26 changes: 26 additions & 0 deletions apps/front-end/src/plugins/CodeActionPlugin/CopyCodeButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import CopyButton from "@/components/CopyButton";
import { $getNodeByKey } from "lexical";
import { WithCodeNode } from "./ActionBar";

type CopyCodeButtonProps = WithCodeNode;

function CopyCodeButton(props: CopyCodeButtonProps) {
const handleClick = () => {
props.editor.getEditorState().read(() => {
const codeNode = $getNodeByKey(props.codeNodeKey);
if (codeNode) {
const text = codeNode.getTextContent();
navigator.clipboard.writeText(text);
}
});
};

return (
<CopyButton
className="!bg-transparent !p-2.5 !text-inherit shadow-sm hover:!bg-slate-700"
onClick={handleClick}
/>
);
}

export default CopyCodeButton;
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,11 @@ import {
import { Command } from "cmdk";
import { LexicalEditor, $getNodeByKey } from "lexical";
import { useState } from "react";
import { WithCodeNode } from "./ActionBar";

const SUPPORTED_LANGUAGES = Object.keys(CODE_LANGUAGE_FRIENDLY_NAME_MAP);

export type LanguageSelectorProps = {
editor: LexicalEditor;
codeNodeKey: string;
};
type LanguageSelectorProps = WithCodeNode;

function LanguageSelector({ codeNodeKey, editor }: LanguageSelectorProps) {
const [open, setOpen] = useState(false);
Expand Down

0 comments on commit 99472e7

Please sign in to comment.