Skip to content

Commit bed52c3

Browse files
committed
Use icons in toolbar
1 parent 8d574ee commit bed52c3

File tree

5 files changed

+147
-14
lines changed

5 files changed

+147
-14
lines changed

src/components/workspace/CodeSandboxButton.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,11 @@ export const CodeSandboxButton = memo(function CodeSandboxButton({
135135
target="_blank"
136136
>
137137
<input type="hidden" name="parameters" value={parameters} />
138-
<button style={styles.button} type="submit">
138+
<button
139+
title={internalOptions.strings.codesandbox}
140+
style={styles.button}
141+
type="submit"
142+
>
139143
<HeaderLink>{children}</HeaderLink>
140144
</button>
141145
</form>

src/components/workspace/HeaderLink.tsx

Lines changed: 42 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,34 +2,67 @@ import React, { CSSProperties, memo } from 'react'
22
import { mergeStyles, prefixObject } from '../../utils/Styles'
33

44
const styles = prefixObject({
5+
buttonReset: {
6+
border: 'none',
7+
margin: '0',
8+
padding: '0',
9+
width: 'auto',
10+
overflow: 'visible',
11+
background: 'transparent',
12+
color: 'inherit',
13+
font: 'inherit',
14+
lineHeight: 'normal',
15+
WebkitFontSmoothing: 'inherit',
16+
MozOsxFontSmoothing: 'inherit',
17+
WebkitAppearance: 'none',
18+
},
519
text: {
620
color: '#FFF',
721
fontSize: 13,
822
fontFamily: 'proxima-nova, "Helvetica Neue", Helvetica, Arial, sans-serif',
9-
padding: '0 20px',
23+
marginRight: '20px',
1024
display: 'flex',
1125
alignItems: 'center',
1226
cursor: 'pointer',
13-
textDecoration: 'underline',
27+
textDecoration: 'none',
1428
},
1529
})
1630

1731
interface Props {
18-
children: React.ReactNode
32+
href?: string
1933
textStyle?: CSSProperties
34+
title?: string
2035
onClick?: () => void
36+
children: React.ReactNode
2137
}
2238

23-
export default memo(function Fullscreen({
39+
export default memo(function HeaderLink({
2440
textStyle,
41+
href,
2542
onClick,
43+
title,
2644
children,
2745
}: Props) {
2846
const computedTextStyle = mergeStyles(styles.text, textStyle)
47+
const buttonStyle = mergeStyles(styles.buttonReset, styles.text, textStyle)
2948

30-
return (
31-
<div style={computedTextStyle} onClick={onClick}>
32-
{children}
33-
</div>
34-
)
49+
if (href) {
50+
return (
51+
<a
52+
title={title}
53+
style={computedTextStyle}
54+
onClick={onClick}
55+
href={href}
56+
target="_blank"
57+
>
58+
{children}
59+
</a>
60+
)
61+
} else {
62+
return (
63+
<button title={title} style={buttonStyle} onClick={onClick}>
64+
{children}
65+
</button>
66+
)
67+
}
3568
})

src/components/workspace/Icons.tsx

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
// https://github.com/radix-ui/icons
2+
3+
// MIT License
4+
//
5+
// Copyright (c) 2020 Modulz
6+
//
7+
// Permission is hereby granted, free of charge, to any person obtaining a copy
8+
// of this software and associated documentation files (the "Software"), to deal
9+
// in the Software without restriction, including without limitation the rights
10+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
// copies of the Software, and to permit persons to whom the Software is
12+
// furnished to do so, subject to the following conditions:
13+
//
14+
// The above copyright notice and this permission notice shall be included in all
15+
// copies or substantial portions of the Software.
16+
//
17+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23+
// SOFTWARE.
24+
25+
import React, { memo } from 'react'
26+
27+
type IconProps = React.SVGProps<SVGSVGElement>
28+
29+
const defaultProps: IconProps = {
30+
width: '15',
31+
height: '15',
32+
viewBox: '0 0 15 15',
33+
fill: 'none',
34+
xmlns: 'http://www.w3.org/2000/svg',
35+
}
36+
37+
export const EnterFullScreenIcon = memo(
38+
({ color = 'currentColor', ...props }: IconProps) => {
39+
return (
40+
<svg {...defaultProps} {...props}>
41+
<path
42+
d="M2 2.5C2 2.22386 2.22386 2 2.5 2H5.5C5.77614 2 6 2.22386 6 2.5C6 2.77614 5.77614 3 5.5 3H3V5.5C3 5.77614 2.77614 6 2.5 6C2.22386 6 2 5.77614 2 5.5V2.5ZM9 2.5C9 2.22386 9.22386 2 9.5 2H12.5C12.7761 2 13 2.22386 13 2.5V5.5C13 5.77614 12.7761 6 12.5 6C12.2239 6 12 5.77614 12 5.5V3H9.5C9.22386 3 9 2.77614 9 2.5ZM2.5 9C2.77614 9 3 9.22386 3 9.5V12H5.5C5.77614 12 6 12.2239 6 12.5C6 12.7761 5.77614 13 5.5 13H2.5C2.22386 13 2 12.7761 2 12.5V9.5C2 9.22386 2.22386 9 2.5 9ZM12.5 9C12.7761 9 13 9.22386 13 9.5V12.5C13 12.7761 12.7761 13 12.5 13H9.5C9.22386 13 9 12.7761 9 12.5C9 12.2239 9.22386 12 9.5 12H12V9.5C12 9.22386 12.2239 9 12.5 9Z"
43+
fill={color}
44+
fillRule="evenodd"
45+
clipRule="evenodd"
46+
/>
47+
</svg>
48+
)
49+
}
50+
)
51+
52+
export const ExternalLinkIcon = memo(
53+
({ color = 'currentColor', ...props }: IconProps) => {
54+
return (
55+
<svg {...defaultProps} {...props}>
56+
<path
57+
d="M3 2C2.44772 2 2 2.44772 2 3V12C2 12.5523 2.44772 13 3 13H12C12.5523 13 13 12.5523 13 12V8.5C13 8.22386 12.7761 8 12.5 8C12.2239 8 12 8.22386 12 8.5V12H3V3L6.5 3C6.77614 3 7 2.77614 7 2.5C7 2.22386 6.77614 2 6.5 2H3ZM12.8536 2.14645C12.9015 2.19439 12.9377 2.24964 12.9621 2.30861C12.9861 2.36669 12.9996 2.4303 13 2.497L13 2.5V2.50049V5.5C13 5.77614 12.7761 6 12.5 6C12.2239 6 12 5.77614 12 5.5V3.70711L6.85355 8.85355C6.65829 9.04882 6.34171 9.04882 6.14645 8.85355C5.95118 8.65829 5.95118 8.34171 6.14645 8.14645L11.2929 3H9.5C9.22386 3 9 2.77614 9 2.5C9 2.22386 9.22386 2 9.5 2H12.4999H12.5C12.5678 2 12.6324 2.01349 12.6914 2.03794C12.7504 2.06234 12.8056 2.09851 12.8536 2.14645Z"
58+
fill={color}
59+
fillRule="evenodd"
60+
clipRule="evenodd"
61+
/>
62+
</svg>
63+
)
64+
}
65+
)
66+
67+
export const CubeIcon = memo(
68+
({ color = 'currentColor', ...props }: IconProps) => {
69+
return (
70+
<svg {...defaultProps} {...props}>
71+
<path
72+
d="M7.28856 0.796908C7.42258 0.734364 7.57742 0.734364 7.71144 0.796908L13.7114 3.59691C13.8875 3.67906 14 3.85574 14 4.05V10.95C14 11.1443 13.8875 11.3209 13.7114 11.4031L7.71144 14.2031C7.57742 14.2656 7.42258 14.2656 7.28856 14.2031L1.28856 11.4031C1.11252 11.3209 1 11.1443 1 10.95V4.05C1 3.85574 1.11252 3.67906 1.28856 3.59691L7.28856 0.796908ZM2 4.80578L7 6.93078V12.9649L2 10.6316V4.80578ZM8 12.9649L13 10.6316V4.80578L8 6.93078V12.9649ZM7.5 6.05672L12.2719 4.02866L7.5 1.80176L2.72809 4.02866L7.5 6.05672Z"
73+
fill={color}
74+
fillRule="evenodd"
75+
clipRule="evenodd"
76+
/>
77+
</svg>
78+
)
79+
}
80+
)

src/components/workspace/panes/EditorPane.tsx

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import type { WorkspaceDiff } from '../App'
2222
import { TypeScriptOptions, UserInterfaceStrings } from '../../../utils/options'
2323
import { useOptions } from '../../../contexts/OptionsContext'
2424
import { CodeSandboxButton } from '../CodeSandboxButton'
25+
import { CubeIcon, EnterFullScreenIcon, ExternalLinkIcon } from '../Icons'
2526

2627
const toggleFullscreen = () => (screenfull as any).toggle()
2728

@@ -117,19 +118,30 @@ export default memo(function EditorPane({
117118

118119
const headerElements = (
119120
<>
120-
{fullscreen && (
121+
{internalOptions.openInNewWindow && (
121122
<HeaderLink
123+
title={strings.openInNewWindow}
122124
textStyle={externalStyles.tabText}
123-
onClick={toggleFullscreen}
125+
// There may not be a need to guard here, but just in case it runs server-side
126+
href={typeof location !== undefined ? location.href : undefined}
124127
>
125-
{strings.fullscreen}
128+
<ExternalLinkIcon />
126129
</HeaderLink>
127130
)}
128131
{internalOptions.codesandbox && (
129132
<CodeSandboxButton files={files}>
130-
{strings.codesandbox}
133+
<CubeIcon />
131134
</CodeSandboxButton>
132135
)}
136+
{fullscreen && (
137+
<HeaderLink
138+
title={strings.fullscreen}
139+
textStyle={externalStyles.tabText}
140+
onClick={toggleFullscreen}
141+
>
142+
<EnterFullScreenIcon />
143+
</HeaderLink>
144+
)}
133145
</>
134146
)
135147

src/utils/options.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ const userInterfaceStrings = {
3535
noErrors: 'No Errors',
3636
showDetails: 'Show Details',
3737
fullscreen: 'Fullscreen',
38+
openInNewWindow: 'Open in new window',
3839
codesandbox: 'Open in CodeSandbox',
3940
}
4041

@@ -59,6 +60,7 @@ export interface PublicOptions {
5960
styles?: ExternalStyles
6061
fullscreen?: boolean
6162
codesandbox?: boolean
63+
openInNewWindow?: boolean
6264
sharedEnvironment?: boolean
6365
compiler?: CompilerOptions
6466
playground?: Partial<PlaygroundOptions>
@@ -296,6 +298,7 @@ export function normalize(options: PublicOptions): InternalOptions {
296298
styles = Object.assign({}, presetOptions[preset]?.styles, options.styles),
297299
fullscreen = false,
298300
codesandbox = false,
301+
openInNewWindow = false,
299302
sharedEnvironment = false,
300303
panes = ['editor', 'player'],
301304
responsivePaneSets = [],
@@ -371,6 +374,7 @@ export function normalize(options: PublicOptions): InternalOptions {
371374
styles,
372375
strings: Object.assign({}, userInterfaceStrings, rawStrings),
373376
codesandbox,
377+
openInNewWindow,
374378
fullscreen,
375379
sharedEnvironment,
376380
responsivePaneSets: normalizedPaneSets,

0 commit comments

Comments
 (0)