diff --git a/src/components/gui/gui.css b/src/components/gui/gui.css index 5132af685bfc81f10541157fcd6e93a6e99292da..fa6c4ce1ab765f448678a6e1e2dd08bcd17bba54 100644 --- a/src/components/gui/gui.css +++ b/src/components/gui/gui.css @@ -57,10 +57,13 @@ .tab { flex-grow: 1; height: 80%; - margin-left: 1px; + margin-left: -0.5rem; - border-radius: $space $space 0 0; - border: none; + border-radius: 1rem 1rem 0 0; + border: $ui-pane-border 1px solid; + + padding: 0.125rem 1rem 0; + font-size: 0.7rem; background-color: #F6F8FA; color: #9AA1B5; @@ -72,13 +75,49 @@ user-select: none; } -.tab.is-selected { +/* Use z-indices to force left-on-top for tabs */ +.tab:nth-of-type(1) { + margin-left: 0; + z-index: 3; +} +.tab:nth-of-type(2) { + z-index: 2; +} +.tab:nth-of-type(3) { z-index: 1; - color: #40B9F5; +} + +.tab.is-selected { + color: $motion-primary; background-color: #FFFFFF; - border-bottom: $ui-background-blue 1px solid; + z-index: 4; /* Make sure selected is always above */ +} + +.tab img { + margin-right: 0.125rem; + filter: grayscale(100%); +} + +.tab.is-selected img { + filter: none; +} + +/* Tab style overrides from react-tabs */ +.tab.is-selected:after { + display: none; +} + +.tab.is-selected:focus { + outline: none; + box-shadow: none; + border-color: $ui-pane-border; +} + +.tab.is-selected:focus:after { + display: none; } +/* Body of the tabs */ .tabs { position: relative; flex-grow: 1; diff --git a/src/components/gui/gui.jsx b/src/components/gui/gui.jsx index 2ec53402bb78ec00bc83a373de6fdfc7c36bcbaf..37a66c308ddfbf10a1403ec63991372b88546ec7 100644 --- a/src/components/gui/gui.jsx +++ b/src/components/gui/gui.jsx @@ -1,7 +1,7 @@ import classNames from 'classnames'; import PropTypes from 'prop-types'; import React from 'react'; -import {defineMessages, injectIntl, intlShape} from 'react-intl'; +import {defineMessages, FormattedMessage, injectIntl, intlShape} from 'react-intl'; import {Tab, Tabs, TabList, TabPanel} from 'react-tabs'; import MediaQuery from 'react-responsive'; import tabStyles from 'react-tabs/style/react-tabs.css'; @@ -25,6 +25,9 @@ import WebGlModal from '../../containers/webgl-modal.jsx'; import layout from '../../lib/layout-constants.js'; import styles from './gui.css'; import addExtensionIcon from './icon--extensions.svg'; +import codeIcon from './icon--code.svg'; +import costumesIcon from './icon--costumes.svg'; +import soundsIcon from './icon--sounds.svg'; const messages = defineMessages({ addExtension: { @@ -110,9 +113,39 @@ const GUIComponent = props => { onSelect={onActivateTab} > <TabList className={tabClassNames.tabList}> - <Tab className={tabClassNames.tab}>Blocks</Tab> - <Tab className={tabClassNames.tab}>Costumes</Tab> - <Tab className={tabClassNames.tab}>Sounds</Tab> + <Tab className={tabClassNames.tab}> + <img + draggable={false} + src={codeIcon} + /> + <FormattedMessage + defaultMessage="Code" + description="Button to get to the code panel" + id="gui.gui.codeTab" + /> + </Tab> + <Tab className={tabClassNames.tab}> + <img + draggable={false} + src={costumesIcon} + /> + <FormattedMessage + defaultMessage="Costumes" + description="Button to get to the costumes panel" + id="gui.gui.costumesTab" + /> + </Tab> + <Tab className={tabClassNames.tab}> + <img + draggable={false} + src={soundsIcon} + /> + <FormattedMessage + defaultMessage="Sounds" + description="Button to get to the sounds panel" + id="gui.gui.soundsTab" + /> + </Tab> </TabList> <TabPanel className={tabClassNames.tabPanel}> <Box className={styles.blocksWrapper}> diff --git a/src/components/gui/icon--code.svg b/src/components/gui/icon--code.svg new file mode 100644 index 0000000000000000000000000000000000000000..390e683b16da01b13bbe8a2df0a0ac0711d9451e Binary files /dev/null and b/src/components/gui/icon--code.svg differ diff --git a/src/components/gui/icon--costumes.svg b/src/components/gui/icon--costumes.svg new file mode 100644 index 0000000000000000000000000000000000000000..de50ce39b013b123e5c94364aad49b80e6a14d32 Binary files /dev/null and b/src/components/gui/icon--costumes.svg differ diff --git a/src/components/gui/icon--sounds.svg b/src/components/gui/icon--sounds.svg new file mode 100644 index 0000000000000000000000000000000000000000..0de67c53780e9305d76d09363d349146222c0a87 Binary files /dev/null and b/src/components/gui/icon--sounds.svg differ diff --git a/test/integration/blocks.test.js b/test/integration/blocks.test.js index 9f073648882d6e3cad7eb8915edb72bbc3410c95..4f3411d5574521f651fbaad4b17ca553535629de 100644 --- a/test/integration/blocks.test.js +++ b/test/integration/blocks.test.js @@ -29,7 +29,7 @@ describe('Working with the blocks', () => { test('Blocks report when clicked in the toolbox', async () => { await loadUri(uri); await clickXpath('//button[@title="tryit"]'); - await clickText('Blocks'); + await clickText('Code'); await clickText('Operators', scope.blocksTab); await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for scroll animation await clickText('join', scope.blocksTab); // Click "join <hello> <world>" block @@ -58,7 +58,7 @@ describe('Working with the blocks', () => { test('Creating variables', async () => { await loadUri(uri); await clickXpath('//button[@title="tryit"]'); - await clickText('Blocks'); + await clickText('Code'); await clickText('Variables', scope.blocksTab); await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for scroll animation diff --git a/test/integration/localization.test.js b/test/integration/localization.test.js index 7c90b32214212f9baf87566375d563542b83d156..deaf1a78814631daa00c044bd595fd31bb6c2fa1 100644 --- a/test/integration/localization.test.js +++ b/test/integration/localization.test.js @@ -29,7 +29,7 @@ describe('Localization', () => { test.skip('Localization', async () => { await loadUri(uri); await clickXpath('//button[@title="tryit"]'); - await clickText('Blocks'); + await clickText('Code'); await clickXpath('//button[@title="Add Extension"]'); await clickText('Pen', scope.modal); // Modal closes await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for scroll animation