Skip to content

Commit e310973

Browse files
committed
feat(embed): add navbar brand props and document embed styling
Expose showNavbarBrand and navbarBrandLabel on RosViewer so hosts can hide or replace the default ROS View label, and document CSS scoping plus branding in the English and Chinese embedding guides.
1 parent 80c7899 commit e310973

5 files changed

Lines changed: 85 additions & 9 deletions

File tree

docs/EMBEDDING.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ The component requires its bundled CSS. Import it once at your application root:
3131
import '@ioai/rosview/style.css';
3232
```
3333

34+
Styles are scoped to `#rosview-root` inside the bundle, so Tailwind preflight does not reset global elements (navbar, buttons, etc.) in your host application.
35+
3436
---
3537

3638
## Step 2 — Basic usage
@@ -133,6 +135,29 @@ const rows = parseRemoteDatasetListJson(await res.json());
133135

134136
---
135137

138+
## Advanced: Navbar branding
139+
140+
The navbar shows **ROS View** on the left by default. When embedding inside a larger app, you can hide it or replace it with your product name:
141+
142+
```tsx
143+
// Hide the brand button (File / Layout menus remain)
144+
<RosViewer url="..." showNavbarBrand={false} />
145+
146+
// Replace with host branding
147+
<RosViewer url="..." navbarBrandLabel="Acme Data Portal" />
148+
```
149+
150+
Related props:
151+
152+
| Prop | Description |
153+
|------|-------------|
154+
| `showNavbarBrand` | Left brand button visibility (`true` by default). |
155+
| `navbarBrandLabel` | Custom brand text; defaults to the localized product name. |
156+
| `navbarSourceName` | Center label for the active dataset (separate from brand). |
157+
| `showNavbar` | Hides the entire navbar when `false` (via `chrome` or explicit prop). |
158+
159+
---
160+
136161
## Advanced: Controlled theme & language
137162

138163
Disable internal localStorage persistence and fully control state from your application:

docs/EMBEDDING.zh.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ npm install @ioai/rosview
3131
import '@ioai/rosview/style.css';
3232
```
3333

34+
样式在构建产物中限定在 `#rosview-root` 内,Tailwind preflight 不会重置宿主应用的全局元素(导航栏、按钮等)。
35+
3436
---
3537

3638
## 步骤 2 — 基本用法
@@ -133,6 +135,29 @@ const rows = parseRemoteDatasetListJson(await res.json());
133135

134136
---
135137

138+
## 进阶:Navbar 品牌文案
139+
140+
Navbar 左侧默认显示 **ROS View**。嵌入到更大页面时,可以隐藏或替换为你的产品名:
141+
142+
```tsx
143+
// 隐藏品牌按钮(File / Layout 菜单仍保留)
144+
<RosViewer url="..." showNavbarBrand={false} />
145+
146+
// 替换为宿主品牌
147+
<RosViewer url="..." navbarBrandLabel="Acme 数据平台" />
148+
```
149+
150+
相关 props:
151+
152+
| Prop | 说明 |
153+
|------|------|
154+
| `showNavbarBrand` | 左侧品牌按钮是否显示(默认 `true`)。 |
155+
| `navbarBrandLabel` | 自定义品牌文案;未设置时使用本地化产品名。 |
156+
| `navbarSourceName` | 中间区域的数据源名称(与品牌文案无关)。 |
157+
| `showNavbar` | 设为 `false` 时隐藏整条 Navbar(通过 `chrome` 或显式 prop)。 |
158+
159+
---
160+
136161
## 进阶:受控主题与语言
137162

138163
关闭组件内部的 localStorage 持久化,由宿主应用完全控制状态:

