diff --git a/lib/utils/role-utils.js b/lib/utils/role-utils.js
--- a/lib/utils/role-utils.js
+++ b/lib/utils/role-utils.js
@@ -54,7 +54,28 @@
   return message;
 }
 
+type RoleDeletableAndEditableStatus = {
+  +isDeletable: boolean,
+  +isEditable: boolean,
+};
+function useRoleDeletableAndEditableStatus(
+  roleName: string,
+  defaultRoleID: string,
+  existingRoleID: string,
+): RoleDeletableAndEditableStatus {
+  return React.useMemo(() => {
+    const canDelete = roleName !== 'Admins' && defaultRoleID !== existingRoleID;
+    const canEdit = roleName !== 'Admins';
+
+    return {
+      isDeletable: canDelete,
+      isEditable: canEdit,
+    };
+  }, [roleName, defaultRoleID, existingRoleID]);
+}
+
 export {
   useFilterPermissionOptionsByThreadType,
   constructRoleDeletionMessagePrompt,
+  useRoleDeletableAndEditableStatus,
 };
diff --git a/web/components/menu.css b/web/components/menu.css
--- a/web/components/menu.css
+++ b/web/components/menu.css
@@ -42,6 +42,14 @@
   top: 24px;
 }
 
+div.menuActionListRoleActions {
+  font-size: var(--s-font-14);
+  background-color: var(--menu-bg-light);
+  color: var(--menu-color);
+  stroke: var(--menu-color);
+  margin-top: 20px;
+}
+
 button.menuAction {
   color: inherit;
   z-index: 1;
diff --git a/web/components/menu.react.js b/web/components/menu.react.js
--- a/web/components/menu.react.js
+++ b/web/components/menu.react.js
@@ -6,7 +6,11 @@
 import css from './menu.css';
 import { useRenderMenu } from '../menu-provider.react.js';
 
-type MenuVariant = 'thread-actions' | 'member-actions' | 'community-actions';
+type MenuVariant =
+  | 'thread-actions'
+  | 'member-actions'
+  | 'community-actions'
+  | 'role-actions';
 
 type MenuProps = {
   +icon: React.Node,
@@ -30,6 +34,7 @@
     [css.menuActionListThreadActions]: variant === 'thread-actions',
     [css.menuActionListMemberActions]: variant === 'member-actions',
     [css.menuActionListCommunityActions]: variant === 'community-actions',
+    [css.menuActionListRoleActions]: variant === 'role-actions',
   });
 
   const menuActionList = React.useMemo(
diff --git a/web/roles/community-roles-modal.css b/web/roles/community-roles-modal.css
--- a/web/roles/community-roles-modal.css
+++ b/web/roles/community-roles-modal.css
@@ -17,7 +17,7 @@
 }
 
 .rolePanelTitle:last-of-type {
-  margin-right: 32px;
+  margin-right: 90px;
 }
 
 .separator {
diff --git a/web/roles/community-roles-modal.react.js b/web/roles/community-roles-modal.react.js
--- a/web/roles/community-roles-modal.react.js
+++ b/web/roles/community-roles-modal.react.js
@@ -32,11 +32,12 @@
       Object.keys(roleNamesToMembers).map(roleName => (
         <RolePanelEntry
           key={roleName}
+          threadInfo={threadInfo}
           roleName={roleName}
           memberCount={roleNamesToMembers[roleName]}
         />
       )),
-    [roleNamesToMembers],
+    [roleNamesToMembers, threadInfo],
   );
 
   const rolePermissionsForNewRole = React.useMemo(() => new Set(), []);
