Skip to content

Commit 36ff10a

Browse files
committed
improve commands and permission page on mobile
1 parent 6c3bbf7 commit 36ff10a

File tree

2 files changed

+163
-8
lines changed

2 files changed

+163
-8
lines changed

app/commands/page.tsx

Lines changed: 91 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,13 +104,13 @@ export default function Commands() {
104104
<div className='flex-1 container mx-auto px-4 py-8'>
105105
<div className='bg-background rounded-lg border shadow-sm overflow-hidden'>
106106
<div className='w-full'>
107-
<div className='flex gap-4 p-4 border-b border-gray-300 dark:border-gray-700'>
107+
<div className='flex flex-col sm:flex-row gap-4 p-4 border-b border-gray-300 dark:border-gray-700'>
108108
<TextInput
109109
placeholder='Search commands'
110110
leftSection={<IconSearch size={16} />}
111111
value={search}
112112
onChange={e => setSearch(e.currentTarget.value)}
113-
style={{ flex: 1 }}
113+
className='flex-1'
114114
/>
115115
<Select
116116
placeholder='Filter module'
@@ -119,9 +119,11 @@ export default function Commands() {
119119
onChange={value =>
120120
setModuleFilter(value === 'All' ? null : value)
121121
}
122+
className='sm:min-w-40'
122123
/>
123124
</div>
124-
<div className='grid grid-cols-5 gap-4 p-4 border-b border-gray-300 dark:border-gray-700 font-semibold text-sm'>
125+
{/* Desktop table header - hidden on mobile */}
126+
<div className='hidden lg:grid grid-cols-5 gap-4 p-4 border-b border-gray-300 dark:border-gray-700 font-semibold text-sm'>
125127
<div>Module</div>
126128
<div>Command</div>
127129
<div>Aliases</div>
@@ -150,7 +152,8 @@ export default function Commands() {
150152
id={cmd}
151153
style={{ scrollMarginTop: '80px' }}
152154
>
153-
<div className='grid grid-cols-5 gap-4 p-4 items-center'>
155+
{/* Desktop table row - hidden on mobile */}
156+
<div className='hidden lg:grid grid-cols-5 gap-4 p-4 items-center'>
154157
<div className='flex items-center'>
155158
<Badge variant='secondary' className='text-xs'>
156159
{mod}
@@ -231,6 +234,90 @@ export default function Commands() {
231234
</div>
232235
</div>
233236

237+
{/* Mobile card layout - hidden on desktop */}
238+
<div className='lg:hidden p-4 space-y-3'>
239+
<div className='flex items-center justify-between'>
240+
<Badge variant='secondary' className='text-xs'>
241+
{mod}
242+
</Badge>
243+
{(obj.usages?.length > 0 ||
244+
sortedAliases.length > 1) && (
245+
<Button
246+
variant='subtle'
247+
size='xs'
248+
px={4}
249+
className='flex-shrink-0 transition-all duration-200 hover:scale-105'
250+
onClick={() => toggleRow(cmd)}
251+
>
252+
<span className='mr-1 text-xs'>
253+
{openRow === cmd ? 'Hide' : 'Show'}{' '}
254+
details
255+
</span>
256+
<motion.div
257+
animate={{
258+
rotate: openRow === cmd ? 180 : 0,
259+
}}
260+
transition={{
261+
duration: 0.2,
262+
ease: 'easeInOut',
263+
}}
264+
>
265+
<IconChevronDown className='h-4 w-4' />
266+
</motion.div>
267+
</Button>
268+
)}
269+
</div>
270+
271+
<div className='prose dark:prose-invert'>
272+
<a
273+
href={`#${cmd}`}
274+
className='flex items-center gap-1'
275+
>
276+
<code className='px-2 py-1 rounded text-sm font-mono'>
277+
/{cmd}
278+
</code>
279+
<IconHash size={14} />
280+
</a>
281+
</div>
282+
283+
<div className='text-sm text-gray-600 dark:text-gray-400'>
284+
{obj.description || 'None'}
285+
</div>
286+
287+
{sortedAliases.length > 0 && (
288+
<div className='space-y-1'>
289+
<div className='text-xs font-medium text-gray-500 dark:text-gray-400'>
290+
Aliases:
291+
</div>
292+
<div className='flex flex-wrap gap-1'>
293+
{sortedAliases.slice(0, 3).map(alias => (
294+
<code
295+
key={alias}
296+
className='text-xs px-1 py-0.5 rounded'
297+
>
298+
{alias}
299+
</code>
300+
))}
301+
{sortedAliases.length > 3 && (
302+
<span className='text-xs text-gray-500 dark:text-gray-400'>
303+
+{sortedAliases.length - 3} more
304+
</span>
305+
)}
306+
</div>
307+
</div>
308+
)}
309+
310+
<div className='space-y-1'>
311+
<div className='text-xs font-medium text-gray-500 dark:text-gray-400'>
312+
Usage:
313+
</div>
314+
<code className='px-2 py-1 rounded text-xs block bg-gray-100 dark:bg-gray-800 overflow-x-auto'>
315+
/{cmd}
316+
{obj.usage ? obj.usage.slice(10) : ''}
317+
</code>
318+
</div>
319+
</div>
320+
234321
<AnimatePresence>
235322
{openRow === cmd && (
236323
<motion.div className='flex flex-col w-full'>

app/permissions/page.tsx

Lines changed: 72 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,13 +100,13 @@ export default function Permissions() {
100100
<div className='flex-1 container mx-auto px-4 py-8'>
101101
<div className='bg-background rounded-lg border shadow-sm overflow-hidden'>
102102
<div className='w-full'>
103-
<div className='flex gap-4 p-4 border-b border-gray-300 dark:border-gray-700'>
103+
<div className='flex flex-col sm:flex-row gap-4 p-4 border-b border-gray-300 dark:border-gray-700'>
104104
<TextInput
105105
placeholder='Search permissions'
106106
leftSection={<IconSearch size={16} />}
107107
value={search}
108108
onChange={e => setSearch(e.currentTarget.value)}
109-
style={{ flex: 1 }}
109+
className='flex-1'
110110
/>
111111
<Select
112112
placeholder='Filter module'
@@ -115,9 +115,11 @@ export default function Permissions() {
115115
onChange={value =>
116116
setModuleFilter(value === 'All' ? null : value)
117117
}
118+
className='sm:min-w-40'
118119
/>
119120
</div>
120-
<div className='grid grid-cols-4 gap-4 p-4 border-b border-gray-300 dark:border-gray-700 font-semibold text-sm'>
121+
{/* Desktop table header - hidden on mobile */}
122+
<div className='hidden lg:grid grid-cols-4 gap-4 p-4 border-b border-gray-300 dark:border-gray-700 font-semibold text-sm'>
121123
<div>Module</div>
122124
<div>Permission</div>
123125
<div>Description</div>
@@ -149,7 +151,8 @@ export default function Permissions() {
149151
id={perm}
150152
style={{ scrollMarginTop: '80px' }}
151153
>
152-
<div className='grid grid-cols-4 gap-4 p-4 items-center'>
154+
{/* Desktop table row - hidden on mobile */}
155+
<div className='hidden lg:grid grid-cols-4 gap-4 p-4 items-center'>
153156
<div className='flex items-center'>
154157
<Badge variant='secondary' className='text-xs'>
155158
{mod}
@@ -202,6 +205,71 @@ export default function Permissions() {
202205
)}
203206
</div>
204207
</div>
208+
209+
{/* Mobile card layout - hidden on desktop */}
210+
<div className='lg:hidden p-4 space-y-3'>
211+
<div className='flex items-center justify-between'>
212+
<Badge variant='secondary' className='text-xs'>
213+
{mod}
214+
</Badge>
215+
<span className='text-sm font-medium'>
216+
{formatDefault(obj.default)}
217+
</span>
218+
</div>
219+
220+
<div className='prose dark:prose-invert'>
221+
<a
222+
href={`#${perm}`}
223+
className='flex items-center gap-1'
224+
>
225+
<code className='px-2 py-1 rounded text-sm font-mono'>
226+
{perm}
227+
</code>
228+
<IconHash size={14} />
229+
</a>
230+
{hasChildren && (
231+
<Badge
232+
variant='secondary'
233+
className='mt-2 text-xs whitespace-nowrap'
234+
>
235+
Permission Group
236+
</Badge>
237+
)}
238+
</div>
239+
240+
<div className='text-sm text-gray-600 dark:text-gray-400'>
241+
{obj.description || 'None'}
242+
</div>
243+
244+
{hasChildren && (
245+
<div className='flex justify-end'>
246+
<Button
247+
variant='subtle'
248+
size='xs'
249+
px={4}
250+
className='flex-shrink-0 transition-all duration-200 hover:scale-105'
251+
onClick={() => toggleRow(rowKey)}
252+
>
253+
<span className='mr-1 text-xs'>
254+
{openRow === rowKey ? 'Hide' : 'Show'}{' '}
255+
children
256+
</span>
257+
<motion.div
258+
animate={{
259+
rotate: openRow === rowKey ? 180 : 0,
260+
}}
261+
transition={{
262+
duration: 0.2,
263+
ease: 'easeInOut',
264+
}}
265+
>
266+
<IconChevronDown className='h-4 w-4' />
267+
</motion.div>
268+
</Button>
269+
</div>
270+
)}
271+
</div>
272+
205273
<AnimatePresence>
206274
{hasChildren && openRow === rowKey && (
207275
<PermissionSets

0 commit comments

Comments
 (0)