Skip to content

Commit 7bca525

Browse files
committed
Merge branch 'wip/fx24-consistency' into wip/platform-org-wiring
2 parents 09fe993 + 9cc1172 commit 7bca525

188 files changed

Lines changed: 1355 additions & 970 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.claude/rules/sim-ui-copy.md‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,17 @@ paths:
1515

1616
This applies to app UI outside the Platform: settings rows, modals, panels, cards, list rows, empty states, form fields, and section headers. Platform views (`app/(product)`, `platform`) follow the stricter one-line-per-control rule in `apps/sim/platform/AGENTS.md`, which `check:platform-design` enforces (`helper-copy`); marketing surfaces (`app/(landing)`, docs) follow `constitution.md`.
1717

18+
## Platform copy vocabulary
19+
20+
Platform views also share one vocabulary, documented in `apps/sim/platform/AGENTS.md` (Code-first product design) and enforced by `check:platform-design`:
21+
22+
- **Sentence case** for every literal `label`, `title`, `confirmLabel`, `pendingLabel` and `cancelLabel`, for `label`s in menu, column, sort and command data, and for button, menu item and chip text (`copy-case`). Product, plan and brand names keep their capitals through `PROPER_NOUNS` / `PROPER_PHRASES` in `scripts/platform-source-rules.ts`; a page or tab name inside a label is a common noun ("Open logs", "Switch to runs").
23+
- **The `…` glyph**, never three periods, in rendered copy and in object or record values such as status labels (`copy-ellipsis`).
24+
- **Confirmations** go through `ConfirmDialog` with a real `pendingLabel` ("Deleting…"), `safe` when nothing is lost (`confirm-owner`). Titles are "{Verb} {noun}" with no question mark, identical for one object everywhere; unsaved changes read "Unsaved changes" / "Discard".
25+
- **Verbs**: editing saves with "Save", creating says "Create {noun}", adding a connection or credential says "Add {noun}", OAuth keeps "Connect".
26+
- **Empty and no-results**: an empty list is `EmptyState` (`Muted` in a narrow rail or dialog picker); no results read "No matching {noun}", the query in curly quotes, no period.
27+
- **Back, tabs, alerts, tooltips** belong to their owners: `DirectoryBack` / `DetailHeader` with bare-noun labels (`back-owner`), `ContentTabs` (`tab-owner`), `InlineNotice` / `FailureNotice` / a field's `error` (`alert-owner`), and `Tooltip` / `OverflowText` rather than a native `title=` (`native-title`). Statuses use Logs' words: a failed run reads "Failed".
28+
1829
**Carve-out — settings section metadata.** `SettingsNavigationItem.description` in `components/settings/navigation.ts` stays required, and `SettingsPanel` keeps rendering it as the page subtitle. Settings sections are reached through a nav list where the description is the only thing distinguishing adjacent sections, so it earns its place by the "prevents misunderstanding" test. Keep those descriptions verb-first and one line, per `sim-settings-pages.md`. Everything else on a settings page — inline `<p>` blurbs under section headings, field hints, modal bodies, row subtitles — follows the default rule above.
1930

2031
## The default is no description

