Skip to content

Conversation

@lucasheriques
Copy link
Contributor

@lucasheriques lucasheriques commented Dec 17, 2025

Problem

Survey appearance customization needs improvement to ensure consistent text contrast across different elements, particularly for rating buttons and text inputs.

Changes

  • Added support for consistent text color handling in surveys:
    • Rating button text now uses the same color as input text
    • Primary text color can be explicitly set or auto-calculated based on background
    • Active rating text color is always auto-calculated for proper contrast

Implemented the changes for both React Native and Web (posthog-js) and now began sharing more fields between them too.

Release info Sub-libraries affected

Libraries affected

  • posthog-js (web)
  • posthog-react-native

Checklist

  • Tests for new code
  • Accounted for the impact of any changes across different platforms
  • Accounted for backwards compatibility of any changes (no breaking changes!)
  • Took care not to unnecessarily increase the bundle size

If releasing new changes

  • Ran pnpm changeset to generate a changeset file
  • Added the "release" label to the PR to indicate we're publishing new versions for the affected packages

@vercel
Copy link

vercel bot commented Dec 17, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
posthog-js Error Error Dec 18, 2025 9:54pm
posthog-nextjs-config Ready Ready Preview Dec 18, 2025 9:54pm

Copy link
Contributor Author

This stack of pull requests is managed by Graphite. Learn more about stacking.

@lucasheriques lucasheriques requested a review from a team December 17, 2025 22:04
@lucasheriques lucasheriques marked this pull request as ready for review December 17, 2025 22:04
@lucasheriques lucasheriques force-pushed the feat/allow-customizing-text-color-on-surveys branch from 77ac12e to f1a534d Compare December 17, 2025 22:04
@github-actions
Copy link
Contributor

github-actions bot commented Dec 17, 2025

@github-actions
Copy link
Contributor

github-actions bot commented Dec 17, 2025

Size Change: +715 B (+0.01%)

Total Size: 5.3 MB

