diff --git a/webapp/packages/core-authentication/src/UsersResource.ts b/webapp/packages/core-authentication/src/UsersResource.ts
index 906393c39fd..775ff4b25cc 100644
--- a/webapp/packages/core-authentication/src/UsersResource.ts
+++ b/webapp/packages/core-authentication/src/UsersResource.ts
@@ -1,6 +1,6 @@
 /*
  * CloudBeaver - Cloud Database Manager
- * Copyright (C) 2020-2025 DBeaver Corp and others
+ * Copyright (C) 2020-2026 DBeaver Corp and others
  *
  * Licensed under the Apache License, Version 2.0.
  * you may not use this file except in compliance with the License.
@@ -35,14 +35,12 @@ import { Executor } from '@cloudbeaver/core-executor';
 import { AUTH_PROVIDER_LOCAL_ID } from './AUTH_PROVIDER_LOCAL_ID.js';
 import { AuthInfoService } from './AuthInfoService.js';
 import { AuthProviderService } from './AuthProviderService.js';
+import { compareUsersById, isNewUser, NEW_USER_SYMBOL, type AdminUserNew } from './compareUser.js';
 import type { IAuthCredentials } from './IAuthCredentials.js';
 
-const NEW_USER_SYMBOL = Symbol('new-user');
-
 export type AdminUser = AdminUserInfoFragment;
 export type AdminUserOrigin = AdminUserInfoFragment['origins'][number];
 
-type AdminUserNew = AdminUser & { [NEW_USER_SYMBOL]: boolean; createdAt: number };
 export type UserResourceIncludes = Omit<GetUsersListQueryVariables, 'userId' | 'page' | 'filter'>;
 
 interface IUserResourceFilterOptions {
@@ -96,7 +94,7 @@ export class UsersResource extends CachedMapResource<string, AdminUser, UserReso
     this.aliases.add(UsersResourceNewUsers, () => {
       const orderedKeys = this.entries
         .filter(k => isNewUser(k[1]))
-        .sort((a, b) => compareUsers(a[1], b[1]))
+        .sort((a, b) => compareUsersById(a[1], b[1]))
         .map(([key]) => key);
       return resourceKeyList(orderedKeys);
     });
@@ -328,34 +326,3 @@ export class UsersResource extends CachedMapResource<string, AdminUser, UserReso
     return typeof key === 'string';
   }
 }
-
-export function isLocalUser(user: AdminUser): boolean {
-  return user.origins.some(origin => origin.type === AUTH_PROVIDER_LOCAL_ID);
-}
-
-export function isNewUser(user: AdminUser | AdminUserNew): user is AdminUserNew {
-  return NEW_USER_SYMBOL in user && user[NEW_USER_SYMBOL] === true && 'createdAt' in user && Boolean(user.createdAt);
-}
-
-export function compareUsers<T extends Pick<AdminUser, 'userId'>>(a: T, b: T): number {
-  return a.userId.localeCompare(b.userId);
-}
-
-export function compareNewUsers(a: AdminUser, b: AdminUser): number {
-  const aIsNew = isNewUser(a);
-  const bIsNew = isNewUser(b);
-
-  if (aIsNew && !bIsNew) {
-    return -1;
-  }
-
-  if (!aIsNew && bIsNew) {
-    return 1;
-  }
-
-  if (aIsNew && bIsNew) {
-    return b.createdAt - a.createdAt;
-  }
-
-  return 0;
-}
diff --git a/webapp/packages/core-authentication/src/compareGrantSubjects.ts b/webapp/packages/core-authentication/src/compareGrantSubjects.ts
new file mode 100644
index 00000000000..fc15c71c8c5
--- /dev/null
+++ b/webapp/packages/core-authentication/src/compareGrantSubjects.ts
@@ -0,0 +1,23 @@
+/*
+ * CloudBeaver - Cloud Database Manager
+ * Copyright (C) 2020-2026 DBeaver Corp and others
+ *
+ * Licensed under the Apache License, Version 2.0.
+ * you may not use this file except in compliance with the License.
+ */
+import { compareUsersByLastLogin, isUser } from './compareUser.js';
+import type { TeamInfo } from './TeamsResource.js';
+import type { AdminUser } from './UsersResource.js';
+
+export function compareGrantSubjectsByName(a: AdminUser | TeamInfo, b: AdminUser | TeamInfo): number {
+  const aName = isUser(a) ? a.userId : a.teamName;
+  const bName = isUser(b) ? b.userId : b.teamName;
+  return (aName ?? '').localeCompare(bName ?? '');
+}
+
+export function compareGrantSubjectsByLastLogin(a: AdminUser | TeamInfo, b: AdminUser | TeamInfo): number {
+  return compareUsersByLastLogin(
+    { lastLoginTime: isUser(a) ? a.lastLoginTime : undefined },
+    { lastLoginTime: isUser(b) ? b.lastLoginTime : undefined },
+  );
+}
diff --git a/webapp/packages/core-authentication/src/compareUser.ts b/webapp/packages/core-authentication/src/compareUser.ts
new file mode 100644
index 00000000000..310518d1d2e
--- /dev/null
+++ b/webapp/packages/core-authentication/src/compareUser.ts
@@ -0,0 +1,54 @@
+/*
+ * CloudBeaver - Cloud Database Manager
+ * Copyright (C) 2020-2026 DBeaver Corp and others
+ *
+ * Licensed under the Apache License, Version 2.0.
+ * you may not use this file except in compliance with the License.
+ */
+import { AUTH_PROVIDER_LOCAL_ID } from './AUTH_PROVIDER_LOCAL_ID.js';
+import type { AdminUser } from './UsersResource.js';
+
+export const NEW_USER_SYMBOL = Symbol('new-user');
+
+export type AdminUserNew = AdminUser & { [NEW_USER_SYMBOL]: boolean; createdAt: number };
+
+export function isLocalUser(user: AdminUser): boolean {
+  return user.origins.some(origin => origin.type === AUTH_PROVIDER_LOCAL_ID);
+}
+
+export function isNewUser(user: AdminUser | AdminUserNew): user is AdminUserNew {
+  return NEW_USER_SYMBOL in user && user[NEW_USER_SYMBOL] === true && 'createdAt' in user && Boolean(user.createdAt);
+}
+
+export function isUser(user: unknown): user is AdminUser {
+  return !!user && typeof user === 'object' && 'userId' in user && 'grantedTeams' in user && 'enabled' in user;
+}
+
+export function compareUsersById<T extends Pick<AdminUser, 'userId'>>(a: T, b: T): number {
+  return a.userId.localeCompare(b.userId);
+}
+
+export function compareUsersByLastLogin<T extends Pick<AdminUser, 'lastLoginTime'>>(a: T, b: T): number {
+  const aTime = a.lastLoginTime ? new Date(a.lastLoginTime).getTime() : 0;
+  const bTime = b.lastLoginTime ? new Date(b.lastLoginTime).getTime() : 0;
+  return aTime - bTime;
+}
+
+export function compareUsersByNewness<T extends AdminUser>(a: T, b: T): number {
+  const aIsNew = isNewUser(a);
+  const bIsNew = isNewUser(b);
+
+  if (aIsNew && !bIsNew) {
+    return -1;
+  }
+
+  if (!aIsNew && bIsNew) {
+    return 1;
+  }
+
+  if (aIsNew && bIsNew) {
+    return b.createdAt - a.createdAt;
+  }
+
+  return 0;
+}
diff --git a/webapp/packages/core-authentication/src/index.ts b/webapp/packages/core-authentication/src/index.ts
index fc811be9bf8..5a08d692a93 100644
--- a/webapp/packages/core-authentication/src/index.ts
+++ b/webapp/packages/core-authentication/src/index.ts
@@ -27,9 +27,11 @@ export * from './UserInfoResource.js';
 export * from './UserMetaParametersResource.js';
 export * from './UsersMetaParametersResource.js';
 export * from './UsersResource.js';
