Skip to content

Commit 7cb4257

Browse files
committed
feat: update icons and improve layout for database constraints, enums, and indexes
1 parent c86d9dd commit 7cb4257

3 files changed

Lines changed: 106 additions & 170 deletions

File tree

apps/desktop/src/routes/_protected/database/$id/definitions/constraints/index.tsx

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { CardContent, CardHeader, CardTitle, MotionCard } from '@conar/ui/compon
66
import { HighlightText } from '@conar/ui/components/custom/highlight'
77
import { SearchInput } from '@conar/ui/components/custom/search-input'
88
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@conar/ui/components/select'
9-
import { RiDatabase2Line, RiKey2Line, RiLinksLine, RiTable2 } from '@remixicon/react'
9+
import { RiDatabase2Line, RiKey2Line, RiLayoutColumnLine, RiLinksLine, RiTable2 } from '@remixicon/react'
1010
import { createFileRoute } from '@tanstack/react-router'
1111
import { useState } from 'react'
1212
import { useConnectionConstraints, useConnectionTablesAndSchemas } from '~/entities/connection/queries'
@@ -157,12 +157,13 @@ function DatabaseConstraintsPage() {
157157
{item.table}
158158
</Badge>
159159
{item.column && (
160-
<span className="flex items-center gap-2">
160+
<>
161161
<span>on</span>
162162
<Badge variant="outline" className="font-mono text-xs">
163+
<RiLayoutColumnLine className="mr-1 size-3" />
163164
{item.column}
164165
</Badge>
165-
</span>
166+
</>
166167
)}
167168
</div>
168169
</div>

apps/desktop/src/routes/_protected/database/$id/definitions/enums/index.tsx

Lines changed: 60 additions & 132 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
11
import { ConnectionType } from '@conar/shared/enums/connection-type'
22
import { title } from '@conar/shared/utils/title'
33
import { Badge } from '@conar/ui/components/badge'
4-
import { CardContent, CardHeader, CardTitle, MotionCard } from '@conar/ui/components/card'
4+
import { CardHeader, CardTitle, MotionCard } from '@conar/ui/components/card'
55
import { HighlightText } from '@conar/ui/components/custom/highlight'
66
import { SearchInput } from '@conar/ui/components/custom/search-input'
77
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@conar/ui/components/select'
8-
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@conar/ui/components/tooltip'
98
import { cn } from '@conar/ui/lib/utils'
10-
import NumberFlow from '@number-flow/react'
11-
import { RiDatabase2Line, RiListIndefinite, RiListUnordered, RiStackLine, RiTable2 } from '@remixicon/react'
9+
import { RiLayoutColumnLine, RiListIndefinite, RiListUnordered, RiTable2 } from '@remixicon/react'
1210
import { createFileRoute } from '@tanstack/react-router'
1311
import { AnimatePresence, motion } from 'motion/react'
1412
import { useState } from 'react'
@@ -101,142 +99,72 @@ function DatabaseEnumsPage() {
10199
{...MOTION_BLOCK_PROPS}
102100
>
103101
<CardHeader className="bg-muted/30 px-4 py-3">
104-
<div className="flex items-center justify-between">
105-
<div className="flex flex-wrap items-center gap-2">
106-
<CardTitle>
107-
<TooltipProvider>
108-
<Tooltip>
109-
<TooltipTrigger asChild>
110-
<span className={`
111-
flex items-center gap-2 text-base font-medium
112-
`}
113-
>
114-
{enumItem.metadata?.isSet
115-
? (
116-
<RiListIndefinite className={`
117-
size-4 text-primary
118-
`}
119-
/>
120-
)
121-
: (
122-
<RiListUnordered className={`
123-
size-4 text-primary
124-
`}
125-
/>
126-
)}
127-
<HighlightText text={enumItem.name} match={search} />
128-
</span>
129-
</TooltipTrigger>
130-
<TooltipContent>
131-
{enumItem.metadata?.isSet ? 'Set type' : 'Enum type'}
132-
{enumItem.metadata?.table && enumItem.metadata.column && (
133-
<div className="mt-1 text-xs text-muted-foreground">
134-
Used in&nbsp;
135-
<Badge
136-
variant="outline"
137-
className="mr-1 px-1 py-0.5 font-mono"
138-
>
139-
{enumItem.metadata.table}
140-
</Badge>
141-
table and
102+
<div className="flex items-start justify-between">
103+
<div>
104+
<CardTitle className="flex items-center gap-2 text-base">
105+
{enumItem.metadata?.isSet
106+
? <RiListIndefinite className="size-4 text-primary" />
107+
: <RiListUnordered className="size-4 text-primary" />}
108+
<HighlightText text={enumItem.name} match={search} />
109+
<Badge
110+
variant="secondary"
111+
className="ml-2 text-xs font-normal"
112+
>
113+
{enumItem.metadata?.isSet ? 'Set' : 'Enum'}
114+
</Badge>
115+
</CardTitle>
116+
<div className={`
117+
mt-2 flex flex-wrap items-center gap-2 text-sm
118+
text-muted-foreground
119+
`}
120+
>
121+
{enumItem.metadata?.table && (
122+
<>
123+
<Badge variant="outline" className="text-xs font-normal">
124+
<RiTable2 className="mr-1 size-3" />
125+
{enumItem.metadata.table}
126+
</Badge>
127+
{enumItem.metadata.column && (
128+
<>
129+
<span>on</span>
130+
<Badge
131+
variant="outline"
132+
className="font-mono text-xs"
133+
>
134+
<RiLayoutColumnLine className="mr-1 size-3" />
135+
{enumItem.metadata.column}
136+
</Badge>
137+
</>
138+
)}
139+
</>
140+
)}
141+
<AnimatePresence initial={false} mode="popLayout">
142+
{enumItem.values.map(value => (
143+
<HighlightText
144+
key={value}
145+
text={value}
146+
match={search}
147+
render={({ html, matched }) => (
148+
<motion.div layout {...MOTION_BLOCK_PROPS}>
142149
<Badge
143150
variant="outline"
144-
className="ml-1 px-1 py-0.5"
151+
className={cn(
152+
'font-mono text-xs',
153+
matched && 'border-primary/30 bg-primary/10',
154+
)}
145155
>
146-
{enumItem.metadata.column}
156+
{/* eslint-disable-next-line react-dom/no-dangerously-set-innerhtml */}
157+
<span dangerouslySetInnerHTML={{ __html: html }} />
147158
</Badge>
148-
{' '}
149-
column
150-
</div>
159+
</motion.div>
151160
)}
152-
</TooltipContent>
153-
</Tooltip>
154-
</TooltipProvider>
155-
</CardTitle>
156-
<TooltipProvider>
157-
<Tooltip>
158-
<TooltipTrigger asChild>
159-
<Badge variant="outline" className="text-xs">
160-
<RiStackLine className="mr-0.5 inline size-3" />
161-
{enumItem.schema}
162-
</Badge>
163-
</TooltipTrigger>
164-
<TooltipContent>
165-
Schema name
166-
</TooltipContent>
167-
</Tooltip>
168-
</TooltipProvider>
169-
{enumItem.metadata?.table && (
170-
<TooltipProvider>
171-
<Tooltip>
172-
<TooltipTrigger asChild>
173-
<Badge variant="outline" className="text-xs">
174-
<RiTable2 className="mr-0.5 inline size-3" />
175-
{enumItem.metadata.table}
176-
</Badge>
177-
</TooltipTrigger>
178-
<TooltipContent>
179-
Table name
180-
</TooltipContent>
181-
</Tooltip>
182-
</TooltipProvider>
183-
)}
184-
{enumItem.metadata?.column && (
185-
<TooltipProvider>
186-
<Tooltip>
187-
<TooltipTrigger asChild>
188-
<Badge variant="outline" className="text-xs">
189-
<RiDatabase2Line className="mr-0.5 inline size-3" />
190-
{enumItem.metadata.column}
191-
</Badge>
192-
</TooltipTrigger>
193-
<TooltipContent>
194-
Column name
195-
</TooltipContent>
196-
</Tooltip>
197-
</TooltipProvider>
198-
)}
161+
/>
162+
))}
163+
</AnimatePresence>
164+
</div>
199165
</div>
200-
<Badge variant="secondary" className="text-xs">
201-
<NumberFlow
202-
className="tabular-nums"
203-
value={enumItem.values.length}
204-
suffix={` value${enumItem.values.length === 1 ? '' : 's'}`}
205-
/>
206-
</Badge>
207166
</div>
208167
</CardHeader>
209-
<CardContent className="flex flex-wrap gap-2 px-4 py-3">
210-
<AnimatePresence initial={false} mode="popLayout">
211-
{enumItem.values.length === 0 && (
212-
<motion.div layout {...MOTION_BLOCK_PROPS}>
213-
<Badge variant="outline">
214-
No values found
215-
</Badge>
216-
</motion.div>
217-
)}
218-
{enumItem.values.map(value => (
219-
<HighlightText
220-
key={value}
221-
text={value}
222-
match={search}
223-
render={({ html, matched }) => (
224-
<motion.div layout {...MOTION_BLOCK_PROPS}>
225-
<Badge
226-
variant="outline"
227-
className={cn(matched && `
228-
border-primary/30 bg-primary/10
229-
`)}
230-
>
231-
{/* eslint-disable-next-line react-dom/no-dangerously-set-innerhtml */}
232-
<span dangerouslySetInnerHTML={{ __html: html }} />
233-
</Badge>
234-
</motion.div>
235-
)}
236-
/>
237-
))}
238-
</AnimatePresence>
239-
</CardContent>
240168
</MotionCard>
241169
))}
242170
</DefinitionsGrid>

apps/desktop/src/routes/_protected/database/$id/definitions/indexes/index.tsx

Lines changed: 42 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { CardHeader, CardTitle, MotionCard } from '@conar/ui/components/card'
55
import { HighlightText } from '@conar/ui/components/custom/highlight'
66
import { SearchInput } from '@conar/ui/components/custom/search-input'
77
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@conar/ui/components/select'
8-
import { RiFileList3Line, RiKey2Line, RiTable2 } from '@remixicon/react'
8+
import { RiFileList3Line, RiKey2Line, RiLayoutColumnLine, RiTable2 } from '@remixicon/react'
99
import { createFileRoute } from '@tanstack/react-router'
1010
import { useState } from 'react'
1111
import { useConnectionIndexes, useConnectionTablesAndSchemas } from '~/entities/connection/queries'
@@ -154,41 +154,48 @@ function DatabaseIndexesPage() {
154154
{...MOTION_BLOCK_PROPS}
155155
>
156156
<CardHeader className="bg-muted/30 px-4 py-3">
157-
<div className="flex items-center justify-between">
158-
<CardTitle className="flex items-center gap-2 text-base">
159-
{item.isPrimary
160-
? <RiKey2Line className="size-4 text-primary" />
161-
: <RiFileList3Line className="size-4 text-primary" />}
162-
<HighlightText text={item.name} match={search} />
163-
{item.isPrimary && (
164-
<Badge
165-
variant="secondary"
166-
className="ml-2 text-xs font-normal"
167-
>
168-
Primary Key
169-
</Badge>
170-
)}
171-
{item.isUnique && !item.isPrimary && (
172-
<Badge variant="secondary" className="text-xs">
173-
Unique
174-
</Badge>
175-
)}
176-
</CardTitle>
177-
<Badge variant="outline" className="text-xs font-normal">
178-
<RiTable2 className="mr-1 size-3" />
179-
{item.table}
180-
</Badge>
181-
</div>
182-
<div className="mt-2 flex flex-wrap gap-1">
183-
{item.columns.map((col: string) => (
184-
<Badge
185-
key={col}
186-
variant="secondary"
187-
className="font-mono text-xs"
157+
<div className="flex items-start justify-between">
158+
<div>
159+
<CardTitle className="flex items-center gap-2 text-base">
160+
{item.isPrimary
161+
? <RiKey2Line className="size-4 text-primary" />
162+
: <RiFileList3Line className="size-4 text-primary" />}
163+
<HighlightText text={item.name} match={search} />
164+
{item.isPrimary && (
165+
<Badge
166+
variant="secondary"
167+
className="ml-2 text-xs font-normal"
168+
>
169+
Primary Key
170+
</Badge>
171+
)}
172+
{item.isUnique && !item.isPrimary && (
173+
<Badge variant="secondary" className="text-xs">
174+
Unique
175+
</Badge>
176+
)}
177+
</CardTitle>
178+
<div className={`
179+
mt-2 flex items-center gap-2 text-sm text-muted-foreground
180+
`}
188181
>
189-
{col}
190-
</Badge>
191-
))}
182+
<Badge variant="outline" className="text-xs font-normal">
183+
<RiTable2 className="mr-1 size-3" />
184+
{item.table}
185+
</Badge>
186+
<span>on</span>
187+
{item.columns.map((col: string) => (
188+
<Badge
189+
key={col}
190+
variant="outline"
191+
className="font-mono text-xs"
192+
>
193+
<RiLayoutColumnLine className="mr-1 size-3" />
194+
{col}
195+
</Badge>
196+
))}
197+
</div>
198+
</div>
192199
</div>
193200
</CardHeader>
194201
</MotionCard>

0 commit comments

Comments
 (0)