style: projects and settings

This commit is contained in:
Cody Bender 2024-10-23 15:44:47 -04:00
parent f50f4b9a4d
commit 1cb7c5a1f4
45 changed files with 293 additions and 226 deletions

View File

@ -1,5 +1,5 @@
<!doctype html>
<html lang="en" class="dark dark:bg-background">
<html lang="en" class="dark dark:bg-background dark:text-foreground">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
@ -10,6 +10,12 @@
<meta name="theme-color" content="#ffffff" />
<link rel="manifest" href="/manifest.json" />
<title>Laconic</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=DM+Mono:ital,wght@0,300;0,400;0,500;1,300;1,400;1,500&display=swap"
rel="stylesheet"
/>
</head>
<body>
<div id="root"></div>

View File

@ -1,5 +1,4 @@
import { Link } from 'react-router-dom';
import { Heading } from './shared/Heading';
interface LogoProps {
orgSlug?: string;

View File

@ -24,8 +24,8 @@ const Stepper = ({ activeStep, stepperValues }: StepperProps) => {
<div
className={`text-sm ${
activeStep === stepperValue.step
? 'text-black font-semibold'
: 'text-gray-600'
? 'text-black font-semibold dark:text-foreground'
: 'text-gray-600 dark:text-foreground-secondary'
}`}
>
{stepperValue.label}

View File

@ -4,7 +4,9 @@ export const projectCardTheme = tv({
slots: {
wrapper: [
'bg-surface-card',
'dark:bg-overlay2',
'shadow-card',
'dark:shadow-background',
'rounded-2xl',
'flex',
'flex-col',
@ -17,10 +19,16 @@ export const projectCardTheme = tv({
'text-sm',
'font-medium',
'text-elements-high-em',
'dark:text-foreground',
'tracking-[-0.006em]',
'truncate',
],
description: ['text-xs', 'text-elements-low-em', 'truncate'],
description: [
'text-xs',
'text-elements-low-em',
'dark:text-foreground-secondary',
'truncate',
],
icons: ['flex', 'items-center', 'gap-1'],
lowerContent: [
'transition-colors',
@ -32,6 +40,7 @@ export const projectCardTheme = tv({
'gap-2',
'rounded-b-2xl',
'group-hover:bg-surface-card-hovered',
'dark:group-hover:bg-overlay3',
],
latestDeployment: ['flex', 'items-center', 'gap-2'],
deploymentStatusContainer: [
@ -42,10 +51,15 @@ export const projectCardTheme = tv({
'justify-center',
],
deploymentStatus: ['w-1', 'h-1', 'rounded-full'],
deploymentName: ['text-xs', 'text-elements-low-em'],
deploymentName: [
'text-xs',
'text-elements-low-em',
'dark:text-foreground-secondary',
],
deploymentText: [
'text-xs',
'text-elements-low-em',
'dark:text-foreground-secondary',
'font-mono',
'flex',
'items-center',
@ -53,9 +67,11 @@ export const projectCardTheme = tv({
],
wavyBorder: [
'bg-surface-card',
'dark:bg-background',
'transition-colors',
'duration-150',
'group-hover:bg-surface-card-hovered',
'dark:group-hover:bg-overlay2',
],
},
variants: {
@ -67,7 +83,7 @@ export const projectCardTheme = tv({
deploymentStatus: ['bg-orange-400'],
},
failure: {
deploymentStatus: ['bg-rose-500'],
deploymentStatus: ['bg-error'],
},
pending: {
deploymentStatus: ['bg-gray-500'],

View File

@ -88,7 +88,7 @@ export const ProjectCard = ({
</div>
{/* Icons */}
<div className={theme.icons()}>
{hasError && <WarningDiamondIcon className="text-elements-danger" />}
{hasError && <WarningDiamondIcon className="text-error" />}
<Menu placement="bottom-end">
<MenuHandler>
<Button
@ -101,12 +101,15 @@ export const ProjectCard = ({
<HorizontalDotIcon />
</Button>
</MenuHandler>
<MenuList>
<MenuItem onClick={navigateToSettingsOnClick}>
<MenuList className="dark:bg-overlay3 dark:shadow-background dark:border-none">
<MenuItem
onClick={navigateToSettingsOnClick}
className="text-foreground"
>
Project settings
</MenuItem>
<MenuItem
className="text-red-500"
className="text-error"
onClick={navigateToSettingsOnClick}
>
Delete project

View File

@ -16,7 +16,7 @@ export const Activity = ({
<div className="flex items-center justify-between">
<Heading className="text-lg leading-6 font-medium">Activity</Heading>
<Button variant="tertiary" size="sm">
See all
SEE ALL
</Button>
</div>
<div className="mt-5">

View File

@ -18,7 +18,6 @@ import { Button, Heading, Tag } from 'components/shared';
const WAIT_DURATION = 5000;
const DIALOG_STYLE = {
backgroundColor: 'rgba(0,0,0, .9)',
padding: '2em',
borderRadius: '0.5em',
marginLeft: '0.5em',
@ -86,27 +85,27 @@ export const AuctionCard = ({ project }: { project: Project }) => {
return (
<>
<div className="p-3 gap-2 rounded-xl border border-gray-200 transition-colors hover:bg-base-bg-alternate flex flex-col mt-8">
<div className="p-3 gap-2 rounded-xl border dark:border-overlay3 border-gray-200 transition-colors hover:bg-base-bg-alternate dark:hover:bg-overlay3 flex flex-col mt-8">
<div className="flex justify-between items-center">
<Heading className="text-lg leading-6 font-medium">
Auction details
</Heading>
<Button onClick={handleOpenDialog} variant="tertiary" size="sm">
View details
VIEW DETAILS
</Button>
</div>
<div className="flex justify-between items-center mt-2">
<span className="text-elements-high-em text-sm font-medium tracking-tight">
<span className="text-elements-high-em dark:text-foreground-secondary text-sm font-medium tracking-tight">
Auction Id
</span>
<span className="text-elements-mid-em text-sm text-right">
<span className="text-elements-mid-em dark:text-foreground text-sm text-right">
{project.auctionId}
</span>
</div>
<div className="flex justify-between items-center mt-1">
<span className="text-elements-high-em text-sm font-medium tracking-tight">
<span className="text-elements-high-em dark:text-foreground-secondary text-sm font-medium tracking-tight">
Auction Status
</span>
<div className="ml-2">{renderAuctionStatus()}</div>
@ -116,17 +115,20 @@ export const AuctionCard = ({ project }: { project: Project }) => {
<>
{deployers?.length > 0 ? (
<div>
<span className="text-elements-high-em text-sm font-medium tracking-tight">
<span className="text-elements-high-em dark:text-foreground-secondary text-sm font-medium tracking-tight">
Deployer LRNs
</span>
{deployers.map((deployer, index) => (
<p key={index} className="text-elements-mid-em text-sm">
<p
key={index}
className="text-elements-mid-em dark:text-foreground text-sm"
>
{'\u2022'} {deployer.deployerLrn}
</p>
))}
<div className="flex justify-between items-center mt-1">
<span className="text-elements-high-em text-sm font-medium tracking-tight">
<span className="text-elements-high-em dark:text-foreground-secondary text-sm font-medium tracking-tight">
Deployer Funds Status
</span>
<div className="ml-2">
@ -141,7 +143,7 @@ export const AuctionCard = ({ project }: { project: Project }) => {
</div>
) : (
<div className="mt-3">
<span className="text-elements-high-em text-sm font-medium tracking-tight">
<span className="text-elements-high-em dark:text-foreground-secondary text-sm font-medium tracking-tight">
No winning deployers
</span>
</div>
@ -155,15 +157,24 @@ export const AuctionCard = ({ project }: { project: Project }) => {
onClose={handleCloseDialog}
fullWidth
maxWidth="md"
PaperProps={{
className: 'dark:bg-overlay2',
}}
>
<DialogTitle>Auction Details</DialogTitle>
<DialogTitle className="dark:text-foreground">
Auction Details
</DialogTitle>
<DialogContent style={DIALOG_STYLE}>
{auctionDetails && (
<pre>{JSON.stringify(auctionDetails, null, 2)}</pre>
<pre className="dark:text-foreground-secondary">
{JSON.stringify(auctionDetails, null, 2)}
</pre>
)}
</DialogContent>
<DialogActions>
<Button onClick={handleCloseDialog}>Close</Button>
<Button onClick={handleCloseDialog} shape="default">
CLOSE
</Button>
</DialogActions>
</Dialog>
</>

View File

@ -18,7 +18,7 @@ export const OverviewInfo = ({
return (
<div className="flex justify-between gap-2 py-3 text-sm items-center">
<div className="flex gap-2 items-center text-elements-high-em">
<div className="flex gap-2 items-center text-elements-high-em dark:text-foreground-secondary">
{styledIcon}
{label}
</div>

View File

@ -93,11 +93,11 @@ const AddMemberDialog = ({
/>
</Modal.Body>
<Modal.Footer>
<Button onClick={handleOpen} variant="secondary">
<Button onClick={handleOpen} variant="danger" shape="default">
Cancel
</Button>
<Button type="submit" disabled={!isValid}>
Send invite
<Button type="submit" disabled={!isValid} shape="default">
SEND INVITE
</Button>
</Modal.Footer>
</form>

View File

@ -24,7 +24,7 @@ const DisplayEnvironmentVariables = ({
return (
<>
<div
className="flex gap-4 p-2"
className="flex gap-4 p-2 dark:text-foreground"
onClick={() => setOpenCollapse((cur) => !cur)}
>
{openCollapse ? <ChevronUpSmallIcon /> : <ChevronDownSmallIcon />}
@ -33,7 +33,7 @@ const DisplayEnvironmentVariables = ({
</div>
<Collapse open={openCollapse}>
{variables.length === 0 ? (
<div className="bg-slate-100 rounded-xl flex-col p-4">
<div className="bg-slate-100 dark:bg-overlay2 dark:text-foreground rounded-xl flex-col p-4">
No environment variables added yet. Once you add them, they'll show
up here.
</div>

View File

@ -80,7 +80,7 @@ const MemberCard = ({
return (
<div
className={`flex py-1 items-center ${!isFirstCard && 'mt-1 border-t border-gray-300'}`}
className={`flex py-1 items-center ${!isFirstCard && 'mt-1 border-t border-gray-300'} dark:text-foreground`}
>
<div className="basis-1/2">
{member.name && (

View File

@ -102,8 +102,8 @@ const SetupDomain = () => {
)}
<div className="self-stretch">
<Button disabled={!isValid} type="submit">
Next
<Button disabled={!isValid} type="submit" shape="default">
NEXT
</Button>
</div>
</form>

View File

@ -30,7 +30,12 @@ export const avatarTheme = tv(
fallback: ['text-elements-warning', 'bg-base-bg-emphasized-warning'],
},
blue: {
fallback: ['text-elements-info', 'bg-base-bg-emphasized-info'],
fallback: [
'text-elements-info',
'bg-base-bg-emphasized-info',
'dark:text-foreground',
'dark:bg-primary',
],
},
},
size: {

View File

@ -16,6 +16,7 @@ export const buttonTheme = tv(
'disabled:cursor-not-allowed',
'transition-colors',
'duration-150',
'font-mono',
],
variants: {
size: {
@ -28,7 +29,7 @@ export const buttonTheme = tv(
true: 'w-full',
},
shape: {
default: 'rounded-lg',
default: 'rounded',
rounded: 'rounded-full',
},
iconOnly: {
@ -95,7 +96,7 @@ export const buttonTheme = tv(
'text-elements-on-danger',
'border',
'border-transparent',
'bg-border-danger',
'bg-error',
'hover:bg-controls-danger-hovered',
'focus-visible:bg-controls-danger-hovered',
'disabled:text-elements-on-disabled',

View File

@ -40,11 +40,11 @@ abbr[title] {
}
.react-calendar__tile {
@apply h-12 w-12 text-elements-high-em;
@apply h-12 w-12 text-elements-high-em dark:text-foreground;
}
.react-calendar__tile:hover {
@apply bg-base-bg-emphasized rounded-lg;
@apply bg-base-bg-emphasized dark:bg-overlay3 rounded-lg;
}
.react-calendar__tile:focus-visible {
@ -52,7 +52,7 @@ abbr[title] {
}
.react-calendar__tile--now {
@apply bg-base-bg-emphasized text-elements-high-em rounded-lg;
@apply bg-base-bg-emphasized dark:bg-overlay3 text-elements-high-em rounded-lg;
}
.react-calendar__tile--now:hover {
@ -77,7 +77,7 @@ abbr[title] {
/* Range -- START */
.react-calendar__tile--range {
@apply bg-controls-secondary text-elements-on-secondary rounded-none;
@apply bg-controls-secondary dark:bg-overlay3 text-elements-on-secondary rounded-none;
}
.react-calendar__tile--range:hover {
@ -89,7 +89,7 @@ abbr[title] {
}
.react-calendar__tile--rangeStart {
@apply bg-controls-primary text-elements-on-primary rounded-lg;
@apply bg-controls-primary dark:bg-primary text-elements-on-primary rounded-lg;
}
.react-calendar__tile--rangeStart:hover {
@ -101,7 +101,7 @@ abbr[title] {
}
.react-calendar__tile--rangeEnd {
@apply bg-controls-primary text-elements-on-primary rounded-lg;
@apply bg-controls-primary dark:bg-primary text-elements-on-primary rounded-lg;
}
.react-calendar__tile--rangeEnd:hover {

View File

@ -5,7 +5,9 @@ export const calendarTheme = tv({
wrapper: [
'max-w-[352px]',
'bg-surface-floating',
'dark:bg-overlay2',
'shadow-dropdown',
'dark:shadow-background',
'rounded-xl',
],
calendar: ['flex', 'flex-col', 'py-2', 'px-2', 'gap-2'],
@ -28,9 +30,12 @@ export const calendarTheme = tv({
'border',
'border-border-interactive',
'text-elements-high-em',
'dark:text-foreground',
'shadow-field',
'bg-white',
'dark:bg-overlay3',
'hover:bg-base-bg-alternate',
'dark:hover:bg-foreground-secondary',
'focus-visible:bg-base-bg-alternate',
],
footer: [

View File

@ -280,6 +280,7 @@ export const Calendar = ({
showNavigation={false}
selectRange={selectRange}
onChange={handleChange}
// tileClassName="dark:text-foreground-secondary dark:hover:bg-overlay3"
onClickMonth={(date) => handleChangeNavigation('month', date)}
onClickYear={(date) => handleChangeNavigation('year', date)}
/>
@ -297,19 +298,20 @@ export const Calendar = ({
) : (
<>
{value && (
<Button variant="danger" onClick={handleReset}>
Reset
<Button variant="danger" onClick={handleReset} shape="default">
RESET
</Button>
)}
<div className="space-x-3">
<Button variant="tertiary" onClick={onCancel}>
Cancel
<Button variant="tertiary" onClick={onCancel} shape="default">
CANCEL
</Button>
<Button
disabled={!value}
onClick={() => (value ? onSelect?.(value) : null)}
shape="default"
>
Select
SELECT
</Button>
</div>
</>

View File

@ -11,7 +11,9 @@ export const getCheckboxVariant = tv({
'focus-visible:text-controls-disabled',
'group-focus-visible:text-controls-disabled',
'data-[state=checked]:text-elements-on-primary',
'dark:data-[state=checked]:text-foreground',
'data-[state=checked]:group-focus-visible:text-elements-on-primary',
'dark:data-[state=checked]:group-focus-visible:text-foreground',
'data-[state=indeterminate]:text-elements-on-primary',
'data-[state=checked]:data-[disabled]:text-elements-on-disabled-active',
],
@ -23,6 +25,7 @@ export const getCheckboxVariant = tv({
'border',
'border-border-interactive/10',
'bg-controls-tertiary',
'dark:bg-background',
'rounded-md',
'transition-all',
'duration-150',
@ -30,9 +33,13 @@ export const getCheckboxVariant = tv({
'shadow-button',
'group-hover:border-border-interactive/[0.14]',
'group-hover:bg-controls-tertiary',
'dark:group-hover:bg-overlay',
'data-[state=checked]:bg-controls-primary',
'dark:data-[state=checked]:bg-primary',
'data-[state=checked]:hover:bg-controls-primary-hovered',
'dark:data-[state=checked]:hover:bg-primary-hovered',
'data-[state=checked]:focus-visible:bg-controls-primary-hovered',
'dark:data-[state=checked]:focus-visible:bg-primary-hovered',
'data-[disabled]:bg-controls-disabled',
'data-[disabled]:shadow-none',
'data-[disabled]:hover:border-border-interactive/10',
@ -43,12 +50,17 @@ export const getCheckboxVariant = tv({
'text-sm',
'tracking-[-0.006em]',
'text-elements-high-em',
'dark:text-foreground',
'flex',
'flex-col',
'gap-1',
'px-1',
],
description: ['text-xs', 'text-elements-low-em'],
description: [
'text-xs',
'text-elements-low-em',
'dark:text-foreground-secondary',
],
},
variants: {
disabled: {

View File

@ -1,7 +1,12 @@
import { tv, type VariantProps } from 'tailwind-variants';
export const headingTheme = tv({
base: ['text-elements-high-em', 'font-display', 'font-normal'],
base: [
'text-elements-high-em',
'dark:text-foreground',
'font-display',
'font-normal',
],
});
export type HeadingVariants = VariantProps<typeof headingTheme>;

View File

@ -14,10 +14,15 @@ export const inputTheme = tv(
'disabled:cursor-not-allowed',
'disabled:bg-controls-disabled',
],
label: ['text-sm', 'text-elements-high-em'],
label: [
'text-sm',
'text-elements-high-em',
'dark:text-foreground-secondary',
],
description: ['text-xs', 'text-elements-low-em'],
input: [
'focus-ring',
'dark:focus:ring-0',
'block',
'w-full',
'h-full',

View File

@ -31,6 +31,7 @@ export const modalTheme = tv({
'sm:px-6',
'sm:py-5',
'bg-base-bg-alternate',
'dark:bg-overlay2',
],
headerTitle: [
'text-base',
@ -39,7 +40,11 @@ export const modalTheme = tv({
'sm:tracking-normal',
'text-elements-high-em',
],
headerDescription: ['text-sm', 'text-elements-low-em'],
headerDescription: [
'text-sm',
'text-elements-low-em',
'dark:text-foreground-secondary',
],
footer: ['flex', 'gap-3', 'px-4', 'pb-4', 'pt-7', 'sm:pb-6', 'sm:px-6'],
content: [
'h-fit',
@ -53,8 +58,11 @@ export const modalTheme = tv({
'sm:max-w-[562px]',
'rounded-2xl',
'bg-base-bg',
'dark:bg-overlay',
'shadow-card',
'dark:shadow-background',
'text-elements-high-em',
'dark:text-foreground-secondary',
],
body: ['flex-1', 'px-4', 'pt-4', 'sm:pt-6', 'sm:px-6'],
},

View File

@ -4,7 +4,12 @@ export const radioTheme = tv({
slots: {
root: ['flex', 'gap-3'],
wrapper: ['flex', 'items-center', 'gap-2', 'group'],
label: ['text-sm', 'tracking-[-0.006em]', 'text-elements-high-em'],
label: [
'text-sm',
'tracking-[-0.006em]',
'text-elements-high-em',
'dark:text-foreground',
],
radio: [
'w-5',
'h-5',
@ -17,6 +22,7 @@ export const radioTheme = tv({
'focus-ring',
// Checked
'data-[state=checked]:bg-controls-primary',
'data-[state=checked]:bg-controls-primary',
'data-[state=checked]:group-hover:bg-controls-primary-hovered',
],
indicator: [
@ -36,6 +42,7 @@ export const radioTheme = tv({
'after:group-focus-visible:bg-controls-disabled',
// Checked
'after:data-[state=checked]:bg-elements-on-primary',
'dark:after:data-[state=checked]:bg-primary-hovered',
'after:data-[state=checked]:group-hover:bg-elements-on-primary',
'after:data-[state=checked]:group-focus-visible:bg-elements-on-primary',
],

View File

@ -3,8 +3,16 @@ import { VariantProps, tv } from 'tailwind-variants';
export const selectTheme = tv({
slots: {
container: ['flex', 'flex-col', 'relative', 'gap-2', 'w-full'],
label: ['text-sm', 'text-elements-high-em'],
description: ['text-xs', 'text-elements-low-em'],
label: [
'text-sm',
'text-elements-high-em',
'dark:text-foreground-secondary',
],
description: [
'text-xs',
'text-elements-low-em',
'dark:text-foreground-secondary',
],
inputWrapper: [
'relative',
'flex',
@ -14,6 +22,7 @@ export const selectTheme = tv({
'w-full',
'rounded-lg',
'bg-transparent',
'dark:bg-overlay2',
'text-elements-mid-em',
'shadow-sm',
'border',
@ -22,7 +31,7 @@ export const selectTheme = tv({
'disabled:shadow-none',
'disabled:border-none',
],
input: ['outline-none'],
input: ['outline-none', 'dark:bg-overlay2', 'dark:text-foreground'],
iconContainer: [
'absolute',
'inset-y-0',
@ -32,9 +41,15 @@ export const selectTheme = tv({
'z-10',
'cursor-pointer',
],
icon: ['text-elements-mid-em'],
icon: ['text-elements-mid-em', 'dark:text-foreground-secondary'],
helperIcon: [],
helperText: ['flex', 'gap-2', 'items-center', 'text-elements-low-em'],
helperText: [
'flex',
'gap-2',
'items-center',
'text-elements-low-em',
'dark:text-foreground-secondary',
],
popover: [
'z-20',
'absolute',
@ -44,12 +59,14 @@ export const selectTheme = tv({
'gap-0.5',
'min-w-full',
'bg-surface-floating',
'dark:bg-overlay2',
'shadow-dropdown',
'w-auto',
'max-h-60',
'overflow-auto',
'border',
'border-gray-200',
'dark:border-overlay',
'rounded-xl',
],
},
@ -79,7 +96,7 @@ export const selectTheme = tv({
'shadow-none',
'focus:outline-border-danger',
],
helperText: ['text-elements-danger'],
helperText: ['text-error'],
},
},
size: {

View File

@ -12,11 +12,12 @@ export const selectItemTheme = tv({
'group',
'data-[disabled]:cursor-not-allowed',
],
icon: ['h-4.5', 'w-4.5', 'text-elements-high-em'],
icon: ['h-4.5', 'w-4.5', 'text-elements-high-em', 'dark:text-foreground'],
content: ['flex', 'flex-1', 'whitespace-nowrap'],
label: [
'text-sm',
'text-elements-high-em',
'dark:text-foreground',
'tracking-[-0.006em]',
'data-[disabled]:text-elements-disabled',
],
@ -47,7 +48,11 @@ export const selectItemTheme = tv({
},
active: {
true: {
wrapper: ['bg-base-bg-emphasized', 'data-[disabled]:bg-transparent'],
wrapper: [
'bg-base-bg-emphasized',
'dark:bg-overlay3',
'data-[disabled]:bg-transparent',
],
},
},
},

View File

@ -87,15 +87,15 @@ export const Sidebar = ({ mobileOpen }: SidebarProps) => {
value=""
className="hidden lg:flex"
>
<a className="cursor-pointer" onClick={handleLogOut}>
Log Out
<a className="cursor-pointer font-mono" onClick={handleLogOut}>
LOG OUT
</a>
</Tabs.Trigger>
<Tabs.Trigger icon={<QuestionMarkRoundIcon />} value="">
<a className="cursor-pointer">Documentation</a>
<a className="cursor-pointer font-mono">DOCUMENTATION</a>
</Tabs.Trigger>
<Tabs.Trigger icon={<LifeBuoyIcon />} value="">
<a className="cursor-pointer">Support</a>
<a className="cursor-pointer font-mono">SUPPORT</a>
</Tabs.Trigger>
</Tabs.List>
</Tabs>

View File

@ -45,6 +45,7 @@ export const switchTheme = tv({
true: {
switch: [
'bg-controls-primary',
'dark:bg-primary',
'hover:bg-controls-primary-hovered',
'focus-visible:bg-controls-primary-hovered',
],

View File

@ -8,6 +8,7 @@ export const tableTheme = tv({
'border-b',
'border-sky-950/opacity-5',
'text-sky-950',
'dark:text-foreground-secondary',
'text-sm',
'font-medium',
'leading-tight',
@ -17,6 +18,7 @@ export const tableTheme = tv({
columnHeaderCell: [
'p-4',
'text-sky-950',
'dark:text-foreground-secondary',
'text-sm',
'font-medium',
'uppercase',
@ -26,6 +28,7 @@ export const tableTheme = tv({
rowHeaderCell: [
'p-4',
'text-slate-600',
'dark:text-foreground',
'text-sm',
'font-normal',
'leading-tight',
@ -36,6 +39,7 @@ export const tableTheme = tv({
'whitespace-nowrap',
'text-sm',
'text-slate-600',
'dark:text-foreground',
'font-normal',
'text-left',
],

View File

@ -11,6 +11,7 @@ export const tabsTheme = tv({
'cursor-default',
'select-none',
'text-elements-low-em',
'dark:text-foreground',
'border-b-2',
'border-transparent',
'hover:border-border-interactive/10',
@ -20,6 +21,7 @@ export const tabsTheme = tv({
'data-[state=active]:font-medium',
'data-[state=active]:text-elements-high-em',
'data-[state=active]:border-elements-high-em',
'data-[state=active]:border-primary',
// Vertical
'data-[orientation=vertical]:px-3',
'data-[orientation=vertical]:py-3',

View File

@ -6,8 +6,10 @@ export const tooltipTheme = tv({
'z-tooltip',
'rounded-md',
'bg-surface-high-contrast',
'dark:bg-overlay3',
'p-2',
'text-elements-on-high-contrast',
'dark:text-foreground-secondary',
],
arrow: ['fill-surface-high-contrast'],
},

View File

@ -144,6 +144,7 @@
@layer utilities {
.focus-ring {
@apply focus-visible:ring-[3px] focus-visible:ring-snowball-200 focus-visible:ring-offset-1 focus-visible:ring-offset-snowball-500 focus-visible:outline-none;
@apply focus-visible:ring-[3px] dark:focus-visible:ring-primary focus-visible:ring-offset-1 dark:focus-visible:ring-offset-primary focus-visible:outline-none;
}
@keyframes dialog-overlay-show {

View File

@ -1,4 +1,3 @@
import { CloudyFlow } from 'components/CloudyFlow';
import { Login } from './auth/Login';
const AuthPage = () => {

View File

@ -3,105 +3,28 @@ import { Navigate } from 'react-router-dom';
import { useGQLClient } from '../context/GQLClientContext';
import { Organization } from 'gql-client';
const owner = {
id: 'user',
name: 'Cody',
email: 'cody@cfb.dev',
isVerified: true,
createdAt: '2024-10-22-12:00:00Z',
updatedAt: '2024-10-22-12:00:00Z',
gitHubToken: 'token',
};
const domain = {
id: 'domain',
branch: 'idk',
name: 'Domain',
status: 'Live',
redirectTo: null,
createdAt: '2024-10-22-12:00:00Z',
updatedAt: '2024-10-22-12:00:00Z',
};
const deployment = {
id: 'deployment',
domain,
branch: 'branch',
commitHash: 'beefb0d',
commitMessage: 'beef',
deployerLrn: 'deployer',
environment: 'Development',
isCurrent: true,
status: 'Ready',
createdBy: owner,
createdAt: '2024-10-22-12:00:00Z',
updatedAt: '2024-10-22-12:00:00Z',
};
const member = {
id: 'member_id',
member: owner,
permissions: ['Edit'],
isPending: false,
createdAt: '2024-10-22-12:00:00Z',
updatedAt: '2024-10-22-12:00:00Z',
};
const environmentVariable = {
id: 'env_var_id',
environment: 'Development',
key: 'key',
value: 'value',
createdAt: '2024-10-22-12:00:00Z',
updatedAt: '2024-10-22-12:00:00Z',
};
const project = {
id: 'project',
owner,
deployments: [deployment],
name: 'Project',
repository: 'snowball',
prodBranch: 'main',
description: 'description',
template: 'template',
framework: 'framework',
webhooks: ['webhook'],
members: [member],
environmentVariables: [environmentVariable],
createdAt: '2024-10-22-12:00:00Z',
updatedAt: '2024-10-22-12:00:00Z',
};
const organizationMember = {
id: 'member_id',
member: owner,
role: 'Owner',
createdAt: '2024-10-22-12:00:00Z',
updatedAt: '2024-10-22-12:00:00Z',
};
const testOrg = {
id: 'org_id',
name: 'Test Org',
slug: 'test',
projects: [project],
createdAt: '2024-10-22-12:00:00Z',
updatedAt: '2024-10-22-12:00:00Z',
members: [organizationMember],
};
const Index = () => {
const client = useGQLClient();
// const [organization, setOrganization] = useState<Organization>(testOrg);
const [organization, setOrganization] = useState<Organization>();
// const fetchUserOrganizations = useCallback(async () => {
// const { organizations } = await client.getOrganizations();
// // By default information of first organization displayed
// setOrganization(organizations[0]);
// }, []);
//
// useEffect(() => {
// fetchUserOrganizations();
// }, []);
const fetchUserOrganizations = useCallback(async () => {
const { organizations } = await client.getOrganizations();
// By default information of first organization displayed
setOrganization(organizations[0]);
}, []);
useEffect(() => {
fetchUserOrganizations();
}, []);
return (
<>{Boolean(testOrg) ? <Navigate to={testOrg!.slug} /> : <>Loading</>}</>
<>
{Boolean(organization) ? (
<Navigate to={organization!.slug} />
) : (
<>Loading</>
)}
</>
);
};

View File

@ -6,11 +6,12 @@ import { Heading, Badge, Button } from 'components/shared';
import { PlusIcon } from 'components/shared/CustomIcon';
import { useGQLClient } from 'context/GQLClientContext';
import { Project } from 'gql-client';
import { project as mockProject } from 'pages/index';
const Projects = () => {
const client = useGQLClient();
const { orgSlug } = useParams();
const [projects, setProjects] = useState<Project[]>([]);
const [projects, setProjects] = useState<Project[]>([mockProject]);
const fetchProjects = useCallback(async () => {
const { projectsInOrganization } = await client.getProjectsInOrganization(
@ -39,7 +40,7 @@ const Projects = () => {
</div>
</div>
<Link to="projects/create">
<Button leftIcon={<PlusIcon />}>Create project</Button>
<Button leftIcon={<PlusIcon />}>CREATE PROJECT</Button>
</Link>
</div>
{/* List of projects */}

View File

@ -78,7 +78,7 @@ const Id = () => {
leftIcon={<ChevronLeft />}
onClick={() => navigate(-1)}
/>
<Heading className="text-2xl font-medium truncate">
<Heading className="text-2xl font-medium truncate dark:text-foreground">
{project?.name}
</Heading>
</div>
@ -88,17 +88,24 @@ const Id = () => {
{...buttonSize}
className="h-11 transition-colors"
variant="tertiary"
shape="default"
>
Open repo
OPEN REPO
</Button>
</Link>
{(project.deployments.length > 0) &&
<Link to={`https://${project.name.toLowerCase()}.${project.deployments[0].deployer.baseDomain}`}>
<Button {...buttonSize} className="h-11 transition-colors">
Go to app
{project.deployments.length > 0 && (
<Link
to={`https://${project.name.toLowerCase()}.${project.deployments[0].deployer.baseDomain}`}
>
<Button
{...buttonSize}
className="h-11 transition-colors"
shape="default"
>
GO TO APP
</Button>
</Link>
}
)}
</div>
</div>
<WavyBorder />

View File

@ -121,21 +121,22 @@ const DeploymentsTabPanel = () => {
})
) : (
// TODO: Update the height based on the layout, need to re-styling the layout similar to create project layout
<div className="h-3/4 bg-base-bg-alternate flex flex-col rounded-xl items-center justify-center text-center gap-5">
<div className="h-3/4 bg-base-bg-alternate dark:bg-overlay3 flex flex-col rounded-xl items-center justify-center text-center gap-5">
<div className="space-y-1">
<p className="font-medium tracking-[-0.011em] text-elements-high-em">
<p className="font-medium tracking-[-0.011em] text-elements-high-em dark:text-foreground">
No deployments found
</p>
<p className="text-sm tracking-[-0.006em] text-elements-mid-em">
<p className="text-sm tracking-[-0.006em] text-elements-mid-em dark:text-foreground-secondary">
Please change your search query or filters.
</p>
</div>
<Button
variant="tertiary"
variant="primary"
shape="default"
leftIcon={<RefreshIcon />}
onClick={handleResetFilters}
>
Reset filters
RESET FILTERS
</Button>
</div>
)}

View File

@ -126,7 +126,7 @@ const OverviewTabPanel = () => {
type="blue"
/>
<div className="flex-1 space-y-1 overflow-hidden">
<Heading className="text-lg leading-6 font-medium truncate">
<Heading className="text-lg leading-6 font-medium truncate dark:text-foreground">
{project.name}
</Heading>
{project.deployments &&
@ -136,7 +136,7 @@ const OverviewTabPanel = () => {
<a
key={index}
href={`https://${project.name.toLowerCase()}.${deployment.deployer.baseDomain}`}
className="text-sm text-elements-low-em tracking-tight truncate"
className="text-sm text-elements-low-em dark:text-foreground tracking-tight truncate"
>
{deployment.deployer.baseDomain}
</a>
@ -161,7 +161,7 @@ const OverviewTabPanel = () => {
variant="tertiary"
size="sm"
>
Setup
SETUP
</Button>
</div>
)}
@ -171,8 +171,8 @@ const OverviewTabPanel = () => {
{/* SOURCE */}
<OverviewInfo label="Source" icon={<GithubStrokeIcon />}>
<div className="flex gap-2 items-center">
<BranchStrokeIcon className="text-elements-low-em w-4 h-5" />
<span className="text-elements-high-em text-sm tracking-tighter">
<BranchStrokeIcon className="text-elements-low-em dark:text-foreground w-4 h-5" />
<span className="text-elements-high-em dark:text-foreground-secondary text-sm tracking-tighter">
{project.deployments[0]?.branch}
</span>
</div>
@ -180,23 +180,25 @@ const OverviewTabPanel = () => {
{/* DEPLOYMENT */}
<OverviewInfo label="Deployment URL" icon={<CursorBoxIcon />}>
{project.deployments &&
project.deployments.length > 0 &&
project.deployments.map((deployment) => (
<div className="flex gap-2 items-center">
<Link to={`https://${project.name.toLowerCase()}.${deployment.deployer.baseDomain}`}>
<span className="text-controls-primary group hover:border-controls-primary transition-colors border-b border-b-transparent flex gap-2 items-center text-sm tracking-tight">
{`https://${project.name.toLowerCase()}.${deployment.deployer.baseDomain}`}
<LinkIcon className="group-hover:rotate-45 transition-transform" />
</span>
</Link>
</div>
))}
{project.deployments &&
project.deployments.length > 0 &&
project.deployments.map((deployment) => (
<div className="flex gap-2 items-center">
<Link
to={`https://${project.name.toLowerCase()}.${deployment.deployer.baseDomain}`}
>
<span className="text-controls-primary dark:text-foreground group hover:border-controls-primary transition-colors border-b border-b-transparent flex gap-2 items-center text-sm tracking-tight">
{`https://${project.name.toLowerCase()}.${deployment.deployer.baseDomain}`}
<LinkIcon className="group-hover:rotate-45 transition-transform" />
</span>
</Link>
</div>
))}
</OverviewInfo>
{/* DEPLOYMENT DATE */}
<OverviewInfo label="Deployment date" icon={<CalendarDaysIcon />}>
<div className="flex gap-2 items-center text-elements-high-em text-sm tracking-tighter">
<div className="flex gap-2 items-center text-elements-high-em dark:text-foreground text-sm tracking-tighter">
<span>{relativeTimeMs(project.deployments[0].createdAt)}</span>
by
<Avatar

View File

@ -8,7 +8,7 @@ import CollaboratorsTabPanel from './settings/Collaborators';
import Domains from './settings/Domains';
const Integrations = () => (
<div>
<div className="dark:text-foreground">
Content of integrations tab
<p className="block">
There are many variations of passages of Lorem Ipsum available.

View File

@ -117,9 +117,10 @@ const CollaboratorsTabPanel = () => {
size="md"
onClick={() => setAddMemberDialogOpen((preVal) => !preVal)}
leftIcon={<PlusIcon />}
variant="secondary"
variant="primary"
shape="default"
>
Add member
ADD MEMBER
</Button>
}
>

View File

@ -111,10 +111,10 @@ export const EnvironmentVariablesTabPanel = () => {
return (
<ProjectSettingContainer headingText="Environment variables">
<p className="text-slate-600 text-sm font-normal leading-tight">
<p className="text-slate-600 dark:text-foreground-secondary text-sm font-normal leading-tight">
A new deployment is required for your changes to take effect.
</p>
<div className="bg-slate-100 rounded-xl flex-col">
<div className="bg-slate-100 dark:bg-overlay2 rounded-xl flex-col">
<Heading
onClick={() => setCreateNewVariable((cur) => !cur)}
className="p-4"
@ -131,12 +131,12 @@ export const EnvironmentVariablesTabPanel = () => {
createEnvironmentVariablesHandler(data),
)}
>
<div className="p-4 bg-slate-100">
<div className="p-4 bg-slate-100 dark:bg-overlay3">
<EnvironmentVariablesForm />
</div>
<div className="p-2">
<Button size="md" type="submit">
Save changes
<Button size="md" type="submit" shape="default">
SAVE CHANGES
</Button>
</div>
</form>

View File

@ -1,13 +1,11 @@
import { useEffect, useMemo } from 'react';
import { useFieldArray, useFormContext } from 'react-hook-form';
// TODO: Use custom checkbox component
import { Checkbox } from '@snowballtools/material-tailwind-react-fork';
import { Button } from 'components/shared/Button';
import { InlineNotification } from 'components/shared/InlineNotification';
import AddEnvironmentVariableRow from 'components/projects/project/settings/AddEnvironmentVariableRow';
import { EnvironmentVariablesFormValues } from 'types/types';
import { Checkbox } from 'components/shared/Checkbox';
const EnvironmentVariablesForm = () => {
const {
@ -54,8 +52,12 @@ const EnvironmentVariablesForm = () => {
/>
))}
<div className="flex gap-1 p-2">
<Button size="md" onClick={() => append({ key: '', value: '' })}>
+ Add variable
<Button
size="md"
onClick={() => append({ key: '', value: '' })}
shape="default"
>
+ ADD VARIABLE
</Button>
</div>
{isFieldEmpty && (

View File

@ -18,6 +18,7 @@ const GeneralTabPanel = () => {
const client = useGQLClient();
const { toast } = useToast();
const { project, onUpdate } = useOutletContext<OutletContextType>();
console.log(project);
const [transferOrganizations, setTransferOrganizations] = useState<
SelectOption[]
@ -157,8 +158,9 @@ const GeneralTabPanel = () => {
type="submit"
size="md"
disabled={!updateProjectFormState.isDirty}
shape="default"
>
Save
SAVE
</Button>
</form>
<form
@ -185,8 +187,8 @@ const GeneralTabPanel = () => {
setSelectedTransferOrganization(value as SelectOption)
}
/>
<Button disabled type="submit" size="md">
Transfer
<Button disabled type="submit" size="md" shape="default">
TRANSFER
</Button>
</form>
<TransferProjectDialog
@ -211,7 +213,7 @@ const GeneralTabPanel = () => {
onClick={handleDeleteProjectDialog}
leftIcon={<TrashIcon />}
>
Delete project
DELETE PROJECT
</Button>
<DeleteProjectDialog
handleOpen={handleDeleteProjectDialog}

View File

@ -139,7 +139,7 @@ const GitTabPanel = () => {
<div className="self-stretch space-y-3">
<div className="flex justify-between mt-4">
<div>
<p className="text-slate-600 text-sm font-normal leading-tight">
<p className="text-slate-600 dark:text-foreground-secondary text-sm font-normal leading-tight">
Pull request comments
</p>
</div>
@ -153,7 +153,7 @@ const GitTabPanel = () => {
<div className="flex justify-between">
<div>
<p className="text-slate-600 text-sm font-normal leading-tight">
<p className="text-slate-600 dark:text-foreground-secondary text-sm font-normal leading-tight">
Commit comments
</p>
</div>
@ -171,18 +171,18 @@ const GitTabPanel = () => {
className="space-y-3"
>
<ProjectSettingHeader headingText="Production branch" />
<p className="text-slate-600 text-sm font-normal leading-tight">
<p className="text-slate-600 dark:text-foreground-secondary text-sm font-normal leading-tight">
By default, each commit pushed to the{' '}
<span className="font-bold">{project.prodBranch}</span> branch
initiates a production deployment. You can opt for a different branch
for deployment in the settings.
</p>
<p className="text-slate-600 text-sm font-normal leading-tight">
<p className="text-slate-600 dark:text-foreground-secondary text-sm font-normal leading-tight">
Branch name
</p>
<Input {...registerProdBranch('prodBranch')} />
<Button size="md" variant="primary">
Save
<Button size="md" variant="primary" shape="default">
SAVE
</Button>
</form>
@ -191,21 +191,21 @@ const GitTabPanel = () => {
className="space-y-3"
>
<ProjectSettingHeader headingText="Deploy webhooks" />
<p className="text-slate-600 text-sm font-normal leading-tight">
<p className="text-slate-600 dark:text-foreground-secondary text-sm font-normal leading-tight">
{' '}
Webhooks configured to trigger when there is a change in a
project&apos;s build or deployment status.
</p>
<div className="flex gap-1">
<div className="grow">
<p className="text-slate-600 text-sm font-normal leading-tight">
<p className="text-slate-600 dark:text-foreground-secondary text-sm font-normal leading-tight">
Webhook URL
</p>
<Input {...registerWebhooks('webhookUrl')} />
</div>
<div className="self-end">
<Button size="sm" type="submit">
Save
<Button size="sm" type="submit" shape="default">
SAVE
</Button>
</div>
</div>

View File

@ -102,9 +102,10 @@ const Config = () => {
className="w-fit"
onClick={handleSubmitDomain}
variant="primary"
shape="default"
rightIcon={<ArrowRightCircleIcon />}
>
Finish
FINISH
</Button>
</ProjectSettingContainer>
);

View File

@ -33,19 +33,29 @@ const AddDomain = () => {
return (
<div className="p-4">
<div className="flex justify-between">
<Typography variant="h3">Add Domain</Typography>
<Typography variant="h3" className="dark:text-foreground">
Add Domain
</Typography>
<Link to={`/${orgSlug}/projects/${id}`}>
<IconButton className="rounded-full" variant="outlined">
<IconButton
className="rounded-full dark:text-foreground dark:border-foreground"
variant="outlined"
>
X
</IconButton>
</Link>
</div>
<div className=" w-2/3 mx-auto">
<div className="bg-blue-gray-50 rounded-lg mt-6 mb-10">
<div className="bg-blue-gray-50 dark:bg-overlay rounded-lg mt-6 mb-10">
<div className="flex justify-start gap-3 p-5">
<i className="bg-gray-100 w-12 h-12 rounded-lg">^</i>
<Typography className="my-auto w-1/3" variant="h5">
<i className="bg-gray-100 dark:bg-overlay dark:text-foreground w-12 h-12 rounded-lg">
^
</i>
<Typography
className="my-auto w-1/3 dark:text-foreground"
variant="h5"
>
Project Name
</Typography>
</div>

View File

@ -13,6 +13,7 @@ export default withMT({
background: '#0F0F0F',
overlay: '#18181A',
overlay2: '#29292E',
overlay3: '#48474F',
primary: '#0000F4',
'primary-hovered': '#0000F4AA',
foreground: '#FBFBFB',
@ -30,7 +31,7 @@ export default withMT({
fontFamily: {
sans: ['Inter', 'sans-serif'],
display: ['Inter Display', 'sans-serif'],
mono: ['JetBrains Mono', 'monospace'],
mono: ['DM Mono', 'monospace'],
},
fontSize: {
'2xs': '0.625rem',