diff --git a/src/components/Containers/Main/Main.js b/src/components/Containers/Main/Main.js
index f915f8c..32f4a1e 100644
--- a/src/components/Containers/Main/Main.js
+++ b/src/components/Containers/Main/Main.js
@@ -97,6 +97,34 @@ const Main = () => {
});
};
+ const setTabEditableHandler = id => {
+ tabs.setTabEditable(id);
+ };
+
+ const handleTabTitleClick = (id, event) => {
+ switch (event.detail) {
+ case 1:
+ if (tabs.activeTabId !== id) {
+ setTabEditableHandler(null);
+ }
+ setTabActiveHandler(id);
+ break;
+ case 2:
+ setTabActiveHandler(id);
+ setTabEditableHandler(id);
+ break;
+ default:
+ return;
+ }
+ };
+
+ const handleTabTitleBlur = (id, newTabName, prevTabName) => {
+ setTabEditableHandler(null);
+ if (newTabName && newTabName !== prevTabName) {
+ tabs.editTabName(id, newTabName);
+ }
+ };
+
const renderEmptyScreen = () => {
return (
@@ -123,8 +151,12 @@ const Main = () => {
setTabActiveHandler(tab.id)}
+ onBlur={tabNewName =>
+ handleTabTitleBlur(tab.id, tabNewName, tab.name)
+ }
+ onClick={e => handleTabTitleClick(tab.id, e)}
onDelete={e => removeTabHandler(e, tab.id)}
/>
));
diff --git a/src/components/UI/NavItem/NavItem.js b/src/components/UI/NavItem/NavItem.js
index f4e0058..4397a4d 100644
--- a/src/components/UI/NavItem/NavItem.js
+++ b/src/components/UI/NavItem/NavItem.js
@@ -1,16 +1,62 @@
import PropTypes from 'prop-types';
-import React from 'react';
+import React, {useState} from 'react';
import {ReactComponent as XIcon} from '../../../assets/svg/x.svg';
import styles from './NavItem.module.scss';
-const NavItem = ({text, isActive, onClick, onDelete}) => {
- const classes = [styles.navItem, isActive && styles.isActive].join(
- ' '
- );
+const NavItem = ({
+ text,
+ isActive,
+ isEditable,
+ onBlur,
+ onClick,
+ onDelete
+}) => {
+ const [tabNameInput, setTabNameInput] = useState(text);
+ const classes = [
+ styles.navItem,
+ isActive && styles.isActive,
+ isEditable && styles.isEditable
+ ].join(' ');
+ const handleKeyPress = event => {
+ if (event?.key === 'Enter') {
+ handleBlur(tabNameInput);
+ }
+ };
+ const editingStateStyle = {
+ maxWidth: 200
+ };
+ const viewingStateStyle = {
+ maxWidth: 142
+ };
+ const getInputSize = () => {
+ return tabNameInput?.length
+ ? (tabNameInput.length * 0.75).toFixed(0)
+ : 5;
+ };
+ const handleBlur = tabNameInput => {
+ if (tabNameInput) {
+ onBlur(tabNameInput);
+ } else {
+ setTabNameInput(text);
+ onBlur(text);
+ }
+ };
return (
);
@@ -19,6 +65,8 @@ const NavItem = ({text, isActive, onClick, onDelete}) => {
NavItem.propTypes = {
text: PropTypes.string,
isActive: PropTypes.bool,
+ isEditable: PropTypes.bool,
+ onBlur: PropTypes.func,
onClick: PropTypes.func,
onDelete: PropTypes.func
};
diff --git a/src/components/UI/NavItem/NavItem.module.scss b/src/components/UI/NavItem/NavItem.module.scss
index 0564cd9..bc1438a 100644
--- a/src/components/UI/NavItem/NavItem.module.scss
+++ b/src/components/UI/NavItem/NavItem.module.scss
@@ -2,13 +2,41 @@
.navItem {
color: $--color-1;
- border: none;
+ border: 0;
+ border-bottom: 3px solid transparent;
+ border-right: 1px solid transparent;
background: transparent;
font-weight: bold;
font-size: 15px;
cursor: pointer;
- transition: 0.3s;
+ transition: 0.1s;
padding-left: 10px;
+ display: flex;
+ flex-flow: row nowrap;
+ align-items: center;
+
+ > div {
+ overflow: hidden;
+ height: 20px;
+ display: inline-block;
+ margin-top: 2px;
+ border-bottom-color: transparent;
+ }
+
+ input {
+ border: 0;
+ outline: 0;
+ padding: 0;
+ appearance: none;
+ color: inherit;
+ height: inherit;
+ font-size: inherit;
+ background: inherit;
+ font-weight: inherit;
+ cursor: text;
+ width: auto;
+ transition: max-width 0.2s ease-in-out;
+ }
&:hover {
background-color: $--bg-color-memory;
@@ -16,10 +44,16 @@
&.isActive {
background-color: $--bg-color-editor;
- border-bottom: 3px solid $--color-5-active;
+ border-bottom-color: $--color-5-active;
cursor: default;
}
+ &.isEditable {
+ > div {
+ border-bottom: 1px solid #7c87ff;
+ }
+ }
+
svg {
margin-left: 10px;
cursor: pointer;
diff --git a/src/context/tabs/TabsProvider.js b/src/context/tabs/TabsProvider.js
index b09378d..ea3fe56 100644
--- a/src/context/tabs/TabsProvider.js
+++ b/src/context/tabs/TabsProvider.js
@@ -18,6 +18,14 @@ const TabsProvider = ({children}) => {
dispatch({type: actions.REMOVE_TAB, payload: id});
};
+ const editTabNameHandler = (id, name) => {
+ dispatch({type: actions.EDIT_TAB_NAME, payload: {id, name}});
+ };
+
+ const setTabEditableHandler = id => {
+ dispatch({type: actions.SET_TAB_NAME_EDITABLE, payload: id});
+ };
+
const setTabActiveHandler = id => {
const tab = getTabById(id);
setParam(tab.type, tab.file);
@@ -31,11 +39,14 @@ const TabsProvider = ({children}) => {
const context = {
tabs: state.tabs,
activeTabId: state.activeTabId,
+ editableTabNameId: state.editableTabNameId,
tabsCount: state.tabsCount,
removeTab: removeTabHandler,
setTabActive: setTabActiveHandler,
addTab: addTabHandler,
- getActiveTab: getActiveTabHandler
+ getActiveTab: getActiveTabHandler,
+ setTabEditable: setTabEditableHandler,
+ editTabName: editTabNameHandler
};
return (
diff --git a/src/context/tabs/tabs-context.js b/src/context/tabs/tabs-context.js
index 24bd757..7f114ea 100644
--- a/src/context/tabs/tabs-context.js
+++ b/src/context/tabs/tabs-context.js
@@ -6,7 +6,8 @@ const TabsContext = createContext({
removeTab: () => {},
setTabActive: () => {},
addTab: () => {},
- getActiveTab: () => {}
+ getActiveTab: () => {},
+ setTabEditable: () => {}
});
export {TabsContext};
diff --git a/src/context/tabs/tabs-reducer.js b/src/context/tabs/tabs-reducer.js
index 764ed6f..b1f53b3 100644
--- a/src/context/tabs/tabs-reducer.js
+++ b/src/context/tabs/tabs-reducer.js
@@ -3,13 +3,16 @@ import {id} from '../../utils/id';
const actions = {
ADD_TAB: 'Tab/ADD_TAB',
REMOVE_TAB: 'Tab/REMOVE_TAB',
- SET_TAB_ACTIVE: 'Tab/SET_TAB_ACTIVE'
+ SET_TAB_ACTIVE: 'Tab/SET_TAB_ACTIVE',
+ SET_TAB_NAME_EDITABLE: 'Tab/SET_TAB_NAME_EDITABLE',
+ EDIT_TAB_NAME: 'Tab/EDIT_TAB_NAME'
};
const initialState = {
tabs: [],
activeTabId: null,
- tabsCount: 0
+ tabsCount: 0,
+ editableTabNameId: null
};
const reducer = (state, action) => {
@@ -26,6 +29,20 @@ const reducer = (state, action) => {
};
}
+ case actions.EDIT_TAB_NAME: {
+ const {id, name} = action.payload;
+ let {tabs} = state;
+ const indexToEditName = tabs.findIndex(tab => tab.id === id);
+ return {
+ ...state,
+ tabs: [
+ ...tabs.slice(0, indexToEditName),
+ {...tabs[indexToEditName], name},
+ ...tabs.slice(indexToEditName + 1)
+ ]
+ };
+ }
+
case actions.REMOVE_TAB: {
const id = action.payload;
let {activeTabId, tabs} = state;
@@ -52,6 +69,12 @@ const reducer = (state, action) => {
activeTabId: action.payload
};
+ case actions.SET_TAB_NAME_EDITABLE:
+ return {
+ ...state,
+ editableTabNameId: action.payload
+ };
+
default:
return initialState;
}