Filename Size Change
packages/browser/dist/all-external-dependencies.js 229 kB +26 B (+0.01%)
packages/browser/dist/array.full.es5.js 306 kB +26 B (+0.01%)
packages/browser/dist/array.full.js 375 kB +26 B (+0.01%)
packages/browser/dist/array.full.no-external.js 390 kB +26 B (+0.01%)
packages/browser/dist/module.full.js 375 kB +26 B (+0.01%)
packages/browser/dist/module.full.no-external.js 391 kB +26 B (+0.01%)
packages/browser/dist/surveys-preview.js 72.9 kB +26 B (+0.04%)
packages/browser/dist/surveys.js 85.2 kB +26 B (+0.03%)
packages/react-native/dist/surveys/components/QuestionHeader.js 1.37 kB +56 B (+4.27%)
packages/react-native/dist/surveys/components/QuestionTypes.js 11.3 kB +451 B (+4.14%)
ℹ️ View Unchanged
Filename Size Change
packages/ai/dist/anthropic/index.cjs 17.8 kB 0 B
packages/ai/dist/anthropic/index.mjs 17.6 kB 0 B
packages/ai/dist/gemini/index.cjs 23.4 kB 0 B
packages/ai/dist/gemini/index.mjs 23.2 kB 0 B
packages/ai/dist/index.cjs 140 kB 0 B
packages/ai/dist/index.mjs 140 kB 0 B
packages/ai/dist/langchain/index.cjs 41.2 kB 0 B
packages/ai/dist/langchain/index.mjs 40.7 kB 0 B
packages/ai/dist/openai/index.cjs 42.3 kB 0 B
packages/ai/dist/openai/index.mjs 42 kB 0 B
packages/ai/dist/vercel/index.cjs 30 kB 0 B
packages/ai/dist/vercel/index.mjs 30 kB 0 B
packages/browser/dist/array.js 169 kB 0 B
packages/browser/dist/array.no-external.js 182 kB 0 B
packages/browser/dist/conversations.js 37.6 kB 0 B
packages/browser/dist/crisp-chat-integration.js 2.11 kB 0 B
packages/browser/dist/customizations.full.js 19.1 kB 0 B
packages/browser/dist/dead-clicks-autocapture.js 13.1 kB 0 B
packages/browser/dist/exception-autocapture.js 11.8 kB 0 B
packages/browser/dist/external-scripts-loader.js 2.95 kB 0 B
packages/browser/dist/intercom-integration.js 2.16 kB 0 B
packages/browser/dist/lazy-recorder.js 150 kB 0 B
packages/browser/dist/main.js 170 kB 0 B
packages/browser/dist/module.js 170 kB 0 B
packages/browser/dist/module.no-external.js 183 kB 0 B
packages/browser/dist/posthog-recorder.js 247 kB 0 B
packages/browser/dist/product-tours.js 61 kB 0 B
packages/browser/dist/recorder-v2.js 113 kB 0 B
packages/browser/dist/recorder.js 113 kB 0 B
packages/browser/dist/tracing-headers.js 1.93 kB 0 B
packages/browser/dist/web-vitals.js 10.5 kB 0 B
packages/browser/react/dist/esm/index.js 19.3 kB 0 B
packages/browser/react/dist/umd/index.js 22.4 kB 0 B
packages/core/dist/error-tracking/chunk-ids.js 2.54 kB 0 B
packages/core/dist/error-tracking/chunk-ids.mjs 1.31 kB 0 B
packages/core/dist/error-tracking/coercers/dom-exception-coercer.js 2.3 kB 0 B
packages/core/dist/error-tracking/coercers/dom-exception-coercer.mjs 993 B 0 B
packages/core/dist/error-tracking/coercers/error-coercer.js 2.02 kB 0 B
packages/core/dist/error-tracking/coercers/error-coercer.mjs 794 B 0 B
packages/core/dist/error-tracking/coercers/error-event-coercer.js 1.76 kB 0 B
packages/core/dist/error-tracking/coercers/error-event-coercer.mjs 513 B 0 B
packages/core/dist/error-tracking/coercers/event-coercer.js 1.82 kB 0 B
packages/core/dist/error-tracking/coercers/event-coercer.mjs 548 B 0 B
packages/core/dist/error-tracking/coercers/index.js 6.79 kB 0 B
packages/core/dist/error-tracking/coercers/index.mjs 326 B 0 B
packages/core/dist/error-tracking/coercers/object-coercer.js 3.46 kB 0 B
packages/core/dist/error-tracking/coercers/object-coercer.mjs 2.07 kB 0 B
packages/core/dist/error-tracking/coercers/primitive-coercer.js 1.67 kB 0 B
packages/core/dist/error-tracking/coercers/primitive-coercer.mjs 419 B 0 B
packages/core/dist/error-tracking/coercers/promise-rejection-event.js 2.25 kB 0 B
packages/core/dist/error-tracking/coercers/promise-rejection-event.mjs 904 B 0 B
packages/core/dist/error-tracking/coercers/string-coercer.js 2.01 kB 0 B
packages/core/dist/error-tracking/coercers/string-coercer.mjs 820 B 0 B
packages/core/dist/error-tracking/coercers/utils.js 2.06 kB 0 B
packages/core/dist/error-tracking/coercers/utils.mjs 716 B 0 B
packages/core/dist/error-tracking/error-properties-builder.js 5.49 kB 0 B
packages/core/dist/error-tracking/error-properties-builder.mjs 4.15 kB 0 B
packages/core/dist/error-tracking/index.js 4.11 kB 0 B
packages/core/dist/error-tracking/index.mjs 152 B 0 B
packages/core/dist/error-tracking/parsers/base.js 1.83 kB 0 B
packages/core/dist/error-tracking/parsers/base.mjs 464 B 0 B
packages/core/dist/error-tracking/parsers/chrome.js 2.73 kB 0 B
packages/core/dist/error-tracking/parsers/chrome.mjs 1.32 kB 0 B
packages/core/dist/error-tracking/parsers/gecko.js 2.47 kB 0 B
packages/core/dist/error-tracking/parsers/gecko.mjs 1.13 kB 0 B
packages/core/dist/error-tracking/parsers/index.js 4.38 kB 0 B
packages/core/dist/error-tracking/parsers/index.mjs 1.94 kB 0 B
packages/core/dist/error-tracking/parsers/node.js 3.94 kB 0 B
packages/core/dist/error-tracking/parsers/node.mjs 2.68 kB 0 B
packages/core/dist/error-tracking/parsers/opera.js 2.26 kB 0 B
packages/core/dist/error-tracking/parsers/opera.mjs 746 B 0 B
packages/core/dist/error-tracking/parsers/safari.js 1.88 kB 0 B
packages/core/dist/error-tracking/parsers/safari.mjs 574 B 0 B
packages/core/dist/error-tracking/parsers/winjs.js 1.72 kB 0 B
packages/core/dist/error-tracking/parsers/winjs.mjs 426 B 0 B
packages/core/dist/error-tracking/types.js 1.33 kB 0 B
packages/core/dist/error-tracking/types.mjs 131 B 0 B
packages/core/dist/error-tracking/utils.js 1.8 kB 0 B
packages/core/dist/error-tracking/utils.mjs 604 B 0 B
packages/core/dist/eventemitter.js 1.78 kB 0 B
packages/core/dist/eventemitter.mjs 571 B 0 B
packages/core/dist/featureFlagUtils.js 6.5 kB 0 B
packages/core/dist/featureFlagUtils.mjs 4.28 kB 0 B
packages/core/dist/gzip.js 1.88 kB 0 B
packages/core/dist/gzip.mjs 577 B 0 B
packages/core/dist/index.js 5.7 kB 0 B
packages/core/dist/index.mjs 485 B 0 B
packages/core/dist/posthog-core-stateless.js 29.7 kB 0 B
packages/core/dist/posthog-core-stateless.mjs 27.2 kB 0 B
packages/core/dist/posthog-core.js 28.2 kB 0 B
packages/core/dist/posthog-core.mjs 24 kB 0 B
packages/core/dist/process/index.js 2.77 kB 0 B
packages/core/dist/process/index.mjs 114 B 0 B
packages/core/dist/process/spawn-local.js 1.82 kB 0 B
packages/core/dist/process/spawn-local.mjs 568 B 0 B
packages/core/dist/process/utils.js 3.12 kB 0 B
packages/core/dist/process/utils.mjs 1.15 kB 0 B
packages/core/dist/testing/index.js 2.93 kB 0 B
packages/core/dist/testing/index.mjs 79 B 0 B
packages/core/dist/testing/PostHogCoreTestClient.js 3.15 kB 0 B
packages/core/dist/testing/PostHogCoreTestClient.mjs 1.74 kB 0 B
packages/core/dist/testing/test-utils.js 2.77 kB 0 B
packages/core/dist/testing/test-utils.mjs 1.09 kB 0 B
packages/core/dist/types.js 8.2 kB 0 B
packages/core/dist/types.mjs 5.93 kB 0 B
packages/core/dist/utils/bot-detection.js 3.28 kB 0 B
packages/core/dist/utils/bot-detection.mjs 1.95 kB 0 B
packages/core/dist/utils/bucketed-rate-limiter.js 3 kB 0 B
packages/core/dist/utils/bucketed-rate-limiter.mjs 1.62 kB 0 B
packages/core/dist/utils/index.js 11.9 kB 0 B
packages/core/dist/utils/index.mjs 1.98 kB 0 B
packages/core/dist/utils/logger.js 2.5 kB 0 B
packages/core/dist/utils/logger.mjs 1.22 kB 0 B
packages/core/dist/utils/number-utils.js 2 kB 0 B
packages/core/dist/utils/number-utils.mjs 735 B 0 B
packages/core/dist/utils/promise-queue.js 2 kB 0 B
packages/core/dist/utils/promise-queue.mjs 768 B 0 B
packages/core/dist/utils/string-utils.js 1.91 kB 0 B
packages/core/dist/utils/string-utils.mjs 414 B 0 B
packages/core/dist/utils/type-utils.js 6.93 kB 0 B
packages/core/dist/utils/type-utils.mjs 3.03 kB 0 B
packages/core/dist/utils/user-agent-utils.js 14.9 kB 0 B
packages/core/dist/utils/user-agent-utils.mjs 11.9 kB 0 B
packages/core/dist/vendor/uuidv7.js 8.29 kB 0 B
packages/core/dist/vendor/uuidv7.mjs 6.72 kB 0 B
packages/nextjs-config/dist/config.js 4.97 kB 0 B
packages/nextjs-config/dist/config.mjs 3.48 kB 0 B
packages/nextjs-config/dist/index.js 2.24 kB 0 B
packages/nextjs-config/dist/index.mjs 30 B 0 B
packages/nextjs-config/dist/utils.js 3.83 kB 0 B
packages/nextjs-config/dist/utils.mjs 1.72 kB 0 B
packages/node/dist/client.js 25.3 kB 0 B
packages/node/dist/client.mjs 23.3 kB 0 B
packages/node/dist/entrypoints/index.edge.js 4.25 kB 0 B
packages/node/dist/entrypoints/index.edge.mjs 723 B 0 B
packages/node/dist/entrypoints/index.node.js 5.55 kB 0 B
packages/node/dist/entrypoints/index.node.mjs 1.08 kB 0 B
packages/node/dist/experimental.js 603 B 0 B
packages/node/dist/experimental.mjs 0 B 0 B 🆕
packages/node/dist/exports.js 3.6 kB 0 B
packages/node/dist/exports.mjs 124 B 0 B
packages/node/dist/extensions/context/context.js 2.12 kB 0 B
packages/node/dist/extensions/context/context.mjs 862 B 0 B
packages/node/dist/extensions/context/types.js 603 B 0 B
packages/node/dist/extensions/context/types.mjs 0 B 0 B 🆕
packages/node/dist/extensions/error-tracking/autocapture.js 2.66 kB 0 B
packages/node/dist/extensions/error-tracking/autocapture.mjs 1.24 kB 0 B
packages/node/dist/extensions/error-tracking/index.js 3.88 kB 0 B
packages/node/dist/extensions/error-tracking/index.mjs 2.61 kB 0 B
packages/node/dist/extensions/error-tracking/modifiers/context-lines.node.js 8.81 kB 0 B
packages/node/dist/extensions/error-tracking/modifiers/context-lines.node.mjs 7.15 kB 0 B
packages/node/dist/extensions/error-tracking/modifiers/module.node.js 2.78 kB 0 B
packages/node/dist/extensions/error-tracking/modifiers/module.node.mjs 1.45 kB 0 B
packages/node/dist/extensions/express.js 2.75 kB 0 B
packages/node/dist/extensions/express.mjs 1.16 kB 0 B
packages/node/dist/extensions/feature-flags/cache.js 603 B 0 B
packages/node/dist/extensions/feature-flags/cache.mjs 0 B 0 B 🆕
packages/node/dist/extensions/feature-flags/crypto.js 1.57 kB 0 B
packages/node/dist/extensions/feature-flags/crypto.mjs 395 B 0 B
packages/node/dist/extensions/feature-flags/feature-flags.js 30.9 kB 0 B
packages/node/dist/extensions/feature-flags/feature-flags.mjs 28.9 kB 0 B
packages/node/dist/extensions/sentry-integration.js 4.66 kB 0 B
packages/node/dist/extensions/sentry-integration.mjs 3.17 kB 0 B
packages/node/dist/storage-memory.js 1.52 kB 0 B
packages/node/dist/storage-memory.mjs 297 B 0 B
packages/node/dist/types.js 1.43 kB 0 B
packages/node/dist/types.mjs 224 B 0 B
packages/node/dist/version.js 1.21 kB 0 B
packages/node/dist/version.mjs 46 B 0 B
packages/nuxt/dist/module.mjs 4.27 kB 0 B
packages/nuxt/dist/runtime/composables/useFeatureFlagEnabled.js 566 B 0 B
packages/nuxt/dist/runtime/composables/useFeatureFlagPayload.js 597 B 0 B
packages/nuxt/dist/runtime/composables/useFeatureFlagVariantKey.js 591 B 0 B
packages/nuxt/dist/runtime/composables/usePostHog.js 128 B 0 B
packages/nuxt/dist/runtime/nitro-plugin.js 1.08 kB 0 B
packages/nuxt/dist/runtime/vue-plugin.js 1.14 kB 0 B
packages/react-native/dist/autocapture.js 5.05 kB 0 B
packages/react-native/dist/error-tracking/index.js 6.77 kB 0 B
packages/react-native/dist/error-tracking/utils.js 2.58 kB 0 B
packages/react-native/dist/frameworks/wix-navigation.js 1.3 kB 0 B
packages/react-native/dist/hooks/useFeatureFlag.js 1.49 kB 0 B
packages/react-native/dist/hooks/useFeatureFlags.js 821 B 0 B
packages/react-native/dist/hooks/useNavigationTracker.js 2.46 kB 0 B
packages/react-native/dist/hooks/usePostHog.js 467 B 0 B
packages/react-native/dist/index.js 3.12 kB 0 B
packages/react-native/dist/native-deps.js 8.05 kB 0 B
packages/react-native/dist/optional/OptionalAsyncStorage.js 299 B 0 B
packages/react-native/dist/optional/OptionalExpoApplication.js 377 B 0 B
packages/react-native/dist/optional/OptionalExpoDevice.js 347 B 0 B
packages/react-native/dist/optional/OptionalExpoFileSystem.js 386 B 0 B
packages/react-native/dist/optional/OptionalExpoFileSystemLegacy.js 423 B 0 B
packages/react-native/dist/optional/OptionalExpoLocalization.js 383 B 0 B
packages/react-native/dist/optional/OptionalReactNativeDeviceInfo.js 415 B 0 B
packages/react-native/dist/optional/OptionalReactNativeLocalize.js 303 B 0 B
packages/react-native/dist/optional/OptionalReactNativeNavigation.js 415 B 0 B
packages/react-native/dist/optional/OptionalReactNativeNavigationWix.js 443 B 0 B
packages/react-native/dist/optional/OptionalReactNativeSafeArea.js 644 B 0 B
packages/react-native/dist/optional/OptionalSessionReplay.js 455 B 0 B
packages/react-native/dist/posthog-rn.js 30.4 kB 0 B
packages/react-native/dist/PostHogContext.js 329 B 0 B
packages/react-native/dist/PostHogProvider.js 4.77 kB 0 B
packages/react-native/dist/storage.js 3.39 kB 0 B
packages/react-native/dist/surveys/components/BottomSection.js 1.34 kB 0 B
packages/react-native/dist/surveys/components/Cancel.js 909 B 0 B
packages/react-native/dist/surveys/components/ConfirmationMessage.js 1.65 kB 0 B
packages/react-native/dist/surveys/components/SurveyModal.js 3.86 kB 0 B
packages/react-native/dist/surveys/components/Surveys.js 7.22 kB 0 B
packages/react-native/dist/surveys/getActiveMatchingSurveys.js 2.64 kB 0 B
packages/react-native/dist/surveys/icons.js 7.76 kB 0 B
packages/react-native/dist/surveys/index.js 600 B 0 B
packages/react-native/dist/surveys/PostHogSurveyProvider.js 5.66 kB 0 B
packages/react-native/dist/surveys/surveys-utils.js 12.7 kB 0 B
packages/react-native/dist/surveys/useActivatedSurveys.js 3.67 kB 0 B
packages/react-native/dist/surveys/useSurveyStorage.js 2.16 kB 0 B
packages/react-native/dist/tooling/expoconfig.js 2.63 kB 0 B
packages/react-native/dist/tooling/metroconfig.js 2.2 kB 0 B
packages/react-native/dist/tooling/posthogMetroSerializer.js 4.78 kB 0 B
packages/react-native/dist/tooling/utils.js 4.05 kB 0 B
packages/react-native/dist/tooling/vendor/expo/expoconfig.js 70 B 0 B
packages/react-native/dist/tooling/vendor/metro/countLines.js 237 B 0 B
packages/react-native/dist/tooling/vendor/metro/utils.js 3.35 kB 0 B
packages/react-native/dist/types.js 70 B 0 B
packages/react-native/dist/utils.js 539 B 0 B
packages/react-native/dist/version.js 130 B 0 B
packages/react/dist/esm/index.js 19.3 kB 0 B
packages/react/dist/umd/index.js 22.4 kB 0 B
packages/rollup-plugin/dist/index.js 3.45 kB 0 B
packages/web/dist/index.cjs 13.8 kB 0 B
packages/web/dist/index.mjs 13.7 kB 0 B
packages/webpack-plugin/dist/config.js 2.65 kB 0 B
packages/webpack-plugin/dist/config.mjs 1.64 kB 0 B
packages/webpack-plugin/dist/index.js 6.38 kB 0 B
packages/webpack-plugin/dist/index.mjs 2.96 kB 0 B
tooling/changelog/dist/index.js 3.31 kB 0 B
tooling/rollup-utils/dist/index.js 1.17 kB 0 B

