From f4348e367da7f2ad85b7680572de69c6bd62e6ff Mon Sep 17 00:00:00 2001
From: Ole-Martin Bratteng <1681525+omBratteng@users.noreply.github.com>
Date: Fri, 23 Jan 2026 17:58:57 +0100
Subject: [PATCH 1/2] feat: add user setting for which default post type to use
---
.../src/components/fields/form/common.tsx | 2 +-
.../freeform/write/WriteFreeFormSkeleton.tsx | 16 +++----
.../post/freeform/write/WritePostHeader.tsx | 2 +-
.../src/components/tabs/TabContainer.tsx | 3 ++
.../shared/src/contexts/SettingsContext.tsx | 2 +
packages/shared/src/graphql/settings.ts | 2 +
packages/webapp/pages/settings/appearance.tsx | 38 +++++++++++++++-
packages/webapp/pages/squads/create.tsx | 45 +++++++++++++++++--
8 files changed, 94 insertions(+), 16 deletions(-)
diff --git a/packages/shared/src/components/fields/form/common.tsx b/packages/shared/src/components/fields/form/common.tsx
index bd3bde5fa5..e01ac0cbb8 100644
--- a/packages/shared/src/components/fields/form/common.tsx
+++ b/packages/shared/src/components/fields/form/common.tsx
@@ -1,6 +1,6 @@
export enum WriteFormTab {
- Share = 'Share a link',
NewPost = 'New post',
+ Share = 'Share a link',
Poll = 'Poll',
}
diff --git a/packages/shared/src/components/post/freeform/write/WriteFreeFormSkeleton.tsx b/packages/shared/src/components/post/freeform/write/WriteFreeFormSkeleton.tsx
index 1ea227b0e8..494830b09e 100644
--- a/packages/shared/src/components/post/freeform/write/WriteFreeFormSkeleton.tsx
+++ b/packages/shared/src/components/post/freeform/write/WriteFreeFormSkeleton.tsx
@@ -14,15 +14,13 @@ export function WriteFreeFormSkeleton({
return (
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
);
diff --git a/packages/shared/src/components/post/freeform/write/WritePostHeader.tsx b/packages/shared/src/components/post/freeform/write/WritePostHeader.tsx
index 463d8f1166..5bee70a90a 100644
--- a/packages/shared/src/components/post/freeform/write/WritePostHeader.tsx
+++ b/packages/shared/src/components/post/freeform/write/WritePostHeader.tsx
@@ -14,7 +14,7 @@ export function WritePostHeader({
const { squad } = useWritePostContext();
return (
-
+
{isEdit ? 'Edit' : 'New'} post
{squad && squad.type === SourceType.Squad && (
diff --git a/packages/shared/src/components/tabs/TabContainer.tsx b/packages/shared/src/components/tabs/TabContainer.tsx
index 7c3cf9a9a0..3fad5ef2aa 100644
--- a/packages/shared/src/components/tabs/TabContainer.tsx
+++ b/packages/shared/src/components/tabs/TabContainer.tsx
@@ -50,6 +50,7 @@ export interface TabContainerProps {
style?: CSSProperties;
tabListProps?: Pick;
tabTag?: AllowedTabTags;
+ extraHeaderContent?: ReactNode;
}
export function TabContainer({
@@ -65,6 +66,7 @@ export function TabContainer({
style,
tabListProps = {},
tabTag,
+ extraHeaderContent,
}: TabContainerProps): ReactElement {
const router = useRouter();
const containerRef = useRef(null);
@@ -168,6 +170,7 @@ export function TabContainer({
autoScrollActive={tabListProps?.autoScrollActive}
tag={tabTag}
/>
+ {extraHeaderContent}
{render}
diff --git a/packages/shared/src/contexts/SettingsContext.tsx b/packages/shared/src/contexts/SettingsContext.tsx
index 065effa84e..bf1e3f8b3a 100644
--- a/packages/shared/src/contexts/SettingsContext.tsx
+++ b/packages/shared/src/contexts/SettingsContext.tsx
@@ -17,6 +17,7 @@ import {
CampaignCtaPlacement,
UPDATE_USER_SETTINGS_MUTATION,
} from '../graphql/settings';
+import { WriteFormTab } from '../components/fields/form/common';
import AuthContext from './AuthContext';
import { capitalize } from '../lib/strings';
import { storageWrapper } from '../lib/storageWrapper';
@@ -136,6 +137,7 @@ const defaultSettings: RemoteSettings = {
sidebarResourcesExpanded: true,
sidebarBookmarksExpanded: true,
clickbaitShieldEnabled: true,
+ defaultWriteTab: WriteFormTab.NewPost,
},
};
diff --git a/packages/shared/src/graphql/settings.ts b/packages/shared/src/graphql/settings.ts
index df5c764025..03862d6b0a 100644
--- a/packages/shared/src/graphql/settings.ts
+++ b/packages/shared/src/graphql/settings.ts
@@ -1,5 +1,6 @@
import { gql } from 'graphql-request';
import type { SortCommentsBy } from './comments';
+import type { WriteFormTab } from '../components/fields/form/common';
export type Spaciness = 'eco' | 'roomy' | 'cozy';
export type RemoteTheme = 'darcula' | 'bright' | 'auto';
@@ -19,6 +20,7 @@ export type SettingsFlags = {
timezoneMismatchIgnore?: string;
prompt?: Record;
lastPrompt?: string;
+ defaultWriteTab?: WriteFormTab;
};
export enum SidebarSettingsFlags {
diff --git a/packages/webapp/pages/settings/appearance.tsx b/packages/webapp/pages/settings/appearance.tsx
index 3a0b6e2169..ea2fdba6e7 100644
--- a/packages/webapp/pages/settings/appearance.tsx
+++ b/packages/webapp/pages/settings/appearance.tsx
@@ -10,6 +10,7 @@ import {
TypographyColor,
TypographyType,
} from '@dailydotdev/shared/src/components/typography/Typography';
+import type { RadioItemProps } from '@dailydotdev/shared/src/components/fields/Radio';
import { Radio } from '@dailydotdev/shared/src/components/fields/Radio';
import { ToggleRadio } from '@dailydotdev/shared/src/components/fields/ToggleRadio';
import { useLogContext } from '@dailydotdev/shared/src/contexts/LogContext';
@@ -18,19 +19,28 @@ import {
TargetId,
TargetType,
} from '@dailydotdev/shared/src/lib/log';
+import { WriteFormTab } from '@dailydotdev/shared/src/components/fields/form/common';
import classNames from 'classnames';
+import { Divider } from '@dailydotdev/shared/src/components/utilities';
import { AccountPageContainer } from '../../components/layouts/SettingsLayout/AccountPageContainer';
import { getSettingsLayout } from '../../components/layouts/SettingsLayout';
import { defaultSeo } from '../../next-seo';
import { getTemplatedTitle } from '../../components/layouts/utils';
import { SettingsSwitch } from '../../components/layouts/SettingsLayout/common';
-const densities = [
+const densities: RadioItemProps[] = [
{ label: 'Eco', value: 'eco' },
{ label: 'Roomy', value: 'roomy' },
{ label: 'Cozy', value: 'cozy' },
];
+const defaultWriteTabs: RadioItemProps[] = Object.keys(WriteFormTab).map(
+ (key) => ({
+ label: WriteFormTab[key],
+ value: key,
+ }),
+);
+
const AccountManageSubscriptionPage = (): ReactElement => {
const isLaptop = useViewSize(ViewSize.Laptop);
const { logEvent } = useLogContext();
@@ -48,6 +58,8 @@ const AccountManageSubscriptionPage = (): ReactElement => {
toggleOptOutCompanion,
autoDismissNotifications,
toggleAutoDismissNotifications,
+ updateFlag,
+ flags,
} = useSettingsContext();
const onLayoutToggle = useCallback(
@@ -164,6 +176,30 @@ const AccountManageSubscriptionPage = (): ReactElement => {
Auto-hide notifications after a few seconds
+
+
+
+
+
+
+ Default post type
+
+
+ {
+ updateFlag('defaultWriteTab', value);
+ }}
+ className={{
+ content: 'w-full justify-between !pr-0',
+ container: '!gap-0',
+ label: 'font-normal text-text-secondary typo-callout',
+ }}
+ reverse
+ />
+
);
diff --git a/packages/webapp/pages/squads/create.tsx b/packages/webapp/pages/squads/create.tsx
index 78c3a05574..1756df3946 100644
--- a/packages/webapp/pages/squads/create.tsx
+++ b/packages/webapp/pages/squads/create.tsx
@@ -36,11 +36,19 @@ import { useQueryClient } from '@tanstack/react-query';
import CreatePoll from '@dailydotdev/shared/src/components/post/poll/CreatePoll';
import { Pill, PillSize } from '@dailydotdev/shared/src/components/Pill';
import { useMultipleSourcePost } from '@dailydotdev/shared/src/features/squads/hooks/useMultipleSourcePost';
-import { webappUrl } from '@dailydotdev/shared/src/lib/constants';
+import { settingsUrl, webappUrl } from '@dailydotdev/shared/src/lib/constants';
import type { WriteForm } from '@dailydotdev/shared/src/contexts';
-import { getLayout as getMainLayout } from '../../components/layouts/MainLayout';
-import { defaultOpenGraph, defaultSeo } from '../../next-seo';
+import { useSettingsContext } from '@dailydotdev/shared/src/contexts/SettingsContext';
+
+import {
+ Button,
+ ButtonSize,
+} from '@dailydotdev/shared/src/components/buttons/Button';
+import { SettingsIcon } from '@dailydotdev/shared/src/components/icons';
+import { LinkWithTooltip } from '@dailydotdev/shared/src/components/tooltips/LinkWithTooltip';
import { getTemplatedTitle } from '../../components/layouts/utils';
+import { defaultOpenGraph, defaultSeo } from '../../next-seo';
+import { getLayout as getMainLayout } from '../../components/layouts/MainLayout';
const seo: NextSeoProps = {
title: getTemplatedTitle('Create post'),
@@ -59,6 +67,10 @@ function CreatePost(): ReactElement {
);
const { push, isReady: isRouteReady, query } = useRouter();
const { squads, user, isAuthReady, isFetched } = useAuthContext();
+ const {
+ flags: { defaultWriteTab },
+ loadedSettings,
+ } = useSettingsContext();
const [selectedSourceIds, setSelectedSourceIds] = useState([]);
const activeSquads = useMemo(() => {
const collator = new Intl.Collator('en');
@@ -191,6 +203,8 @@ function CreatePost(): ReactElement {
setDisplay(WriteFormTab.Share);
} else if (isInitialPoll) {
setDisplay(WriteFormTab.Poll);
+ } else if (defaultWriteTab in WriteFormTab) {
+ setDisplay(WriteFormTab[defaultWriteTab]);
}
const preselectedSquad =
@@ -220,6 +234,7 @@ function CreatePost(): ReactElement {
activeSquads,
selectedSourceIds.length,
query,
+ defaultWriteTab,
]);
useEffect(() => {
@@ -228,7 +243,7 @@ function CreatePost(): ReactElement {
}
}, [display, hasCheckedPollTab, completeAction]);
- if (!isFetched || !isAuthReady || !isRouteReady) {
+ if (!isFetched || !isAuthReady || !isRouteReady || !loadedSettings) {
return ;
}
@@ -255,6 +270,28 @@ function CreatePost(): ReactElement {
shouldMountInactive
className={{ header: 'px-1' }}
showHeader={isTablet}
+ extraHeaderContent={
+ !isMobile && (
+
+ You can change the default post type settings
+
+ ),
+ placement: 'left',
+ }}
+ href={`${settingsUrl}/appearance#compose`}
+ passHref
+ >
+ }
+ size={ButtonSize.Small}
+ className="ml-auto mr-3 self-center text-text-quaternary"
+ />
+
+ )
+ }
>
Date: Fri, 23 Jan 2026 18:53:35 +0100
Subject: [PATCH 2/2] refactor: split to new settings page
---
.../profile/ProfileSettingsMenu.tsx | 6 ++
packages/webapp/pages/settings/appearance.tsx | 56 ++++------------
.../webapp/pages/settings/composition.tsx | 65 +++++++++++++++++++
packages/webapp/pages/squads/create.tsx | 2 +-
4 files changed, 83 insertions(+), 46 deletions(-)
create mode 100644 packages/webapp/pages/settings/composition.tsx
diff --git a/packages/shared/src/components/profile/ProfileSettingsMenu.tsx b/packages/shared/src/components/profile/ProfileSettingsMenu.tsx
index c290c4125a..57a43eb39d 100644
--- a/packages/shared/src/components/profile/ProfileSettingsMenu.tsx
+++ b/packages/shared/src/components/profile/ProfileSettingsMenu.tsx
@@ -31,6 +31,7 @@ import {
JobIcon,
TerminalIcon,
TourIcon,
+ FeatherIcon,
} from '../icons';
import { NavDrawer } from '../drawers/NavDrawer';
import {
@@ -112,6 +113,11 @@ const useAccountPageItems = () => {
icon: NewTabIcon,
href: `${settingsUrl}/appearance`,
},
+ composition: {
+ title: 'Composition',
+ icon: FeatherIcon,
+ href: `${settingsUrl}/composition`,
+ },
notifications: {
title: 'Notifications',
icon: BellIcon,
diff --git a/packages/webapp/pages/settings/appearance.tsx b/packages/webapp/pages/settings/appearance.tsx
index ea2fdba6e7..efc58501f7 100644
--- a/packages/webapp/pages/settings/appearance.tsx
+++ b/packages/webapp/pages/settings/appearance.tsx
@@ -19,9 +19,8 @@ import {
TargetId,
TargetType,
} from '@dailydotdev/shared/src/lib/log';
-import { WriteFormTab } from '@dailydotdev/shared/src/components/fields/form/common';
import classNames from 'classnames';
-import { Divider } from '@dailydotdev/shared/src/components/utilities';
+import { FlexCol } from '@dailydotdev/shared/src/components/utilities';
import { AccountPageContainer } from '../../components/layouts/SettingsLayout/AccountPageContainer';
import { getSettingsLayout } from '../../components/layouts/SettingsLayout';
import { defaultSeo } from '../../next-seo';
@@ -34,13 +33,6 @@ const densities: RadioItemProps[] = [
{ label: 'Cozy', value: 'cozy' },
];
-const defaultWriteTabs: RadioItemProps[] = Object.keys(WriteFormTab).map(
- (key) => ({
- label: WriteFormTab[key],
- value: key,
- }),
-);
-
const AccountManageSubscriptionPage = (): ReactElement => {
const isLaptop = useViewSize(ViewSize.Laptop);
const { logEvent } = useLogContext();
@@ -58,8 +50,6 @@ const AccountManageSubscriptionPage = (): ReactElement => {
toggleOptOutCompanion,
autoDismissNotifications,
toggleAutoDismissNotifications,
- updateFlag,
- flags,
} = useSettingsContext();
const onLayoutToggle = useCallback(
@@ -76,11 +66,11 @@ const AccountManageSubscriptionPage = (): ReactElement => {
return (
-
+
{isLaptop && (
-
+
Layout
@@ -98,10 +88,10 @@ const AccountManageSubscriptionPage = (): ReactElement => {
offLabel="Cards"
onLabel="List"
/>
-
+
)}
-
+
Density
@@ -131,9 +121,9 @@ const AccountManageSubscriptionPage = (): ReactElement => {
}}
reverse
/>
-
+
-
+
Preferences
@@ -161,9 +151,9 @@ const AccountManageSubscriptionPage = (): ReactElement => {
>
Show companion widget on external sites
-
+
-
+
Accessibility
@@ -175,32 +165,8 @@ const AccountManageSubscriptionPage = (): ReactElement => {
>
Auto-hide notifications after a few seconds
-
-
-
-
-
-
-
- Default post type
-
-
- {
- updateFlag('defaultWriteTab', value);
- }}
- className={{
- content: 'w-full justify-between !pr-0',
- container: '!gap-0',
- label: 'font-normal text-text-secondary typo-callout',
- }}
- reverse
- />
-
-
+
+
);
};
diff --git a/packages/webapp/pages/settings/composition.tsx b/packages/webapp/pages/settings/composition.tsx
new file mode 100644
index 0000000000..419fefa50d
--- /dev/null
+++ b/packages/webapp/pages/settings/composition.tsx
@@ -0,0 +1,65 @@
+import React from 'react';
+import type { ReactElement } from 'react';
+import type { NextSeoProps } from 'next-seo';
+
+import { useSettingsContext } from '@dailydotdev/shared/src/contexts/SettingsContext';
+import {
+ Typography,
+ TypographyType,
+} from '@dailydotdev/shared/src/components/typography/Typography';
+import type { RadioItemProps } from '@dailydotdev/shared/src/components/fields/Radio';
+import { Radio } from '@dailydotdev/shared/src/components/fields/Radio';
+
+import { WriteFormTab } from '@dailydotdev/shared/src/components/fields/form/common';
+import { FlexCol } from '@dailydotdev/shared/src/components/utilities';
+import { AccountPageContainer } from '../../components/layouts/SettingsLayout/AccountPageContainer';
+import { getSettingsLayout } from '../../components/layouts/SettingsLayout';
+import { defaultSeo } from '../../next-seo';
+import { getTemplatedTitle } from '../../components/layouts/utils';
+
+const defaultWriteTabs: RadioItemProps[] = Object.keys(WriteFormTab).map(
+ (key) => ({
+ label: WriteFormTab[key],
+ value: key,
+ }),
+);
+
+const AccountManageSubscriptionPage = (): ReactElement => {
+ const { updateFlag, flags } = useSettingsContext();
+
+ return (
+
+
+
+
+ Default post type
+
+
+ {
+ updateFlag('defaultWriteTab', value);
+ }}
+ className={{
+ content: 'w-full justify-between !pr-0',
+ container: '!gap-0',
+ label: 'font-normal text-text-secondary typo-callout',
+ }}
+ reverse
+ />
+
+
+ );
+};
+
+const seo: NextSeoProps = {
+ ...defaultSeo,
+ title: getTemplatedTitle('Appearance'),
+};
+
+AccountManageSubscriptionPage.getLayout = getSettingsLayout;
+AccountManageSubscriptionPage.layoutProps = { seo };
+
+export default AccountManageSubscriptionPage;
diff --git a/packages/webapp/pages/squads/create.tsx b/packages/webapp/pages/squads/create.tsx
index 1756df3946..a09b15795b 100644
--- a/packages/webapp/pages/squads/create.tsx
+++ b/packages/webapp/pages/squads/create.tsx
@@ -281,7 +281,7 @@ function CreatePost(): ReactElement {
),
placement: 'left',
}}
- href={`${settingsUrl}/appearance#compose`}
+ href={`${settingsUrl}/composition`}
passHref
>