mirror of
https://github.com/outline/outline.git
synced 2026-02-15 15:29:02 -06:00
Sidebar design tweaks (#10684)
* Single line sidebar items * fix: Letter icon in breadcrumb missing letter Alignment of sidebar items * fix: Editing state * fix: Shared sidebar * fix: Drag over unloaded document in sidebar does not allow drop * perf * Sidebar hover background * Allow click toggle closed * fix: Disclosure toggle * perf: Avoid rendering collapsed folders
This commit is contained in:
@@ -163,7 +163,7 @@ export const importDocument = createActionV2({
|
||||
const { documents } = stores;
|
||||
const input = document.createElement("input");
|
||||
input.type = "file";
|
||||
input.accept = documents.importFileTypes.join(", ");
|
||||
input.accept = documents.importFileTypesString;
|
||||
|
||||
input.onchange = async (ev) => {
|
||||
const files = getEventFiles(ev);
|
||||
|
||||
@@ -870,7 +870,7 @@ export const importDocument = createActionV2({
|
||||
const { documents } = stores;
|
||||
const input = document.createElement("input");
|
||||
input.type = "file";
|
||||
input.accept = documents.importFileTypes.join(", ");
|
||||
input.accept = documents.importFileTypesString;
|
||||
|
||||
input.onchange = async (ev) => {
|
||||
const files = getEventFiles(ev);
|
||||
|
||||
@@ -99,7 +99,12 @@ function DocumentBreadcrumb(
|
||||
return createInternalLinkActionV2({
|
||||
name: node.icon ? (
|
||||
<>
|
||||
<StyledIcon value={node.icon} color={node.color} /> {title}
|
||||
<StyledIcon
|
||||
value={node.icon}
|
||||
color={node.color}
|
||||
initial={node.title.charAt(0).toUpperCase()}
|
||||
/>{" "}
|
||||
{title}
|
||||
</>
|
||||
) : (
|
||||
title
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as React from "react";
|
||||
import { toast } from "sonner";
|
||||
import styled from "styled-components";
|
||||
import { s, truncateMultiline } from "@shared/styles";
|
||||
import { s, ellipsis } from "@shared/styles";
|
||||
|
||||
type Props = Omit<React.HTMLAttributes<HTMLInputElement>, "onSubmit"> & {
|
||||
/** A callback when the title is submitted. */
|
||||
@@ -168,8 +168,8 @@ function EditableTitle(
|
||||
);
|
||||
}
|
||||
|
||||
const Text = styled.span`
|
||||
${truncateMultiline(3)}
|
||||
const Text = styled.div`
|
||||
${ellipsis()}
|
||||
`;
|
||||
|
||||
const Input = styled.input`
|
||||
|
||||
@@ -30,15 +30,13 @@ export const ContextMenu = observer(
|
||||
isMenu: true,
|
||||
});
|
||||
|
||||
const menuItems = useComputed(() => {
|
||||
if (!open) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return ((action?.children as ActionV2Variant[]) ?? []).map(
|
||||
(childAction) => actionV2ToMenuItem(childAction, actionContext)
|
||||
);
|
||||
}, [open, action?.children, actionContext]);
|
||||
const menuItems = useComputed(
|
||||
() =>
|
||||
((action?.children as ActionV2Variant[]) ?? []).map((childAction) =>
|
||||
actionV2ToMenuItem(childAction, actionContext)
|
||||
),
|
||||
[action?.children, actionContext]
|
||||
);
|
||||
|
||||
const handleOpenChange = React.useCallback(
|
||||
(open: boolean) => {
|
||||
@@ -48,7 +46,7 @@ export const ContextMenu = observer(
|
||||
onClose?.();
|
||||
}
|
||||
},
|
||||
[onOpen, onClose]
|
||||
[open, onOpen, onClose]
|
||||
);
|
||||
|
||||
const enablePointerEvents = React.useCallback(() => {
|
||||
|
||||
@@ -32,7 +32,7 @@ import CollectionLinkChildren from "./CollectionLinkChildren";
|
||||
type Props = {
|
||||
collection: Collection;
|
||||
expanded?: boolean;
|
||||
onDisclosureClick: (ev?: React.MouseEvent<HTMLButtonElement>) => void;
|
||||
onDisclosureClick: (ev?: React.MouseEvent<HTMLElement>) => void;
|
||||
activeDocument: Document | undefined;
|
||||
isDraggingAnyCollection?: boolean;
|
||||
depth?: number;
|
||||
|
||||
@@ -130,17 +130,13 @@ function InnerDocumentLink(
|
||||
}
|
||||
}, [setCollapsed, expanded, hasChildDocuments]);
|
||||
|
||||
const handleDisclosureClick = React.useCallback(
|
||||
(ev) => {
|
||||
ev?.preventDefault();
|
||||
if (expanded) {
|
||||
setCollapsed();
|
||||
} else {
|
||||
setExpanded();
|
||||
}
|
||||
},
|
||||
[setCollapsed, setExpanded, expanded]
|
||||
);
|
||||
const handleDisclosureClick = React.useCallback(() => {
|
||||
if (expanded) {
|
||||
setCollapsed();
|
||||
} else {
|
||||
setExpanded();
|
||||
}
|
||||
}, [setCollapsed, setExpanded, expanded]);
|
||||
|
||||
const handlePrefetch = React.useCallback(() => {
|
||||
void prefetchDocument?.(node.id);
|
||||
@@ -418,7 +414,7 @@ function InnerDocumentLink(
|
||||
onKeyDown={handleKeyDown}
|
||||
>
|
||||
<div ref={dropToReparent}>
|
||||
<DropToImport documentId={node.id} activeClassName="activeDropZone">
|
||||
<DropToImport documentId={node.id}>
|
||||
<SidebarLink
|
||||
// @ts-expect-error react-router type is wrong, string component is fine.
|
||||
component={isEditing ? "div" : undefined}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
import { VisuallyHidden } from "@radix-ui/react-visually-hidden";
|
||||
import invariant from "invariant";
|
||||
import { observer } from "mobx-react";
|
||||
import { useCallback } from "react";
|
||||
import { useCallback, useState } from "react";
|
||||
import Dropzone from "react-dropzone";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { toast } from "sonner";
|
||||
import styled, { css } from "styled-components";
|
||||
import LoadingIndicator from "~/components/LoadingIndicator";
|
||||
import useEventListener from "~/hooks/useEventListener";
|
||||
import useImportDocument from "~/hooks/useImportDocument";
|
||||
import usePolicy from "~/hooks/usePolicy";
|
||||
import useStores from "~/hooks/useStores";
|
||||
@@ -22,6 +23,7 @@ type Props = {
|
||||
function DropToImport({ disabled, children, collectionId, documentId }: Props) {
|
||||
const { t } = useTranslation();
|
||||
const { documents } = useStores();
|
||||
const [prerender, setPreRendered] = useState(false);
|
||||
const { handleFiles, isImporting } = useImportDocument(
|
||||
collectionId,
|
||||
documentId
|
||||
@@ -30,6 +32,7 @@ function DropToImport({ disabled, children, collectionId, documentId }: Props) {
|
||||
collectionId || documentId,
|
||||
"Must provide either collectionId or documentId"
|
||||
);
|
||||
useEventListener("dragenter", () => setPreRendered(true));
|
||||
|
||||
const canCollection = usePolicy(collectionId);
|
||||
const canDocument = usePolicy(documentId);
|
||||
@@ -42,6 +45,7 @@ function DropToImport({ disabled, children, collectionId, documentId }: Props) {
|
||||
|
||||
if (
|
||||
disabled ||
|
||||
!prerender ||
|
||||
(collectionId && !canCollection.createDocument) ||
|
||||
(documentId && !canDocument.createChildDocument)
|
||||
) {
|
||||
@@ -50,7 +54,7 @@ function DropToImport({ disabled, children, collectionId, documentId }: Props) {
|
||||
|
||||
return (
|
||||
<Dropzone
|
||||
accept={documents.importFileTypes.join(", ")}
|
||||
accept={documents.importFileTypesString}
|
||||
onDropAccepted={handleFiles}
|
||||
onDropRejected={handleRejection}
|
||||
noClick
|
||||
|
||||
@@ -1,30 +1,14 @@
|
||||
import * as React from "react";
|
||||
import styled from "styled-components";
|
||||
|
||||
type Props = {
|
||||
expanded: boolean;
|
||||
children?: React.ReactNode;
|
||||
};
|
||||
|
||||
const Folder: React.FC<Props> = ({ expanded, children }: Props) => {
|
||||
const [openedOnce, setOpenedOnce] = React.useState(expanded);
|
||||
|
||||
// allows us to avoid rendering all children when the folder hasn't been opened
|
||||
React.useEffect(() => {
|
||||
if (expanded) {
|
||||
setOpenedOnce(true);
|
||||
}
|
||||
}, [expanded]);
|
||||
|
||||
if (!openedOnce) {
|
||||
if (!expanded) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <Wrapper $expanded={expanded}>{children}</Wrapper>;
|
||||
return <>{children}</>;
|
||||
};
|
||||
|
||||
const Wrapper = styled.div<{ $expanded?: boolean }>`
|
||||
display: ${(props) => (props.$expanded ? "block" : "none")};
|
||||
`;
|
||||
|
||||
export default Folder;
|
||||
|
||||
@@ -40,7 +40,7 @@ function CollectionLink({ node, shareId, hideRootNode }: Props) {
|
||||
<SharedDocumentLink
|
||||
key={childNode.id}
|
||||
index={index}
|
||||
depth={hideRootNode ? 0 : 2}
|
||||
depth={hideRootNode ? 1 : 2}
|
||||
shareId={shareId}
|
||||
node={childNode}
|
||||
prefetchDocument={documents.prefetchDocument}
|
||||
|
||||
@@ -3,7 +3,7 @@ import * as React from "react";
|
||||
import styled, { useTheme, css } from "styled-components";
|
||||
import breakpoint from "styled-components-breakpoint";
|
||||
import EventBoundary from "@shared/components/EventBoundary";
|
||||
import { hover, s } from "@shared/styles";
|
||||
import { ellipsis, hover, s } from "@shared/styles";
|
||||
import { isMobile } from "@shared/utils/browser";
|
||||
import NudeButton from "~/components/NudeButton";
|
||||
import { UnreadBadge } from "~/components/UnreadBadge";
|
||||
@@ -14,15 +14,14 @@ import NavLink, { Props as NavLinkProps } from "./NavLink";
|
||||
import { ActionV2WithChildren } from "~/types";
|
||||
import { ContextMenu } from "~/components/Menu/ContextMenu";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import useBoolean from "~/hooks/useBoolean";
|
||||
|
||||
type Props = Omit<NavLinkProps, "to"> & {
|
||||
to?: LocationDescriptor;
|
||||
innerRef?: (ref: HTMLElement | null | undefined) => void;
|
||||
onClick?: React.MouseEventHandler<HTMLAnchorElement>;
|
||||
/** Callback when we expect the user to click on the link. Used for prefetching data. */
|
||||
onClickIntent?: () => void;
|
||||
onDisclosureClick?: React.MouseEventHandler<HTMLButtonElement>;
|
||||
onClickIntent?: React.MouseEventHandler<HTMLElement>;
|
||||
onDisclosureClick?: React.MouseEventHandler<HTMLElement>;
|
||||
icon?: React.ReactNode;
|
||||
label?: React.ReactNode;
|
||||
menu?: React.ReactNode;
|
||||
@@ -45,6 +44,7 @@ const activeDropStyle = {
|
||||
|
||||
const preventDefault = (ev: React.MouseEvent) => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
};
|
||||
|
||||
function SidebarLink(
|
||||
@@ -77,10 +77,10 @@ function SidebarLink(
|
||||
const { handleMouseEnter, handleMouseLeave } = useClickIntent(onClickIntent);
|
||||
const style = React.useMemo(
|
||||
() => ({
|
||||
paddingLeft: `${(depth || 0) * 16 + 12}px`,
|
||||
paddingLeft: `${(depth || 0) * 16 + (icon ? -8 : 12)}px`,
|
||||
paddingRight: unreadBadge ? "32px" : undefined,
|
||||
}),
|
||||
[depth]
|
||||
[depth, icon, unreadBadge]
|
||||
);
|
||||
|
||||
const unreadStyle = React.useMemo(
|
||||
@@ -99,81 +99,71 @@ function SidebarLink(
|
||||
[theme.text, theme.sidebarActiveBackground, style]
|
||||
);
|
||||
|
||||
const hoverStyle = React.useMemo(
|
||||
() => ({
|
||||
color: theme.text,
|
||||
...style,
|
||||
}),
|
||||
[theme.text, style]
|
||||
);
|
||||
const handleClick = React.useCallback(
|
||||
(ev: React.MouseEvent<HTMLAnchorElement>) => {
|
||||
onDisclosureClick?.(ev);
|
||||
|
||||
const [openContextMenu, setOpen, setClosed] = useBoolean(false);
|
||||
const DisclosureComponent = depth === 0 ? HiddenDisclosure : Disclosure;
|
||||
|
||||
const handleClickCapture = React.useCallback(
|
||||
(event: React.MouseEvent<HTMLAnchorElement>) => {
|
||||
if (event.altKey && onDisclosureClick && expanded !== undefined) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
onDisclosureClick(
|
||||
event as unknown as React.MouseEvent<HTMLButtonElement>
|
||||
);
|
||||
if (onClick && !disabled && ev.isDefaultPrevented() === false) {
|
||||
onClick(ev);
|
||||
}
|
||||
},
|
||||
[onDisclosureClick, expanded]
|
||||
[onClick, disabled, expanded]
|
||||
);
|
||||
|
||||
const handleDisclosureClick = React.useCallback(
|
||||
(ev: React.MouseEvent<HTMLElement>) => {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
onDisclosureClick?.(ev);
|
||||
},
|
||||
[onDisclosureClick]
|
||||
);
|
||||
|
||||
const DisclosureComponent = icon ? HiddenDisclosure : Disclosure;
|
||||
|
||||
return (
|
||||
<>
|
||||
<ContextMenu
|
||||
action={contextAction}
|
||||
ariaLabel={t("Link options")}
|
||||
onOpen={setOpen}
|
||||
onClose={setClosed}
|
||||
<ContextMenu action={contextAction} ariaLabel={t("Link options")}>
|
||||
<Link
|
||||
$isActiveDrop={isActiveDrop}
|
||||
$isDraft={isDraft}
|
||||
$disabled={disabled}
|
||||
style={style}
|
||||
activeStyle={isActiveDrop ? activeDropStyle : activeStyle}
|
||||
onClick={handleClick}
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
onDragEnter={handleMouseEnter}
|
||||
// @ts-expect-error exact does not exist on div
|
||||
exact={exact !== false}
|
||||
to={to}
|
||||
as={to ? undefined : href ? "a" : "div"}
|
||||
href={href}
|
||||
className={className}
|
||||
ref={ref}
|
||||
{...rest}
|
||||
>
|
||||
<Link
|
||||
$isActiveDrop={isActiveDrop}
|
||||
$isDraft={isDraft}
|
||||
$disabled={disabled}
|
||||
activeStyle={isActiveDrop ? activeDropStyle : activeStyle}
|
||||
style={openContextMenu ? hoverStyle : active ? activeStyle : style}
|
||||
onClickCapture={handleClickCapture}
|
||||
onClick={onClick}
|
||||
onMouseEnter={handleMouseEnter}
|
||||
onMouseLeave={handleMouseLeave}
|
||||
// @ts-expect-error exact does not exist on div
|
||||
exact={exact !== false}
|
||||
to={to}
|
||||
as={to ? undefined : href ? "a" : "div"}
|
||||
href={href}
|
||||
className={className}
|
||||
ref={ref}
|
||||
{...rest}
|
||||
>
|
||||
<Content>
|
||||
{expanded !== undefined && (
|
||||
<DisclosureComponent
|
||||
expanded={expanded}
|
||||
onMouseDown={onDisclosureClick}
|
||||
onClick={preventDefault}
|
||||
tabIndex={-1}
|
||||
/>
|
||||
)}
|
||||
{icon && <IconWrapper>{icon}</IconWrapper>}
|
||||
<Label>{label}</Label>
|
||||
{unreadBadge && <UnreadBadge style={unreadStyle} />}
|
||||
</Content>
|
||||
</Link>
|
||||
</ContextMenu>
|
||||
{menu && <Actions showActions={showActions}>{menu}</Actions>}
|
||||
</>
|
||||
<Content>
|
||||
{expanded !== undefined && (
|
||||
<DisclosureComponent
|
||||
expanded={expanded}
|
||||
onClick={preventDefault}
|
||||
onPointerDown={handleDisclosureClick}
|
||||
tabIndex={-1}
|
||||
/>
|
||||
)}
|
||||
{icon && <IconWrapper>{icon}</IconWrapper>}
|
||||
<Label $ellipsis={typeof label === "string"}>{label}</Label>
|
||||
{unreadBadge && <UnreadBadge style={unreadStyle} />}
|
||||
</Content>
|
||||
{menu && <Actions showActions={showActions}>{menu}</Actions>}
|
||||
</Link>
|
||||
</ContextMenu>
|
||||
);
|
||||
}
|
||||
|
||||
// accounts for whitespace around icon
|
||||
export const IconWrapper = styled.span`
|
||||
margin-left: -4px;
|
||||
margin-right: 4px;
|
||||
height: 24px;
|
||||
overflow: hidden;
|
||||
flex-shrink: 0;
|
||||
@@ -191,12 +181,13 @@ const Actions = styled(EventBoundary)<{ showActions?: boolean }>`
|
||||
display: inline-flex;
|
||||
visibility: ${(props) => (props.showActions ? "visible" : "hidden")};
|
||||
position: absolute;
|
||||
top: 4px;
|
||||
top: 3px;
|
||||
right: 4px;
|
||||
gap: 4px;
|
||||
color: ${s("textTertiary")};
|
||||
transition: opacity 50ms;
|
||||
height: 24px;
|
||||
background: var(--background);
|
||||
|
||||
svg {
|
||||
color: ${s("textSecondary")};
|
||||
@@ -226,16 +217,28 @@ const Link = styled(NavLink)<{
|
||||
$isDraft?: boolean;
|
||||
$disabled?: boolean;
|
||||
}>`
|
||||
&:hover,
|
||||
&:active {
|
||||
--background: ${s("sidebarHoverBackground")};
|
||||
}
|
||||
|
||||
&[aria-current="page"] ${Actions} {
|
||||
--background: ${s("sidebarActiveBackground")};
|
||||
}
|
||||
|
||||
${(props) => props.$isActiveDrop && `--background: ${props.theme.slateDark};`}
|
||||
|
||||
display: flex;
|
||||
position: relative;
|
||||
text-overflow: ellipsis;
|
||||
font-weight: 475;
|
||||
padding: ${isMobile() ? 12 : 6}px 16px;
|
||||
border-radius: 4px;
|
||||
min-height: 32px;
|
||||
min-height: 30px;
|
||||
user-select: none;
|
||||
background: ${(props) =>
|
||||
props.$isActiveDrop ? props.theme.slateDark : "inherit"};
|
||||
white-space: nowrap;
|
||||
margin-top: 1px;
|
||||
background: var(--background);
|
||||
color: ${(props) =>
|
||||
props.$isActiveDrop ? props.theme.white : props.theme.sidebarText};
|
||||
font-size: 16px;
|
||||
@@ -282,30 +285,13 @@ const Link = styled(NavLink)<{
|
||||
}
|
||||
}
|
||||
|
||||
& + ${Actions} {
|
||||
background: ${s("sidebarBackground")};
|
||||
|
||||
${NudeButton} {
|
||||
background: transparent;
|
||||
|
||||
&:hover,
|
||||
&[aria-expanded="true"] {
|
||||
background: ${s("sidebarControlHoverBackground")};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&[aria-current="page"] + ${Actions} {
|
||||
background: ${s("sidebarActiveBackground")};
|
||||
}
|
||||
|
||||
${breakpoint("tablet")`
|
||||
padding: 4px 8px 4px 16px;
|
||||
padding: 3px 8px 3px 12px;
|
||||
font-size: 14px;
|
||||
`}
|
||||
|
||||
@media (hover: hover) {
|
||||
&:hover + ${Actions}, &:active + ${Actions} {
|
||||
&:hover ${Actions}, &:active ${Actions} {
|
||||
visibility: visible;
|
||||
|
||||
svg {
|
||||
@@ -318,12 +304,25 @@ const Link = styled(NavLink)<{
|
||||
props.$isActiveDrop ? props.theme.white : props.theme.text};
|
||||
}
|
||||
}
|
||||
|
||||
& ${Actions} {
|
||||
${NudeButton} {
|
||||
background: transparent;
|
||||
|
||||
&:hover,
|
||||
&[aria-expanded="true"] {
|
||||
background: ${s("sidebarControlHoverBackground")};
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const Label = styled.div`
|
||||
const Label = styled.div<{ $ellipsis: boolean }>`
|
||||
position: relative;
|
||||
width: 100%;
|
||||
line-height: 24px;
|
||||
margin-left: 2px;
|
||||
${(props) => props.$ellipsis && ellipsis()}
|
||||
|
||||
* {
|
||||
unicode-bidi: plaintext;
|
||||
|
||||
@@ -41,7 +41,7 @@ type StarredDocumentLinkProps = {
|
||||
expanded: boolean;
|
||||
sidebarContext: SidebarContextType;
|
||||
isDragging: boolean;
|
||||
handleDisclosureClick: (ev?: React.MouseEvent<HTMLButtonElement>) => void;
|
||||
handleDisclosureClick: React.MouseEventHandler<HTMLElement>;
|
||||
handlePrefetch: () => void;
|
||||
icon: React.ReactNode;
|
||||
label: React.ReactNode;
|
||||
@@ -234,7 +234,7 @@ function StarredLink({ star }: Props) {
|
||||
}, [documentId, documents]);
|
||||
|
||||
const handleDisclosureClick = React.useCallback(
|
||||
(ev?: React.MouseEvent<HTMLButtonElement>) => {
|
||||
(ev?: React.MouseEvent<HTMLElement>) => {
|
||||
ev?.preventDefault();
|
||||
ev?.stopPropagation();
|
||||
setExpanded((prevExpanded) => !prevExpanded);
|
||||
|
||||
@@ -7,7 +7,7 @@ import useUnmount from "./useUnmount";
|
||||
* and clears the timer on mouse leave or component unmount.
|
||||
*/
|
||||
export default function useClickIntent(
|
||||
onClickIntent?: () => void,
|
||||
onClickIntent?: React.MouseEventHandler<HTMLElement>,
|
||||
delay = 100
|
||||
) {
|
||||
const timer = React.useRef<number>();
|
||||
|
||||
@@ -197,7 +197,7 @@ const CollectionScene = observer(function _CollectionScene() {
|
||||
}
|
||||
>
|
||||
<DropToImport
|
||||
accept={documents.importFileTypes.join(", ")}
|
||||
accept={documents.importFileTypesString}
|
||||
disabled={!can.createDocument}
|
||||
collectionId={collection.id}
|
||||
>
|
||||
|
||||
@@ -69,6 +69,11 @@ export default class DocumentsStore extends Store<Document> {
|
||||
super(rootStore, Document);
|
||||
}
|
||||
|
||||
@computed
|
||||
get importFileTypesString(): string {
|
||||
return this.importFileTypes.join(",");
|
||||
}
|
||||
|
||||
@computed
|
||||
get all(): Document[] {
|
||||
return filter(
|
||||
|
||||
1
app/typings/styled-components.d.ts
vendored
1
app/typings/styled-components.d.ts
vendored
@@ -145,6 +145,7 @@ declare module "styled-components" {
|
||||
placeholder: string;
|
||||
commentMarkBackground: string;
|
||||
sidebarBackground: string;
|
||||
sidebarHoverBackground: string;
|
||||
sidebarActiveBackground: string;
|
||||
sidebarControlHoverBackground: string;
|
||||
sidebarDraftBorder: string;
|
||||
|
||||
@@ -129,7 +129,8 @@ export const buildLightTheme = (input: Partial<Colors>): DefaultTheme => {
|
||||
textDiffDeletedBackground: "#ffebe9",
|
||||
placeholder: "#a2b2c3",
|
||||
sidebarBackground: colors.warmGrey,
|
||||
sidebarActiveBackground: "#d7e0ea",
|
||||
sidebarHoverBackground: "hsl(212 31% 90% / 1)",
|
||||
sidebarActiveBackground: "hsl(212 31% 85% / 1)",
|
||||
sidebarControlHoverBackground: "rgb(138 164 193 / 20%)",
|
||||
sidebarDraftBorder: darken("0.25", colors.warmGrey),
|
||||
sidebarText: "rgb(78, 92, 110)",
|
||||
@@ -192,6 +193,7 @@ export const buildDarkTheme = (input: Partial<Colors>): DefaultTheme => {
|
||||
textDiffDeletedBackground: "rgba(248,81,73,0.15)",
|
||||
placeholder: "#596673",
|
||||
sidebarBackground: colors.veryDarkBlue,
|
||||
sidebarHoverBackground: lighten(0.05, colors.veryDarkBlue),
|
||||
sidebarActiveBackground: lighten(0.09, colors.veryDarkBlue),
|
||||
sidebarControlHoverBackground: colors.white10,
|
||||
sidebarDraftBorder: darken("0.35", colors.slate),
|
||||
|
||||
Reference in New Issue
Block a user