From 25a5d228490f879d65ca342151b4e01a6bb130b3 Mon Sep 17 00:00:00 2001 From: Jonathan Gin Date: Sat, 23 May 2020 02:50:32 -0400 Subject: [PATCH 1/6] Add basic tabs --- src/containers/App.jsx | 107 ++++++++++++++++++++++++++---------- src/containers/TabPanel.jsx | 51 +++++++++++++++++ src/containers/index.js | 1 + src/utils/index.js | 1 + src/utils/useFilters.js | 4 +- src/utils/useTabs.js | 69 +++++++++++++++++++++++ 6 files changed, 203 insertions(+), 30 deletions(-) create mode 100644 src/containers/TabPanel.jsx create mode 100644 src/utils/useTabs.js diff --git a/src/containers/App.jsx b/src/containers/App.jsx index 2ed4b68..f6c4c33 100644 --- a/src/containers/App.jsx +++ b/src/containers/App.jsx @@ -1,27 +1,48 @@ import React from "react"; -import { CssBaseline, ThemeProvider, Container, Box } from "@material-ui/core"; +import { AppBar, Tabs, Tab, CssBaseline, ThemeProvider, Container, Box } from "@material-ui/core"; +import AddIcon from "@material-ui/icons/Add"; +import Close from "@material-ui/icons/Close"; +import { makeStyles } from "@material-ui/core/styles"; import { ThemeProvider as StyledComponentsThemeProvider } from "styled-components"; import { - useFilters, useTitle, + useTabs, theme, - useShare, - useCalculation, } from "../utils"; -import { Title, Filter, Footer } from "../containers"; -import { ShareDialog, Chart, Table } from "../components"; +import { Title, Footer, TabPanel } from "../containers"; const App = () => { useTitle(); - const { inputFilters, filters, saveFilters } = useFilters(); - const { - onCloseShareModal, - showShareDialog, - openShareDialog, - shareFilters, - } = useShare(filters); + const tabClasses = useTabStyles(); + const tabsClasses = useTabsStyles(); + const iconClasses = useIconStyles(); + const {tabs, addTab, deleteTab, value, setValue} = useTabs(); - const result = useCalculation({ filters }); + const handleTabChange = (_event, newValue) => { + if (newValue === tabs.length) { + addTab(); + } else { + setValue(newValue); + } + }; + + const tabsMarkup = tabs.map((tab, index) => { + return ( + } + /> + ); + }); + + const panelMarkup = tabs.map((tab, index) => { + return ( + + ); + }); return ( @@ -30,24 +51,54 @@ const App = () => { <Box mx={[-1.5, 0]}> - <Filter - filters={inputFilters} - onChange={saveFilters} - openShareDialog={openShareDialog} - /> - <Chart {...result} /> - <Table {...result} /> - <Footer /> - </Box> + <AppBar position="static"> + <Tabs value={value} onChange={handleTabChange} scrollButtons="auto" variant="scrollable" classes={tabsClasses}> + {tabsMarkup} + <Tab label="Add island" icon={<AddIcon onClick={addTab} />} /> + </Tabs> + </AppBar> + {panelMarkup} + <Footer /> + </Box> </Container> - <ShareDialog - open={showShareDialog} - filters={shareFilters} - onClose={onCloseShareModal} - /> </StyledComponentsThemeProvider> </ThemeProvider> ); }; +const useTabsStyles = makeStyles(({ spacing, palette }) => ({ + root: { + marginLeft: spacing(1), + }, + indicator: { + height: 3, + borderTopLeftRadius: 3, + borderTopRightRadius: 3, + backgroundColor: palette.common.white, + }, +})); + +const useTabStyles = makeStyles(({ breakpoints, spacing }) => ({ + root: { + textTransform: 'initial', + margin: spacing(0, 2), + minWidth: 0, + [breakpoints.up('md')]: { + minWidth: 0, + }, + }, + wrapper: { + flexDirection: 'row-reverse', + fontWeight: 'normal', + letterSpacing: 0.5, + }, +})); + +const useIconStyles = makeStyles(({ spacing }) => ({ + root: { + marginTop: spacing(1), + marginLeft: spacing(1.5), + }, +})); + export default App; diff --git a/src/containers/TabPanel.jsx b/src/containers/TabPanel.jsx new file mode 100644 index 0000000..a4a3d78 --- /dev/null +++ b/src/containers/TabPanel.jsx @@ -0,0 +1,51 @@ +import React from "react"; +import { any, number } from "prop-types"; +import { useFilters, useShare, useCalculation } from "../utils"; +import { Filter } from "../containers"; +import { ShareDialog, Chart, Table } from "../components"; + +const TabPanel = ({ value, index, filterKey, ...other }) => { + const { inputFilters, filters, saveFilters } = useFilters(filterKey); + const { + onCloseShareModal, + showShareDialog, + openShareDialog, + shareFilters, + } = useShare(filters); + + const result = useCalculation({ filters }); + + return ( + <div + role="tabpanel" + hidden={value !== index} + id={`simple-tabpanel-${index}`} + {...other} + > + {value === index && ( + <> + <Filter + filters={inputFilters} + onChange={saveFilters} + openShareDialog={openShareDialog} + /> + <Chart {...result} /> + <Table {...result} /> + <ShareDialog + open={showShareDialog} + filters={shareFilters} + onClose={onCloseShareModal} + /> + </> + )} + </div> + ); +}; + +TabPanel.propTypes = { + value: number.isRequired, + index: number.isRequired, + filterKey: any.isRequired, +}; + +export default TabPanel; diff --git a/src/containers/index.js b/src/containers/index.js index cfd2c46..7df1139 100644 --- a/src/containers/index.js +++ b/src/containers/index.js @@ -1,4 +1,5 @@ export { default as App } from "./App"; +export { default as TabPanel } from "./TabPanel"; export { default as Filter } from "./Filter"; export { default as Footer } from "./Footer"; export { default as Localizer } from "./Localizer"; diff --git a/src/utils/index.js b/src/utils/index.js index 2cf4679..37a6fa5 100644 --- a/src/utils/index.js +++ b/src/utils/index.js @@ -5,3 +5,4 @@ export { default as useShare } from "./useShare"; export { default as useTitle } from "./useTitle"; export { default as useWeekDays } from "./useWeekDays"; export { default as useCalculation } from "./useCalculation"; +export { default as useTabs } from "./useTabs"; diff --git a/src/utils/useFilters.js b/src/utils/useFilters.js index ff8307f..f797b51 100644 --- a/src/utils/useFilters.js +++ b/src/utils/useFilters.js @@ -1,8 +1,8 @@ import { useEffect, useMemo } from "react"; import { useLocalStorage } from "react-use"; -const useFilters = () => { - const [filters, saveFilters] = useLocalStorage("filters", []); +const useFilters = (key) => { + const [filters, saveFilters] = useLocalStorage(key, []); // Array of strings const inputFilters = useMemo( diff --git a/src/utils/useTabs.js b/src/utils/useTabs.js new file mode 100644 index 0000000..4f02765 --- /dev/null +++ b/src/utils/useTabs.js @@ -0,0 +1,69 @@ +import { useState, useEffect } from "react"; +import { useLocalStorage } from "react-use"; + +const useTabs = () => { + const [value, setValue] = useState(0); + const [tabs, saveTabs] = useLocalStorage("tablist", [ + { + id: 0, + key: 'filters-0', + }, + ]); + + useEffect(() => { + if (!Array.isArray(tabs)) { + saveTabs([]); + } + }, [tabs, saveTabs]); + + const addTab = () => { + let id = 0 + for (id = 0; id < tabs.length; id++) { + if (tabs[id].id !== id) { + break; + } + } + saveTabs([...tabs.slice(0, id), { + id, + key: `filters-${id}`, + }, ...tabs.slice(id)]); + }; + + const deleteTab = (event) => { + // Prevent MaterialUI from switching tabs + event.stopPropagation(); + + // Prevent deleting the last tab + if (tabs.length === 1) { + return; + } + + const tabId = parseInt(event.target.id, 10); + let tabIdIndex = 0; + + const tabList = tabs.filter((tab, index) => { + if (tab.id === tabId) { + tabIdIndex = index; + localStorage.removeItem(tab.key); + } + return tab.id !== tabId; + }); + + if (tabIdIndex !== 0) { + setValue(tabIdIndex - 1) + } + + saveTabs(tabList); + }; + + return { + value, + setValue, + tabs, + saveTabs, + addTab, + deleteTab, + }; +}; + +export default useTabs; From 7e2d96b50bbc1f99d553da5877e3ef3c3e645afb Mon Sep 17 00:00:00 2001 From: Jonathan Gin <jonathangin52@gmail.com> Date: Sat, 23 May 2020 18:58:04 -0400 Subject: [PATCH 2/6] Modularize TabPanel, update styling --- src/containers/App.jsx | 88 ++++++----------------------------- src/containers/Calculator.jsx | 41 ++++++++++++++++ src/containers/IslandTabs.jsx | 87 ++++++++++++++++++++++++++++++++++ src/containers/TabPanel.jsx | 43 ++++------------- src/containers/index.js | 2 + src/utils/useTabs.js | 25 +++++++--- 6 files changed, 169 insertions(+), 117 deletions(-) create mode 100644 src/containers/Calculator.jsx create mode 100644 src/containers/IslandTabs.jsx diff --git a/src/containers/App.jsx b/src/containers/App.jsx index f6c4c33..f5f7a50 100644 --- a/src/containers/App.jsx +++ b/src/containers/App.jsx @@ -1,48 +1,20 @@ import React from "react"; -import { AppBar, Tabs, Tab, CssBaseline, ThemeProvider, Container, Box } from "@material-ui/core"; -import AddIcon from "@material-ui/icons/Add"; -import Close from "@material-ui/icons/Close"; -import { makeStyles } from "@material-ui/core/styles"; +import { CssBaseline, ThemeProvider, Container, Box } from "@material-ui/core"; import { ThemeProvider as StyledComponentsThemeProvider } from "styled-components"; import { useTitle, useTabs, theme, } from "../utils"; -import { Title, Footer, TabPanel } from "../containers"; +import { Title, Footer, IslandTabs, Calculator } from "../containers"; const App = () => { useTitle(); - const tabClasses = useTabStyles(); - const tabsClasses = useTabsStyles(); - const iconClasses = useIconStyles(); - const {tabs, addTab, deleteTab, value, setValue} = useTabs(); + const {tabs, addTab, deleteTab, value, handleTabChange} = useTabs(); - const handleTabChange = (_event, newValue) => { - if (newValue === tabs.length) { - addTab(); - } else { - setValue(newValue); - } - }; - - const tabsMarkup = tabs.map((tab, index) => { - return ( - <Tab - key={tab.key} - value={index} - label={`Island ${tab.id + 1}`} - classes={tabClasses} - icon={<Close id={tab.id} onClick={deleteTab} fontSize="small" classes={iconClasses} />} - /> - ); - }); - - const panelMarkup = tabs.map((tab, index) => { - return ( - <TabPanel key={tab.key} value={value} filterKey={tab.key} index={index} /> - ); - }); + const panelMarkup = tabs.map((tab, index) => ( + <Calculator filterKey={tab.key} key={tab.key} value={value} index={index} /> + )); return ( <ThemeProvider theme={theme}> @@ -51,12 +23,13 @@ const App = () => { <Container maxWidth="md"> <Title /> <Box mx={[-1.5, 0]}> - <AppBar position="static"> - <Tabs value={value} onChange={handleTabChange} scrollButtons="auto" variant="scrollable" classes={tabsClasses}> - {tabsMarkup} - <Tab label="Add island" icon={<AddIcon onClick={addTab} />} /> - </Tabs> - </AppBar> + <IslandTabs + tabs={tabs} + value={value} + onAdd={addTab} + onDelete={deleteTab} + onChange={handleTabChange} + /> {panelMarkup} <Footer /> </Box> @@ -66,39 +39,4 @@ const App = () => { ); }; -const useTabsStyles = makeStyles(({ spacing, palette }) => ({ - root: { - marginLeft: spacing(1), - }, - indicator: { - height: 3, - borderTopLeftRadius: 3, - borderTopRightRadius: 3, - backgroundColor: palette.common.white, - }, -})); - -const useTabStyles = makeStyles(({ breakpoints, spacing }) => ({ - root: { - textTransform: 'initial', - margin: spacing(0, 2), - minWidth: 0, - [breakpoints.up('md')]: { - minWidth: 0, - }, - }, - wrapper: { - flexDirection: 'row-reverse', - fontWeight: 'normal', - letterSpacing: 0.5, - }, -})); - -const useIconStyles = makeStyles(({ spacing }) => ({ - root: { - marginTop: spacing(1), - marginLeft: spacing(1.5), - }, -})); - export default App; diff --git a/src/containers/Calculator.jsx b/src/containers/Calculator.jsx new file mode 100644 index 0000000..78db731 --- /dev/null +++ b/src/containers/Calculator.jsx @@ -0,0 +1,41 @@ +import React from "react"; +import PropTypes from "prop-types"; +import { useFilters, useShare, useCalculation } from "../utils"; +import { Filter, TabPanel } from "../containers"; +import { ShareDialog, Chart, Table } from "../components"; + +const Calculator = ({ value, index, filterKey }) => { + const { inputFilters, filters, saveFilters } = useFilters(filterKey); + const { + onCloseShareModal, + showShareDialog, + openShareDialog, + shareFilters, + } = useShare(filters); + const result = useCalculation({ filters }); + + return ( + <TabPanel value={value} index={index}> + <Filter + filters={inputFilters} + onChange={saveFilters} + openShareDialog={openShareDialog} + /> + <Chart {...result} /> + <Table {...result} /> + <ShareDialog + open={showShareDialog} + filters={shareFilters} + onClose={onCloseShareModal} + /> + </TabPanel> + ); +}; + +Calculator.propTypes = { + value: PropTypes.number.isRequired, + index: PropTypes.number.isRequired, + filterKey: PropTypes.string.isRequired, +}; + +export default Calculator; diff --git a/src/containers/IslandTabs.jsx b/src/containers/IslandTabs.jsx new file mode 100644 index 0000000..22df199 --- /dev/null +++ b/src/containers/IslandTabs.jsx @@ -0,0 +1,87 @@ +import React from "react"; +import PropTypes from "prop-types"; +import { makeStyles } from "@material-ui/styles"; +import { Tab, Tabs } from "@material-ui/core"; +import { Add, Close } from "@material-ui/icons"; + +const useTabsStyles = makeStyles(({ spacing }) => ({ + root: { + marginLeft: spacing(2), + }, + indicator: { + backgroundColor: "#18A558", + }, +})); + +const useTabStyles = makeStyles(({ breakpoints, spacing }) => ({ + root: { + textTransform: "initial", + padding: spacing(-1, 2), + minWidth: 0, + [breakpoints.up("md")]: { + minWidth: 0, + }, + "&:hover": { + backgroundColor: "rgba(13, 152, 186, 0.1)", + "& .MuiTab-label": { + color: "#18A558", + }, + }, + "&$selected": { + "& *": { + color: "#18A558", + }, + }, + }, + selected: {}, + textColorInherit: { + opacity: 1, + }, + wrapper: { + textTransform: "initial", + flexDirection: "row-reverse", + letterSpacing: 0.5, + '& svg, .material-icons': { + marginLeft: 12, + marginTop: 7, + }, + }, +})); + +const IslandTabs = ({ tabs, onAdd, onDelete, onChange, value }) => { + const tabClasses = useTabStyles(); + const tabsClasses = useTabsStyles(); + + return ( + <Tabs variant="scrollable" scrollButtons="auto" value={value} onChange={onChange} classes={tabsClasses}> + {tabs.map((tab) => ( + <Tab + key={tab.key} + label={`Island ${tab.id + 1}`} + disableRipple + icon={<Close id={tab.id} onClick={onDelete} fontSize="small" />} + classes={{ + ...tabClasses, + wrapper: `${tabClasses.wrapper} MuiTab-label`, + }} + /> + ))} + <Tab label="Add island" classes={tabClasses} icon={<Add onClick={onAdd} />} /> + </Tabs> + ); +}; + +IslandTabs.propTypes = { + tabs: PropTypes.arrayOf( + PropTypes.shape({ + id: PropTypes.number.isRequired, + key: PropTypes.string.isRequired, + }), + ), + value: PropTypes.number.isRequired, + onChange: PropTypes.func.isRequired, + onAdd: PropTypes.func.isRequired, + onDelete: PropTypes.func.isRequired, +}; + +export default IslandTabs; diff --git a/src/containers/TabPanel.jsx b/src/containers/TabPanel.jsx index a4a3d78..8e5b2f9 100644 --- a/src/containers/TabPanel.jsx +++ b/src/containers/TabPanel.jsx @@ -1,51 +1,24 @@ import React from "react"; -import { any, number } from "prop-types"; -import { useFilters, useShare, useCalculation } from "../utils"; -import { Filter } from "../containers"; -import { ShareDialog, Chart, Table } from "../components"; - -const TabPanel = ({ value, index, filterKey, ...other }) => { - const { inputFilters, filters, saveFilters } = useFilters(filterKey); - const { - onCloseShareModal, - showShareDialog, - openShareDialog, - shareFilters, - } = useShare(filters); - - const result = useCalculation({ filters }); +import PropTypes from "prop-types"; +// Manual implementation of https://material-ui.com/api/tab-panel/ +// TabPanel not yet available in @material-ui/core +const TabPanel = ({ value, index, children }) => { return ( <div role="tabpanel" hidden={value !== index} id={`simple-tabpanel-${index}`} - {...other} > - {value === index && ( - <> - <Filter - filters={inputFilters} - onChange={saveFilters} - openShareDialog={openShareDialog} - /> - <Chart {...result} /> - <Table {...result} /> - <ShareDialog - open={showShareDialog} - filters={shareFilters} - onClose={onCloseShareModal} - /> - </> - )} + {value === index && children} </div> ); }; TabPanel.propTypes = { - value: number.isRequired, - index: number.isRequired, - filterKey: any.isRequired, + value: PropTypes.number.isRequired, + index: PropTypes.number.isRequired, + children: PropTypes.node, }; export default TabPanel; diff --git a/src/containers/index.js b/src/containers/index.js index 7df1139..189872b 100644 --- a/src/containers/index.js +++ b/src/containers/index.js @@ -1,5 +1,7 @@ export { default as App } from "./App"; +export { default as IslandTabs } from "./IslandTabs"; export { default as TabPanel } from "./TabPanel"; +export { default as Calculator } from "./Calculator"; export { default as Filter } from "./Filter"; export { default as Footer } from "./Footer"; export { default as Localizer } from "./Localizer"; diff --git a/src/utils/useTabs.js b/src/utils/useTabs.js index 4f02765..9edcf69 100644 --- a/src/utils/useTabs.js +++ b/src/utils/useTabs.js @@ -1,18 +1,20 @@ import { useState, useEffect } from "react"; import { useLocalStorage } from "react-use"; +const DEFAULT_TAB_LIST = [ + { + id: 0, + key: "filters-0", + }, +]; + const useTabs = () => { const [value, setValue] = useState(0); - const [tabs, saveTabs] = useLocalStorage("tablist", [ - { - id: 0, - key: 'filters-0', - }, - ]); + const [tabs, saveTabs] = useLocalStorage("tablist", DEFAULT_TAB_LIST); useEffect(() => { if (!Array.isArray(tabs)) { - saveTabs([]); + saveTabs(DEFAULT_TAB_LIST); } }, [tabs, saveTabs]); @@ -56,6 +58,14 @@ const useTabs = () => { saveTabs(tabList); }; + const handleTabChange = (_event, newValue) => { + if (newValue === tabs.length) { + addTab(); + } else { + setValue(newValue); + } + }; + return { value, setValue, @@ -63,6 +73,7 @@ const useTabs = () => { saveTabs, addTab, deleteTab, + handleTabChange, }; }; From aae9445f84e15af4040a37b88b8ba7acf0ee099e Mon Sep 17 00:00:00 2001 From: Jonathan Gin <jonathangin52@gmail.com> Date: Sat, 23 May 2020 22:35:49 -0400 Subject: [PATCH 3/6] Memoize useTab functions --- src/utils/useTabs.js | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/utils/useTabs.js b/src/utils/useTabs.js index 9edcf69..de821e1 100644 --- a/src/utils/useTabs.js +++ b/src/utils/useTabs.js @@ -1,4 +1,4 @@ -import { useState, useEffect } from "react"; +import { useState, useEffect, useCallback } from "react"; import { useLocalStorage } from "react-use"; const DEFAULT_TAB_LIST = [ @@ -18,7 +18,7 @@ const useTabs = () => { } }, [tabs, saveTabs]); - const addTab = () => { + const addTab = useCallback(() => { let id = 0 for (id = 0; id < tabs.length; id++) { if (tabs[id].id !== id) { @@ -29,9 +29,9 @@ const useTabs = () => { id, key: `filters-${id}`, }, ...tabs.slice(id)]); - }; + }, [tabs, saveTabs]); - const deleteTab = (event) => { + const deleteTab = useCallback((event) => { // Prevent MaterialUI from switching tabs event.stopPropagation(); @@ -40,37 +40,35 @@ const useTabs = () => { return; } + let deletedTabIndex = 0; const tabId = parseInt(event.target.id, 10); - let tabIdIndex = 0; const tabList = tabs.filter((tab, index) => { if (tab.id === tabId) { - tabIdIndex = index; + deletedTabIndex = index; localStorage.removeItem(tab.key); } return tab.id !== tabId; }); - if (tabIdIndex !== 0) { - setValue(tabIdIndex - 1) + if (deletedTabIndex !== 0) { + setValue(deletedTabIndex - 1) } saveTabs(tabList); - }; + }, [tabs, saveTabs]); - const handleTabChange = (_event, newValue) => { + const handleTabChange = useCallback((_event, newValue) => { if (newValue === tabs.length) { addTab(); } else { setValue(newValue); } - }; + }, [tabs, addTab]); return { value, - setValue, tabs, - saveTabs, addTab, deleteTab, handleTabChange, From 6c22f2ad720a5c5103bfc90106c9b448a13947b4 Mon Sep 17 00:00:00 2001 From: Jonathan Gin <jonathangin52@gmail.com> Date: Sat, 23 May 2020 23:42:05 -0400 Subject: [PATCH 4/6] Only show delete tab icon when tab is selected --- src/containers/IslandTabs.jsx | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/containers/IslandTabs.jsx b/src/containers/IslandTabs.jsx index 22df199..571f613 100644 --- a/src/containers/IslandTabs.jsx +++ b/src/containers/IslandTabs.jsx @@ -17,9 +17,8 @@ const useTabStyles = makeStyles(({ breakpoints, spacing }) => ({ root: { textTransform: "initial", padding: spacing(-1, 2), - minWidth: 0, [breakpoints.up("md")]: { - minWidth: 0, + minWidth: 120, }, "&:hover": { backgroundColor: "rgba(13, 152, 186, 0.1)", @@ -38,7 +37,6 @@ const useTabStyles = makeStyles(({ breakpoints, spacing }) => ({ opacity: 1, }, wrapper: { - textTransform: "initial", flexDirection: "row-reverse", letterSpacing: 0.5, '& svg, .material-icons': { @@ -54,12 +52,12 @@ const IslandTabs = ({ tabs, onAdd, onDelete, onChange, value }) => { return ( <Tabs variant="scrollable" scrollButtons="auto" value={value} onChange={onChange} classes={tabsClasses}> - {tabs.map((tab) => ( + {tabs.map((tab, index) => ( <Tab key={tab.key} label={`Island ${tab.id + 1}`} disableRipple - icon={<Close id={tab.id} onClick={onDelete} fontSize="small" />} + icon={value === index && <Close id={tab.id} onClick={onDelete} fontSize="small" />} classes={{ ...tabClasses, wrapper: `${tabClasses.wrapper} MuiTab-label`, From 91f4dd57c19e8219a539d3e8c4d4251c8e5f8c95 Mon Sep 17 00:00:00 2001 From: Jonathan Gin <jonathangin52@gmail.com> Date: Sat, 23 May 2020 23:57:08 -0400 Subject: [PATCH 5/6] Add text to localizations --- src/containers/IslandTabs.jsx | 6 ++++-- src/locales/en/translation.json | 4 +++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/containers/IslandTabs.jsx b/src/containers/IslandTabs.jsx index 571f613..e0630de 100644 --- a/src/containers/IslandTabs.jsx +++ b/src/containers/IslandTabs.jsx @@ -1,5 +1,6 @@ import React from "react"; import PropTypes from "prop-types"; +import { useTranslation } from "react-i18next"; import { makeStyles } from "@material-ui/styles"; import { Tab, Tabs } from "@material-ui/core"; import { Add, Close } from "@material-ui/icons"; @@ -47,6 +48,7 @@ const useTabStyles = makeStyles(({ breakpoints, spacing }) => ({ })); const IslandTabs = ({ tabs, onAdd, onDelete, onChange, value }) => { + const { t } = useTranslation() const tabClasses = useTabStyles(); const tabsClasses = useTabsStyles(); @@ -55,7 +57,7 @@ const IslandTabs = ({ tabs, onAdd, onDelete, onChange, value }) => { {tabs.map((tab, index) => ( <Tab key={tab.key} - label={`Island ${tab.id + 1}`} + label={`${t("Island")} ${tab.id + 1}`} disableRipple icon={value === index && <Close id={tab.id} onClick={onDelete} fontSize="small" />} classes={{ @@ -64,7 +66,7 @@ const IslandTabs = ({ tabs, onAdd, onDelete, onChange, value }) => { }} /> ))} - <Tab label="Add island" classes={tabClasses} icon={<Add onClick={onAdd} />} /> + <Tab label={t("Add Island")} classes={tabClasses} icon={<Add onClick={onAdd} />} /> </Tabs> ); }; diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index 3d1dbd1..3aaf024 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -33,5 +33,7 @@ "Chance": "Chance", "Pattern": "Pattern", "patternNames": "Fluctuating_High Spike_Decreasing_Small Spike", - "All Patterns": "All Patterns" + "All Patterns": "All Patterns", + "Add Island": "Add Island", + "Island": "Island" } From e9c91463cb60eebc0fa6b73736145225f871536e Mon Sep 17 00:00:00 2001 From: Jonathan Gin <jonathangin52@gmail.com> Date: Sun, 24 May 2020 00:22:25 -0400 Subject: [PATCH 6/6] Switch to new tab when adding island --- src/utils/useTabs.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/utils/useTabs.js b/src/utils/useTabs.js index de821e1..6cc7711 100644 --- a/src/utils/useTabs.js +++ b/src/utils/useTabs.js @@ -25,6 +25,7 @@ const useTabs = () => { break; } } + setValue(id); saveTabs([...tabs.slice(0, id), { id, key: `filters-${id}`,