Skip to content

OUT-3510 | Add side-menu setting to hide home page greeting - #203

Merged
arpandhakal merged 16 commits into
mainfrom
OUT-3510
Jun 11, 2026
Merged

OUT-3510 | Add side-menu setting to hide home page greeting#203
arpandhakal merged 16 commits into
mainfrom
OUT-3510

Conversation

@arpandhakal

Copy link
Copy Markdown
Collaborator

Changes

  • Renamed the Banner sidebar section to Header.
  • Added a Show greeting toggle at the top of the Header section that hides the heading + subheading block above the banner.
  • Toggle persists per workspace/segment via a new show_greeting column on settings (default true).
  • Hidden across editor, preview, and the client-facing view (EditorWrapper, Preview, ClientEditorWrapper).
  • Hardened useBannerSettingsMutation with a stale-response guard so rapid toggling doesn't flicker the UI when responses arrive out of order (same pattern as useSettingsMutation).

Testing Criteria

  • Sidebar accordion now reads "Header" instead of "Banner".
  • Toggling Show greeting OFF in the sidebar immediately hides the greeting block in the editor.
  • The greeting stays hidden in Preview mode and in the client-facing view (/c/...).
  • Refreshing the page preserves the toggle state.
  • Toggling rapidly settles correctly without UI flicker.
  • Setting is scoped per segment (toggle in one segment doesn't affect another).
  • Loom: add link

Notes

  • DB migration: src/db/migrations/20260601130809_add-show-greeting-to-settings.sql — adds show_greeting boolean NOT NULL DEFAULT true. Forward-only, safe on existing rows.
  • The mid-flight-on-refresh race (rapid toggle → refresh inside in-flight PATCH) is acknowledged as an accepted edge case; toggle is not debounced.

Impact & Surface Area of Change

  • settings table schema + Drizzle snapshot — apply migration before deploying.
  • useBannerSettingsMutation now also handles showGreeting and dedupes stale responses; existing banner image/reposition flows go through the same hook, double-check they still save as expected.
  • Heading/Subheading components themselves are unchanged; only their parent containers conditionally render them.

🤖 Generated with Claude Code

Renames the Banner sidebar section to "Header" and adds a "Show greeting"
toggle that controls visibility of the heading/subheading block above the
banner across editor, preview, and the client-facing view. Persisted via a
new show_greeting column on settings.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Jun 1, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
client-home-v3 Ready Ready Preview, Comment Jun 11, 2026 8:49am

Request Review

@linear-code

linear-code Bot commented Jun 1, 2026

Copy link
Copy Markdown

OUT-3510

@greptile-apps

greptile-apps Bot commented Jun 1, 2026

Copy link
Copy Markdown

Greptile Summary

Adds a per-segment "Show greeting" toggle to the sidebar (renamed from "Banner" to "Header") that conditionally renders the heading/subheading block in the editor, preview, and client-facing views. The change is backed by a new show_greeting DB column with a safe ALTER TABLE … DEFAULT true migration and a stale-response guard in useBannerSettingsMutation.

  • DB + schema: show_greeting boolean NOT NULL DEFAULT true added via a forward-only migration; Drizzle schema and Zod DTO pick it up automatically.
  • Mutation hook: showGreeting is now included in the banner settings payload, and the new mutationCounter guard prevents out-of-order responses from overwriting optimistic state.
  • UI consumers: All three rendering surfaces (EditorWrapper, ClientEditorWrapper, Preview) conditionally render the greeting block; a setShowGreeting dedicated store action was added but is never called.

Confidence Score: 4/5

Safe to merge after addressing the missing ?? true fallback and removing the unused setShowGreeting action; the migration is non-destructive and the core toggle flow is correct.

The greeting-visibility logic is straightforward and the DB migration is safe. The three consumer components read showGreeting without a ?? true fallback, unlike the pattern used for bannerPositionX and bannerPositionY; if the store ever holds undefined for this field the greeting is silently hidden, which is the wrong safe default. The setShowGreeting store action is dead code. Neither issue blocks the feature, but the fallback omission could surface unexpectedly during a rolling deployment.

EditorWrapper.tsx, ClientEditorWrapper.tsx, and Preview.tsx — all three are missing the ?? true guard on showGreeting. settingsStore.ts has a dead setShowGreeting action that should be removed.

Important Files Changed

Filename Overview
src/features/settings/hooks/useBannerSettingsMutation.ts Adds showGreeting to the banner payload and introduces a mutationCounter stale-response guard; pattern is sound but counter is component-scoped so it resets on remount.
src/features/settings/stores/settingsStore.ts Adds setShowGreeting action that is never called anywhere; all updates go through the generic setSettings path, making this a dead-code addition.
src/features/editor/components/EditorWrapper.tsx Conditionally renders the greeting block based on showGreeting; missing ?? true fallback unlike sibling store reads for bannerPositionX/bannerPositionY.
src/features/editor/components/ClientEditorWrapper.tsx Same conditional greeting pattern as EditorWrapper; same missing ?? true fallback on the client-facing route.
src/features/editor/components/Preview/Preview.tsx Preview mode now honours showGreeting from the settings store; missing ?? true fallback consistent with the other views.
src/features/editor/components/Sidebar/BannerOptions.tsx Adds "Show greeting" toggle wired to useBannerSettingsMutation; straightforward and correct.
src/features/settings/lib/settings/settings.schema.ts Adds showGreeting: boolean().notNull().default(true) to the Drizzle settings table; matches migration SQL.
src/db/migrations/20260601130809_add-show-greeting-to-settings.sql Adds show_greeting boolean NOT NULL DEFAULT true via ALTER TABLE; forward-only, non-destructive, safe for existing rows.

Reviews (1): Last reviewed commit: "feat(OUT-3510): add side-menu setting to..." | Re-trigger Greptile

Comment on lines +20 to 21
setShowGreeting: (showGreeting: boolean) => void
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 The setShowGreeting action is added to both the SettingsAction interface and the store implementation, but it is never called anywhere in the codebase. All showGreeting updates flow through the generic setSettings path in useBannerSettingsMutation. This dedicated setter is dead code that adds surface area with no benefit — either wire it up where appropriate or remove it to keep the store consistent with what other dedicated setters (like setContent, setSubheading) are actually used for.

Suggested change
setShowGreeting: (showGreeting: boolean) => void
}
}

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