+export * from './compareUser.js';
 export * from './UsersOriginDetailsResource.js';
 export * from './UserInfoMetaParametersResource.js';
 export * from './TeamMetaParametersResource.js';
+export * from './compareGrantSubjects.js';
 export * from './AUTH_SETTINGS_GROUP.js';
 export * from './PasswordPolicyService.js';
 export * from './TeamRolesResource.js';
diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamsForm/GrantedUsers/GrantedUsersTable.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamsForm/GrantedUsers/GrantedUsersTable.tsx
index 8b03e0de9e4..77fa4194ee9 100644
--- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamsForm/GrantedUsers/GrantedUsersTable.tsx
+++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/Teams/TeamsForm/GrantedUsers/GrantedUsersTable.tsx
@@ -14,7 +14,8 @@ import { CachedResourceOffsetPageListKey } from '@cloudbeaver/core-resource';
 import { GrantManagementTable, type IGrantManagementTableColumn } from '@cloudbeaver/plugin-data-grid';
 import { ServerConfigResource } from '@cloudbeaver/core-root';
 import {
-  compareUsers,
+  compareUsersById,
+  compareUsersByLastLogin,
   TeamRolesResource,
   USER_TEAM_ROLE_SUPERVISOR,
   UsersResource,
@@ -24,15 +25,21 @@ import {
 
 import type { TeamFormProps } from '../TeamsAdministrationFormService.js';
 import type { GrantedUsersFormPart } from './GrantedUsersFormPart.js';
+import { useMemo } from 'react';
 
-const USER_ID_COLUMN: IGrantManagementTableColumn = { key: 'userId', label: 'administration_teams_team_granted_users_user_id' };
-const LAST_LOGIN_COLUMN: IGrantManagementTableColumn = { key: 'lastLogin', label: 'plugin_authentication_administration_user_last_login' };
-const TEAM_ROLE_COLUMN: IGrantManagementTableColumn = {
-  key: 'teamRole',
-  label: 'plugin_authentication_administration_team_user_team_role_supervisor',
+const USER_ID_COLUMN: IGrantManagementTableColumn<AdminUser> = {
+  key: 'userId',
+  label: 'administration_teams_team_granted_users_user_id',
+  compare: compareUsersById,
 };
+const LAST_LOGIN_COLUMN: IGrantManagementTableColumn<AdminUser> = {
+  key: 'lastLogin',
+  label: 'plugin_authentication_administration_user_last_login',
+  compare: compareUsersByLastLogin,
+};
+const TEAM_ROLE_COLUMN_KEY = 'teamRole';
 
-const COLUMNS: IGrantManagementTableColumn[] = [USER_ID_COLUMN, LAST_LOGIN_COLUMN];
+const COLUMNS: IGrantManagementTableColumn<AdminUser>[] = [USER_ID_COLUMN, LAST_LOGIN_COLUMN];
 
 export const GrantedUsersTable: TabContainerPanelComponent<TeamFormProps> = observer(function GrantedUsersTable({ tabId, formState }) {
   const translate = useTranslate();
@@ -48,6 +55,7 @@ export const GrantedUsersTable: TabContainerPanelComponent<TeamFormProps> = obse
   const usersLoader = useResource(GrantedUsersTable, UsersResource, CachedResourceOffsetPageListKey(0, 1000).setParent(UsersResourceFilterKey()), {
     active,
   });
+  const grantedUsersIdsMap = useMemo(() => new Map(tabState.state.grantedUsers.map(user => [user.userId, user])), [tabState.state.grantedUsers]);
 
   useAutoLoad(GrantedUsersTable, tabState, active);
 
@@ -78,10 +86,24 @@ export const GrantedUsersTable: TabContainerPanelComponent<TeamFormProps> = obse
     return !usersLoader.resource.isActiveUser(user.userId);
   }
 
+  function getTeamRoleRank(user: AdminUser) {
+    const granted = grantedUsersIdsMap.get(user.userId);
+
+    if (!granted) {
+      return 0;
+    }
+
+    return granted.teamRole === USER_TEAM_ROLE_SUPERVISOR ? 2 : 1;
+  }
+
   const columns = [...COLUMNS];
 
   if (teamRolesResource.data.length > 0) {
-    columns.push(TEAM_ROLE_COLUMN);
+    columns.push({
+      key: TEAM_ROLE_COLUMN_KEY,
+      label: 'plugin_authentication_administration_team_user_team_role_supervisor',
+      compare: (a, b) => getTeamRoleRank(a) - getTeamRoleRank(b),
+    });
   }
 
   function getCell(user: AdminUser, colKey: string) {
@@ -114,7 +136,7 @@ export const GrantedUsersTable: TabContainerPanelComponent<TeamFormProps> = obse
       return <span title={lastLoginFullTime}>{lastLoginDate}</span>;
     }
 
-    if (colKey === TEAM_ROLE_COLUMN.key) {
+    if (colKey === TEAM_ROLE_COLUMN_KEY) {
       const granted = tabState.state.grantedUsers.find(grantedUser => grantedUser.userId === user.userId);
 
       if (granted) {
@@ -134,7 +156,7 @@ export const GrantedUsersTable: TabContainerPanelComponent<TeamFormProps> = obse
     return null;
   }
 
-  const items = (usersLoader.data.filter(user => user?.enabled) as AdminUser[]).sort(compareUsers);
+  const items = (usersLoader.data.filter(user => user?.enabled) as AdminUser[]).sort(compareUsersById);
 
   return (
     <GrantManagementTable
diff --git a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/useUsersTable.tsx b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/useUsersTable.tsx
index 7eda9d414e8..eaef0223f35 100644
--- a/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/useUsersTable.tsx
+++ b/webapp/packages/plugin-authentication-administration/src/Administration/Users/UsersTable/useUsersTable.tsx
@@ -7,7 +7,7 @@
  */
 import { action, computed, observable } from 'mobx';
 
-import { type AdminUser, compareUsers, compareNewUsers, UsersResource, UsersResourceFilterKey } from '@cloudbeaver/core-authentication';
+import { type AdminUser, compareUsersById, compareUsersByNewness, UsersResource, UsersResourceFilterKey } from '@cloudbeaver/core-authentication';
 import { TableState, useExecutor, useObservableRef, useOffsetPagination, useResource } from '@cloudbeaver/core-blocks';
 import { useService } from '@cloudbeaver/core-di';
 import { NotificationService } from '@cloudbeaver/core-events';
@@ -35,14 +35,14 @@ export function useUsersTable(filters: IUserFilters) {
   const notificationService = useService(NotificationService);
 
   useExecutor({
-    executor: usersLoader.resource.onUserCreate, handlers: [
+    executor: usersLoader.resource.onUserCreate,
+    handlers: [
       function handleUserCreation() {
         pagination.refresh();
       },
     ],
   });
 
-
   const state: State = useObservableRef(
     () => ({
       loading: false,
@@ -61,8 +61,8 @@ export function useUsersTable(filters: IUserFilters) {
             ]),
           )
             .filter(isDefined)
-            .sort(compareUsers)
-            .sort(compareNewUsers),
+            .sort(compareUsersById)
+            .sort(compareUsersByNewness),
         );
       },
       update() {
diff --git a/webapp/packages/plugin-connections-administration/src/ConnectionFormAccess/ConnectionAccessTable.tsx b/webapp/packages/plugin-connections-administration/src/ConnectionFormAccess/ConnectionAccessTable.tsx
index 4cb9f49f062..3d1710029f2 100644
--- a/webapp/packages/plugin-connections-administration/src/ConnectionFormAccess/ConnectionAccessTable.tsx
+++ b/webapp/packages/plugin-connections-administration/src/ConnectionFormAccess/ConnectionAccessTable.tsx
@@ -12,17 +12,33 @@ import { Alert, StaticImage, useAutoLoad, useResource, useTranslate } from '@clo
 import { useTab, type TabContainerPanelComponent } from '@cloudbeaver/core-ui';
 import { getConnectionFormOptionsPart, type IConnectionFormProps } from '@cloudbeaver/plugin-connections';
 import { CachedMapAllKey, CachedResourceOffsetPageListKey } from '@cloudbeaver/core-resource';
-import { TeamsResource, UsersResource, UsersResourceFilterKey, type AdminUser, type TeamInfo } from '@cloudbeaver/core-authentication';
+import {
+  compareGrantSubjectsByLastLogin,
+  compareGrantSubjectsByName,
+  TeamsResource,
+  UsersResource,
+  UsersResourceFilterKey,
+  type AdminUser,
+  type TeamInfo,
+} from '@cloudbeaver/core-authentication';
 import { ConnectionInfoOriginResource, ConnectionInfoResource, createConnectionParam, isCloudConnection } from '@cloudbeaver/core-connections';
 import { GrantManagementTable, type IGrantManagementTableColumn } from '@cloudbeaver/plugin-data-grid';
 
 import { getConnectionFormAccessPart } from './getConnectionFormAccessPart.js';
 
-const NAME_COLUMN: IGrantManagementTableColumn = { key: 'name', label: 'connections_connection_access_user_or_team_name' };
-const DESCRIPTION_COLUMN: IGrantManagementTableColumn = { key: 'description', label: 'connections_connection_description' };
-const LAST_LOGIN_COLUMN: IGrantManagementTableColumn = { key: 'lastLogin', label: 'plugin_connections_administration_user_last_login' };
-
-const COLUMNS: IGrantManagementTableColumn[] = [NAME_COLUMN, DESCRIPTION_COLUMN, LAST_LOGIN_COLUMN];
+const NAME_COLUMN: IGrantManagementTableColumn<AdminUser | TeamInfo> = {
+  key: 'name',
+  label: 'connections_connection_access_user_or_team_name',
+  compare: compareGrantSubjectsByName,
+};
+const DESCRIPTION_COLUMN: IGrantManagementTableColumn<AdminUser | TeamInfo> = { key: 'description', label: 'connections_connection_description' };
+const LAST_LOGIN_COLUMN: IGrantManagementTableColumn<AdminUser | TeamInfo> = {
+  key: 'lastLogin',
+  label: 'plugin_connections_administration_user_last_login',
+  compare: compareGrantSubjectsByLastLogin,
+};
+
+const COLUMNS: IGrantManagementTableColumn<AdminUser | TeamInfo>[] = [NAME_COLUMN, DESCRIPTION_COLUMN, LAST_LOGIN_COLUMN];
 
 export const ConnectionAccessTable: TabContainerPanelComponent<IConnectionFormProps> = observer(function ConnectionAccessTable({ tabId, formState }) {
   const translate = useTranslate();
diff --git a/webapp/packages/plugin-data-grid/src/GrantManagementTable.tsx b/webapp/packages/plugin-data-grid/src/GrantManagementTable.tsx
index a238f759b1c..8b303b0337e 100644
--- a/webapp/packages/plugin-data-grid/src/GrantManagementTable.tsx
+++ b/webapp/packages/plugin-data-grid/src/GrantManagementTable.tsx
@@ -1,6 +1,6 @@
 /*
  * CloudBeaver - Cloud Database Manager
- * Copyright (C) 2020-2025 DBeaver Corp and others
+ * Copyright (C) 2020-2026 DBeaver Corp and others
  *
  * Licensed under the Apache License, Version 2.0.
  * you may not use this file except in compliance with the License.
@@ -21,19 +21,18 @@ import { TableSelectionContext } from './TableSelectionContext.js';
 import { TableRowSelect } from './TableRowSelect.js';
 import classes from './GrantManagementTable.module.css';
 
-export interface IGrantManagementTableColumn {
+export interface IGrantManagementTableColumn<T = unknown> {
   key: string;
   label: TLocalizationToken;
+  compare?: (a: T, b: T) => number;
 }
 
 const SELECT_COLUMN: IGrantManagementTableColumn = { key: 'gmt_select', label: '' };
-const STATUS_COLUMN: IGrantManagementTableColumn = { key: 'gmt_status', label: 'ui_granted' };
-
-const DEFAULT_COLUMNS: IGrantManagementTableColumn[] = [SELECT_COLUMN, STATUS_COLUMN];
+const STATUS_COLUMN_KEY = 'gmt_status';
 
 export interface IGrantManagementTableProps<T> {
   items: T[];
-  columns: IGrantManagementTableColumn[];
+  columns: IGrantManagementTableColumn<T>[];
   getItemId: (item: T) => string;
   isGranted: (item: T) => boolean;
   isEdited: (item: T) => boolean;
@@ -61,7 +60,7 @@ export const GrantManagementTable = observer(function GrantManagementTable<T>({
   const translate = useTranslate();
   const styles = useS(classes);
 
-  const [sort, setSort] = useState<'asc' | 'desc' | null>('desc');
+  const [sort, setSort] = useState<{ colIdx: number; order: 'asc' | 'desc' } | null>({ colIdx: 1, order: 'desc' });
   const [filter, setFilter] = useState('');
   const deferredFilter = useDeferredValue(filter);
 
@@ -73,23 +72,28 @@ export const GrantManagementTable = observer(function GrantManagementTable<T>({
     return items;
   }, [isVisible, items, deferredFilter]);
 
+  const allColumns = useMemo<IGrantManagementTableColumn<T>[]>(() => {
+    const statusColumn: IGrantManagementTableColumn<T> = {
+      key: STATUS_COLUMN_KEY,
+      label: 'ui_granted',
+      compare: (a, b) => Number(isGranted(a)) - Number(isGranted(b)),
+    };
+
+    return [SELECT_COLUMN, statusColumn, ...columns];
+  }, [columns, isGranted]);
+
   const sortedItems = useMemo(() => {
     if (sort) {
-      return visibleItems.slice().sort((a, b) => {
-        const aGranted = isGranted(a);
-        const bGranted = isGranted(b);
+      const column = allColumns[sort.colIdx];
 
-        if (aGranted === bGranted) {
-          return 0;
-        }
-
-        const granted = sort === 'asc' ? aGranted : !aGranted;
-        return granted ? 1 : -1;
-      });
+      if (column?.compare) {
+        const compare = column.compare;
+        return visibleItems.slice().sort((a, b) => (sort.order === 'asc' ? compare(a, b) : compare(b, a)));
+      }
     }
 
     return visibleItems;
-  }, [visibleItems, sort, isGranted]);
+  }, [visibleItems, sort, allColumns]);
 
   const keys = useMemo(() => {
     const filtered = isManageable ? visibleItems.filter(isManageable) : visibleItems;
@@ -114,11 +118,9 @@ export const GrantManagementTable = observer(function GrantManagementTable<T>({
     selection.clear();
   }
 
-  const _columns = useMemo(() => [...DEFAULT_COLUMNS, ...columns], [columns]);
-
   function _getCell(rowIdx: number, colIdx: number) {
     const row = sortedItems[rowIdx] as T;
-    const column = _columns[colIdx];
+    const column = allColumns[colIdx];
 
     if (!row || !column) {
       return null;
@@ -128,7 +130,7 @@ export const GrantManagementTable = observer(function GrantManagementTable<T>({
       return <TableRowSelect id={getItemId(row)} disabled={isManageable?.(row) === false} />;
     }
 
-    if (column.key === STATUS_COLUMN.key) {
+    if (column.key === STATUS_COLUMN_KEY) {
       const granted = isGranted(row);
       return (
         <div
@@ -142,7 +144,7 @@ export const GrantManagementTable = observer(function GrantManagementTable<T>({
 
   const cell = useCreateGridReactiveValue(_getCell, (onValueChange, rowIds, colIdx) => reaction(() => _getCell(rowIds, colIdx), onValueChange), [
     sortedItems,
-    _columns,
+    allColumns,
     isGranted,
     isManageable,
     getCell,
@@ -169,9 +171,9 @@ export const GrantManagementTable = observer(function GrantManagementTable<T>({
   );
 
   const columnsCount = useCreateGridReactiveValue(
-    () => _columns.length,
-    onValueChange => reaction(() => _columns.length, onValueChange),
-    [_columns],
+    () => allColumns.length,
+    onValueChange => reaction(() => allColumns.length, onValueChange),
+    [allColumns],
   );
 
   const rowsCount = useCreateGridReactiveValue(
@@ -181,7 +183,7 @@ export const GrantManagementTable = observer(function GrantManagementTable<T>({
   );
 
   function getHeaderText(colIdx: number) {
-    return translate(_columns[colIdx]?.label) ?? '';
+    return translate(allColumns[colIdx]?.label) ?? '';
   }
 
   function getHeaderElement(colIdx: number) {
@@ -195,27 +197,27 @@ export const GrantManagementTable = observer(function GrantManagementTable<T>({
   const headerElement = useCreateGridReactiveValue(
     getHeaderElement,
     (onValueChange, colIdx) => reaction(() => getHeaderElement(colIdx), onValueChange),
-    [_columns, translate],
+    [allColumns, translate],
   );
 
   const headerText = useCreateGridReactiveValue(getHeaderText, (onValueChange, colIdx) => reaction(() => getHeaderText(colIdx), onValueChange), [
-    _columns,
+    allColumns,
     translate,
   ]);
 
   function getColumnSortable(colIdx: number) {
-    return colIdx === 1;
+    return allColumns[colIdx]?.compare !== undefined;
   }
 
   const columnSortable = useCreateGridReactiveValue(
     getColumnSortable,
     (onValueChange, colIdx) => reaction(() => getColumnSortable(colIdx), onValueChange),
-    [],
+    [allColumns],
   );
 
   function getColumnSortingState(colIdx: number) {
-    if (colIdx === 1) {
-      return sort;
+    if (sort?.colIdx === colIdx) {
+      return sort.order;
     }
 
     return null;
@@ -228,9 +230,7 @@ export const GrantManagementTable = observer(function GrantManagementTable<T>({
   );
 
   function handleSort(colIdx: number, order: 'asc' | 'desc' | null) {
-    if (colIdx === 1) {
-      setSort(order);
-    }
+    setSort(order ? { colIdx, order } : null);
   }
 
   return (
