toes/src/client/styles/misc.ts
2026-02-13 09:02:21 -08:00

160 lines
3.4 KiB
TypeScript

import { define } from '@because/forge'
import { theme } from '../themes'
import type { AppState } from '../../shared/types'
export const StatusDotLink = define('StatusDotLink', {
base: 'a',
position: 'relative',
cursor: 'pointer',
textDecoration: 'none',
selectors: {
'&::after': {
content: 'attr(data-tooltip)',
position: 'absolute',
bottom: '100%',
left: '50%',
transform: 'translateX(-50%)',
marginBottom: 6,
padding: '2px 6px',
fontSize: 10,
fontFamily: theme('fonts-mono'),
color: theme('colors-text'),
background: theme('colors-bgElement'),
border: `1px solid ${theme('colors-border')}`,
borderRadius: 4,
whiteSpace: 'pre',
opacity: 0,
pointerEvents: 'none',
transition: 'opacity 0.15s',
},
'&:hover::after': {
opacity: 1,
},
},
})
export const StatusDotsRow = define('StatusDotsRow', {
display: 'flex',
gap: 8,
alignItems: 'center',
justifyContent: 'center',
})
export const StatusDot = define('StatusDot', {
width: 8,
height: 8,
borderRadius: '50%',
flexShrink: 0,
variants: {
state: {
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') },
},
inline: {
display: 'inline'
}
},
})
export const Section = define('Section', {
marginBottom: 32,
})
export const SectionTitle = define('SectionTitle', {
fontSize: 12,
fontWeight: 600,
color: theme('colors-textFaint'),
textTransform: 'uppercase',
letterSpacing: '0.05em',
marginBottom: 12,
paddingBottom: 8,
borderBottom: `1px solid ${theme('colors-border')}`,
})
export const InfoRow = define('InfoRow', {
display: 'flex',
alignItems: 'center',
gap: 12,
marginBottom: 12,
fontSize: 14,
})
export const InfoLabel = define('InfoLabel', {
color: theme('colors-textFaint'),
width: 80,
flexShrink: 0,
})
export const InfoValue = define('InfoValue', {
color: theme('colors-text'),
display: 'flex',
alignItems: 'center',
gap: 8,
})
export const Link = define('Link', {
base: 'a',
color: theme('colors-link'),
textDecoration: 'none',
selectors: {
'&:hover': { textDecoration: 'underline' },
},
})
export const EmptyState = define('EmptyState', {
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
height: '100%',
color: theme('colors-textFaint'),
fontSize: 14,
})
export const TabBar = define('TabBar', {
display: 'flex',
gap: 24,
marginBottom: 20,
})
export const Tab = define('Tab', {
base: 'button',
padding: '6px 0',
background: 'none',
border: 'none',
borderBottom: '2px solid transparent',
cursor: 'pointer',
fontSize: 14,
color: theme('colors-textMuted'),
selectors: {
'&:hover': { color: theme('colors-text') },
},
variants: {
active: {
color: theme('colors-text'),
borderBottomColor: theme('colors-primary'),
fontWeight: 500,
},
},
})
export const TabContent = define('TabContent', {
display: 'none',
variants: {
active: {
display: 'block'
}
}
})
export const stateLabels: Record<AppState, string> = {
invalid: 'Invalid',
stopped: 'Stopped',
starting: 'Starting',
running: 'Running',
stopping: 'Stopping',
}