‎.cursor/rules/sim-ui-copy.mdc‎

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,17 @@ globs: ["apps/sim/components/**/*.tsx","apps/sim/ee/**/*.tsx","apps/sim/app/_she
1111

1212
This applies to app UI outside the Platform: settings rows, modals, panels, cards, list rows, empty states, form fields, and section headers. Platform views (`app/(product)`, `platform`) follow the stricter one-line-per-control rule in `apps/sim/platform/AGENTS.md`, which `check:platform-design` enforces (`helper-copy`); marketing surfaces (`app/(landing)`, docs) follow `constitution.md`.
1313

14+
## Platform copy vocabulary
15+
16+
Platform views also share one vocabulary, documented in `apps/sim/platform/AGENTS.md` (Code-first product design) and enforced by `check:platform-design`:
17+
18+
- **Sentence case** for every literal `label`, `title`, `confirmLabel`, `pendingLabel` and `cancelLabel`, for `label`s in menu, column, sort and command data, and for button, menu item and chip text (`copy-case`). Product, plan and brand names keep their capitals through `PROPER_NOUNS` / `PROPER_PHRASES` in `scripts/platform-source-rules.ts`; a page or tab name inside a label is a common noun ("Open logs", "Switch to runs").
19+
- **The `…` glyph**, never three periods, in rendered copy and in object or record values such as status labels (`copy-ellipsis`).
20+
- **Confirmations** go through `ConfirmDialog` with a real `pendingLabel` ("Deleting…"), `safe` when nothing is lost (`confirm-owner`). Titles are "{Verb} {noun}" with no question mark, identical for one object everywhere; unsaved changes read "Unsaved changes" / "Discard".
21+
- **Verbs**: editing saves with "Save", creating says "Create {noun}", adding a connection or credential says "Add {noun}", OAuth keeps "Connect".
22+
- **Empty and no-results**: an empty list is `EmptyState` (`Muted` in a narrow rail or dialog picker); no results read "No matching {noun}", the query in curly quotes, no period.
23+
- **Back, tabs, alerts, tooltips** belong to their owners: `DirectoryBack` / `DetailHeader` with bare-noun labels (`back-owner`), `ContentTabs` (`tab-owner`), `InlineNotice` / `FailureNotice` / a field's `error` (`alert-owner`), and `Tooltip` / `OverflowText` rather than a native `title=` (`native-title`). Statuses use Logs' words: a failed run reads "Failed".
24+
1425
**Carve-out — settings section metadata.** `SettingsNavigationItem.description` in `components/settings/navigation.ts` stays required, and `SettingsPanel` keeps rendering it as the page subtitle. Settings sections are reached through a nav list where the description is the only thing distinguishing adjacent sections, so it earns its place by the "prevents misunderstanding" test. Keep those descriptions verb-first and one line, per `sim-settings-pages.md`. Everything else on a settings page — inline `<p>` blurbs under section headings, field hints, modal bodies, row subtitles — follows the default rule above.
1526

1627
## The default is no description

‎apps/sim/app/(product)/_components/access-requests/my-requests.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export function MyRequests({ scope, view, mine }: MyRequestsProps) {
7373
<EmptyState
7474
title={
7575
mine.query
76-
? 'No matching results'
76+
? 'No matching requests'
7777
: mine.page > 0
7878
? 'No more access to request'
7979
: 'Nothing to request in this organization'

‎apps/sim/app/(product)/_components/access-requests/review-requests.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ interface ReviewRequestsProps {
2323
}
2424

2525
function emptyTitle(query: string, status: RequestStatusFilter, statusLabel: string | null) {
26-
if (query) return `No matching requests for "${query}"`
26+
if (query) return `No matching requests for “${query}”`
2727
if (status === 'pending') return 'No pending requests'
2828
if (status === 'all') return 'No requests yet'
2929
return `No ${statusLabel?.toLowerCase()} requests`

‎apps/sim/app/(product)/_components/chat/cards/live-credential-card.tsx‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ export function LiveCredentialCard({
243243
render={
244244
<Link href={integrationsHref} target='_blank' rel='noopener noreferrer' />
245245
}
246-
label={`Connect ${serviceName(item)} in Integrations`}
246+
label={`Connect ${serviceName(item)} in integrations`}
247247
trailingIcon='I030'
248248
/>
249249
) : null
@@ -291,12 +291,12 @@ export function LiveUsageNotice({ action, reason, message }: UsageNoticeProps) {
291291
!canManage && reason === 'usage_limit' && action === 'increase_limit'
292292
)
293293
if (reason === 'job_run_budget')
294-
return <InlineNotice intent='warning' title='Run Spend Limit Reached' message={message} />
294+
return <InlineNotice intent='warning' title='Run spend limit reached' message={message} />
295295
return (
296296
<>
297297
<InlineNotice
298298
intent='warning'
299-
title={reason === 'chat_plan_required' ? 'Paid Plan Required' : 'Usage Limit Reached'}
299+
title={reason === 'chat_plan_required' ? 'Paid plan required' : 'Usage limit reached'}
300300
message={
301301
canManage
302302
? message
@@ -306,7 +306,7 @@ export function LiveUsageNotice({ action, reason, message }: UsageNoticeProps) {
306306
canManage ? (
307307
<ControlRow
308308
render={<Link href={href} />}
309-
label={upgrade ? 'Upgrade Plan' : 'Increase Limit'}
309+
label={upgrade ? 'Upgrade plan' : 'Increase limit'}
310310
trailingIcon='I030'
311311
/>
312312
) : memberLimit ? (

‎apps/sim/app/(product)/_components/chat/cards/tool-approval.tsx‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { ActivityBody } from '@sim/emcn/activity-row/activity-body'
55
import { Button } from '@sim/emcn/button'
66
import { Icon } from '@sim/emcn/icon'
77
import { ActionMenu } from '@sim/emcn/menu/action-menu'
8+
import { Tooltip } from '@sim/emcn/tooltip'
89
import { generateId } from '@sim/utils/id'
910
import styles from '@/app/(product)/_components/chat/cards/cards.module.css'
1011
import { usePlatformNotices } from '@/app/(product)/_components/notification-tray/notification-tray'
@@ -50,9 +51,11 @@ export function ToolApproval({ tool }: { tool: PlatformTool }) {
5051
return (
5152
<div className={styles.card}>
5253
<ActivityBody leading={<Icon name='I084' />} decorativeLeading>
53-
<span className={styles.title} data-type='T048' title={tool.input}>
54-
{tool.title}
55-
</span>
54+
<Tooltip label={tool.input ?? ''} enabled={Boolean(tool.input)}>
55+
<span className={styles.title} data-type='T048'>
56+
{tool.title}
57+
</span>
58+
</Tooltip>
5659
</ActivityBody>
5760
<div className={styles.actions}>
5861
<Button

‎apps/sim/app/(product)/_components/chat/panel/browser-session/browser-session.tsx‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,33 +52,33 @@ export function BrowserSession({ scopeId, visible }: BrowserSessionProps) {
5252
const menuActions = (): MenuAction[] => [
5353
{
5454
id: 'find',
55-
label: 'Find in Page',
55+
label: 'Find in page',
5656
shortcut: '⌘F',
5757
onSelect: menu.afterClose(browser.openFind),
5858
},
5959
...continueSignInActions(signIn, menu.afterClose),
6060
{
6161
id: 'zoom-in',
62-
label: 'Zoom In',
62+
label: 'Zoom in',
6363
shortcut: '⌘+',
6464
separatorBefore: true,
6565
onSelect: menu.afterClose(() => menu.zoom('zoom-in')),
6666
},
6767
{
6868
id: 'zoom-out',
69-
label: 'Zoom Out',
69+
label: 'Zoom out',
7070
shortcut: '⌘−',
7171
onSelect: menu.afterClose(() => menu.zoom('zoom-out')),
7272
},
7373
{
7474
id: 'zoom-reset',
75-
label: 'Actual Size',
75+
label: 'Actual size',
7676
shortcut: '⌘0',
7777
onSelect: menu.afterClose(() => menu.zoom('zoom-reset')),
7878
},
7979
{
8080
id: 'fill-password',
81-
label: 'Fill Saved Password',
81+
label: 'Fill saved password',
8282
separatorBefore: true,
8383
disabled: !menu.fillAvailable,
8484
onSelect: menu.afterClose(() => menu.fillPassword(menuAnchor.current)),
@@ -90,13 +90,13 @@ export function BrowserSession({ scopeId, visible }: BrowserSessionProps) {
9090
},
9191
{
9292
id: 'import-passwords',
93-
label: 'Import Passwords',
93+
label: 'Import passwords',
9494
disabled: !menu.canImport,
9595
onSelect: menu.afterClose(() => menu.settings('?browserImport=1')),
9696
},
9797
{
9898
id: 'browser-settings',
99-
label: 'Browser Settings',
99+
label: 'Browser settings',
100100
separatorBefore: true,
101101
onSelect: menu.afterClose(() => menu.settings('')),
102102
},

‎apps/sim/app/(product)/_components/chat/panel/browser-session/continue-sign-in.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ export function continueSignInActions(
3737
return [
3838
{
3939
id: 'continue-sign-in',
40-
label: 'Continue in Browser',
40+
label: 'Continue in browser',
4141
separatorBefore: true,
4242
children: [head, ...tail],
4343
},

‎apps/sim/app/(product)/_components/chat/panel/browser-session/page-prompts.tsx‎

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { Button, IconButton } from '@sim/emcn/button'
55
import { Checkbox } from '@sim/emcn/checkbox'
66
import { SelectField, TextField } from '@sim/emcn/field'
77
import { Modal } from '@sim/emcn/modal'
8+
import { ConfirmDialog } from '@sim/emcn/modal/confirm-dialog'
89
import { InlineNotice } from '@sim/emcn/status'
910
import { useActivationDelay, type useBrowserPanel } from '@/platform/lib/data/browser-panel'
1011
import { formatInstantDate } from '@/platform/shared/time'
@@ -48,7 +49,7 @@ export function PageDialogModal({ dialog, onAnswer }: PageDialogModalProps) {
4849
onOpenChange={(open) => {
4950
if (!open) answer(false)
5051
}}
51-
title='Leave page?'
52+
title='Leave page'
5253
description='Changes on this page may not be saved.'
5354
cancelLabel='Stay'
5455
confirmLabel='Leave'
@@ -240,15 +241,14 @@ function ExternalAppPrompt({ prompt, respond }: PromptModalProps<'external-app'>
240241
const armed = useActivationDelay(true)
241242
const [alwaysAllow, setAlwaysAllow] = useState(false)
242243
return (
243-
<Modal
244-
variant='confirm'
245-
open
246-
onOpenChange={(open) => {
247-
if (!open) respond({ allowed: false })
248-
}}
249-
title={`Open ${prompt.appName}?`}
244+
<ConfirmDialog
245+
target={prompt}
246+
onClose={() => respond({ allowed: false })}
247+
safe
248+
title={`Open ${prompt.appName}`}
250249
description={`${prompt.origin} wants to open this app.`}
251250
confirmLabel='Open'
251+
pendingLabel='Opening…'
252252
confirmDisabled={!armed}
253253
onConfirm={() =>
254254
respond({
@@ -265,7 +265,7 @@ function ExternalAppPrompt({ prompt, respond }: PromptModalProps<'external-app'>
265265
onCheckedChange={setAlwaysAllow}
266266
/>
267267
)}
268-
</Modal>
268+
</ConfirmDialog>
269269
)
270270
}
271271

‎apps/sim/app/(product)/_components/credential-members/credential-members.tsx‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ export function AddPeopleModal({
255255
if (!next) close()
256256
}}
257257
title='Add people'
258-
confirmLabel='Add'
258+
confirmLabel='Add people'
259259
confirmDisabled={emails.length === 0 || Boolean(firstError)}
260260
onConfirm={add}
261261
>

0 commit comments

Comments
 (0)