Merge pull request #897 from quantified-uncertainty/copy-share-link
"Copy share link" button
This commit is contained in:
commit
f7e6061f17
|
@ -13,6 +13,7 @@ import { yupResolver } from "@hookform/resolvers/yup";
|
||||||
import {
|
import {
|
||||||
ChartSquareBarIcon,
|
ChartSquareBarIcon,
|
||||||
CheckCircleIcon,
|
CheckCircleIcon,
|
||||||
|
ClipboardCopyIcon,
|
||||||
CodeIcon,
|
CodeIcon,
|
||||||
CogIcon,
|
CogIcon,
|
||||||
CurrencyDollarIcon,
|
CurrencyDollarIcon,
|
||||||
|
@ -40,6 +41,7 @@ import {
|
||||||
defaultColor,
|
defaultColor,
|
||||||
defaultTickFormat,
|
defaultTickFormat,
|
||||||
} from "../lib/distributionSpecBuilder";
|
} from "../lib/distributionSpecBuilder";
|
||||||
|
import { Button } from "./ui/Button";
|
||||||
|
|
||||||
type PlaygroundProps = SquiggleChartProps & {
|
type PlaygroundProps = SquiggleChartProps & {
|
||||||
/** The initial squiggle string to put in the playground */
|
/** The initial squiggle string to put in the playground */
|
||||||
|
@ -49,6 +51,8 @@ type PlaygroundProps = SquiggleChartProps & {
|
||||||
onSettingsChange?(settings: any): void;
|
onSettingsChange?(settings: any): void;
|
||||||
/** Should we show the editor? */
|
/** Should we show the editor? */
|
||||||
showEditor?: boolean;
|
showEditor?: boolean;
|
||||||
|
/** Useful for playground on squiggle website, where we update the anchor link based on current code and settings */
|
||||||
|
showShareButton?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
const schema = yup
|
const schema = yup
|
||||||
|
@ -197,6 +201,29 @@ const RunControls: React.FC<{
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const ShareButton: React.FC = () => {
|
||||||
|
const [isCopied, setIsCopied] = useState(false);
|
||||||
|
const copy = () => {
|
||||||
|
navigator.clipboard.writeText((window.top || window).location.href);
|
||||||
|
setIsCopied(true);
|
||||||
|
setTimeout(() => setIsCopied(false), 1000);
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<div className="w-36">
|
||||||
|
<Button onClick={copy} wide>
|
||||||
|
{isCopied ? (
|
||||||
|
"Copied to clipboard!"
|
||||||
|
) : (
|
||||||
|
<div className="flex items-center space-x-1">
|
||||||
|
<ClipboardCopyIcon className="w-4 h-4" />
|
||||||
|
<span>Copy share link</span>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
type PlaygroundContextShape = {
|
type PlaygroundContextShape = {
|
||||||
getLeftPanelElement: () => HTMLDivElement | undefined;
|
getLeftPanelElement: () => HTMLDivElement | undefined;
|
||||||
};
|
};
|
||||||
|
@ -220,6 +247,7 @@ export const SquigglePlayground: FC<PlaygroundProps> = ({
|
||||||
onCodeChange,
|
onCodeChange,
|
||||||
onSettingsChange,
|
onSettingsChange,
|
||||||
showEditor = true,
|
showEditor = true,
|
||||||
|
showShareButton = false,
|
||||||
}) => {
|
}) => {
|
||||||
const [code, setCode] = useMaybeControlledValue({
|
const [code, setCode] = useMaybeControlledValue({
|
||||||
value: controlledCode,
|
value: controlledCode,
|
||||||
|
@ -370,6 +398,7 @@ export const SquigglePlayground: FC<PlaygroundProps> = ({
|
||||||
<StyledTab name="View Settings" icon={ChartSquareBarIcon} />
|
<StyledTab name="View Settings" icon={ChartSquareBarIcon} />
|
||||||
<StyledTab name="Input Variables" icon={CurrencyDollarIcon} />
|
<StyledTab name="Input Variables" icon={CurrencyDollarIcon} />
|
||||||
</StyledTab.List>
|
</StyledTab.List>
|
||||||
|
<div className="flex space-x-2 items-center">
|
||||||
<RunControls
|
<RunControls
|
||||||
autorunMode={autorunMode}
|
autorunMode={autorunMode}
|
||||||
isStale={renderedCode !== code}
|
isStale={renderedCode !== code}
|
||||||
|
@ -377,6 +406,8 @@ export const SquigglePlayground: FC<PlaygroundProps> = ({
|
||||||
isRunning={isRunning}
|
isRunning={isRunning}
|
||||||
onAutorunModeChange={setAutorunMode}
|
onAutorunModeChange={setAutorunMode}
|
||||||
/>
|
/>
|
||||||
|
{showShareButton && <ShareButton />}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{vars.showEditor ? withEditor : withoutEditor}
|
{vars.showEditor ? withEditor : withoutEditor}
|
||||||
</div>
|
</div>
|
||||||
|
|
22
packages/components/src/components/ui/Button.tsx
Normal file
22
packages/components/src/components/ui/Button.tsx
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
import clsx from "clsx";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
type Props = {
|
||||||
|
onClick: () => void;
|
||||||
|
children: React.ReactNode;
|
||||||
|
wide?: boolean; // stretch the button horizontally
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Button: React.FC<Props> = ({ onClick, wide, children }) => {
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
className={clsx(
|
||||||
|
"rounded-md py-1.5 px-2 bg-slate-500 text-white text-xs font-semibold flex items-center justify-center space-x-1",
|
||||||
|
wide && "w-full"
|
||||||
|
)}
|
||||||
|
onClick={onClick}
|
||||||
|
>
|
||||||
|
{children}
|
||||||
|
</button>
|
||||||
|
);
|
||||||
|
};
|
|
@ -21,3 +21,16 @@ including sampling settings, in squiggle.
|
||||||
{Template.bind({})}
|
{Template.bind({})}
|
||||||
</Story>
|
</Story>
|
||||||
</Canvas>
|
</Canvas>
|
||||||
|
|
||||||
|
<Canvas>
|
||||||
|
<Story
|
||||||
|
name="With share button"
|
||||||
|
args={{
|
||||||
|
defaultCode: "normal(5,2)",
|
||||||
|
height: 800,
|
||||||
|
showShareButton: true,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{Template.bind({})}
|
||||||
|
</Story>
|
||||||
|
</Canvas>
|
||||||
|
|
|
@ -44,6 +44,7 @@ export default function PlaygroundPage() {
|
||||||
const playgroundProps = {
|
const playgroundProps = {
|
||||||
defaultCode: "normal(0,1)",
|
defaultCode: "normal(0,1)",
|
||||||
height: 700,
|
height: 700,
|
||||||
|
showShareButton: true,
|
||||||
...hashData,
|
...hashData,
|
||||||
onCodeChange: (code) => setHashData({ initialSquiggleString: code }),
|
onCodeChange: (code) => setHashData({ initialSquiggleString: code }),
|
||||||
onSettingsChange: (settings) => {
|
onSettingsChange: (settings) => {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user