diff --git a/src/client/components/DashboardLanding.tsx b/src/client/components/DashboardLanding.tsx
index 3a1b848..1c5e5cc 100644
--- a/src/client/components/DashboardLanding.tsx
+++ b/src/client/components/DashboardLanding.tsx
@@ -63,7 +63,7 @@ export function DashboardLanding({ render }: { render: () => void }) {
-
+
diff --git a/src/client/components/Urls.tsx b/src/client/components/Urls.tsx
index ffe9aca..da171d8 100644
--- a/src/client/components/Urls.tsx
+++ b/src/client/components/Urls.tsx
@@ -1,16 +1,16 @@
import { buildAppUrl } from '../../shared/urls'
-import { apps } from '../state'
+import { apps, setSelectedApp } from '../state'
import {
EmptyState,
- StatusDot,
- UrlLeft,
- UrlLink,
- UrlList,
- UrlPort,
- UrlRow,
+ Tile,
+ TileGrid,
+ TileIcon,
+ TileName,
+ TilePort,
+ TileStatus,
} from '../styles'
-export function Urls() {
+export function Urls({ render }: { render: () => void }) {
const nonTools = apps.filter(a => !a.tool)
if (nonTools.length === 0) {
@@ -18,26 +18,32 @@ export function Urls() {
}
return (
-
+
{nonTools.map(app => {
const url = buildAppUrl(app.name, location.origin)
const running = app.state === 'running'
+ const openAppPage = (e: MouseEvent) => {
+ e.preventDefault()
+ e.stopPropagation()
+ setSelectedApp(app.name)
+ render()
+ }
+
return (
-
-
-
- {app.icon}
- {running ? (
- {url}
- ) : (
- {app.name}
- )}
-
- {app.port ? :{app.port} : null}
-
+
+
+ {app.icon}
+ {app.name}
+ {app.port ? `:${app.port}` : '\u2014'}
+
)
})}
-
+
)
}
diff --git a/src/client/styles/dashboard.ts b/src/client/styles/dashboard.ts
index 9e3d9b7..d6e7e26 100644
--- a/src/client/styles/dashboard.ts
+++ b/src/client/styles/dashboard.ts
@@ -203,58 +203,73 @@ export const LogStatus = define('LogStatus', {
},
})
-// URL List
-export const UrlLeft = define('UrlLeft', {
- display: 'flex',
- alignItems: 'center',
- gap: 8,
- minWidth: 0,
-})
-
-export const UrlLink = define('UrlLink', {
- base: 'a',
- color: theme('colors-link'),
- textDecoration: 'none',
- overflow: 'hidden',
- textOverflow: 'ellipsis',
- whiteSpace: 'nowrap',
- selectors: {
- '&:hover': { textDecoration: 'underline' },
- },
-})
-
-export const UrlList = define('UrlList', {
+// App Tiles Grid
+export const TileGrid = define('TileGrid', {
width: '100%',
- minWidth: 400,
- maxWidth: 800,
+ maxWidth: 900,
+ display: 'grid',
+ gridTemplateColumns: 'repeat(auto-fill, minmax(240px, 1fr))',
+ gap: 20,
+})
+
+export const Tile = define('Tile', {
+ base: 'a',
+ position: 'relative',
display: 'flex',
flexDirection: 'column',
+ alignItems: 'center',
+ gap: 8,
+ padding: '28px 20px 24px',
background: theme('colors-bgElement'),
border: `1px solid ${theme('colors-border')}`,
borderRadius: theme('radius-md'),
- overflow: 'hidden',
-})
-
-export const UrlPort = define('UrlPort', {
- fontFamily: theme('fonts-mono'),
- fontSize: 12,
- color: theme('colors-textFaint'),
- flexShrink: 0,
-})
-
-export const UrlRow = define('UrlRow', {
- display: 'flex',
- justifyContent: 'space-between',
- alignItems: 'center',
- padding: '10px 16px',
- fontFamily: theme('fonts-mono'),
- fontSize: 13,
+ textDecoration: 'none',
+ cursor: 'pointer',
selectors: {
'&:hover': {
background: theme('colors-bgHover'),
- },
- '&:not(:last-child)': {
- borderBottom: `1px solid ${theme('colors-border')}`,
+ borderColor: theme('colors-textFaint'),
+ },
+ },
+})
+
+export const TileIcon = define('TileIcon', {
+ fontSize: 48,
+ lineHeight: 1,
+ userSelect: 'none',
+})
+
+export const TileName = define('TileName', {
+ fontSize: 15,
+ fontWeight: 600,
+ color: theme('colors-text'),
+ textAlign: 'center',
+})
+
+export const TilePort = define('TilePort', {
+ fontFamily: theme('fonts-mono'),
+ fontSize: 13,
+ color: theme('colors-textFaint'),
+})
+
+export const TileStatus = define('TileStatus', {
+ position: 'absolute',
+ top: 8,
+ right: 8,
+ width: 2,
+ height: 2,
+ borderRadius: '50%',
+ cursor: 'pointer',
+ padding: 4,
+ backgroundClip: 'content-box',
+ variants: {
+ state: {
+ error: { background: theme('colors-statusInvalid') },
+ invalid: { background: theme('colors-statusInvalid') },
+ stopped: { background: theme('colors-statusStopped') },
+ starting: { background: theme('colors-statusStarting') },
+ running: { background: theme('colors-statusRunning') },
+ stopping: { background: theme('colors-statusStarting') },
},
},
})
diff --git a/src/client/styles/index.ts b/src/client/styles/index.ts
index 3e33da7..f9223fa 100644
--- a/src/client/styles/index.ts
+++ b/src/client/styles/index.ts
@@ -15,11 +15,12 @@ export {
LogStatus,
LogText,
LogTimestamp,
- UrlLeft,
- UrlLink,
- UrlList,
- UrlPort,
- UrlRow,
+ Tile,
+ TileGrid,
+ TileIcon,
+ TileName,
+ TilePort,
+ TileStatus,
VitalCard,
VitalLabel,
VitalsSection,