diff --git a/web/roles/role-actions-menu.css b/web/roles/role-actions-menu.css
new file mode 100644
--- /dev/null
+++ b/web/roles/role-actions-menu.css
@@ -0,0 +1,4 @@
+.menuContainer {
+  color: var(--menu-color-light);
+  width: 10px;
+}
diff --git a/web/roles/role-actions-menu.react.js b/web/roles/role-actions-menu.react.js
new file mode 100644
--- /dev/null
+++ b/web/roles/role-actions-menu.react.js
@@ -0,0 +1,84 @@
+// @flow
+
+import invariant from 'invariant';
+import * as React from 'react';
+
+import SWMansionIcon from 'lib/components/SWMansionIcon.react.js';
+import type { ThreadInfo } from 'lib/types/thread-types.js';
+import { useRoleDeletableAndEditableStatus } from 'lib/utils/role-utils.js';
+
+import css from './role-actions-menu.css';
+import MenuItem from '../components/menu-item.react.js';
+import Menu from '../components/menu.react.js';
+
+const menuIcon = <SWMansionIcon icon="menu-horizontal" size={20} />;
+
+type RoleActionsMenuProps = {
+  +threadInfo: ThreadInfo,
+  +roleName: string,
+};
+
+function RoleActionsMenu(props: RoleActionsMenuProps): React.Node {
+  const { threadInfo, roleName } = props;
+
+  const defaultRoleID = Object.keys(threadInfo.roles).find(
+    roleID => threadInfo.roles[roleID].isDefault,
+  );
+  invariant(defaultRoleID, 'default role should exist');
+
+  const existingRoleID = Object.keys(threadInfo.roles).find(
+    roleID => threadInfo.roles[roleID].name === roleName,
+  );
+  invariant(existingRoleID, 'existing role should exist');
+
+  const roleOptions = useRoleDeletableAndEditableStatus(
+    roleName,
+    defaultRoleID,
+    existingRoleID,
+  );
+
+  // TODO: Implement in following diffs
+  const openEditRoleModal = React.useCallback(() => {}, []);
+  const openDeleteRoleModal = React.useCallback(() => {}, []);
+
+  const menuItems = React.useMemo(() => {
+    const availableOptions = [];
+    const { isDeletable, isEditable } = roleOptions;
+
+    if (isEditable) {
+      availableOptions.push(
+        <MenuItem
+          key="Edit role"
+          text="Edit role"
+          icon="edit-1"
+          onClick={openEditRoleModal}
+          dangerous={false}
+        />,
+      );
+    }
+
+    if (isDeletable) {
+      availableOptions.push(
+        <MenuItem
+          key="Delete role"
+          text="Delete role"
+          icon="cross-circle"
+          onClick={openDeleteRoleModal}
+          dangerous={true}
+        />,
+      );
+    }
+
+    return availableOptions;
+  }, [roleOptions, openDeleteRoleModal, openEditRoleModal]);
+
+  return (
+    <div className={css.menuContainer}>
+      <Menu icon={menuIcon} variant="role-actions">
+        {menuItems}
+      </Menu>
+    </div>
+  );
+}
+
+export default RoleActionsMenu;
diff --git a/web/roles/role-panel-entry.css b/web/roles/role-panel-entry.css
--- a/web/roles/role-panel-entry.css
+++ b/web/roles/role-panel-entry.css
@@ -1,7 +1,5 @@
 .rolePanelEntry {
-  display: flex;
-  flex-direction: row;
-  justify-content: space-between;
+  display: grid;
   align-items: center;
   padding: 12px;
   color: var(--community-roles-text-color);
@@ -13,9 +11,16 @@
 }
 
 .rolePanelCountEntryContainer {
-  margin-right: 40px;
   display: flex;
-  align-items: flex-end;
+  align-items: center;
+  justify-content: flex-end;
+  grid-column: 3;
+}
+
+.rolePanelCountAndIcon {
+  display: flex;
+  align-items: center;
+  margin-right: 90px;
 }
 
 .rolePanelCountEntry {
diff --git a/web/roles/role-panel-entry.react.js b/web/roles/role-panel-entry.react.js
--- a/web/roles/role-panel-entry.react.js
+++ b/web/roles/role-panel-entry.react.js
@@ -2,22 +2,29 @@
 
 import * as React from 'react';
 
+import type { ThreadInfo } from 'lib/types/thread-types.js';
+
+import RoleActionsMenu from './role-actions-menu.react.js';
 import css from './role-panel-entry.css';
 import CommIcon from '../CommIcon.react.js';
 
 type RolePanelEntryProps = {
+  +threadInfo: ThreadInfo,
   +roleName: string,
   +memberCount: number,
 };
 
 function RolePanelEntry(props: RolePanelEntryProps): React.Node {
-  const { roleName, memberCount } = props;
+  const { threadInfo, roleName, memberCount } = props;
   return (
     <div className={css.rolePanelEntry}>
       <div className={css.rolePanelNameEntry}>{roleName}</div>
       <div className={css.rolePanelCountEntryContainer}>
-        <div className={css.rolePanelCountEntry}>{memberCount}</div>
-        <CommIcon icon="user-filled" size={18} />
+        <div className={css.rolePanelCountAndIcon}>
+          <div className={css.rolePanelCountEntry}>{memberCount}</div>
+          <CommIcon icon="user-filled" size={18} />
+        </div>
+        <RoleActionsMenu threadInfo={threadInfo} roleName={roleName} />
       </div>
     </div>
   );