const bannerUrl = bannerImages?.find((item) => item.id === bannerId)
const bannerPositionX = useSettingsStore((store) => store.bannerPositionX) ?? 50
const bannerPositionY = useSettingsStore((store) => store.bannerPositionY) ?? 50
const showGreeting = useSettingsStore((store) => store.showGreeting)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 The existing bannerPositionX and bannerPositionY reads both carry ?? 50 fallbacks to guard against an undefined store value. showGreeting lacks a matching ?? true fallback. If the store ever holds undefined for this field — during an intermediate hydration state or when hitting an un-migrated API pod — the greeting block is silently hidden instead of shown, which is the wrong safe default.

Suggested change
const showGreeting = useSettingsStore((store) => store.showGreeting)
const showGreeting = useSettingsStore((store) => store.showGreeting) ?? true

const bannerUrl = bannerImages?.find((item) => item.id === bannerId)
const bannerPositionX = useSettingsStore((store) => store.bannerPositionX) ?? 50
const bannerPositionY = useSettingsStore((store) => store.bannerPositionY) ?? 50
const showGreeting = useSettingsStore((store) => store.showGreeting)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Same ?? true fallback missing as in EditorWrapper. Without it, an undefined showGreeting value silently hides the greeting on the client-facing route.

Suggested change
const showGreeting = useSettingsStore((store) => store.showGreeting)
const showGreeting = useSettingsStore((store) => store.showGreeting) ?? true

export function Preview({ content, backgroundColor, bannerUrl, bannerPositionX, bannerPositionY }: PreviewProps) {
const displayMode = useViewStore((store) => store.displayMode)
const workspace = useViewStore((store) => store.workspace)
const showGreeting = useSettingsStore((store) => store.showGreeting)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Same ?? true fallback missing as in EditorWrapper and ClientEditorWrapper. Without it, an undefined showGreeting value silently hides the greeting in Preview mode.

Suggested change
const showGreeting = useSettingsStore((store) => store.showGreeting)
const showGreeting = useSettingsStore((store) => store.showGreeting) ?? true

arpandhakal and others added 15 commits June 2, 2026 17:11
- Replace bulky cards with compact pill rows matching the new design
- Verb-sentence labels (Pay/Sign/Submit/Complete) with inline count; short {{N}} chip in editor
- Container-query grid: 4 and 3 actions fill the row; 1 and 2 stay third-width and left-align
- Hide actions with 0 pending events and the whole section when nothing is pending (OUT-3717)
- Preserve click-through navigation to the underlying apps

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 and 2 action cards now cap at a fixed 240px width and left-align in both the
editor (IU) and client views, so space stays on the right regardless of which
view renders them. Also lower the fill breakpoint to 700px so 3 and 4 actions
fill the row in the editor's content column (which sits just under 768px due to
the customization sidebar).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Convert the container-query breakpoints and the capped card width to rem
(400px->25rem, 700px->43.75rem, 240px->15rem). No behavior change.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace the static time-of-day greeting with an editable, autofill-capable
header. The heading defaults to "Welcome, {{client.firstName}}" and both the
heading and subheading are now minimal single-line rich-text fields that
support plain text + autofill fields only (no marks, lists, tables, etc).

- Add MinimalEditor + getMinimalExtensions (Document content:'block' for
  single-line, Paragraph, Text, UndoRedo, reused AutofillField, Placeholder)
- Add settings.heading column (HTML, default "Welcome, {{client.firstName}}");
  subheading now stores HTML and is backward compatible with existing plain text
- Wire heading through the store, change-detection and save payload
- Scope .minimal-editor CSS so global .tiptap block styles don't leak in
- Remove the now-unused getTimeOfDay greeting helper

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The change-detection baseline kept the subheading in its legacy plain-text
form (e.g. "Here's …") while the editor always emits "<p>…</p>", so reverting
a subheading edit never string-matched the baseline and the Save Changes button
stayed visible. The heading was unaffected because its default is already
canonical "<p>…</p>".

Normalize heading/subheading to the editor's canonical serialization when a
non-canonical value loads, updating the live value and the change-detection
baseline atomically via a new syncCanonicalContent store action.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Autofill fields are an inline atom TipTap node rendered via a React
NodeView. In client/preview view the resolved value was neither
selectable/copiable nor clickable when it was a link.

- Add `renderText` to the autofill node so TipTap's clipboard text
  serializer emits the resolved value (template `{{...}}` falls back when
  no preview client is available, e.g. in the editor). Resolution happens
  outside React via a store/query-cache helper.
- Render resolved URLs and emails as anchors styled with the editor's
  `cop-text-link cursor-pointer` classes; `stopPropagation` on mousedown
  lets native navigation work in the readonly view.

Both fixes live on the shared extension/NodeView, so the minimal editor
(home header/subheading) inherits them automatically.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
OUT-3841 | Home App - Autofill Fields Are Not Copiable or Clickable
feat(OUT-3510): make home page header editable with autofill
…-visual-appearance-of-the-your-actions-field

OUT-3729, OUT-3717 | Improve visual appearance of the Your Actions field
@arpandhakal
arpandhakal merged commit 9736abb into main Jun 11, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant