@@ -52,7 +56,7 @@ const MainLayout = ({ children, location, uiConfig }) => {
                                 position: 'fixed',
                                 right: '0',
                                 bottom: '-4px',
-                                zIndex: '1',
+                                zIndex: 1,
                             }}
                         >
                             
@@ -64,9 +68,3 @@ const MainLayout = ({ children, location, uiConfig }) => {
         >
     );
 };
-
-MainLayout.propTypes = {
-    location: PropTypes.object.isRequired,
-};
-
-export default MainLayout;
diff --git a/frontend/src/component/layout/MainLayout/index.js b/frontend/src/component/layout/MainLayout/index.js
deleted file mode 100644
index 04ae6cce09..0000000000
--- a/frontend/src/component/layout/MainLayout/index.js
+++ /dev/null
@@ -1,10 +0,0 @@
-import { connect } from 'react-redux';
-import MainLayout from './MainLayout';
-
-const mapStateToProps = (state, ownProps) => ({
-    uiConfig: state.uiConfig.toJS(),
-    location: ownProps.location,
-    children: ownProps.children,
-});
-
-export default connect(mapStateToProps)(MainLayout);
diff --git a/frontend/src/component/menu/Header/Header.styles.ts b/frontend/src/component/menu/Header/Header.styles.ts
index 091b89226a..410b6787e6 100644
--- a/frontend/src/component/menu/Header/Header.styles.ts
+++ b/frontend/src/component/menu/Header/Header.styles.ts
@@ -7,7 +7,7 @@ export const useStyles = makeStyles(theme => ({
         padding: '0.5rem',
         boxShadow: 'none',
         position: 'relative',
-        zIndex: '300',
+        zIndex: 300,
     },
     links: {
         display: 'flex',
diff --git a/frontend/src/component/menu/__tests__/__snapshots__/routes-test.jsx.snap b/frontend/src/component/menu/__tests__/__snapshots__/routes-test.jsx.snap
index 062bc1ea4c..f643fa4014 100644
--- a/frontend/src/component/menu/__tests__/__snapshots__/routes-test.jsx.snap
+++ b/frontend/src/component/menu/__tests__/__snapshots__/routes-test.jsx.snap
@@ -286,7 +286,7 @@ Array [
     "layout": "main",
     "menu": Object {},
     "parent": "/addons",
-    "path": "/addons/create/:provider",
+    "path": "/addons/create/:providerId",
     "title": "Create",
     "type": "protected",
   },
@@ -295,7 +295,7 @@ Array [
     "layout": "main",
     "menu": Object {},
     "parent": "/addons",
-    "path": "/addons/edit/:id",
+    "path": "/addons/edit/:addonId",
     "title": "Edit",
     "type": "protected",
   },
diff --git a/frontend/src/component/menu/routes.js b/frontend/src/component/menu/routes.js
index b0724648e5..22d66f43a1 100644
--- a/frontend/src/component/menu/routes.js
+++ b/frontend/src/component/menu/routes.js
@@ -6,10 +6,8 @@ import Strategies from '../../page/strategies';
 import HistoryPage from '../../page/history';
 import HistoryTogglePage from '../../page/history/toggle';
 import { ArchiveListContainer } from '../archive/ArchiveListContainer';
-import ListTagTypes from '../../page/tag-types';
-import Addons from '../../page/addons';
-import AddonsCreate from '../../page/addons/create';
-import AddonsEdit from '../../page/addons/edit';
+import { TagTypeList } from '../tags/TagTypeList/TagTypeList';
+import { AddonList } from '../addons/AddonList/AddonList';
 import Admin from '../admin';
 import AdminApi from '../admin/api';
 import AdminInvoice from '../admin/invoice/InvoiceAdminPage';
@@ -35,8 +33,8 @@ import CreateEnvironment from '../environments/CreateEnvironment/CreateEnvironme
 import EditEnvironment from '../environments/EditEnvironment/EditEnvironment';
 import CreateContext from '../context/CreateContext/CreateContext';
 import EditContext from '../context/EditContext/EditContext';
-import EditTagType from '../tagTypes/EditTagType/EditTagType';
-import CreateTagType from '../tagTypes/CreateTagType/CreateTagType';
+import EditTagType from '../tags/EditTagType/EditTagType';
+import CreateTagType from '../tags/CreateTagType/CreateTagType';
 import EditProject from '../project/Project/EditProject/EditProject';
 import CreateProject from '../project/Project/CreateProject/CreateProject';
 import CreateFeature from '../feature/CreateFeature/CreateFeature';
@@ -45,6 +43,8 @@ import { ApplicationEdit } from '../application/ApplicationEdit/ApplicationEdit'
 import { ApplicationList } from '../application/ApplicationList/ApplicationList';
 import ContextList from '../context/ContextList/ContextList';
 import RedirectFeatureView from '../feature/RedirectFeatureView/RedirectFeatureView';
+import { CreateAddon } from '../addons/CreateAddon/CreateAddon';
+import { EditAddon } from '../addons/EditAddon/EditAddon';
 
 export const routes = [
     // Project
@@ -314,7 +314,7 @@ export const routes = [
     {
         path: '/tag-types',
         title: 'Tag types',
-        component: ListTagTypes,
+        component: TagTypeList,
         type: 'protected',
         layout: 'main',
         menu: { mobile: true, advanced: true },
@@ -322,19 +322,19 @@ export const routes = [
 
     // Addons
     {
-        path: '/addons/create/:provider',
+        path: '/addons/create/:providerId',
         parent: '/addons',
         title: 'Create',
-        component: AddonsCreate,
+        component: CreateAddon,
         type: 'protected',
         layout: 'main',
         menu: {},
     },
     {
-        path: '/addons/edit/:id',
+        path: '/addons/edit/:addonId',
         parent: '/addons',
         title: 'Edit',
-        component: AddonsEdit,
+        component: EditAddon,
         type: 'protected',
         layout: 'main',
         menu: {},
@@ -342,7 +342,7 @@ export const routes = [
     {
         path: '/addons',
         title: 'Addons',
-        component: Addons,
+        component: AddonList,
         hidden: false,
         type: 'protected',
         layout: 'main',
diff --git a/frontend/src/component/project/Project/CreateProject/CreateProject.tsx b/frontend/src/component/project/Project/CreateProject/CreateProject.tsx
index c22425b5ad..eed75ece87 100644
--- a/frontend/src/component/project/Project/CreateProject/CreateProject.tsx
+++ b/frontend/src/component/project/Project/CreateProject/CreateProject.tsx
@@ -10,7 +10,6 @@ import PermissionButton from '../../../common/PermissionButton/PermissionButton'
 import { CREATE_PROJECT } from '../../../providers/AccessProvider/permissions';
 
 const CreateProject = () => {
-    /* @ts-ignore */
     const { setToastData, setToastApiError } = useToast();
     const { refetch } = useUser();
     const { uiConfig } = useUiConfig();
diff --git a/frontend/src/component/project/Project/Project.tsx b/frontend/src/component/project/Project/Project.tsx
index 70c60bd618..f05acc4c40 100644
--- a/frontend/src/component/project/Project/Project.tsx
+++ b/frontend/src/component/project/Project/Project.tsx
@@ -12,7 +12,7 @@ import useQueryParams from '../../../hooks/useQueryParams';
 import { useEffect } from 'react';
 import useTabs from '../../../hooks/useTabs';
 import TabPanel from '../../common/TabNav/TabPanel';
-import ProjectAccess from '../access-container';
+import { ProjectAccess } from '../ProjectAccess/ProjectAccess';
 import ProjectEnvironment from '../ProjectEnvironment/ProjectEnvironment';
 import ProjectOverview from './ProjectOverview';
 import ProjectHealth from './ProjectHealth/ProjectHealth';
diff --git a/frontend/src/component/project/Project/ProjectForm/ProjectForm.style.ts b/frontend/src/component/project/Project/ProjectForm/ProjectForm.style.ts
index e5e5e19a86..6b8a221e3a 100644
--- a/frontend/src/component/project/Project/ProjectForm/ProjectForm.style.ts
+++ b/frontend/src/component/project/Project/ProjectForm/ProjectForm.style.ts
@@ -38,7 +38,7 @@ export const useStyles = makeStyles(theme => ({
         position: 'relative',
     },
     errorMessage: {
-        //@ts-ignore
+        // @ts-expect-error
         fontSize: theme.fontSizes.smallBody,
         color: theme.palette.error.main,
         position: 'absolute',
diff --git a/frontend/src/component/project/ProjectAccess/ProjectAccess.styles.ts b/frontend/src/component/project/ProjectAccess/ProjectAccess.styles.ts
index 388a9a9da1..d34ce9b1d1 100644
--- a/frontend/src/component/project/ProjectAccess/ProjectAccess.styles.ts
+++ b/frontend/src/component/project/ProjectAccess/ProjectAccess.styles.ts
@@ -11,18 +11,11 @@ export const useStyles = makeStyles(theme => ({
         backgroundColor: '#efefef',
         marginTop: '2rem',
     },
-    actionList: {
-        display: 'flex',
-        alignItems: 'center',
-    },
     inputLabel: { backgroundColor: '#fff' },
     roleName: {
         fontWeight: 'bold',
         padding: '5px 0px',
     },
-    iconButton: {
-        marginLeft: '0.5rem',
-    },
     menuItem: {
         width: '340px',
         whiteSpace: 'normal',
diff --git a/frontend/src/component/project/ProjectAccess/ProjectAccess.tsx b/frontend/src/component/project/ProjectAccess/ProjectAccess.tsx
index fee3f58a6d..48ac53420d 100644
--- a/frontend/src/component/project/ProjectAccess/ProjectAccess.tsx
+++ b/frontend/src/component/project/ProjectAccess/ProjectAccess.tsx
@@ -1,71 +1,40 @@
 /* eslint-disable react/jsx-no-target-blank */
-import { useEffect, useState } from 'react';
-import {
-    Avatar,
-    Button,
-    Dialog,
-    DialogActions,
-    DialogContent,
-    DialogContentText,
-    DialogTitle,
-    List,
-    ListItem,
-    ListItemAvatar,
-    ListItemSecondaryAction,
-    ListItemText,
-    MenuItem,
-} from '@material-ui/core';
-import { Delete } from '@material-ui/icons';
+import React, { useState } from 'react';
 import { Alert } from '@material-ui/lab';
 
-import AddUserComponent from '../access-add-user';
+import { ProjectAccessAddUser } from './ProjectAccessAddUser/ProjectAccessAddUser';
 
-import projectApi from '../../../store/project/api';
 import PageContent from '../../common/PageContent';
 import useUiConfig from '../../../hooks/api/getters/useUiConfig/useUiConfig';
 import { useStyles } from './ProjectAccess.styles';
-import PermissionIconButton from '../../common/PermissionIconButton/PermissionIconButton';
 import { useParams } from 'react-router-dom';
-import { IFeatureViewParams } from '../../../interfaces/params';
-import ProjectRoleSelect from './ProjectRoleSelect/ProjectRoleSelect';
+import { IProjectViewParams } from '../../../interfaces/params';
 import usePagination from '../../../hooks/usePagination';
 import PaginateUI from '../../common/PaginateUI/PaginateUI';
 import useToast from '../../../hooks/useToast';
 import ConfirmDialogue from '../../common/Dialogue';
+import useProjectAccess, {
+    IProjectAccessUser,
+} from '../../../hooks/api/getters/useProjectAccess/useProjectAccess';
+import useProjectApi from '../../../hooks/api/actions/useProjectApi/useProjectApi';
+import HeaderTitle from '../../common/HeaderTitle';
+import { ProjectAccessList } from './ProjectAccessList/ProjectAccessList';
 
-const ProjectAccess = () => {
-    const { id } = useParams
();
+export const ProjectAccess = () => {
+    const { id: projectId } = useParams();
     const styles = useStyles();
-    const [roles, setRoles] = useState([]);
-    const [users, setUsers] = useState([]);
-    const [error, setError] = useState();
-    const { setToastData, setToastApiError } = useToast();
+    const { access, refetchProjectAccess } = useProjectAccess(projectId);
+    const { setToastData } = useToast();
     const { isOss } = useUiConfig();
     const { page, pages, nextPage, prevPage, setPageIndex, pageIndex } =
-        usePagination(users, 10);
+        usePagination(access.users, 10);
+    const { removeUserFromRole, addUserToRole } = useProjectApi();
     const [showDelDialogue, setShowDelDialogue] = useState(false);
-    const [user, setUser] = useState({});
-
-    useEffect(() => {
-        fetchAccess();
-        // eslint-disable-next-line react-hooks/exhaustive-deps
-    }, [id]);
-
-    const fetchAccess = async () => {
-        try {
-            const access = await projectApi.fetchAccess(id);
-            setRoles(access.roles);
-            setUsers(
-                access.users.map(u => ({ ...u, name: u.name || '(No name)' }))
-            );
-        } catch (e) {
-            setToastApiError(e.toString());
-        }
-    };
+    const [user, setUser] = useState();
 
     if (isOss()) {
         return (
-            
+            }>
                 
                     Controlling access to projects requires a paid version of
                     Unleash. Check out{' '}
@@ -78,58 +47,49 @@ const ProjectAccess = () => {
         );
     }
 
-    const handleRoleChange = (userId, currRoleId) => async evt => {
-        const roleId = evt.target.value;
-        try {
-            await projectApi.removeUserFromRole(id, currRoleId, userId);
-            await projectApi.addUserToRole(id, roleId, userId).then(() => {
+    const handleRoleChange =
+        (userId: number, currRoleId: number) =>
+        async (
+            evt: React.ChangeEvent<{
+                name?: string;
+                value: unknown;
+            }>
+        ) => {
+            const roleId = Number(evt.target.value);
+            try {
+                await removeUserFromRole(projectId, currRoleId, userId);
+                await addUserToRole(projectId, roleId, userId);
+                refetchProjectAccess();
+
                 setToastData({
                     type: 'success',
                     title: 'User role changed successfully',
                 });
-            });
-            const newUsers = users.map(u => {
-                if (u.id === userId) {
-                    return { ...u, roleId };
-                } else return u;
-            });
-            setUsers(newUsers);
-        } catch (err) {
-            setToastData({
-                type: 'error',
-                title: err.message || 'Server problems when adding users.',
-            });
-        }
+            } catch (err: any) {
+                setToastData({
+                    type: 'error',
+                    title: err.message || 'Server problems when adding users.',
+                });
+            }
+        };
+
+    const handleRemoveAccess = (user: IProjectAccessUser) => {
+        setUser(user);
+        setShowDelDialogue(true);
     };
 
-    const addUser = async (userId, roleId) => {
-        try {
-            await projectApi.addUserToRole(id, roleId, userId);
-            await fetchAccess().then(() => {
-                setToastData({
-                    type: 'success',
-                    title: 'Successfully added user to the project',
-                });
-            });
-        } catch (err) {
-            setToastData({
-                type: 'error',
-                title: err.message || 'Server problems when adding users.',
-            });
-        }
-    };
+    const removeAccess = (user: IProjectAccessUser | undefined) => async () => {
+        if (!user) return;
+        const { id, roleId } = user;
 
-    const removeAccess = (userId: number, roleId: number) => async () => {
         try {
-            await projectApi.removeUserFromRole(id, roleId, userId).then(() => {
-                setToastData({
-                    type: 'success',
-                    title: 'User have been removed from project',
-                });
+            await removeUserFromRole(projectId, roleId, id);
+            refetchProjectAccess();
+            setToastData({
+                type: 'success',
+                title: 'The user has been removed from project',
             });
-            const newUsers = users.filter(u => u.id !== userId);
-            setUsers(newUsers);
-        } catch (err) {
+        } catch (err: any) {
             setToastData({
                 type: 'error',
                 title: err.message || 'Server problems when adding users.',
@@ -138,91 +98,20 @@ const ProjectAccess = () => {
         setShowDelDialogue(false);
     };
 
-    const handleCloseError = () => {
-        setError(undefined);
-    };
-
     return (
-        
-            
-            
-            
-            
-                {page.map(user => {
-                    const labelId = `checkbox-list-secondary-label-${user.id}`;
-                    return (
-                        
-                            
-                                
-                            
-                            
-                            
-                                
-                                    
-                                
+        }
+            className={styles.pageContent}
+        >
+            
 
-                                 {
-                                        setUser(user);
-                                        setShowDelDialogue(true);
-                                    }}
-                                    disabled={users.length === 1}
-                                    tooltip={
-                                        users.length === 1
-                                            ? 'A project must have at least one owner'
-                                            : 'Remove access'
-                                    }
-                                >
-                                    
-                                
-                            
-                        
-                    );
-                })}
+            
+            
                  {
                     prevPage={prevPage}
                     style={{ bottom: '-21px' }}
                 />
-            
+            
+
              {
-                    setUser({});
+                    setUser(undefined);
                     setShowDelDialogue(false);
                 }}
                 title="Really remove user from this project"
@@ -244,5 +134,3 @@ const ProjectAccess = () => {
         
     );
 };
-
-export default ProjectAccess;
diff --git a/frontend/src/component/project/ProjectAccess/ProjectAccessAddUser/ProjectAccessAddUser.tsx b/frontend/src/component/project/ProjectAccess/ProjectAccessAddUser/ProjectAccessAddUser.tsx
new file mode 100644
index 0000000000..26116a29f9
--- /dev/null
+++ b/frontend/src/component/project/ProjectAccess/ProjectAccessAddUser/ProjectAccessAddUser.tsx
@@ -0,0 +1,236 @@
+import React, { ChangeEvent, useEffect, useState } from 'react';
+import {
+    TextField,
+    CircularProgress,
+    Grid,
+    Button,
+    InputAdornment,
+} from '@material-ui/core';
+import { Search } from '@material-ui/icons';
+import Autocomplete from '@material-ui/lab/Autocomplete';
+import { Alert } from '@material-ui/lab';
+import { ProjectRoleSelect } from '../ProjectRoleSelect/ProjectRoleSelect';
+import useProjectApi from '../../../../hooks/api/actions/useProjectApi/useProjectApi';
+import { useParams } from 'react-router-dom';
+import useToast from '../../../../hooks/useToast';
+import useProjectAccess, {
+    IProjectAccessUser,
+} from '../../../../hooks/api/getters/useProjectAccess/useProjectAccess';
+import { IProjectRole } from '../../../../interfaces/role';
+import ConditionallyRender from '../../../common/ConditionallyRender';
+
+interface IProjectAccessAddUserProps {
+    roles: IProjectRole[];
+}
+
+export const ProjectAccessAddUser = ({ roles }: IProjectAccessAddUserProps) => {
+    const { id } = useParams<{ id: string }>();
+    const [user, setUser] = useState();
+    const [role, setRole] = useState();
+    const [options, setOptions] = useState([]);
+    const [loading, setLoading] = useState(false);
+    const { setToastData } = useToast();
+    const { refetchProjectAccess, access } = useProjectAccess(id);
+
+    const { searchProjectUser, addUserToRole } = useProjectApi();
+
+    useEffect(() => {
+        if (roles.length > 0) {
+            const regularRole = roles.find(
+                r => r.name.toLowerCase() === 'regular'
+            );
+            setRole(regularRole || roles[0]);
+        }
+    }, [roles]);
+
+    const search = async (query: string) => {
+        if (query.length > 1) {
+            setLoading(true);
+
+            const result = await searchProjectUser(query);
+            const userSearchResults = await result.json();
+
+            const filteredUsers = userSearchResults.filter(
+                (selectedUser: IProjectAccessUser) => {
+                    const selected = access.users.find(
+                        (user: IProjectAccessUser) =>
+                            user.id === selectedUser.id
+                    );
+                    return !selected;
+                }
+            );
+            setOptions(filteredUsers);
+        } else {
+            setOptions([]);
+        }
+        setLoading(false);
+    };
+
+    const handleQueryUpdate = (evt: { target: { value: string } }) => {
+        const q = evt.target.value;
+        search(q);
+    };
+
+    const handleBlur = () => {
+        if (options.length > 0) {
+            const user = options[0];
+            setUser(user);
+        }
+    };
+
+    const handleSelectUser = (
+        evt: ChangeEvent<{}>,
+        selectedUser: string | IProjectAccessUser | null
+    ) => {
+        setOptions([]);
+
+        if (typeof selectedUser === 'string' || selectedUser === null) {
+            return;
+        }
+
+        if (selectedUser?.id) {
+            setUser(selectedUser);
+        }
+    };
+
+    const handleRoleChange = (
+        evt: React.ChangeEvent<{
+            name?: string | undefined;
+            value: unknown;
+        }>
+    ) => {
+        const roleId = Number(evt.target.value);
+        const role = roles.find(role => role.id === roleId);
+        if (role) {
+            setRole(role);
+        }
+    };
+
+    const handleSubmit = async (evt: React.SyntheticEvent) => {
+        evt.preventDefault();
+        if (!role || !user) {
+            setToastData({
+                type: 'error',
+                title: 'Invalid selection',
+                text: `The selected user or role does not exist`,
+            });
+            return;
+        }
+
+        try {
+            await addUserToRole(id, role.id, user.id);
+            refetchProjectAccess();
+            setUser(undefined);
+            setOptions([]);
+            setToastData({
+                type: 'success',
+                title: 'Added user to project',
+                text: `User added to the project with the role of ${role.name}`,
+            });
+        } catch (e: any) {
+            let error;
+
+            if (
+                e
+                    .toString()
+                    .includes(`User already has access to project=${id}`)
+            ) {
+                error = `User already has access to project ${id}`;
+            } else {
+                error = e.toString() || 'Server problems when adding users.';
+            }
+            setToastData({
+                type: 'error',
+                title: error,
+            });
+        }
+    };
+
+    const getOptionLabel = (option: IProjectAccessUser) => {
+        if (option) {
+            return `${option.name || '(Empty name)'} <${
+                option.email || option.username
+            }>`;
+        } else return '';
+    };
+
+    return (
+        <>
+            
+                The user must have an Unleash root role before added to the
+                project.
+            
+            
+                
+                     handleBlur()}
+                        value={user || ''}
+                        freeSolo
+                        getOptionSelected={() => true}
+                        filterOptions={o => o}
+                        getOptionLabel={getOptionLabel}
+                        options={options}
+                        loading={loading}
+                        renderInput={params => (
+                            
+                                            
+                                        
+                                    ),
+                                    endAdornment: (
+                                        <>
+                                            
+                                                }
+                                            />
+
+                                            {params.InputProps.endAdornment}
+                                        >
+                                    ),
+                                }}
+                            />
+                        )}
+                    />
+                
+                
+                    
+                
+                
+                    
+                
+            
+        >
+    );
+};
diff --git a/frontend/src/component/project/ProjectAccess/ProjectAccessList/ProjectAccessList.tsx b/frontend/src/component/project/ProjectAccess/ProjectAccessList/ProjectAccessList.tsx
new file mode 100644
index 0000000000..42c15e3b42
--- /dev/null
+++ b/frontend/src/component/project/ProjectAccess/ProjectAccessList/ProjectAccessList.tsx
@@ -0,0 +1,64 @@
+import { List } from '@material-ui/core';
+import {
+    IProjectAccessOutput,
+    IProjectAccessUser,
+} from '../../../../hooks/api/getters/useProjectAccess/useProjectAccess';
+import { ProjectAccessListItem } from './ProjectAccessListItem/ProjectAccessListItem';
+
+interface IProjectAccesListProps {
+    page: IProjectAccessUser[];
+    handleRoleChange: (
+        userId: number,
+        currRoleId: number
+    ) => (
+        evt: React.ChangeEvent<{
+            name?: string;
+            value: unknown;
+        }>
+    ) => void;
+    handleRemoveAccess: (user: IProjectAccessUser) => void;
+    access: IProjectAccessOutput;
+}
+
+export const ProjectAccessList: React.FC = ({
+    page,
+    access,
+    handleRoleChange,
+    handleRemoveAccess,
+    children,
+}) => {
+    const sortUsers = (users: IProjectAccessUser[]): IProjectAccessUser[] => {
+        /* This should be done on the API side in the future, 
+                we should expect the list of users to come in the 
+                same order each time and not jump around on the screen*/
+
+        return users.sort(
+            (userA: IProjectAccessUser, userB: IProjectAccessUser) => {
+                if (!userA.name) {
+                    return -1;
+                } else if (!userB.name) {
+                    return 1;
+                }
+
+                return userA.name.localeCompare(userB.name);
+            }
+        );
+    };
+
+    return (
+
+            {sortUsers(page).map(user => {
+                return (
+                    
+                );
+            })}
+            {children}
+        
+    );
+};
diff --git a/frontend/src/component/project/ProjectAccess/ProjectAccessList/ProjectAccessListItem/ProjectAccessListItem.styles.ts b/frontend/src/component/project/ProjectAccess/ProjectAccessList/ProjectAccessListItem/ProjectAccessListItem.styles.ts
new file mode 100644
index 0000000000..72f94047e0
--- /dev/null
+++ b/frontend/src/component/project/ProjectAccess/ProjectAccessList/ProjectAccessListItem/ProjectAccessListItem.styles.ts
@@ -0,0 +1,11 @@
+import { makeStyles } from '@material-ui/core/styles';
+
+export const useStyles = makeStyles(() => ({
+    iconButton: {
+        marginLeft: '0.5rem',
+    },
+    actionList: {
+        display: 'flex',
+        alignItems: 'center',
+    },
+}));
diff --git a/frontend/src/component/project/ProjectAccess/ProjectAccessList/ProjectAccessListItem/ProjectAccessListItem.tsx b/frontend/src/component/project/ProjectAccess/ProjectAccessList/ProjectAccessListItem/ProjectAccessListItem.tsx
new file mode 100644
index 0000000000..be16175c34
--- /dev/null
+++ b/frontend/src/component/project/ProjectAccess/ProjectAccessList/ProjectAccessListItem/ProjectAccessListItem.tsx
@@ -0,0 +1,93 @@
+import {
+    ListItem,
+    ListItemAvatar,
+    Avatar,
+    ListItemText,
+    ListItemSecondaryAction,
+    MenuItem,
+} from '@material-ui/core';
+import { Delete } from '@material-ui/icons';
+import { useParams } from 'react-router-dom';
+import {
+    IProjectAccessUser,
+    IProjectAccessOutput,
+} from '../../../../../hooks/api/getters/useProjectAccess/useProjectAccess';
+import { IProjectViewParams } from '../../../../../interfaces/params';
+import PermissionIconButton from '../../../../common/PermissionIconButton/PermissionIconButton';
+import { UPDATE_PROJECT } from '../../../../providers/AccessProvider/permissions';
+import { ProjectRoleSelect } from '../../ProjectRoleSelect/ProjectRoleSelect';
+import { useStyles } from '../ProjectAccessListItem/ProjectAccessListItem.styles';
+
+interface IProjectAccessListItemProps {
+    user: IProjectAccessUser;
+    handleRoleChange: (
+        userId: number,
+        currRoleId: number
+    ) => (
+        evt: React.ChangeEvent<{
+            name?: string;
+            value: unknown;
+        }>
+    ) => void;
+    handleRemoveAccess: (user: IProjectAccessUser) => void;
+    access: IProjectAccessOutput;
+}
+
+export const ProjectAccessListItem = ({
+    user,
+    access,
+    handleRoleChange,
+    handleRemoveAccess,
+}: IProjectAccessListItemProps) => {
+    const { id: projectId } = useParams();
+    const styles = useStyles();
+
+    const labelId = `checkbox-list-secondary-label-${user.id}`;
+
+    return (
+        
+            
+                
+            
+            
+            
+                
+                    
+                
+                 {
+                        handleRemoveAccess(user);
+                    }}
+                    disabled={access.users.length === 1}
+                    tooltip={
+                        access.users.length === 1
+                            ? 'A project must have at least one owner'
+                            : 'Remove access'
+                    }
+                >
+                    
+                
+            
+        
+    );
+};
diff --git a/frontend/src/component/project/ProjectAccess/ProjectRoleSelect/ProjectRoleSelect.tsx b/frontend/src/component/project/ProjectAccess/ProjectRoleSelect/ProjectRoleSelect.tsx
index deae3eda52..c8f7dcf257 100644
--- a/frontend/src/component/project/ProjectAccess/ProjectRoleSelect/ProjectRoleSelect.tsx
+++ b/frontend/src/component/project/ProjectAccess/ProjectRoleSelect/ProjectRoleSelect.tsx
@@ -1,19 +1,24 @@
 import { FormControl, InputLabel, Select, MenuItem } from '@material-ui/core';
 import React from 'react';
-import IRole from '../../../../interfaces/role';
+import { IProjectRole } from '../../../../interfaces/role';
 
 import { useStyles } from '../ProjectAccess.styles';
 
 interface IProjectRoleSelect {
-    roles: IRole[];
+    roles: IProjectRole[];
     labelId: string;
     id: string;
     placeholder?: string;
-    onChange: () => void;
+    onChange: (
+        evt: React.ChangeEvent<{
+            name?: string | undefined;
+            value: unknown;
+        }>
+    ) => void;
     value: any;
 }
 
-const ProjectRoleSelect: React.FC = ({
+export const ProjectRoleSelect: React.FC = ({
     roles,
     onChange,
     labelId,
@@ -39,9 +44,10 @@ const ProjectRoleSelect: React.FC = ({
                 value={value || ''}
                 onChange={onChange}
                 renderValue={roleId => {
-                    return roles?.find(role => {
+                    const role = roles?.find(role => {
                         return role.id === roleId;
-                    }).name;
+                    });
+                    return role?.name || '';
                 }}
             >
                 {children}
@@ -66,5 +72,3 @@ const ProjectRoleSelect: React.FC = ({
         
     );
 };
-
-export default ProjectRoleSelect;
diff --git a/frontend/src/component/project/access-add-user.tsx b/frontend/src/component/project/access-add-user.tsx
deleted file mode 100644
index e5029160c9..0000000000
--- a/frontend/src/component/project/access-add-user.tsx
+++ /dev/null
@@ -1,162 +0,0 @@
-import React, { useEffect, useState } from 'react';
-import projectApi from '../../store/project/api';
-import PropTypes from 'prop-types';
-import {
-    TextField,
-    CircularProgress,
-    Grid,
-    Button,
-    InputAdornment,
-} from '@material-ui/core';
-import { Search } from '@material-ui/icons';
-import Autocomplete from '@material-ui/lab/Autocomplete';
-import { Alert } from '@material-ui/lab';
-import ProjectRoleSelect from './ProjectAccess/ProjectRoleSelect/ProjectRoleSelect';
-
-function AddUserComponent({ roles, addUserToRole }) {
-    const [user, setUser] = useState();
-    const [role, setRole] = useState({});
-    const [options, setOptions] = useState([]);
-    const [loading, setLoading] = useState(false);
-    const [select, setSelect] = useState(false);
-
-    useEffect(() => {
-        if (roles.length > 0) {
-            const regularRole = roles.find(
-                r => r.name.toLowerCase() === 'regular'
-            );
-            setRole(regularRole || roles[0]);
-        }
-    }, [roles]);
-
-    const search = async q => {
-        if (q.length > 1) {
-            setLoading(true);
-            // TODO: Do not hard-code fetch here.
-            const users = await projectApi.searchProjectUser(q);
-            setOptions([...users]);
-        } else {
-            setOptions([]);
-        }
-        setLoading(false);
-    };
-
-    const handleQueryUpdate = evt => {
-        const q = evt.target.value;
-        search(q);
-        if (options.length === 1) {
-            setSelect(true);
-            return;
-        }
-        setSelect(false);
-    };
-
-    const handleSelectUser = (evt, selectedUser) => {
-        setOptions([]);
-        if (selectedUser?.id) {
-            setUser(selectedUser);
-        }
-    };
-
-    const handleRoleChange = evt => {
-        const roleId = +evt.target.value;
-        const role = roles.find(r => r.id === roleId);
-        setRole(role);
-    };
-
-    const handleSubmit = async evt => {
-        evt.preventDefault();
-        await addUserToRole(user.id, role.id);
-        setUser(undefined);
-        setOptions([]);
-    };
-
-    return (
-        <>
-            
-                The user must have an Unleash root role before added to the
-                project.
-            
-            
-                
-                     true}
-                        filterOptions={o => o}
-                        getOptionLabel={option => {
-                            if (option) {
-                                return `${option.name || '(Empty name)'} <${
-                                    option.email || option.username
-                                }>`;
-                            } else return '';
-                        }}
-                        options={options}
-                        loading={loading}
-                        renderInput={params => (
-                            
-                                            
-                                        
-                                    ),
-                                    endAdornment: (
-                                        
-                                            {loading ? (
-                                                
-                                            ) : null}
-                                            {params.InputProps.endAdornment}
-                                        
-                                    ),
-                                }}
-                            />
-                        )}
-                    />
-                
-                
-                    
-                
-                
-                    
-                
-            
-        >
-    );
-}
-
-AddUserComponent.propTypes = {
-    roles: PropTypes.array.isRequired,
-    addUserToRole: PropTypes.func.isRequired,
-};
-
-export default AddUserComponent;
diff --git a/frontend/src/component/project/access-container.js b/frontend/src/component/project/access-container.js
deleted file mode 100644
index 692a07f425..0000000000
--- a/frontend/src/component/project/access-container.js
+++ /dev/null
@@ -1,20 +0,0 @@
-import { connect } from 'react-redux';
-import Component from './ProjectAccess/ProjectAccess';
-
-const mapStateToProps = (state, props) => {
-    const projectBase = { id: '', name: '', description: '' };
-    const realProject = state.projects
-        .toJS()
-        .find(n => n.id === props.projectId);
-    const project = Object.assign(projectBase, realProject);
-
-    return {
-        project,
-    };
-};
-
-const mapDispatchToProps = () => ({});
-
-const AccessContainer = connect(mapStateToProps, mapDispatchToProps)(Component);
-
-export default AccessContainer;
diff --git a/frontend/src/component/tag-types/TagTypeList/index.jsx b/frontend/src/component/tag-types/TagTypeList/index.jsx
deleted file mode 100644
index 20507a5dfc..0000000000
--- a/frontend/src/component/tag-types/TagTypeList/index.jsx
+++ /dev/null
@@ -1,3 +0,0 @@
-import TagTypeList from './TagTypeList';
-
-export default TagTypeList;
diff --git a/frontend/src/component/tag-types/__tests__/__snapshots__/tag-type-create-component-test.js.snap b/frontend/src/component/tag-types/__tests__/__snapshots__/tag-type-create-component-test.js.snap
deleted file mode 100644
index 29b3b14a98..0000000000
--- a/frontend/src/component/tag-types/__tests__/__snapshots__/tag-type-create-component-test.js.snap
+++ /dev/null
@@ -1,157 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`it supports editMode 1`] = `
-
-  
-    
-      
-        
-          Update Tag type
-        
-      
-    
-  
-  
-    
-      
-        Tag types allow you to group tags together in the management UI
-      
-      
-    
-  
-
-  
-    
-      
-        
-          Create Tag type
-        
-      
-    
-  
-  
-    
-      
-        Tag types allow you to group tags together in the management UI
-      
-      
-    
-  
-
-  
-    
-      
-        
-          Create Tag type
-        
-      
-    
-  
-  
-    
-      
-        Tag types allow you to group tags together in the management UI
-      
-      
-    
-  
-
 
-                        }
-                        elseShow={
-