Skip to content

Commit c1f9dce

Browse files
committed
Add admonition and copy to clipboard button
1 parent 2de2cae commit c1f9dce

File tree

10 files changed

+157
-29
lines changed

10 files changed

+157
-29
lines changed

client/common/icons.jsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import CircleInfo from '../images/circle-info.svg';
2525
import Add from '../images/add.svg';
2626
import Filter from '../images/filter.svg';
2727
import Cross from '../images/cross.svg';
28+
import Copy from '../images/copy.svg';
2829

2930
// HOC that adds the right web accessibility props
3031
// https://www.scottohara.me/blog/2019/05/22/contextual-images-svgs-and-a11y.html
@@ -102,3 +103,4 @@ export const CircleFolderIcon = withLabel(CircleFolder);
102103
export const CircleInfoIcon = withLabel(CircleInfo);
103104
export const AddIcon = withLabel(Add);
104105
export const FilterIcon = withLabel(Filter);
106+
export const CopyIcon = withLabel(Copy);

client/images/copy.svg

Lines changed: 6 additions & 0 deletions
Loading
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import { useTranslation } from 'react-i18next';
4+
5+
export default function Admonition({ children }) {
6+
const { t } = useTranslation();
7+
return (
8+
<div className="admonition">
9+
<h3 className="admonition__title">
10+
<span role="img" aria-label="Flower" className="admonition__icon">
11+
🌸
12+
</span>
13+
{t('Admonition.Note')}
14+
</h3>
15+
{children}
16+
</div>
17+
);
18+
}
19+
20+
Admonition.propTypes = {
21+
children: PropTypes.node
22+
};
23+
24+
Admonition.defaultProps = {
25+
children: undefined
26+
};

client/modules/IDE/components/Preferences/index.jsx

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import VersionPicker from '../VersionPicker';
2424
import { updateFileContent } from '../../actions/files';
2525
import { CmControllerContext } from '../../pages/IDEView';
2626
import Stars from '../Stars';
27+
import Admonition from '../Admonition';
28+
import TextArea from '../TextArea';
2729