src/app/AppShell.tsx

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ interface AppShellProps {
2727
onLanguageChange: (lang: 'en' | 'zh' | 'ja') => void;
2828
showLanguageSwitcher?: boolean;
2929
showThemeSwitcher?: boolean;
30+
showNavbarBrand?: boolean;
31+
navbarBrandLabel?: string;
3032
onBrandClick?: () => void;
3133
preferAutoLayout?: boolean;
3234
preferencePersistence: PreferencePersistence;
@@ -77,6 +79,8 @@ export const AppShell: React.FC<AppShellProps> = ({
7779
onLanguageChange,
7880
showLanguageSwitcher = true,
7981
showThemeSwitcher = true,
82+
showNavbarBrand = true,
83+
navbarBrandLabel,
8084
onBrandClick,
8185
preferAutoLayout = false,
8286
preferencePersistence,
@@ -150,6 +154,8 @@ export const AppShell: React.FC<AppShellProps> = ({
150154
onLanguageChange={onLanguageChange}
151155
showLanguageSwitcher={showLanguageSwitcher}
152156
showThemeSwitcher={showThemeSwitcher}
157+
showNavbarBrand={showNavbarBrand}
158+
brandLabel={navbarBrandLabel}
153159
onBrandClick={onBrandClick}
154160
onOpenFilePick={hideOpenFileMenus ? undefined : onOpenFilePick}
155161
onOpenDirectory={hideOpenFileMenus ? undefined : onOpenDirectory}

src/features/viewer/RosViewerImpl.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,10 @@ export interface RosViewerProps {
250250
extensions?: RosViewExtension[];
251251
/** Optional center label override shown in navbar source area. */
252252
navbarSourceName?: string;
253+
/** Whether to show the left navbar brand button. @default true */
254+
showNavbarBrand?: boolean;
255+
/** Custom label for the left navbar brand button (defaults to product name). */
256+
navbarBrandLabel?: string;
253257
/** Whether to show navbar language switcher. @default true */
254258
showLanguageSwitcher?: boolean;
255259
/** Whether to show navbar theme switcher. @default true */
@@ -1145,6 +1149,8 @@ export const RosViewer: React.FC<RosViewerProps> = (props) => {
11451149
onLanguageChange={handleLanguageChange}
11461150
showLanguageSwitcher={props.showLanguageSwitcher ?? true}
11471151
showThemeSwitcher={props.showThemeSwitcher ?? true}
1152+
showNavbarBrand={props.showNavbarBrand ?? true}
1153+
navbarBrandLabel={props.navbarBrandLabel}
11481154
onBrandClick={handleGoHome}
11491155
preferAutoLayout={props.preferAutoLayout ?? false}
11501156
preferencePersistence={persistence}
@@ -1206,6 +1212,8 @@ export const RosViewer: React.FC<RosViewerProps> = (props) => {
12061212
onLanguageChange={handleLanguageChange}
12071213
showLanguageSwitcher={props.showLanguageSwitcher ?? true}
12081214
showThemeSwitcher={props.showThemeSwitcher ?? true}
1215+
showNavbarBrand={props.showNavbarBrand ?? true}
1216+
brandLabel={props.navbarBrandLabel}
12091217
onBrandClick={handleGoHome}
12101218
onOpenFilePick={() => {
12111219
clearOpenFeedback();
@@ -1309,6 +1317,8 @@ export const RosViewer: React.FC<RosViewerProps> = (props) => {
13091317
onLanguageChange={handleLanguageChange}
13101318
showLanguageSwitcher={props.showLanguageSwitcher ?? true}
13111319
showThemeSwitcher={props.showThemeSwitcher ?? true}
1320+
showNavbarBrand={props.showNavbarBrand ?? true}
1321+
brandLabel={props.navbarBrandLabel}
13121322
onBrandClick={handleGoHome}
13131323
onOpenFilePick={() => {
13141324
clearOpenFeedback();

src/features/workspace/navbar/Navbar.tsx

Lines changed: 19 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,10 @@ interface NavbarProps {
8383
onLanguageChange?: (lang: 'en' | 'zh' | 'ja') => void;
8484
showLanguageSwitcher?: boolean;
8585
showThemeSwitcher?: boolean;
86+
/** When false, hide the left brand button. @default true */
87+
showNavbarBrand?: boolean;
88+
/** Override default product name in the left brand button. */
89+
brandLabel?: string;
8690
onBrandClick?: () => void;
8791
onOpenFilePick?: () => void;
8892
onOpenDirectory?: () => void;
@@ -103,6 +107,8 @@ export const Navbar: React.FC<NavbarProps> = ({
103107
onLanguageChange,
104108
showLanguageSwitcher = true,
105109
showThemeSwitcher = true,
110+
showNavbarBrand = true,
111+
brandLabel,
106112
onBrandClick,
107113
onOpenFilePick,
108114
onOpenDirectory,
@@ -164,20 +170,24 @@ export const Navbar: React.FC<NavbarProps> = ({
164170
onOpenFilePick || onOpenDirectory || onOpenTarPick || onOpenRemotePrompt || onOpenSampleDialog;
165171
const showCenter = Boolean(sourceLoading || (sourceName && sourceName.trim().length > 0));
166172
const centerLabel = sourceLoading ? formatMessage({ id: 'navbar.sourceLoading' }) : (sourceName ?? '');
173+
const brandText = brandLabel ?? formatMessage({ id: 'common.productName' });
174+
const brandAccessibleName = brandLabel ?? formatMessage({ id: 'navbar.goHome' });
167175

168176
return (
169177
<nav className="sticky top-0 z-50 w-full shrink-0 border-b border-border bg-background select-none">
170178
<div className="grid h-12 w-full grid-cols-[minmax(0,1fr)_minmax(0,1fr)_minmax(0,1fr)] items-center gap-x-2 gap-y-0 px-4">
171179
<div className="flex min-w-0 items-center gap-2 justify-self-start sm:gap-3">
172-
<button
173-
type="button"
174-
className="min-w-0 max-w-[min(11rem,28vw)] shrink truncate rounded-sm text-left text-sm font-semibold tracking-tight text-foreground transition-colors hover:text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background sm:max-w-[11rem]"
175-
onClick={onBrandClick}
176-
title={formatMessage({ id: 'navbar.goHome' })}
177-
aria-label={formatMessage({ id: 'navbar.goHome' })}
178-
>
179-
{formatMessage({ id: 'common.productName' })}
180-
</button>
180+
{showNavbarBrand ? (
181+
<button
182+
type="button"
183+
className="min-w-0 max-w-[min(11rem,28vw)] shrink truncate rounded-sm text-left text-sm font-semibold tracking-tight text-foreground transition-colors hover:text-primary focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background sm:max-w-[11rem]"
184+
onClick={onBrandClick}
185+
title={brandAccessibleName}
186+
aria-label={brandAccessibleName}
187+
>
188+
{brandText}
189+
</button>
190+
) : null}
181191

182192
<Menubar
183193
ref={leftMenubarRef}

0 commit comments

Comments
 (0)