Swap out primary UI color for Zoo brand blue, add theme color setting to control its hue (#2017)
* Add a setting for themeColor * Add primary-color to Tailwind, driven by themeColor setting * Get rid of most uses of "energy" colors * Change out the rest of the energy colors * Tweak NetworkHealthIndicator light mode checkmarks * Handful of other CSS tweaks while I'm here: - remove the AppHeader bg and border - pane margins - better dark mode button styles * Make Zoo logomark a badge * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu) * Re-run CI post-snapshots * A snapshot a day keeps the bugs away! 📷🐛 (OS: ubuntu) * Retrigger CI --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
@ -30,9 +30,9 @@ export const ActionIcon = ({
|
||||
children,
|
||||
}: ActionIconProps) => {
|
||||
// By default, we reverse the icon color and background color in dark mode
|
||||
const computedIconClassName = `h-auto dark:text-energy-10 !group-disabled:text-chalkboard-60 !group-disabled:text-chalkboard-60 ${iconClassName}`
|
||||
const computedIconClassName = `h-auto text-primary dark:text-current !group-disabled:text-chalkboard-60 !group-disabled:text-chalkboard-60 ${iconClassName}`
|
||||
|
||||
const computedBgClassName = `bg-chalkboard-20 dark:bg-chalkboard-90 !group-disabled:bg-chalkboard-30 !dark:group-disabled:bg-chalkboard-80 ${bgClassName}`
|
||||
const computedBgClassName = `bg-primary/10 dark:bg-chalkboard-90 !group-disabled:bg-chalkboard-30 !dark:group-disabled:bg-chalkboard-80 ${bgClassName}`
|
||||
|
||||
return (
|
||||
<div
|
||||
|
@ -33,7 +33,7 @@ export const AppHeader = ({
|
||||
className={
|
||||
'w-full grid ' +
|
||||
styles.header +
|
||||
' overlaid-panes sticky top-0 z-20 py-1 px-2 bg-chalkboard-10/70 dark:bg-chalkboard-100/50 border-b dark:border-b-2 border-chalkboard-30 dark:border-chalkboard-90 items-center ' +
|
||||
' overlaid-panes sticky top-0 z-20 px-2 items-center ' +
|
||||
className
|
||||
}
|
||||
>
|
||||
@ -53,13 +53,13 @@ export const AppHeader = ({
|
||||
className="text-sm self-center flex items-center w-fit gap-3"
|
||||
>
|
||||
Command Palette{' '}
|
||||
<kbd className="bg-energy-10/50 dark:bg-chalkboard-100 dark:text-energy-10 inline-block px-1 py-0.5 border-energy-10 dark:border-chalkboard-90">
|
||||
<kbd className="bg-primary/10 dark:bg-chalkboard-100 dark:text-primary inline-block px-1 py-0.5 border-primary dark:border-chalkboard-90">
|
||||
{platform === 'darwin' ? '⌘K' : 'Ctrl+/'}
|
||||
</kbd>
|
||||
</ActionButton>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center gap-1 ml-auto">
|
||||
<div className="flex items-center gap-1 py-1 ml-auto">
|
||||
{/* If there are children, show them, otherwise show User menu */}
|
||||
{children || (
|
||||
<>
|
||||
|
@ -1,13 +1,13 @@
|
||||
.button {
|
||||
@apply flex justify-between items-center gap-2 px-2 py-1 text-left border-none rounded-sm;
|
||||
@apply font-mono !no-underline text-xs font-bold select-none text-chalkboard-90;
|
||||
@apply ui-active:bg-energy-10/50 ui-active:text-inherit;
|
||||
@apply ui-active:bg-primary/10 ui-active:text-primary ui-active:text-inherit;
|
||||
@apply transition-colors ease-out;
|
||||
}
|
||||
|
||||
:global(.dark) .button {
|
||||
@apply text-chalkboard-30;
|
||||
@apply ui-active:bg-chalkboard-80 ui-active:text-energy-10;
|
||||
@apply !text-chalkboard-30;
|
||||
@apply ui-active:bg-chalkboard-90;
|
||||
}
|
||||
|
||||
.button small {
|
||||
|
@ -30,12 +30,12 @@ export const CodeMenu = ({ children }: PropsWithChildren) => {
|
||||
className="p-1"
|
||||
size="sm"
|
||||
bgClassName={
|
||||
'bg-chalkboard-20 dark:bg-chalkboard-110 hover:bg-energy-10/50 hover:dark:bg-chalkboard-90 ui-active:bg-chalkboard-80 ui-active:dark:bg-chalkboard-90 rounded-sm'
|
||||
'!bg-transparent hover:!bg-primary/10 hover:dark:!bg-chalkboard-100 ui-active:!bg-primary/10 dark:ui-active:!bg-chalkboard-100 rounded-sm'
|
||||
}
|
||||
iconClassName={'text-chalkboard-90 dark:text-chalkboard-40'}
|
||||
iconClassName={'!text-chalkboard-90 dark:!text-chalkboard-40'}
|
||||
/>
|
||||
</Menu.Button>
|
||||
<Menu.Items className="absolute right-0 left-auto w-72 flex flex-col gap-1 divide-y divide-chalkboard-20 dark:divide-chalkboard-70 align-stretch px-0 py-1 bg-chalkboard-10 dark:bg-chalkboard-90 rounded-sm shadow-lg border border-solid border-chalkboard-20/50 dark:border-chalkboard-80/50">
|
||||
<Menu.Items className="absolute right-0 left-auto w-72 flex flex-col gap-1 divide-y divide-chalkboard-20 dark:divide-chalkboard-70 align-stretch px-0 py-1 bg-chalkboard-10 dark:bg-chalkboard-100 rounded-sm shadow-lg border border-solid border-chalkboard-20/50 dark:border-chalkboard-80/50">
|
||||
<Menu.Item>
|
||||
<button
|
||||
onClick={() => kclManager.format()}
|
||||
|
@ -3,6 +3,11 @@
|
||||
@apply bg-chalkboard-10/70 backdrop-blur-sm;
|
||||
}
|
||||
|
||||
.header::before,
|
||||
.header::-webkit-details-marker {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:global(.dark) .panel {
|
||||
@apply bg-chalkboard-110/50 backdrop-blur-0;
|
||||
}
|
||||
@ -11,7 +16,7 @@
|
||||
@apply sticky top-0 z-10 cursor-pointer;
|
||||
@apply flex items-center justify-between gap-2 w-full p-2;
|
||||
@apply font-mono text-xs font-bold select-none text-chalkboard-90;
|
||||
@apply bg-chalkboard-20;
|
||||
@apply bg-chalkboard-10;
|
||||
}
|
||||
|
||||
.header:not(:last-of-type) {
|
||||
|
@ -30,11 +30,11 @@ export const PanelHeader = ({
|
||||
className="p-1"
|
||||
size="sm"
|
||||
bgClassName={
|
||||
'dark:!bg-chalkboard-100 group-open:bg-chalkboard-80 dark:group-open:!bg-chalkboard-90 border border-transparent dark:group-open:border-chalkboard-60 rounded-sm ' +
|
||||
'dark:!bg-transparent group-open:bg-primary dark:group-open:!bg-primary rounded-sm ' +
|
||||
(iconClassNames?.bg || '')
|
||||
}
|
||||
iconClassName={
|
||||
'group-open:text-energy-10 ' + (iconClassNames?.icon || '')
|
||||
'group-open:text-chalkboard-10 ' + (iconClassNames?.icon || '')
|
||||
}
|
||||
/>
|
||||
{title}
|
||||
|
@ -141,7 +141,7 @@ function CommandArgOptionInput({
|
||||
<Combobox.Option
|
||||
key={option.name}
|
||||
value={option}
|
||||
className="flex items-center gap-2 px-4 py-1 first:mt-2 last:mb-2 ui-active:bg-energy-10/50 dark:ui-active:bg-chalkboard-90"
|
||||
className="flex items-center gap-2 px-4 py-1 first:mt-2 last:mb-2 ui-active:bg-primary/10 dark:ui-active:bg-chalkboard-90"
|
||||
>
|
||||
<p className="flex-grow">{option.name} </p>
|
||||
{option.value === currentOption?.value && (
|
||||
|
@ -104,7 +104,7 @@ function CommandBarHeader({ children }: React.PropsWithChildren<{}>) {
|
||||
key={argName}
|
||||
className={`relative w-fit px-2 py-1 rounded-sm flex gap-2 items-center border ${
|
||||
argName === currentArgument?.name
|
||||
? 'disabled:bg-energy-10/50 dark:disabled:bg-energy-10/20 disabled:border-energy-10 dark:disabled:border-energy-10 disabled:text-chalkboard-100 dark:disabled:text-chalkboard-10'
|
||||
? 'disabled:bg-primary/10 dark:disabled:bg-primary/20 disabled:border-primary dark:disabled:border-primary disabled:text-chalkboard-100 dark:disabled:text-chalkboard-10'
|
||||
: 'bg-chalkboard-20/50 dark:bg-chalkboard-80/50 border-chalkboard-20 dark:border-chalkboard-80'
|
||||
}`}
|
||||
>
|
||||
@ -129,7 +129,7 @@ function CommandBarHeader({ children }: React.PropsWithChildren<{}>) {
|
||||
)
|
||||
) : null}
|
||||
{showShortcuts && (
|
||||
<small className="absolute -top-[1px] right-full translate-x-1/2 px-0.5 rounded-sm bg-chalkboard-80 text-chalkboard-10 dark:bg-energy-10 dark:text-chalkboard-100">
|
||||
<small className="absolute -top-[1px] right-full translate-x-1/2 px-0.5 rounded-sm bg-chalkboard-80 text-chalkboard-10 dark:bg-primary dark:text-chalkboard-100">
|
||||
<span className="sr-only">Hotkey: </span>
|
||||
{i + 1}
|
||||
</small>
|
||||
@ -174,12 +174,11 @@ function ReviewingButton() {
|
||||
autoFocus
|
||||
type="submit"
|
||||
form="review-form"
|
||||
className="w-fit !p-0 rounded-sm border !border-chalkboard-100 dark:!border-energy-10 hover:shadow"
|
||||
className="w-fit !p-0 rounded-sm border !border-primary hover:shadow"
|
||||
icon={{
|
||||
icon: 'checkmark',
|
||||
bgClassName:
|
||||
'p-1 rounded-sm !bg-chalkboard-100 hover:!bg-chalkboard-110 dark:!bg-energy-20 dark:hover:!bg-energy-10',
|
||||
iconClassName: '!text-energy-10 dark:!text-chalkboard-100',
|
||||
bgClassName: 'p-1 rounded-sm !bg-primary hover:brightness-110',
|
||||
iconClassName: '!text-chalkboard-10',
|
||||
}}
|
||||
>
|
||||
<span className="sr-only">Submit command</span>
|
||||
@ -193,10 +192,11 @@ function GatheringArgsButton() {
|
||||
Element="button"
|
||||
type="submit"
|
||||
form="arg-form"
|
||||
className="w-fit !p-0 rounded-sm"
|
||||
className="w-fit !p-0 rounded-sm border !border-primary hover:shadow"
|
||||
icon={{
|
||||
icon: 'arrowRight',
|
||||
bgClassName: 'p-1 rounded-sm',
|
||||
bgClassName: 'p-1 rounded-sm !bg-primary hover:brightness-110',
|
||||
iconClassName: '!text-chalkboard-10',
|
||||
}}
|
||||
>
|
||||
<span className="sr-only">Continue</span>
|
||||
|
@ -9,9 +9,9 @@
|
||||
.editor :global(.cm-line)::selection {
|
||||
@apply px-1;
|
||||
@apply text-chalkboard-100;
|
||||
@apply bg-energy-10/50;
|
||||
@apply bg-primary/40;
|
||||
}
|
||||
:global(.dark) .editor :global(.cm-line)::selection {
|
||||
@apply text-energy-10;
|
||||
@apply bg-energy-10/20;
|
||||
@apply text-chalkboard-10;
|
||||
@apply bg-primary/40;
|
||||
}
|
||||
|
@ -153,7 +153,7 @@ function CommandBarKclInput({
|
||||
className={
|
||||
calcResult === 'NAN'
|
||||
? 'text-destroy-80 dark:text-destroy-40'
|
||||
: 'text-energy-60 dark:text-energy-20'
|
||||
: 'text-succeed-80 dark:text-succeed-40'
|
||||
}
|
||||
>
|
||||
{calcResult === 'NAN'
|
||||
@ -173,7 +173,7 @@ function CommandBarKclInput({
|
||||
type="text"
|
||||
id="variable-name"
|
||||
name="variable-name"
|
||||
className="flex-1 border-none bg-transparent"
|
||||
className="flex-1 border-none bg-transparent focus:outline-none"
|
||||
placeholder="Variable name"
|
||||
value={newVariableName}
|
||||
autoCapitalize="off"
|
||||
@ -196,7 +196,7 @@ function CommandBarKclInput({
|
||||
<span
|
||||
className={
|
||||
isNewVariableNameUnique
|
||||
? 'text-energy-60 dark:text-energy-20'
|
||||
? 'text-succeed-60 dark:text-succeed-40'
|
||||
: 'text-destroy-60 dark:text-destroy-40'
|
||||
}
|
||||
>
|
||||
|
@ -38,11 +38,11 @@ function CommandComboBox({
|
||||
<div className="flex items-center gap-2 px-4 pb-2 border-solid border-0 border-b border-b-chalkboard-20 dark:border-b-chalkboard-80">
|
||||
<CustomIcon
|
||||
name="search"
|
||||
className="w-5 h-5 bg-energy-10/50 dark:bg-chalkboard-90 dark:text-energy-10"
|
||||
className="w-5 h-5 bg-primary/10 text-primary"
|
||||
/>
|
||||
<Combobox.Input
|
||||
onChange={(event) => setQuery(event.target.value)}
|
||||
className="w-full bg-transparent focus:outline-none selection:bg-energy-10/50 dark:selection:bg-energy-10/20 dark:focus:outline-none"
|
||||
className="w-full bg-transparent focus:outline-none selection:bg-primary/20 dark:selection:bg-primary/40 dark:focus:outline-none"
|
||||
onKeyDown={(event) => {
|
||||
if (
|
||||
(event.metaKey && event.key === 'k') ||
|
||||
@ -72,13 +72,10 @@ function CommandComboBox({
|
||||
<Combobox.Option
|
||||
key={option.name}
|
||||
value={option}
|
||||
className="flex items-center gap-2 px-4 py-1 first:mt-2 last:mb-2 ui-active:bg-energy-10/50 dark:ui-active:bg-chalkboard-90"
|
||||
className="flex items-center gap-2 px-4 py-1 first:mt-2 last:mb-2 ui-active:bg-primary/10 dark:ui-active:bg-chalkboard-90"
|
||||
>
|
||||
{'icon' in option && option.icon && (
|
||||
<CustomIcon
|
||||
name={option.icon}
|
||||
className="w-5 h-5 dark:text-energy-10"
|
||||
/>
|
||||
<CustomIcon name={option.icon} className="w-5 h-5" />
|
||||
)}
|
||||
<p className="flex-grow">{option.displayName || option.name} </p>
|
||||
{option.description && (
|
||||
|
@ -192,8 +192,8 @@ const FileTreeItem = ({
|
||||
{fileOrDir.children === undefined ? (
|
||||
<li
|
||||
className={
|
||||
'group m-0 p-0 border-solid border-0 text-energy-100 hover:text-energy-70 hover:bg-energy-10/50 dark:text-energy-30 dark:hover:!text-energy-20 dark:hover:bg-energy-90/50 focus-within:bg-energy-10/80 dark:focus-within:bg-energy-80/50 hover:focus-within:bg-energy-10/80 dark:hover:focus-within:bg-energy-80/50 ' +
|
||||
(isCurrentFile ? 'bg-energy-10/50 dark:bg-energy-90/50' : '')
|
||||
'group m-0 p-0 border-solid border-0 hover:text-primary hover:bg-primary/5 focus-within:bg-primary/5 ' +
|
||||
(isCurrentFile ? '!bg-primary/10 !text-primary' : '')
|
||||
}
|
||||
>
|
||||
{!isRenaming ? (
|
||||
@ -206,12 +206,7 @@ const FileTreeItem = ({
|
||||
>
|
||||
<CustomIcon
|
||||
name={fileOrDir.name?.endsWith(FILE_EXT) ? 'kcl' : 'file'}
|
||||
className={
|
||||
'inline-block w-3 ' +
|
||||
(isCurrentFile
|
||||
? 'text-energy-90 dark:text-energy-10'
|
||||
: 'text-energy-50 dark:text-energy-50')
|
||||
}
|
||||
className="inline-block w-3 text-current"
|
||||
/>
|
||||
{fileOrDir.name}
|
||||
</button>
|
||||
@ -230,9 +225,9 @@ const FileTreeItem = ({
|
||||
{!isRenaming ? (
|
||||
<Disclosure.Button
|
||||
className={
|
||||
' group border-none text-sm rounded-none p-0 m-0 flex items-center justify-start w-full py-0.5 text-chalkboard-70 dark:text-chalkboard-30 hover:bg-energy-10/50 dark:hover:bg-energy-90/50' +
|
||||
' group border-none text-sm rounded-none p-0 m-0 flex items-center justify-start w-full py-0.5 hover:text-primary hover:bg-primary/5' +
|
||||
(context.selectedDirectory.path.includes(fileOrDir.path)
|
||||
? ' group-focus-within:bg-chalkboard-20/50 dark:group-focus-within:bg-chalkboard-80/20 hover:group-focus-within:bg-chalkboard-20 dark:hover:group-focus-within:bg-chalkboard-80/20 group-active:bg-chalkboard-20/50 dark:group-active:bg-chalkboard-80/20 hover:group-active:bg-chalkboard-20/50 dark:hover:group-active:bg-chalkboard-80/20'
|
||||
? ' ui-open:text-primary'
|
||||
: '')
|
||||
}
|
||||
style={{ paddingInlineStart: getIndentationCSS(level) }}
|
||||
@ -353,17 +348,16 @@ export const FileTree = ({
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<div className="flex items-center gap-1 px-4 py-1 bg-chalkboard-20/50 dark:bg-chalkboard-80/50 border-b border-b-chalkboard-30 dark:border-b-chalkboard-80">
|
||||
<div className="flex items-center gap-1 px-4 py-1 bg-chalkboard-20/40 dark:bg-chalkboard-80/50 border-b border-b-chalkboard-30 dark:border-b-chalkboard-80">
|
||||
<h2 className="flex-1 m-0 p-0 text-sm mono">Files</h2>
|
||||
<ActionButton
|
||||
Element="button"
|
||||
icon={{
|
||||
icon: 'filePlus',
|
||||
iconClassName: '!text-energy-80 dark:!text-energy-20',
|
||||
bgClassName:
|
||||
'bg-chalkboard-20/50 hover:bg-energy-10/50 dark:hover:bg-transparent',
|
||||
iconClassName: '!text-current',
|
||||
bgClassName: 'bg-transparent',
|
||||
}}
|
||||
className="!p-0 bg-transparent !outline-none"
|
||||
className="!p-0 !bg-transparent hover:text-primary border-transparent hover:border-primary !outline-none"
|
||||
onClick={createFile}
|
||||
>
|
||||
<Tooltip position="inlineStart" delay={750}>
|
||||
@ -375,11 +369,10 @@ export const FileTree = ({
|
||||
Element="button"
|
||||
icon={{
|
||||
icon: 'folderPlus',
|
||||
iconClassName: '!text-energy-80 dark:!text-energy-20',
|
||||
bgClassName:
|
||||
'bg-chalkboard-20/50 hover:bg-energy-10/50 dark:hover:bg-transparent',
|
||||
iconClassName: '!text-current',
|
||||
bgClassName: 'bg-transparent',
|
||||
}}
|
||||
className="!p-0 bg-transparent !outline-none"
|
||||
className="!p-0 !bg-transparent hover:text-primary border-transparent hover:border-primary !outline-none"
|
||||
onClick={createFolder}
|
||||
>
|
||||
<Tooltip position="inlineStart" delay={750}>
|
||||
|
@ -15,23 +15,20 @@ const Loading = ({ children }: React.PropsWithChildren) => {
|
||||
data-testid="loading"
|
||||
>
|
||||
<svg viewBox="0 0 10 10" className="w-8 h-8">
|
||||
<circle cx="5" cy="5" r="4" stroke="var(--energy-50)" fill="none" />
|
||||
<circle
|
||||
cx="5"
|
||||
cy="5"
|
||||
r="4"
|
||||
stroke="var(--energy-10)"
|
||||
stroke="var(--primary)"
|
||||
fill="none"
|
||||
strokeDasharray="4, 4"
|
||||
className="animate-spin origin-center"
|
||||
/>
|
||||
</svg>
|
||||
<p className="text-base mt-4 text-energy-80 dark:text-energy-30">
|
||||
{children || 'Loading'}
|
||||
</p>
|
||||
<p className="text-base mt-4 text-primary">{children || 'Loading'}</p>
|
||||
<p
|
||||
className={
|
||||
'text-sm mt-4 text-energy-70 dark:text-energy-50 transition-opacity duration-500' +
|
||||
'text-sm mt-4 text-primary/60 transition-opacity duration-500' +
|
||||
(hasLongLoadTime ? ' opacity-100' : ' opacity-0')
|
||||
}
|
||||
>
|
||||
|
@ -50,7 +50,7 @@ const hasIssueToIconColors: Record<string | number | symbol, IconColorConfig> =
|
||||
bg: 'bg-chalkboard-30 dark:bg-chalkboard-70',
|
||||
},
|
||||
false: {
|
||||
icon: 'text-chalkboard-110 dark:!text-chalkboard-10',
|
||||
icon: '!text-chalkboard-110 dark:!text-chalkboard-10',
|
||||
bg: 'bg-transparent dark:bg-transparent',
|
||||
},
|
||||
}
|
||||
@ -58,8 +58,8 @@ const hasIssueToIconColors: Record<string | number | symbol, IconColorConfig> =
|
||||
const overallConnectionStateColor: Record<NetworkHealthState, IconColorConfig> =
|
||||
{
|
||||
[NetworkHealthState.Ok]: {
|
||||
icon: 'text-energy-80 dark:text-energy-10',
|
||||
bg: 'bg-energy-10/30 dark:bg-energy-80/50',
|
||||
icon: 'text-succeed-80 dark:text-succeed-10',
|
||||
bg: 'bg-succeed-10/30 dark:bg-succeed-80/50',
|
||||
},
|
||||
[NetworkHealthState.Issue]: {
|
||||
icon: 'text-destroy-80 dark:text-destroy-10',
|
||||
@ -214,7 +214,7 @@ export const NetworkHealthIndicator = () => {
|
||||
'p-0 border-none bg-transparent dark:bg-transparent relative ' +
|
||||
(hasIssues
|
||||
? 'focus-visible:outline-destroy-80'
|
||||
: 'focus-visible:outline-energy-80')
|
||||
: 'focus-visible:outline-succeed-80')
|
||||
}
|
||||
data-testid="network-toggle"
|
||||
>
|
||||
@ -227,7 +227,7 @@ export const NetworkHealthIndicator = () => {
|
||||
'rounded-sm ' + overallConnectionStateColor[overallState].bg
|
||||
}
|
||||
/>
|
||||
<Tooltip position="blockEnd" delay={750} className="ui-open:hidden">
|
||||
<Tooltip position="left" delay={750} className="ui-open:hidden">
|
||||
Network Health ({NETWORK_HEALTH_TEXT[overallState]})
|
||||
</Tooltip>
|
||||
</Popover.Button>
|
||||
|
@ -13,6 +13,7 @@ import { getPartsCount, readProject } from '../lib/tauriFS'
|
||||
import { FILE_EXT } from 'lib/constants'
|
||||
import { Dialog } from '@headlessui/react'
|
||||
import { useHotkeys } from 'react-hotkeys-hook'
|
||||
import Tooltip from './Tooltip'
|
||||
|
||||
function ProjectCard({
|
||||
project,
|
||||
@ -64,17 +65,17 @@ function ProjectCard({
|
||||
inputRef.current.focus()
|
||||
inputRef.current.select()
|
||||
}
|
||||
}, [inputRef])
|
||||
}, [inputRef.current])
|
||||
|
||||
return (
|
||||
<li
|
||||
{...props}
|
||||
className="group relative min-h-[5em] p-1 rounded-sm border border-chalkboard-20 dark:border-chalkboard-90 hover:border-energy-10 dark:hover:border-chalkboard-70 hover:bg-energy-10/20 dark:hover:bg-chalkboard-90"
|
||||
className="group relative min-h-[5em] p-1 rounded-sm border border-chalkboard-20 dark:border-chalkboard-80 hover:!border-primary"
|
||||
>
|
||||
{isEditing ? (
|
||||
<form onSubmit={handleSave} className="flex gap-2 items-center">
|
||||
<input
|
||||
className="dark:bg-chalkboard-80 dark:border-chalkboard-40 min-w-0 p-1 selection:bg-energy-10/20 focus:outline-none"
|
||||
className="dark:bg-chalkboard-80 dark:border-chalkboard-40 min-w-0 p-1 focus:outline-none"
|
||||
type="text"
|
||||
id="newProjectName"
|
||||
name="newProjectName"
|
||||
@ -87,27 +88,41 @@ function ProjectCard({
|
||||
<ActionButton
|
||||
Element="button"
|
||||
type="submit"
|
||||
icon={{ icon: faCheck, size: 'sm', className: 'p-1' }}
|
||||
icon={{
|
||||
icon: faCheck,
|
||||
size: 'sm',
|
||||
className: 'p-1',
|
||||
bgClassName: '!bg-transparent',
|
||||
}}
|
||||
className="!p-0"
|
||||
></ActionButton>
|
||||
>
|
||||
<Tooltip position="left" delay={1000}>
|
||||
Rename project
|
||||
</Tooltip>
|
||||
</ActionButton>
|
||||
<ActionButton
|
||||
Element="button"
|
||||
icon={{
|
||||
icon: faX,
|
||||
size: 'sm',
|
||||
iconClassName: 'dark:!text-chalkboard-20',
|
||||
bgClassName: '!bg-transparent',
|
||||
className: 'p-1',
|
||||
}}
|
||||
className="!p-0"
|
||||
onClick={() => setIsEditing(false)}
|
||||
/>
|
||||
>
|
||||
<Tooltip position="left" delay={1000}>
|
||||
Cancel
|
||||
</Tooltip>
|
||||
</ActionButton>
|
||||
</div>
|
||||
</form>
|
||||
) : (
|
||||
<>
|
||||
<div className="p-1 flex flex-col h-full gap-2">
|
||||
<Link
|
||||
className="flex-1 !no-underline text-liquid-100 after:content-[''] after:absolute after:inset-0"
|
||||
className="flex-1 !no-underline !text-chalkboard-110 dark:!text-chalkboard-10 after:content-[''] after:absolute after:inset-0"
|
||||
to={`${paths.FILE}/${encodeURIComponent(project.path)}`}
|
||||
data-testid="project-link"
|
||||
>
|
||||
@ -130,6 +145,7 @@ function ProjectCard({
|
||||
icon: faPenAlt,
|
||||
className: 'p-1',
|
||||
iconClassName: 'dark:!text-chalkboard-20',
|
||||
bgClassName: '!bg-transparent',
|
||||
size: 'xs',
|
||||
}}
|
||||
onClick={(e) => {
|
||||
@ -138,15 +154,19 @@ function ProjectCard({
|
||||
setIsEditing(true)
|
||||
}}
|
||||
className="!p-0"
|
||||
/>
|
||||
>
|
||||
<Tooltip position="left" delay={1000}>
|
||||
Rename project
|
||||
</Tooltip>
|
||||
</ActionButton>
|
||||
<ActionButton
|
||||
Element="button"
|
||||
icon={{
|
||||
icon: faTrashAlt,
|
||||
className: 'p-1',
|
||||
size: 'xs',
|
||||
bgClassName: 'bg-destroy-80',
|
||||
iconClassName: '!text-destroy-20 dark:!text-destroy-40',
|
||||
bgClassName: '!bg-transparent',
|
||||
iconClassName: '!text-destroy-70',
|
||||
}}
|
||||
className="!p-0 hover:border-destroy-40 dark:hover:border-destroy-40"
|
||||
onClick={(e) => {
|
||||
@ -154,7 +174,11 @@ function ProjectCard({
|
||||
e.nativeEvent.stopPropagation()
|
||||
setIsConfirmingDelete(true)
|
||||
}}
|
||||
/>
|
||||
>
|
||||
<Tooltip position="left" delay={1000}>
|
||||
Delete project
|
||||
</Tooltip>
|
||||
</ActionButton>
|
||||
</div>
|
||||
</div>
|
||||
<Dialog
|
||||
|
@ -25,15 +25,15 @@ const ProjectSidebarMenu = ({
|
||||
}) => {
|
||||
const { onProjectClose } = useLspContext()
|
||||
return (
|
||||
<div className="rounded-sm !no-underline h-9 mr-auto max-h-min min-w-max border-0 py-1 px-2 flex items-center gap-2 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-energy-50 dark:hover:bg-chalkboard-90">
|
||||
<div className="!no-underline h-full mr-auto max-h-min min-w-max flex items-center gap-2">
|
||||
<Link
|
||||
onClick={() => {
|
||||
onProjectClose(file || null, project?.path || null, false)
|
||||
}}
|
||||
to={paths.HOME}
|
||||
className="group"
|
||||
className="relative h-full grid place-content-center group p-1.5 before:block before:content-[''] before:absolute before:inset-0 before:bottom-2.5 before:z-[-1] before:bg-primary hover:before:brightness-110 before:rounded-b-sm"
|
||||
>
|
||||
<Logo className="w-auto h-5 text-chalkboard-120 dark:text-chalkboard-10 group-hover:text-energy-10" />
|
||||
<Logo className="w-auto h-4 text-chalkboard-10" />
|
||||
</Link>
|
||||
{renderAsLink ? (
|
||||
<>
|
||||
@ -80,7 +80,7 @@ function ProjectMenuPopover({
|
||||
return (
|
||||
<Popover className="relative">
|
||||
<Popover.Button
|
||||
className="rounded-sm h-9 mr-auto max-h-min min-w-max border-0 py-1 pl-0 pr-2 flex items-center focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-energy-50 dark:hover:bg-chalkboard-90"
|
||||
className="rounded-sm h-9 mr-auto max-h-min min-w-max border-0 py-1 pl-0 pr-2 flex items-center focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-primary dark:hover:bg-chalkboard-90"
|
||||
data-testid="project-sidebar-toggle"
|
||||
>
|
||||
<CustomIcon name="three-dots" className="w-5 h-5 rotate-90" />
|
||||
@ -126,15 +126,12 @@ function ProjectMenuPopover({
|
||||
<>
|
||||
<div className="flex items-center gap-4 px-4 py-3">
|
||||
<div>
|
||||
<p
|
||||
className="m-0 text-chalkboard-100 dark:text-energy-10 text-mono"
|
||||
data-testid="projectName"
|
||||
>
|
||||
<p className="m-0 text-mono" data-testid="projectName">
|
||||
{project?.name ? project.name : APP_NAME}
|
||||
</p>
|
||||
{project?.entrypointMetadata && (
|
||||
<p
|
||||
className="m-0 text-xs text-chalkboard-100 dark:text-energy-40"
|
||||
className="m-0 text-xs text-chalkboard-80 dark:text-chalkboard-40"
|
||||
data-testid="createdAt"
|
||||
>
|
||||
Created{' '}
|
||||
@ -183,11 +180,10 @@ function ProjectMenuPopover({
|
||||
onProjectClose(file || null, project?.path || null, true)
|
||||
}}
|
||||
icon={{
|
||||
icon: faHome,
|
||||
icon: 'arrowLeft',
|
||||
className: 'p-1',
|
||||
size: 'sm',
|
||||
}}
|
||||
className="border-transparent dark:border-transparent hover:bg-energy-10/20 dark:hover:bg-chalkboard-90"
|
||||
className="border-transparent dark:border-transparent"
|
||||
>
|
||||
Go to Home
|
||||
</ActionButton>
|
||||
|
@ -199,6 +199,17 @@ export const SettingsAuthProviderBase = ({
|
||||
return () => matcher.removeEventListener('change', listener)
|
||||
}, [settingsState.context])
|
||||
|
||||
/**
|
||||
* Update the --primary-hue CSS variable
|
||||
* to match the setting app.themeColor.current
|
||||
*/
|
||||
useEffect(() => {
|
||||
document.documentElement.style.setProperty(
|
||||
`--primary-hue`,
|
||||
settingsState.context.app.themeColor.current
|
||||
)
|
||||
}, [settingsState.context.app.themeColor.current])
|
||||
|
||||
// Auth machine setup
|
||||
const [authState, authSend, authActor] = useMachine(authMachine, {
|
||||
actions: {
|
||||
|
@ -154,10 +154,9 @@ const UserSidebarMenu = ({ user }: { user?: User }) => {
|
||||
icon={{
|
||||
icon: faSignOutAlt,
|
||||
className: 'p-1',
|
||||
bgClassName: 'bg-destroy-80',
|
||||
bgClassName: '!bg-transparent',
|
||||
size: 'sm',
|
||||
iconClassName:
|
||||
'text-destroy-20 group-hover:text-destroy-10 hover:text-destroy-10',
|
||||
iconClassName: '!text-destroy-70',
|
||||
}}
|
||||
className="border-transparent dark:border-transparent hover:border-destroy-40 dark:hover:border-destroy-60 hover:bg-destroy-10/20 dark:hover:bg-destroy-80/20"
|
||||
data-testid="user-sidebar-sign-out"
|
||||
|
Reference in New Issue
Block a user