2830
export default function Preferences() {
2931
const { t } = useTranslation();
@@ -492,34 +494,39 @@ export default function Preferences() {
492494
</TabPanel>
493495
<TabPanel>
494496
<div className="preference">
495-
<h4 className="preference__title">
496-
{t('Preferences.LibraryVersion')}
497-
</h4>
498-
<div>
499-
{showStars && <Stars top={showStars.top} left={showStars.left} />}
500-
<VersionPicker
501-
ref={pickerRef}
502-
onChangeVersion={onChangeVersion}
503-
/>
504-
{versionInfo && indexID ? (
505-
<p className="preference__paragraph">
506-
{t('Preferences.LibraryVersionInfo')}
507-
</p>
508-
) : (
509-
<>
510-
<p className="preference__paragraph">
511-
{t('Preferences.CustomVersionInfo')}
512-
</p>
497+
{showStars && <Stars top={showStars.top} left={showStars.left} />}
498+
{versionInfo && indexID ? (
499+
<>
500+
<h4 className="preference__title">
501+
{t('Preferences.LibraryVersion')}
502+
</h4>
503+
<div>
504+
<VersionPicker
505+
ref={pickerRef}
506+
onChangeVersion={onChangeVersion}
507+
/>
513508
<p className="preference__paragraph">
514-
{t('Preferences.CustomVersionReset')}
509+
{t('Preferences.LibraryVersionInfo')}
515510
</p>
516-
<textarea className="preference__textarea">
517-
{'<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.7.0/p5.js"></script>\n' +
518-
'<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.7.0/addons/p5.sound.min.js"></script>'}
519-
</textarea>
520-
</>
521-
)}
522-
</div>
511+
</div>
512+
</>
513+
) : (
514+
<div>
515+
<Admonition>
516+
<p>{t('Preferences.CustomVersionInfo')}</p>
517+
</Admonition>
518+
<p className="preference__paragraph">
519+
{t('Preferences.CustomVersionReset')}
520+
</p>
521+
<TextArea
522+
className="preference__textarea"
523+
src={
524+
'<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.7.0/p5.js"></script>\n' +
525+
'<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.7.0/addons/p5.sound.min.js"></script>'
526+
}
527+
/>
528+
</div>
529+
)}
523530
</div>
524531
{versionInfo && indexID && (
525532
<>
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import React from 'react';
2+
import PropTypes from 'prop-types';
3+
import styled from 'styled-components';
4+
import { useTranslation } from 'react-i18next';
5+
import { useDispatch } from 'react-redux';
6+
import { CopyIcon } from '../../../common/icons';
7+
import { showToast } from '../actions/toast';
8+
9+
const TextAreaWrapper = styled.div`
10+
position: relative;
11+
`;
12+
13+
const CornerButton = styled.button`
14+
position: absolute;
15+
top: 0.5rem;
16+
right: 0.5rem;
17+
`;
18+
19+
export default function TextArea({ src, className }) {
20+
const { t } = useTranslation();
21+
const dispatch = useDispatch();
22+
const copyTextToClipboard = async () => {
23+
try {
24+
await navigator.clipboard.writeText(src);
25+
dispatch(showToast(t('Preferences.CopyToClipboardSuccess')));
26+
} catch (_e) {
27+
dispatch(showToast(t('Preferences.CopyToClipboardFailure'), 5000));
28+
}
29+
};
30+
31+
return (
32+
<TextAreaWrapper>
33+
<textarea className={className}>{src}</textarea>
34+
<CornerButton onClick={copyTextToClipboard}>
35+
<CopyIcon aria-label="Copy" />
36+
</CornerButton>
37+
</TextAreaWrapper>
38+
);
39+
}
40+
41+
TextArea.propTypes = {
42+
src: PropTypes.string.isRequired,
43+
className: PropTypes.string
44+
};
45+
46+
TextArea.defaultProps = {
47+
className: undefined
48+
};

client/styles/abstracts/_variables.scss

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,10 @@ $themes: (
126126
hint-item-active-outline-offset: 0,
127127
hint-inline-text-color-light: $middle-light,
128128
hint-inline-text-color: $middle-gray,
129+
130+
admonition-border: #ED225D,
131+
admonition-background: #FFE4EC,
132+
admonition-text: #AF0E3D,
129133
),
130134
dark: (
131135
logo-color: $p5js-pink,
@@ -221,6 +225,10 @@ $themes: (
221225
hint-item-active-outline-offset: 0,
222226
hint-inline-text-color-light: $middle-gray,
223227
hint-inline-text-color: #cfcfcf,
228+
229+
admonition-border: #ED225D,
230+
admonition-background: #FFE4EC,
231+
admonition-text: #AF0E3D,
224232
),
225233
contrast: (
226234
logo-color: $yellow,
@@ -316,6 +324,10 @@ $themes: (
316324
hint-item-active-outline-offset: -2px,
317325
hint-inline-text-color-light: $middle-gray,
318326
hint-inline-text-color: #cfcfcf,
327+
328+
admonition-border: #ED225D,
329+
admonition-background: $white,
330+
admonition-text: #AF0E3D,
319331
)
320332
);
321333

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
.admonition {
2+
@include themify() {
3+
padding: 1rem;
4+
margin-bottom: 1rem;
5+
margin-top: 1rem;
6+
background: getThemifyVariable('admonition-background');
7+
color: getThemifyVariable('admonition-text');
8+
border: 1px solid getThemifyVariable('admonition-border');
9+
border-left-width: 3px;
10+
}
11+
}
12+
13+
.admonition__icon {
14+
margin-right: 0.5rem;
15+
}
16+
17+
.admonition__title {
18+
font-weight: bold;
19+
margin-bottom: 0.5rem;
20+
}

client/styles/components/_preferences.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@
7272
}
7373

7474
.preference__textarea {
75+
font-family: Inconsolata, monospace;
7576
width: 100%;
7677
min-height: 8em;
7778
}

client/styles/main.scss

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
@import 'components/quick-add';
5555
@import 'components/skip-link';
5656
@import 'components/stars';
57+
@import 'components/admonition';
5758

5859
@import 'layout/dashboard';
5960
@import 'layout/ide';

translations/locales/en-US/translations.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,12 +218,14 @@
218218
"TableOutputARIA": "table output on",
219219
"LibraryVersion": "p5.js Version",
220220
"LibraryVersionInfo": "TODO Add helpful info about the new p5.js version, compatibility, etc.",
221-
"CustomVersionInfo": "It looks like you've changed the <script> tag to manage the version yourself. In that case, the version can't be managed from this tab, only from the code in index.html.",
222-
"CustomVersionReset": "If you do want to use the default libraries, you can replace your script tags in index.html to the following:",
221+
"CustomVersionInfo": "The version of p5.js is currently being managed in the code of index.html. This means it can't be adjusted from this tab.",
222+
"CustomVersionReset": "If you'd like to use the default libraries, you can replace the script tags in index.html with the following:",
223223
"SoundAddon": "p5.sound.js Addon",
224224
"PreloadAddon": "p5.js 2.0 Addon - Preload",
225225
"ShapesAddon": "p5.js 2.0 Addon - Shapes",
226-
"UndoSoundVersion": "Want to use p5.sound.js again? Turning it back on will restore the version you were using before."
226+
"UndoSoundVersion": "Want to use p5.sound.js again? Turning it back on will restore the version you were using before.",
227+
"CopyToClipboardSuccess": "Copied to clipboard!",
228+
"CopyToClipboardFailure": "We weren't able to copy the text, try selecting it and copying it manually."
227229
},
228230
"KeyboardShortcuts": {
229231
"Title": " Keyboard Shortcuts",
@@ -664,5 +666,8 @@
664666
},
665667
"SkipLink": {
666668
"PlaySketch": "Skip to Play Sketch"
669+
},
670+
"Admonition": {
671+
"Note": "Note"
667672
}
668673
}

0 commit comments

Comments
 (0)