feat: Optional full-width toggle for document display (#2869)

* Migration, model, presenter

* Working implementation

* fix: Account for table of contents

* Checkbox -> Toggle

* Checkbox -> Toggle
This commit is contained in:
Tom Moor
2021-12-19 13:58:16 -08:00
committed by GitHub
parent 73bc7d9f2a
commit 66d5a567c2
18 changed files with 239 additions and 146 deletions

View File

@@ -7,6 +7,7 @@ import useWindowScrollPosition from "~/hooks/useWindowScrollPosition";
const HEADING_OFFSET = 20;
type Props = {
isFullWidth: boolean;
headings: {
title: string;
level: number;
@@ -14,7 +15,7 @@ type Props = {
}[];
};
export default function Contents({ headings }: Props) {
export default function Contents({ headings, isFullWidth }: Props) {
const [activeSlug, setActiveSlug] = React.useState<string>();
const position = useWindowScrollPosition({
throttle: 100,
@@ -49,8 +50,8 @@ export default function Contents({ headings }: Props) {
const headingAdjustment = minHeading - 1;
return (
<div>
<Wrapper>
<Wrapper isFullWidth={isFullWidth}>
<Sticky>
<Heading>Contents</Heading>
{headings.length ? (
<List>
@@ -67,30 +68,38 @@ export default function Contents({ headings }: Props) {
) : (
<Empty>Headings you add to the document will appear here</Empty>
)}
</Wrapper>
</div>
</Sticky>
</Wrapper>
);
}
const Wrapper = styled.div`
const Wrapper = styled.div<{ isFullWidth: boolean }>`
width: 256px;
display: none;
${breakpoint("tablet")`
display: block;
`};
${(props) =>
!props.isFullWidth &&
breakpoint("desktopLarge")`
transform: translateX(-256px);
width: 0;
`}
`;
const Sticky = styled.div`
position: sticky;
top: 80px;
max-height: calc(100vh - 80px);
box-shadow: 1px 0 0 ${(props) => props.theme.divider};
margin-top: 40px;
margin-right: 3.2em;
margin-right: 32px;
width: 224px;
min-height: 40px;
overflow-y: auto;
${breakpoint("desktopLarge")`
margin-left: -16em;
`};
${breakpoint("tablet")`
display: block;
`};
`;
const Heading = styled.h3`

View File

@@ -493,6 +493,7 @@ class DocumentScene extends React.Component<Props> {
archived={document.isArchived}
showContents={showContents}
isEditing={!readOnly}
isFullWidth={document.fullWidth}
column
auto
>
@@ -544,7 +545,12 @@ class DocumentScene extends React.Component<Props> {
)}
<React.Suspense fallback={<PlaceholderDocument />}>
<Flex auto={!readOnly}>
{showContents && <Contents headings={headings} />}
{showContents && (
<Contents
headings={headings}
isFullWidth={document.fullWidth}
/>
)}
<Editor
id={document.id}
key={disableEmbeds ? "disabled" : "enabled"}
@@ -628,6 +634,7 @@ const ReferencesWrapper = styled.div<{ isOnlyTitle?: boolean }>`
type MaxWidthProps = {
isEditing?: boolean;
isFullWidth?: boolean;
archived?: boolean;
showContents?: boolean;
};
@@ -636,22 +643,23 @@ const MaxWidth = styled(Flex)<MaxWidthProps>`
${(props) =>
props.archived && `* { color: ${props.theme.textSecondary} !important; } `};
// Adds space to the gutter to make room for heading annotations on mobile
// Adds space to the gutter to make room for heading annotations
padding: 0 32px;
transition: padding 100ms;
max-width: 100vw;
width: 100%;
${breakpoint("tablet")`
padding: 0 24px;
margin: 4px auto 12px;
max-width: calc(48px + ${(props: MaxWidthProps) =>
props.showContents ? "64em" : "46em"});
max-width: ${(props: MaxWidthProps) =>
props.isFullWidth
? "100vw"
: `calc(64px + 46em + ${props.showContents ? "256px" : "0px"});`}
`};
${breakpoint("desktopLarge")`
max-width: calc(48px + 52em);
max-width: ${(props: MaxWidthProps) =>
props.isFullWidth ? "100vw" : `calc(64px + 52em);`}
`};
`;

View File

@@ -306,7 +306,7 @@ function DocumentHeader({
/>
)}
showToggleEmbeds={canToggleEmbeds}
showPrint
showDisplayOptions
/>
</Action>
</>