Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions packages/shared/src/components/MainLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { SharedFeedPage } from './utilities';
import { isTesting, onboardingUrl } from '../lib/constants';
import { isOnboardingFeedPathname } from '../lib/onboarding';
import { useBanner } from '../hooks/useBanner';
import { useSidebarCompact } from '../hooks/useSidebarCompact';
import { useGrowthBookContext } from './GrowthBookProvider';
import {
ActiveFeedNameContextProvider,
Expand Down Expand Up @@ -109,9 +110,9 @@ function MainLayoutComponent({
const { growthbook } = useGrowthBookContext();
const { sidebarRendered } = useSidebarRendered();
const { isAvailable: isBannerAvailable } = useBanner();
const { sidebarExpanded, autoDismissNotifications, loadedSettings, flags } =
const { sidebarExpanded, autoDismissNotifications, loadedSettings } =
useContext(SettingsContext);
const isSidebarCompact = !!flags?.sidebarCompact;
const { value: isSidebarCompact } = useSidebarCompact();
const v2CollapsedPadding = isSidebarCompact
? 'tablet:pl-16 laptop:pl-16'
: 'tablet:pl-16 laptop:pl-20';
Expand Down
110 changes: 61 additions & 49 deletions packages/shared/src/components/sidebar/SidebarDesktopV2.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ import {
TerminalIcon,
TrendingIcon,
} from '../icons';
import { useSettingsBooleanFlag } from '../../hooks/useSettingsBooleanFlag';
import { useSidebarCompact } from '../../hooks/useSidebarCompact';
import { IconSize } from '../Icon';
import { Tooltip } from '../tooltip/Tooltip';
import { RailHoverPanel } from './RailHoverPanel';
Expand Down Expand Up @@ -729,7 +729,7 @@ export const SidebarDesktopV2 = ({
if (isExtension) {
myFeedPath = `${webappUrl}my-feed`;
}
const { value: isCompact } = useSettingsBooleanFlag('sidebarCompact');
const { value: isCompact } = useSidebarCompact();
// Compact mode reverts to the original icon-only widths (pre-label rail).
// Both width sets are known-good; MainLayout mirrors the collapsed/expanded
// padding so the content never overlaps the rail.
Expand Down Expand Up @@ -2345,60 +2345,72 @@ export const SidebarDesktopV2 = ({
suppressTransition,
)}
>
{/* pl-5 lines the panel title up with the list rows' icon glyphs
(icons sit ~8px into their w-9 column) and the section titles. */}
<div className="pl-5 pr-3 pt-6">
{isSettingsSelected ? (
<Button
type="button"
variant={ButtonVariant.Subtle}
size={ButtonSize.Small}
// Smaller glyph, flipped to point left (it's a back action).
icon={
<MoveToIcon size={IconSize.Size16} className="-scale-x-100" />
}
onClick={onBackToApp}
className="-ml-1"
>
Back to app
</Button>
) : (
<div className="flex h-10 items-center gap-1">
<Typography bold type={TypographyType.Callout}>
{utilityPanelTitle}
</Typography>
</div>
{/* Pinned to the open width so the content does not reflow while
the panel animates its own width. */}
<div
className={classNames(
'flex min-h-0 flex-1 flex-col',
!isSettingsSelected && 'w-60',
)}
</div>

{isLoggedIn && !isUtilityPanelSelected && additionalButtons && (
<div className="mt-2 flex items-center gap-1 px-3">
{additionalButtons}
>
{/* pl-5 lines the panel title up with the list rows' icon glyphs
(icons sit ~8px into their w-9 column) and the section titles. */}
<div className="pl-5 pr-3 pt-6">
{isSettingsSelected ? (
<Button
type="button"
variant={ButtonVariant.Subtle}
size={ButtonSize.Small}
// Smaller glyph, flipped to point left (it's a back action).
icon={
<MoveToIcon
size={IconSize.Size16}
className="-scale-x-100"
/>
}
onClick={onBackToApp}
className="-ml-1"
>
Back to app
</Button>
) : (
<div className="flex h-10 items-center gap-1">
<Typography bold type={TypographyType.Callout}>
{utilityPanelTitle}
</Typography>
</div>
)}
</div>
)}

<SidebarScrollWrapper
className={classNames(
'mt-1 min-h-0 flex-1',
showFeedbackWidget && !isUtilityPanelSelected && 'pb-16',
{isLoggedIn && !isUtilityPanelSelected && additionalButtons && (
<div className="mt-2 flex items-center gap-1 px-3">
{additionalButtons}
</div>
)}
>
<Nav

<SidebarScrollWrapper
className={classNames(
isUtilityPanelSelected ? '!pb-2 !pt-0' : '!pt-0',
isStreakPanel && 'min-h-0 flex-1',
'mt-1 min-h-0 flex-1',
showFeedbackWidget && !isUtilityPanelSelected && 'pb-16',
)}
>
{renderSelectedSection()}
</Nav>
</SidebarScrollWrapper>

{!isUtilityPanelSelected && <HelpWidget sidebarExpanded />}
{showFeedbackWidget && !isUtilityPanelSelected && (
<div className="absolute inset-x-3 bottom-3">
<FeedbackWidget placement="sidebar" />
</div>
)}
<Nav
className={classNames(
isUtilityPanelSelected ? '!pb-2 !pt-0' : '!pt-0',
isStreakPanel && 'min-h-0 flex-1',
)}
>
{renderSelectedSection()}
</Nav>
</SidebarScrollWrapper>

{!isUtilityPanelSelected && <HelpWidget sidebarExpanded />}
{showFeedbackWidget && !isUtilityPanelSelected && (
<div className="absolute inset-x-3 bottom-3">
<FeedbackWidget placement="sidebar" />
</div>
)}
</div>
</section>
</SidebarAside>
</SidebarDragStateProvider>
Expand Down
9 changes: 6 additions & 3 deletions packages/shared/src/hooks/useSettingsBooleanFlag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,18 @@ interface UseSettingsBooleanFlag {

/**
* Reads a boolean flag from `SettingsFlags` and exposes setters that persist
* through the shared `useSettingsContext`. Coerces undefined to `false` so
* callers can use the value directly. Only accepts keys whose value type is
* through the shared `useSettingsContext`. An unset flag falls back to
* `defaultValue`, so a flag that ships on by default stays distinguishable from
* one the user explicitly turned off. Only accepts keys whose value type is
* `boolean | undefined`.
*/
export const useSettingsBooleanFlag = <K extends BooleanFlagKey>(
key: K,
defaultValue = false,
): UseSettingsBooleanFlag => {
const { flags, updateFlag } = useSettingsContext();
const value = Boolean(flags?.[key]);
const stored = flags?.[key];
const value = stored === undefined ? defaultValue : Boolean(stored);
return {
value,
set: (next) => updateFlag(key, next as SettingsFlags[K]),
Expand Down
12 changes: 12 additions & 0 deletions packages/shared/src/hooks/useSidebarCompact.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { useSettingsBooleanFlag } from './useSettingsBooleanFlag';

// The v2 rail ships without the labels under its icons, so an account that
// never touched the density setting gets compact. Only an explicit `false`
// (the user picking Comfortable) brings the labels back.
//
// Read it through here rather than the raw flag: the rail sets its own width
// from this and MainLayout pads the content to match, so the two disagreeing
// would leave the content overlapping the rail or short of it.
export const useSidebarCompact = (): ReturnType<
typeof useSettingsBooleanFlag
> => useSettingsBooleanFlag('sidebarCompact', true);
3 changes: 2 additions & 1 deletion packages/webapp/pages/settings/appearance.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { ThemeSection } from '@dailydotdev/shared/src/components/ProfileMenu/sec
import { useSettingsContext } from '@dailydotdev/shared/src/contexts/SettingsContext';
import { useViewSize, ViewSize } from '@dailydotdev/shared/src/hooks';
import { useSettingsBooleanFlag } from '@dailydotdev/shared/src/hooks/useSettingsBooleanFlag';
import { useSidebarCompact } from '@dailydotdev/shared/src/hooks/useSidebarCompact';
import { useLayoutVariant } from '@dailydotdev/shared/src/hooks/layout/useLayoutVariant';
import { useReaderModalEligibility } from '@dailydotdev/shared/src/components/post/reader/hooks/useReaderModalEligibility';
import { useLegacyPostLayoutOptOut } from '@dailydotdev/shared/src/components/post/reader/hooks/useLegacyPostLayoutOptOut';
Expand Down Expand Up @@ -71,7 +72,7 @@ const AccountManageSubscriptionPage = (): ReactElement => {
flags?.readerInstallPromptAcknowledged ?? false;
const { isV2: isLayoutV2 } = useLayoutVariant();
const { value: isSidebarCompact, toggle: toggleSidebarCompact } =
useSettingsBooleanFlag('sidebarCompact');
useSidebarCompact();
const onToggleReadInside = () => {
if (isReadInsideEnabled) {
optOut();
Expand Down
Loading