- {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. */}
+
diff --git a/packages/shared/src/hooks/useSettingsBooleanFlag.ts b/packages/shared/src/hooks/useSettingsBooleanFlag.ts
index e3ab0b60be..547505e575 100644
--- a/packages/shared/src/hooks/useSettingsBooleanFlag.ts
+++ b/packages/shared/src/hooks/useSettingsBooleanFlag.ts
@@ -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 = (
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]),
diff --git a/packages/shared/src/hooks/useSidebarCompact.ts b/packages/shared/src/hooks/useSidebarCompact.ts
new file mode 100644
index 0000000000..c07795a3aa
--- /dev/null
+++ b/packages/shared/src/hooks/useSidebarCompact.ts
@@ -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);
diff --git a/packages/webapp/pages/settings/appearance.tsx b/packages/webapp/pages/settings/appearance.tsx
index c2a37e05ac..9e3ab546ac 100644
--- a/packages/webapp/pages/settings/appearance.tsx
+++ b/packages/webapp/pages/settings/appearance.tsx
@@ -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';
@@ -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();