+
+ {!value ? '-' : value}
+
{!!value && (
}
- className="transition opacity-0 group-hover:opacity-100 px-1"
+ className="shrink-0 px-1 opacity-100 transition sm:opacity-0 sm:group-hover:opacity-100"
text={value}
/>
)}
diff --git a/apps/studio/components/interfaces/Auth/Users/UserPanel.test.tsx b/apps/studio/components/interfaces/Auth/Users/UserPanel.test.tsx
index 23b4caea738..94dc0eeb142 100644
--- a/apps/studio/components/interfaces/Auth/Users/UserPanel.test.tsx
+++ b/apps/studio/components/interfaces/Auth/Users/UserPanel.test.tsx
@@ -1,7 +1,7 @@
import { screen } from '@testing-library/react'
import { http, HttpResponse } from 'msw'
import { ResizablePanelGroup } from 'ui'
-import { beforeEach, describe, expect, it, vi } from 'vitest'
+import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'
import { UserPanel } from './UserPanel'
import type { User } from '@/data/auth/users-infinite-query'
@@ -69,10 +69,16 @@ const renderPanel = (disabledFeatures: string[] = []) => {
}
describe('UserPanel', () => {
+ const desktopWidth = window.innerWidth
+
beforeEach(() => {
vi.clearAllMocks()
})
+ afterEach(() => {
+ Object.defineProperty(window, 'innerWidth', { configurable: true, value: desktopWidth })
+ })
+
it('shows the Logs tab when logs:all is enabled', async () => {
renderPanel([])
@@ -88,4 +94,14 @@ describe('UserPanel', () => {
expect(screen.queryByRole('tab', { name: 'Logs' })).not.toBeInTheDocument()
expect(screen.getByRole('tab', { name: 'Raw JSON' })).toBeInTheDocument()
})
+
+ it('uses a full-width dialog on mobile', async () => {
+ Object.defineProperty(window, 'innerWidth', { configurable: true, value: 390 })
+
+ renderPanel([])
+
+ const dialog = await screen.findByRole('dialog', { name: 'User details' })
+ expect(dialog).toHaveClass('w-screen')
+ expect(screen.getByRole('button', { name: 'Close user details' })).toBeInTheDocument()
+ })
})
diff --git a/apps/studio/components/interfaces/Auth/Users/UserPanel.tsx b/apps/studio/components/interfaces/Auth/Users/UserPanel.tsx
index f9d7342f6ed..25a5e6d4df3 100644
--- a/apps/studio/components/interfaces/Auth/Users/UserPanel.tsx
+++ b/apps/studio/components/interfaces/Auth/Users/UserPanel.tsx
@@ -1,5 +1,6 @@
import { X } from 'lucide-react'
import { parseAsString, useQueryState } from 'nuqs'
+import { Dialog, VisuallyHidden } from 'radix-ui'
import { useState } from 'react'
import {
Button,
@@ -7,10 +8,12 @@ import {
Input,
ResizableHandle,
ResizablePanel,
+ SidePanel,
Tabs,
TabsContent,
TabsList,
TabsTrigger,
+ useIsMobile,
} from 'ui'
import { GenericSkeletonLoader } from 'ui-patterns/ShimmeringLoader'
import { SimpleCodeBlock } from 'ui-patterns/SimpleCodeBlock'
@@ -26,6 +29,7 @@ import { useSelectedProjectQuery } from '@/hooks/misc/useSelectedProject'
export const UserPanel = () => {
const { data: project } = useSelectedProjectQuery()
const showLogs = useIsFeatureEnabled('logs:all')
+ const isMobile = useIsMobile()
const [selectedId, setSelectedId] = useQueryState(
'show',
@@ -56,99 +60,131 @@ export const UserPanel = () => {
}, {} as Partial
)
: {}
+ const content = (
+ <>
+ }
+ aria-label="Close user details"
+ onClick={() => setSelectedId(null)}
+ />
+ setView(value as 'overview' | 'raw' | 'logs')}
+ >
+ {isPending ? (
+
+ ) : !!selectedUser ? (
+ <>
+
+
+ Overview
+
+ {showLogs && (
+
+ Logs
+
+ )}
+
+ Raw JSON
+
+
+
+
+ {selectedUser && (
+ setSelectedId(null)} />
+ )}
+
+ {showLogs && (
+
+ {selectedUser && }
+
+ )}
+
+
+ setSearchQuery(e.target.value)}
+ className="mr-2"
+ />
+
+
+
+ {JSON.stringify(filteredProperties, null, 2)}
+
+
+ >
+ ) : (
+
+
+ Unable to find user with the following ID in project
+
+
ID: {selectedId}
+
+ )}
+
+ >
+ )
+
+ if (isMobile) {
+ return (
+ setSelectedId(null)}
+ >
+
+ User details
+
+ {content}
+
+ )
+ }
+
return (
<>
-
- }
- onClick={() => setSelectedId(null)}
- />
- setView(value as 'overview' | 'raw' | 'logs')}
- >
- {isPending ? (
-
- ) : !!selectedUser ? (
- <>
-
-
- Overview
-
- {showLogs && (
-
- Logs
-
- )}
-
- Raw JSON
-
-
-
-
- {selectedUser && (
- setSelectedId(null)} />
- )}
-
- {showLogs && (
-
- {selectedUser && }
-
- )}
-
-
- setSearchQuery(e.target.value)}
- className="mr-2"
- />
-
-
-
- {JSON.stringify(filteredProperties, null, 2)}
-
-
- >
- ) : (
-
-
- Unable to find user with the following ID in project
-
-
ID: {selectedId}
-
- )}
-
+
+ {content}
>
)