compressed-size-action

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there are many tests here and some of them repeated, so i'm consolidating them a little

// keep in sync with frontend/src/types.ts -> SurveyAppearance
backgroundColor?: string
// Optional override for main survey text color. If not set, auto-calculated from backgroundColor.
textColor?: string
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will now exist on the rn sdk types, so we should still document somewhere that it doesn't work on react-native (until we update it)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the implementation is a part of the PR, not sure if you saw it before the update, can you double check?

placeholder={appearance.placeholder}
placeholderTextColor={
getContrastingTextColor(appearance.inputBackground) === 'black'
(appearance.inputTextColor ?? getContrastingTextColor(appearance.inputBackground)) === 'black'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would be white if inputTextColor is anything other than black right? Doesn't seem right

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Case Result
No inputTextColor, light bg → 'black' → needs 'white' contrast dark placeholder ✓
No inputTextColor, dark bg → 'white' → needs 'black' contrast light placeholder ✓
inputTextColor = 'black' → needs 'white' contrast dark placeholder ✓
inputTextColor = '#000000' → needs 'white' contrast dark placeholder ✓ (FIXED)

fixed it now, see if the table above makes sense too

Comment on lines 123 to +130
export type SurveyAppearanceTheme = Omit<
Required<SurveyAppearance>,
'widgetSelector' | 'widgetType' | 'widgetColor' | 'widgetLabel' | 'shuffleQuestions'
>
'widgetSelector' | 'widgetType' | 'widgetColor' | 'widgetLabel' | 'shuffleQuestions' | 'textColor' | 'inputTextColor'
> & {
textColor?: string
inputTextColor?: string
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't really know how to read this type. Are we omitting textColor, inputTextColor from original type and adding them back as optional properties?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

its omitting all hardcoded values and adding back the 2 as optional

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't really know how to read this type. Are we omitting textColor, inputTextColor from original type and adding them back as optional properties?

yep! we're making most fields required (so we always have defaults to render with), but textColor and inputTextColor stay optional since they're overrides - if not set, we auto-calculate them from the background for contrast.

@lucasheriques lucasheriques force-pushed the feat/allow-customizing-text-color-on-surveys branch from 3cc50e3 to c8d1fe7 Compare December 18, 2025 21:49
@lucasheriques lucasheriques merged commit b676b4d into main Dec 18, 2025
37 of 38 checks passed
Copy link
Contributor Author

Merge activity

@lucasheriques lucasheriques deleted the feat/allow-customizing-text-color-on-surveys branch December 18, 2025 21:57
lucasheriques added a commit to PostHog/posthog that referenced this pull request Dec 23, 2025
## Problem

The survey appearance customization UI needs improvement to be more organized and user-friendly. The current layout doesn't group related options logically and lacks explicit text color controls.

Requires PostHog/posthog-js#2787 to be in before this is ready to ship

## Changes

- Reorganized the survey appearance options into logical subgroups (Survey background, Inputs and ratings, Submit button)
- Added explicit text color controls with "auto-contrast" hints
- Improved responsive layout with better grid structure (1 column on mobile, 3 columns on larger screens)
- Updated the "inherit" font label to be more concise

Before:

![CleanShot 2025-12-17 at [email protected]](https://app.graphite.com/user-attachments/assets/3efe948e-54bb-46c3-ada4-6a481f150001.jpg)

After:

![CleanShot 2025-12-17 at [email protected]](https://app.graphite.com/user-attachments/assets/b072dabe-2984-4d57-812a-ed7c95b060d7.jpg)

## How did you test this code?

Tested the UI in both mobile and desktop viewports to ensure the responsive layout works correctly. Verified that all color controls function properly and that the auto-contrast hint displays correctly. Confirmed that the new text color fields are properly saved and applied to surveys.

## Changelog

Yes, feature completed
warpbuild-benchmark-bot bot added a commit to WarpBuilds/benchmarks-posthog that referenced this pull request Dec 23, 2025
## Problem

The survey appearance customization UI needs improvement to be more organized and user-friendly. The current layout doesn't group related options logically and lacks explicit text color controls.

Requires PostHog/posthog-js#2787 to be in before this is ready to ship

## Changes

- Reorganized the survey appearance options into logical subgroups (Survey background, Inputs and ratings, Submit button)
- Added explicit text color controls with "auto-contrast" hints
- Improved responsive layout with better grid structure (1 column on mobile, 3 columns on larger screens)
- Updated the "inherit" font label to be more concise

Before:

![CleanShot 2025-12-17 at [email protected]](https://app.graphite.com/user-attachments/assets/3efe948e-54bb-46c3-ada4-6a481f150001.jpg)

After:

![CleanShot 2025-12-17 at [email protected]](https://app.graphite.com/user-attachments/assets/b072dabe-2984-4d57-812a-ed7c95b060d7.jpg)

## How did you test this code?

Tested the UI in both mobile and desktop viewports to ensure the responsive layout works correctly. Verified that all color controls function properly and that the auto-contrast hint displays correctly. Confirmed that the new text color fields are properly saved and applied to surveys.

## Changelog

Yes, feature completed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants