Assorted cleanup, minor bug fixes, styling fixes, eslint rules (#5165
* fix: Logic error in toast fix: Remove useless component * fix: Logout not clearing all stores * Add icons to notification settings * Add eslint rule to enforce spaced comment * Add eslint rule for arrow-body-style * Add eslint rule to enforce self-closing components * Add menu to api key settings Fix: Deleting webhook subscription does not remove from UI Split webhook subscriptions into active and inactive Styling updates
This commit is contained in:
@@ -26,12 +26,10 @@ const Content = styled.div`
|
||||
`};
|
||||
`;
|
||||
|
||||
const CenteredContent: React.FC<Props> = ({ children, ...rest }) => {
|
||||
return (
|
||||
<Container {...rest}>
|
||||
<Content>{children}</Content>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
const CenteredContent: React.FC<Props> = ({ children, ...rest }) => (
|
||||
<Container {...rest}>
|
||||
<Content>{children}</Content>
|
||||
</Container>
|
||||
);
|
||||
|
||||
export default CenteredContent;
|
||||
|
||||
@@ -42,7 +42,7 @@ const Circle = ({
|
||||
style={{
|
||||
transition: "stroke-dashoffset 0.6s ease 0s",
|
||||
}}
|
||||
></circle>
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ export type Placement =
|
||||
| "left-start";
|
||||
|
||||
type Props = MenuStateReturn & {
|
||||
"aria-label": string;
|
||||
"aria-label"?: string;
|
||||
/** The parent menu state if this is a submenu. */
|
||||
parentMenuState?: MenuStateReturn;
|
||||
/** Called when the context menu is opened. */
|
||||
|
||||
@@ -131,7 +131,7 @@ const SmallSlash = styled(GoToIcon)`
|
||||
vertical-align: middle;
|
||||
flex-shrink: 0;
|
||||
|
||||
fill: ${(props) => props.theme.slate};
|
||||
fill: ${(props) => props.theme.textTertiary};
|
||||
opacity: 0.5;
|
||||
`;
|
||||
|
||||
|
||||
@@ -63,11 +63,13 @@ function DocumentExplorer({ onSubmit, onSelect, items }: Props) {
|
||||
const VERTICAL_PADDING = 6;
|
||||
const HORIZONTAL_PADDING = 24;
|
||||
|
||||
const searchIndex = React.useMemo(() => {
|
||||
return new FuzzySearch(items, ["title"], {
|
||||
caseSensitive: false,
|
||||
});
|
||||
}, [items]);
|
||||
const searchIndex = React.useMemo(
|
||||
() =>
|
||||
new FuzzySearch(items, ["title"], {
|
||||
caseSensitive: false,
|
||||
}),
|
||||
[items]
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (searchTerm) {
|
||||
@@ -119,9 +121,7 @@ function DocumentExplorer({ onSubmit, onSelect, items }: Props) {
|
||||
setSearchTerm(ev.target.value);
|
||||
};
|
||||
|
||||
const isExpanded = (node: number) => {
|
||||
return includes(expandedNodes, nodes[node].id);
|
||||
};
|
||||
const isExpanded = (node: number) => includes(expandedNodes, nodes[node].id);
|
||||
|
||||
const calculateInitialScrollOffset = (itemCount: number) => {
|
||||
if (listRef.current) {
|
||||
@@ -169,9 +169,7 @@ function DocumentExplorer({ onSubmit, onSelect, items }: Props) {
|
||||
return selectedNodeId === nodeId;
|
||||
};
|
||||
|
||||
const hasChildren = (node: number) => {
|
||||
return nodes[node].children.length > 0;
|
||||
};
|
||||
const hasChildren = (node: number) => nodes[node].children.length > 0;
|
||||
|
||||
const toggleCollapse = (node: number) => {
|
||||
if (!hasChildren(node)) {
|
||||
@@ -275,13 +273,9 @@ function DocumentExplorer({ onSubmit, onSelect, items }: Props) {
|
||||
inputSearchRef.current?.focus();
|
||||
};
|
||||
|
||||
const next = () => {
|
||||
return Math.min(activeNode + 1, nodes.length - 1);
|
||||
};
|
||||
const next = () => Math.min(activeNode + 1, nodes.length - 1);
|
||||
|
||||
const prev = () => {
|
||||
return Math.max(activeNode - 1, 0);
|
||||
};
|
||||
const prev = () => Math.max(activeNode - 1, 0);
|
||||
|
||||
const handleKeyDown = (ev: React.KeyboardEvent<HTMLDivElement>) => {
|
||||
switch (ev.key) {
|
||||
|
||||
@@ -116,13 +116,11 @@ function Editor(props: Props, ref: React.RefObject<SharedEditor> | null) {
|
||||
const results = await documents.searchTitles(term);
|
||||
|
||||
return sortBy(
|
||||
results.map((document: Document) => {
|
||||
return {
|
||||
title: document.title,
|
||||
subtitle: <DocumentBreadcrumb document={document} onlyText />,
|
||||
url: document.url,
|
||||
};
|
||||
}),
|
||||
results.map((document: Document) => ({
|
||||
title: document.title,
|
||||
subtitle: <DocumentBreadcrumb document={document} onlyText />,
|
||||
url: document.url,
|
||||
})),
|
||||
(document) =>
|
||||
deburr(document.title)
|
||||
.toLowerCase()
|
||||
|
||||
@@ -240,29 +240,27 @@ function IconPicker({ onOpen, onClose, icon, color, onChange }: Props) {
|
||||
aria-label={t("Choose icon")}
|
||||
>
|
||||
<Icons>
|
||||
{Object.keys(icons).map((name, index) => {
|
||||
return (
|
||||
<MenuItem
|
||||
key={name}
|
||||
onClick={() => onChange(color, name)}
|
||||
{...menu}
|
||||
>
|
||||
{(props) => (
|
||||
<IconButton
|
||||
style={
|
||||
{
|
||||
...style,
|
||||
"--delay": `${index * 8}ms`,
|
||||
} as React.CSSProperties
|
||||
}
|
||||
{...props}
|
||||
>
|
||||
<Icon as={icons[name].component} color={color} size={30} />
|
||||
</IconButton>
|
||||
)}
|
||||
</MenuItem>
|
||||
);
|
||||
})}
|
||||
{Object.keys(icons).map((name, index) => (
|
||||
<MenuItem
|
||||
key={name}
|
||||
onClick={() => onChange(color, name)}
|
||||
{...menu}
|
||||
>
|
||||
{(props) => (
|
||||
<IconButton
|
||||
style={
|
||||
{
|
||||
...style,
|
||||
"--delay": `${index * 8}ms`,
|
||||
} as React.CSSProperties
|
||||
}
|
||||
{...props}
|
||||
>
|
||||
<Icon as={icons[name].component} color={color} size={30} />
|
||||
</IconButton>
|
||||
)}
|
||||
</MenuItem>
|
||||
))}
|
||||
</Icons>
|
||||
<Colors>
|
||||
<React.Suspense
|
||||
|
||||
@@ -46,9 +46,8 @@ export type Props = {
|
||||
onChange?: (value: string | null) => void;
|
||||
};
|
||||
|
||||
const getOptionFromValue = (options: Option[], value: string | null) => {
|
||||
return options.find((option) => option.value === value);
|
||||
};
|
||||
const getOptionFromValue = (options: Option[], value: string | null) =>
|
||||
options.find((option) => option.value === value);
|
||||
|
||||
const InputSelect = (props: Props) => {
|
||||
const {
|
||||
|
||||
@@ -14,18 +14,16 @@ type Props = {
|
||||
body?: PlaceholderTextProps;
|
||||
};
|
||||
|
||||
const Placeholder = ({ count, className, header, body }: Props) => {
|
||||
return (
|
||||
<Fade>
|
||||
{times(count || 2, (index) => (
|
||||
<Item key={index} className={className} column auto>
|
||||
<PlaceholderText {...header} header delay={0.2 * index} />
|
||||
<PlaceholderText {...body} delay={0.2 * index} />
|
||||
</Item>
|
||||
))}
|
||||
</Fade>
|
||||
);
|
||||
};
|
||||
const Placeholder = ({ count, className, header, body }: Props) => (
|
||||
<Fade>
|
||||
{times(count || 2, (index) => (
|
||||
<Item key={index} className={className} column auto>
|
||||
<PlaceholderText {...header} header delay={0.2 * index} />
|
||||
<PlaceholderText {...body} delay={0.2 * index} />
|
||||
</Item>
|
||||
))}
|
||||
</Fade>
|
||||
);
|
||||
|
||||
const Item = styled(Flex)`
|
||||
padding: 10px 0;
|
||||
|
||||
@@ -2,13 +2,11 @@ import * as React from "react";
|
||||
import styled, { keyframes } from "styled-components";
|
||||
import { depths, s } from "@shared/styles";
|
||||
|
||||
const LoadingIndicatorBar = () => {
|
||||
return (
|
||||
<Container>
|
||||
<Loader />
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
const LoadingIndicatorBar = () => (
|
||||
<Container>
|
||||
<Loader />
|
||||
</Container>
|
||||
);
|
||||
|
||||
const loadingFrame = keyframes`
|
||||
from { margin-left: -100%; }
|
||||
|
||||
@@ -9,24 +9,22 @@ type Props = {
|
||||
description?: JSX.Element;
|
||||
};
|
||||
|
||||
const Notice: React.FC<Props> = ({ children, icon, description }) => {
|
||||
return (
|
||||
<Container>
|
||||
<Flex as="span" gap={8}>
|
||||
{icon}
|
||||
<span>
|
||||
<Title>{children}</Title>
|
||||
{description && (
|
||||
<>
|
||||
<br />
|
||||
{description}
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
</Flex>
|
||||
</Container>
|
||||
);
|
||||
};
|
||||
const Notice: React.FC<Props> = ({ children, icon, description }) => (
|
||||
<Container>
|
||||
<Flex as="span" gap={8}>
|
||||
{icon}
|
||||
<span>
|
||||
<Title>{children}</Title>
|
||||
{description && (
|
||||
<>
|
||||
<br />
|
||||
{description}
|
||||
</>
|
||||
)}
|
||||
</span>
|
||||
</Flex>
|
||||
</Container>
|
||||
);
|
||||
|
||||
const Title = styled.span`
|
||||
font-weight: 500;
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
import * as React from "react";
|
||||
import Notice from "~/components/Notice";
|
||||
|
||||
const NoticeAlert: React.FC = ({ children }) => {
|
||||
return (
|
||||
<Notice>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
style={{
|
||||
position: "relative",
|
||||
top: "2px",
|
||||
marginRight: "4px",
|
||||
}}
|
||||
>
|
||||
<path
|
||||
d="M15.6676 11.5372L10.0155 1.14735C9.10744 -0.381434 6.89378 -0.383465 5.98447 1.14735L0.332715 11.5372C-0.595598 13.0994 0.528309 15.0776 2.34778 15.0776H13.652C15.47 15.0776 16.5959 13.101 15.6676 11.5372ZM8 13.2026C7.48319 13.2026 7.0625 12.7819 7.0625 12.2651C7.0625 11.7483 7.48319 11.3276 8 11.3276C8.51681 11.3276 8.9375 11.7483 8.9375 12.2651C8.9375 12.7819 8.51681 13.2026 8 13.2026ZM8.9375 9.45257C8.9375 9.96938 8.51681 10.3901 8 10.3901C7.48319 10.3901 7.0625 9.96938 7.0625 9.45257V4.76507C7.0625 4.24826 7.48319 3.82757 8 3.82757C8.51681 3.82757 8.9375 4.24826 8.9375 4.76507V9.45257Z"
|
||||
fill="currentColor"
|
||||
/>
|
||||
</svg>{" "}
|
||||
{children}
|
||||
</Notice>
|
||||
);
|
||||
};
|
||||
|
||||
export default NoticeAlert;
|
||||
@@ -21,32 +21,30 @@ const Scene: React.FC<Props> = ({
|
||||
left,
|
||||
children,
|
||||
centered,
|
||||
}) => {
|
||||
return (
|
||||
<FillWidth>
|
||||
<PageTitle title={textTitle || title} />
|
||||
<Header
|
||||
hasSidebar
|
||||
title={
|
||||
icon ? (
|
||||
<>
|
||||
{icon} {title}
|
||||
</>
|
||||
) : (
|
||||
title
|
||||
)
|
||||
}
|
||||
actions={actions}
|
||||
left={left}
|
||||
/>
|
||||
{centered !== false ? (
|
||||
<CenteredContent withStickyHeader>{children}</CenteredContent>
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</FillWidth>
|
||||
);
|
||||
};
|
||||
}) => (
|
||||
<FillWidth>
|
||||
<PageTitle title={textTitle || title} />
|
||||
<Header
|
||||
hasSidebar
|
||||
title={
|
||||
icon ? (
|
||||
<>
|
||||
{icon} {title}
|
||||
</>
|
||||
) : (
|
||||
title
|
||||
)
|
||||
}
|
||||
actions={actions}
|
||||
left={left}
|
||||
/>
|
||||
{centered !== false ? (
|
||||
<CenteredContent withStickyHeader>{children}</CenteredContent>
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
</FillWidth>
|
||||
);
|
||||
|
||||
const FillWidth = styled.div`
|
||||
width: 100%;
|
||||
|
||||
@@ -158,21 +158,19 @@ function SearchPopover({ shareId }: Props) {
|
||||
return (
|
||||
<>
|
||||
<PopoverDisclosure {...popover}>
|
||||
{(props) => {
|
||||
{(props) => (
|
||||
// props assumes the disclosure is a button, but we want a type-ahead
|
||||
// so we take the aria props, and ref and ignore the event handlers
|
||||
return (
|
||||
<StyledInputSearch
|
||||
aria-controls={props["aria-controls"]}
|
||||
aria-expanded={props["aria-expanded"]}
|
||||
aria-haspopup={props["aria-haspopup"]}
|
||||
ref={props.ref}
|
||||
onChange={handleSearchInputChange}
|
||||
onFocus={handleSearchInputFocus}
|
||||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
);
|
||||
}}
|
||||
<StyledInputSearch
|
||||
aria-controls={props["aria-controls"]}
|
||||
aria-expanded={props["aria-expanded"]}
|
||||
aria-haspopup={props["aria-haspopup"]}
|
||||
ref={props.ref}
|
||||
onChange={handleSearchInputChange}
|
||||
onFocus={handleSearchInputFocus}
|
||||
onKeyDown={handleKeyDown}
|
||||
/>
|
||||
)}
|
||||
</PopoverDisclosure>
|
||||
<Popover
|
||||
{...popover}
|
||||
|
||||
@@ -34,9 +34,7 @@ function Collections() {
|
||||
fractionalIndex(null, orderedCollections[0].index)
|
||||
);
|
||||
},
|
||||
canDrop: (item) => {
|
||||
return item.id !== orderedCollections[0].id;
|
||||
},
|
||||
canDrop: (item) => item.id !== orderedCollections[0].id,
|
||||
collect: (monitor) => ({
|
||||
isCollectionDropping: monitor.isOver(),
|
||||
isDraggingAnyCollection: monitor.getItemType() === "collection",
|
||||
|
||||
@@ -76,18 +76,20 @@ function InnerDocumentLink(
|
||||
[collection, node]
|
||||
);
|
||||
|
||||
const showChildren = React.useMemo(() => {
|
||||
return !!(
|
||||
hasChildDocuments &&
|
||||
activeDocument &&
|
||||
collection &&
|
||||
(collection
|
||||
.pathToDocument(activeDocument.id)
|
||||
.map((entry) => entry.id)
|
||||
.includes(node.id) ||
|
||||
isActiveDocument)
|
||||
);
|
||||
}, [hasChildDocuments, activeDocument, isActiveDocument, node, collection]);
|
||||
const showChildren = React.useMemo(
|
||||
() =>
|
||||
!!(
|
||||
hasChildDocuments &&
|
||||
activeDocument &&
|
||||
collection &&
|
||||
(collection
|
||||
.pathToDocument(activeDocument.id)
|
||||
.map((entry) => entry.id)
|
||||
.includes(node.id) ||
|
||||
isActiveDocument)
|
||||
),
|
||||
[hasChildDocuments, activeDocument, isActiveDocument, node, collection]
|
||||
);
|
||||
|
||||
const [expanded, setExpanded] = React.useState(showChildren);
|
||||
|
||||
|
||||
@@ -56,12 +56,9 @@ function DraggableCollectionLink({
|
||||
fractionalIndex(collection.index, belowCollectionIndex)
|
||||
);
|
||||
},
|
||||
canDrop: (item) => {
|
||||
return (
|
||||
collection.id !== item.id &&
|
||||
(!belowCollection || item.id !== belowCollection.id)
|
||||
);
|
||||
},
|
||||
canDrop: (item) =>
|
||||
collection.id !== item.id &&
|
||||
(!belowCollection || item.id !== belowCollection.id),
|
||||
collect: (monitor: DropTargetMonitor<Collection, Collection>) => ({
|
||||
isCollectionDropping: monitor.isOver(),
|
||||
isDraggingAnyCollection: monitor.canDrop(),
|
||||
|
||||
@@ -21,15 +21,13 @@ const resolveToLocation = (
|
||||
const normalizeToLocation = (
|
||||
to: LocationDescriptor,
|
||||
currentLocation: Location
|
||||
) => {
|
||||
return typeof to === "string"
|
||||
) =>
|
||||
typeof to === "string"
|
||||
? createLocation(to, null, undefined, currentLocation)
|
||||
: to;
|
||||
};
|
||||
|
||||
const joinClassnames = (...classnames: (string | undefined)[]) => {
|
||||
return classnames.filter((i) => i).join(" ");
|
||||
};
|
||||
const joinClassnames = (...classnames: (string | undefined)[]) =>
|
||||
classnames.filter((i) => i).join(" ");
|
||||
|
||||
export type Props = React.AnchorHTMLAttributes<HTMLAnchorElement> & {
|
||||
activeClassName?: string;
|
||||
@@ -103,16 +101,13 @@ const NavLink = ({
|
||||
}, [linkRef, scrollIntoViewIfNeeded, isActive]);
|
||||
|
||||
const shouldFastClick = React.useCallback(
|
||||
(event: React.MouseEvent<HTMLAnchorElement>): boolean => {
|
||||
return (
|
||||
event.button === 0 && // Only intercept left clicks
|
||||
!event.defaultPrevented &&
|
||||
!rest.target &&
|
||||
!event.altKey &&
|
||||
!event.metaKey &&
|
||||
!event.ctrlKey
|
||||
);
|
||||
},
|
||||
(event: React.MouseEvent<HTMLAnchorElement>): boolean =>
|
||||
event.button === 0 && // Only intercept left clicks
|
||||
!event.defaultPrevented &&
|
||||
!rest.target &&
|
||||
!event.altKey &&
|
||||
!event.metaKey &&
|
||||
!event.ctrlKey,
|
||||
[rest.target]
|
||||
);
|
||||
|
||||
@@ -153,7 +148,7 @@ const NavLink = ({
|
||||
<Link
|
||||
key={isActive ? "active" : "inactive"}
|
||||
ref={linkRef}
|
||||
//onMouseDown={handleClick}
|
||||
// onMouseDown={handleClick}
|
||||
onKeyDown={(event) => {
|
||||
if (["Enter", " "].includes(event.key)) {
|
||||
navigateTo();
|
||||
|
||||
@@ -42,9 +42,9 @@ function DocumentLink(
|
||||
!!node.children.length || activeDocument?.parentDocumentId === node.id;
|
||||
const document = documents.get(node.id);
|
||||
|
||||
const showChildren = React.useMemo(() => {
|
||||
return !!hasChildDocuments;
|
||||
}, [hasChildDocuments]);
|
||||
const showChildren = React.useMemo(() => !!hasChildDocuments, [
|
||||
hasChildDocuments,
|
||||
]);
|
||||
|
||||
const [expanded, setExpanded] = React.useState(showChildren);
|
||||
|
||||
@@ -111,9 +111,7 @@ function DocumentLink(
|
||||
scrollIntoViewIfNeeded={!document?.isStarred}
|
||||
isDraft={isDraft}
|
||||
ref={ref}
|
||||
isActive={() => {
|
||||
return !!isActiveDocument;
|
||||
}}
|
||||
isActive={() => !!isActiveDocument}
|
||||
/>
|
||||
{expanded &&
|
||||
nodeChildren.map((childNode, index) => (
|
||||
|
||||
@@ -6,7 +6,6 @@ import { useTranslation } from "react-i18next";
|
||||
import Star from "~/models/Star";
|
||||
import Flex from "~/components/Flex";
|
||||
import useStores from "~/hooks/useStores";
|
||||
import useToasts from "~/hooks/useToasts";
|
||||
import DropCursor from "./DropCursor";
|
||||
import Header from "./Header";
|
||||
import PlaceholderCollections from "./PlaceholderCollections";
|
||||
@@ -22,7 +21,6 @@ function Starred() {
|
||||
const [displayedStarsCount, setDisplayedStarsCount] = React.useState(
|
||||
STARRED_PAGINATION_LIMIT
|
||||
);
|
||||
const { showToast } = useToasts();
|
||||
const { stars } = useStores();
|
||||
const { t } = useTranslation();
|
||||
|
||||
@@ -34,13 +32,10 @@ function Starred() {
|
||||
offset,
|
||||
});
|
||||
} catch (error) {
|
||||
showToast(t("Starred documents could not be loaded"), {
|
||||
type: "error",
|
||||
});
|
||||
setFetchError(error);
|
||||
}
|
||||
},
|
||||
[stars, showToast, t]
|
||||
[stars]
|
||||
);
|
||||
|
||||
React.useEffect(() => {
|
||||
|
||||
@@ -22,7 +22,7 @@ export default function Spinner({ color, ...props }: Props) {
|
||||
cx="8"
|
||||
cy="8"
|
||||
r="6"
|
||||
></Circle>
|
||||
/>
|
||||
</SVG>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,23 +7,21 @@ type Props = {
|
||||
color?: string;
|
||||
};
|
||||
|
||||
const Squircle: React.FC<Props> = ({ color, size = 28, children }) => {
|
||||
return (
|
||||
<Wrapper
|
||||
style={{ width: size, height: size }}
|
||||
align="center"
|
||||
justify="center"
|
||||
>
|
||||
<svg width={size} height={size} viewBox="0 0 28 28">
|
||||
<path
|
||||
fill={color}
|
||||
d="M0 11.1776C0 1.97285 1.97285 0 11.1776 0H16.8224C26.0272 0 28 1.97285 28 11.1776V16.8224C28 26.0272 26.0272 28 16.8224 28H11.1776C1.97285 28 0 26.0272 0 16.8224V11.1776Z"
|
||||
/>
|
||||
</svg>
|
||||
<Content>{children}</Content>
|
||||
</Wrapper>
|
||||
);
|
||||
};
|
||||
const Squircle: React.FC<Props> = ({ color, size = 28, children }) => (
|
||||
<Wrapper
|
||||
style={{ width: size, height: size }}
|
||||
align="center"
|
||||
justify="center"
|
||||
>
|
||||
<svg width={size} height={size} viewBox="0 0 28 28">
|
||||
<path
|
||||
fill={color}
|
||||
d="M0 11.1776C0 1.97285 1.97285 0 11.1776 0H16.8224C26.0272 0 28 1.97285 28 11.1776V16.8224C28 26.0272 26.0272 28 16.8224 28H11.1776C1.97285 28 0 26.0272 0 16.8224V11.1776Z"
|
||||
/>
|
||||
</svg>
|
||||
<Content>{children}</Content>
|
||||
</Wrapper>
|
||||
);
|
||||
|
||||
const Wrapper = styled(Flex)`
|
||||
position: relative;
|
||||
|
||||
@@ -34,14 +34,12 @@ const Background = styled.div<{ sticky?: boolean }>`
|
||||
z-index: 1;
|
||||
`;
|
||||
|
||||
const Subheading: React.FC<Props> = ({ children, sticky, ...rest }) => {
|
||||
return (
|
||||
<Background sticky={sticky}>
|
||||
<H3 {...rest}>
|
||||
<Underline>{children}</Underline>
|
||||
</H3>
|
||||
</Background>
|
||||
);
|
||||
};
|
||||
const Subheading: React.FC<Props> = ({ children, sticky, ...rest }) => (
|
||||
<Background sticky={sticky}>
|
||||
<H3 {...rest}>
|
||||
<Underline>{children}</Underline>
|
||||
</H3>
|
||||
</Background>
|
||||
);
|
||||
|
||||
export default Subheading;
|
||||
|
||||
@@ -17,6 +17,7 @@ const TabLink = styled(NavLink)`
|
||||
font-size: 14px;
|
||||
cursor: var(--pointer);
|
||||
color: ${s("textTertiary")};
|
||||
user-select: none;
|
||||
margin-right: 24px;
|
||||
padding: 6px 0;
|
||||
|
||||
|
||||
@@ -195,23 +195,21 @@ export const Placeholder = ({
|
||||
}: {
|
||||
columns: number;
|
||||
rows?: number;
|
||||
}) => {
|
||||
return (
|
||||
<DelayedMount>
|
||||
<tbody>
|
||||
{new Array(rows).fill(1).map((_, row) => (
|
||||
<Row key={row}>
|
||||
{new Array(columns).fill(1).map((_, col) => (
|
||||
<Cell key={col}>
|
||||
<PlaceholderText minWidth={25} maxWidth={75} />
|
||||
</Cell>
|
||||
))}
|
||||
</Row>
|
||||
))}
|
||||
</tbody>
|
||||
</DelayedMount>
|
||||
);
|
||||
};
|
||||
}) => (
|
||||
<DelayedMount>
|
||||
<tbody>
|
||||
{new Array(rows).fill(1).map((_, row) => (
|
||||
<Row key={row}>
|
||||
{new Array(columns).fill(1).map((_, col) => (
|
||||
<Cell key={col}>
|
||||
<PlaceholderText minWidth={25} maxWidth={75} />
|
||||
</Cell>
|
||||
))}
|
||||
</Row>
|
||||
))}
|
||||
</tbody>
|
||||
</DelayedMount>
|
||||
);
|
||||
|
||||
const Anchor = styled.div`
|
||||
top: -32px;
|
||||
|
||||
@@ -61,8 +61,9 @@ function Toast({ closeAfterMs = 3000, onRequestClose, toast }: Props) {
|
||||
{type === "loading" && <Spinner color="currentColor" />}
|
||||
{type === "info" && <InfoIcon color="currentColor" />}
|
||||
{type === "success" && <CheckboxIcon checked color="currentColor" />}
|
||||
{type === "warning" ||
|
||||
(type === "error" && <WarningIcon color="currentColor" />)}
|
||||
{(type === "warning" || type === "error") && (
|
||||
<WarningIcon color="currentColor" />
|
||||
)}
|
||||
<Message>{toast.message}</Message>
|
||||
{action && <Action onClick={action.onClick}>{action.text}</Action>}
|
||||
</Container>
|
||||
|
||||
Reference in New Issue
Block a user