diff --git a/brand/README.md b/brand/README.md index 6822c4615..ee8721da6 100644 --- a/brand/README.md +++ b/brand/README.md @@ -42,6 +42,7 @@ and `brand.json` colors when absent. { "name": "Streamplace", "wordmark": "stream.place", + "defaultSiteTitle": "My Streamplace Node", "monochrome": false, "colors": { "ink": "#0A0A0B", @@ -65,7 +66,10 @@ and `brand.json` colors when absent. All colors are optional; `*Foreground` colors default to `ink` and only apply to monochrome marks (a multi-color mark renders as-is). `wordmark` is the text rendered next to the mark in the app's lockup — a `.` in it gets -the accent treatment. `story` optionally carries the mark's design story for +the accent treatment. `defaultSiteTitle` (default `My Node`) is what +an unbranded node calls itself in the nav until its operator sets a runtime +siteTitle via the branding admin; a first-party brand points it at its own +wordmark so its nodes show the styled wordmark with no runtime config. `story` optionally carries the mark's design story for the `/brand` guidelines screen (`tagline`, `readings`, `geometry`, `specs`, `usage` — see `BrandStory` in the generated `js/app/assets/generated/brand.ts`); sections without data are hidden. diff --git a/js/app/components/brand/logo.tsx b/js/app/components/brand/logo.tsx index 92111245b..218450c86 100644 --- a/js/app/components/brand/logo.tsx +++ b/js/app/components/brand/logo.tsx @@ -1,4 +1,4 @@ -import { Text, useTheme } from "@streamplace/components"; +import { Text, useBrandingAsset, useTheme } from "@streamplace/components"; import { fontFamilies } from "@streamplace/components/src/lib/theme/tokens"; import { Fragment } from "react"; import { View, type ViewProps } from "react-native"; @@ -61,12 +61,15 @@ export function LogoTile({ size = 32 }: { size?: number }) { export function Wordmark({ size = 20, + text = BRAND.wordmark, color, dotColor, weight = "semibold", letterSpacing, }: { size?: number; + /** Text to set in wordmark styling; defaults to the brand wordmark. */ + text?: string; color?: string; /** Optional accent color for any "." — omit to keep the wordmark mono. */ dotColor?: string; @@ -85,7 +88,7 @@ export function Wordmark({ fontWeight: (isMedium ? "500" : "600") as "500" | "600", color: color ?? theme.colors.text1, }; - const parts = BRAND.wordmark.split("."); + const parts = text.split("."); return ( {parts.map((part, i) => ( @@ -102,6 +105,7 @@ export function Wordmark({ export function LogoLockup({ size = 20, + text, color, markColor, dotColor, @@ -110,6 +114,7 @@ export function LogoLockup({ ...props }: ViewProps & { size?: number; + text?: string; color?: string; markColor?: string; dotColor?: string; @@ -133,6 +138,7 @@ export function LogoLockup({ ); } + +/** + * The nav-header lockup: the mark plus what this node calls itself — the + * operator's runtime siteTitle branding when set, else the brand's + * defaultSiteTitle (which the first-party brand points at its own wordmark, + * so branded nodes show the styled wordmark with no runtime config). + */ +export function SiteTitleLockup( + props: Omit[0], "text">, +) { + const siteTitle = useBrandingAsset("siteTitle")?.data; + return ; +} diff --git a/js/app/components/sidebar/sidebar-overlay.tsx b/js/app/components/sidebar/sidebar-overlay.tsx index 007f41f51..b0938ac46 100644 --- a/js/app/components/sidebar/sidebar-overlay.tsx +++ b/js/app/components/sidebar/sidebar-overlay.tsx @@ -14,7 +14,7 @@ import { import { BlueskyIcon } from "@streamplace/components/src/components/icons/bluesky-icon"; import { DiscordIcon } from "@streamplace/components/src/components/icons/discord-icon"; import { colors, spacing } from "@streamplace/components/src/lib/theme/tokens"; -import { LogoLockup } from "components/brand/logo"; +import { SiteTitleLockup } from "components/brand/logo"; import { LogoBrandMenu } from "components/brand/logo-brand-menu"; import { Image } from "expo-image"; import usePlatform from "hooks/usePlatform"; @@ -427,7 +427,7 @@ export function SidebarOverlay() { }); }} > - -