stillmade-sdk 0.1.40 → 0.1.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +6 -2
- package/FRAME_VIEWS.md +41 -0
- package/INTERFACE_DESIGN.md +95 -8
- package/MOBILE_UI.md +3 -1
- package/PASTE_TO_LLM.md +10 -5
- package/SDK.md +163 -21
- package/UI_AESTHETIC.md +86 -4
- package/package.json +1 -1
- package/packages/block-cli/dev-host/assets/host.js +203 -37
- package/packages/block-cli/dev-host/assets/index.css +1 -1
- package/packages/block-platform/block-readiness.js +22 -2
- package/packages/block-platform/canvas.js +17 -0
- package/packages/block-platform/catalog.js +21 -6
- package/packages/block-platform/host-release-manifests.js +95 -0
- package/packages/block-platform/native-host-inventory.js +29 -4
- package/packages/block-platform/node-defaults.js +1 -0
- package/packages/block-platform/project-context.js +1 -1
- package/packages/block-platform/script-handoff.js +1 -1
- package/packages/block-platform/step-groups.js +3 -1
- package/packages/block-sdk/builder-contract.js +15 -4
- package/packages/block-sdk/contracts.js +3 -1
- package/packages/block-sdk/index.d.ts +2 -2
- package/packages/block-sdk/view-design.js +92 -17
- package/packages/block-sdk/workspace-navigation.js +6 -2
- package/packages/design-system/block-kit.css +28 -6
- package/packages/design-system/block-kit.html +14 -4
- package/packages/design-system/theme.css +6 -5
package/SDK.md
CHANGED
|
@@ -201,7 +201,7 @@ The archive needs Node.js 22 or later and nothing else; its runtime is bundled,
|
|
|
201
201
|
|
|
202
202
|
## Block builder contract
|
|
203
203
|
|
|
204
|
-
Contract `stillmade.block-builder@1.
|
|
204
|
+
Contract `stillmade.block-builder@1.16.0`. Humans, coding agents, imported source, GitHub repositories and generated code all adapt to the Block platform; anything that becomes a StillMade Block obeys this contract.
|
|
205
205
|
|
|
206
206
|
### Source of truth
|
|
207
207
|
|
|
@@ -263,9 +263,13 @@ Give the Block a short, plain name of 40 characters or fewer that says what it d
|
|
|
263
263
|
|
|
264
264
|
Name each input for what the person brings, in the job's words: `sermonVideo` for a sermon clip Block, `listingPhotos` for a listing, `lessonSlides` for a lesson podcast. StillMade titles the input from that name ("Sermon video") and words its drop area from it ("Drop your sermon video here", the formats, "Choose a video"), in StillMade and the SDK preview, so never draw your own upload box for an input. Keep a bare type name (`video`, `file`) only when any file of that kind does the job. The `description` says what makes a good one.
|
|
265
265
|
|
|
266
|
+
### Speak the job
|
|
267
|
+
|
|
268
|
+
These are StillMade's defaults: unless the person or the creator asked for something else, every screen speaks the job in its own words and adds nothing else. `manifest.action` names the Step's button, {label:"Plan the tour", running:"Planning the tour…"}, and StillMade adds the price ("Plan the tour · 1 credit"). When the Block makes a picture, video or sound with AI the label starts with Generate and says what ("Generate tour", "Generate voiceover"); one that cuts or renders the person's own media says Make ("Make 6 clips"); never "Make it", "Run", "Submit", "Process" or a bare "Generate". The main button stands out: one solid `sm-primary` in the kit's ink, never restyled to the background; everything else is `sm-quiet` or an `sm-icon`, and close is an X icon. Report progress in the job's units with `stillmade.progress(fraction, label)` ("Moving through the kitchen, 4 of 9 rooms"), never "Processing". Head the result in the job's words ("9 rooms", "Your tour · 44 s"), never "Output". Say a problem in one line with its fix beside it ("No bathroom photo. Guests look for one." and Add photo). Stay quiet: no welcome text, tips under fields, tours or banners, and at most one line of guidance on a screen, only where the next move is not obvious; anything more goes in the input's `description`, which StillMade shows behind an (i). Say nothing about how the Block works (where it runs, saving, syncing, recovery, accounts, credits) or where a file is kept: StillMade tells the person what they need as one short notification, or nothing; never a sentence on the page, and never the same line under each item. Every drop area offers "Use a reference", which fills the Step from the person's saved photos, videos and notes: media inputs fill by kind, so take `video` or `asset` where a clip works as well as a photo, and text inputs fill by plain names and labels (`productName`, `website`, `brandColors`, `fonts`, `voice`, and `details` or `notes` for the reference's note); never build your own reference picker. Days and times are picked, never typed: use the `date` type, which StillMade shows as a calendar, with a list of times when the input is about a time (`postAt`, `startsAt`); a custom view uses `<input type="date">` or `type="datetime-local"`. Posting is a connector Step of its own, and StillMade words its button from the app and action ("Post to Instagram"). Before handing the Block back, clear every Wording note that `gate` and readiness list, unless the person asked for those words.
|
|
269
|
+
|
|
266
270
|
### Interface
|
|
267
271
|
|
|
268
|
-
If the capability needs UI, use the Block UI SDK: generated `manifest.ui` controls first; a sandboxed custom view (`view.html`/`view.css`/`view.js`) only when the core interaction needs one. Build custom views from the Block kit the host injects (`block-kit.css`): the result in `sm-stage`, picks as pictures in `sm-choices`, one `sm-primary` naming the action (
|
|
272
|
+
If the capability needs UI, use the Block UI SDK: generated `manifest.ui` controls first; a sandboxed custom view (`view.html`/`view.css`/`view.js`) only when the core interaction needs one. Build custom views from the Block kit the host injects (`block-kit.css`): the result in `sm-stage`, picks as pictures in `sm-choices`, the picked one in the kit's ink fill (never restyled to an outline, a tint or the page's background) so it reads at a glance, one solid `sm-primary` naming the action in the job's words ("Plan the tour", "Generate voiceover"; never "Run" or "Make it") and no price (StillMade's run button adds it), extras in a closed `sm-more`; a look the person names wins. Fit one laptop screen without scrolling: label beside control, status in a few words, files as tiles, rare tools as icons, (i) on unclear controls. These compact rules are for a job or an ingredient. Size the view to the Block's tier (block-tier.js): an app, a workspace a person works in for a while (video editor, 3D configurator, CAD or drawing tool), looks and works like that kind of app instead of a compact page: its canvas or stage fills the view, with the panels, toolbars, inspector or timeline such an app has, direct manipulation (select, drag, zoom), keyboard shortcuts and undo; it keeps the host appearance and Block kit controls, its panels may scroll, and on a phone its tools fold into sheets while the canvas stays usable. Never shrink an app into a form of fields and one button. StillMade centers a standard view narrower than its Step and zooms a view to fill its space; an app that lays itself out (full-size canvas or WebGL, its own scroll, pan or zoom, its own Ctrl/Cmd +/- keys) puts `data-stillmade-layout="own"` on its outermost element, and StillMade then never centers, zooms or takes those keys. StillMade draws one player for every `<video controls>` (play, timeline, time, sound and full screen, shown while the pointer is on the video, with keys and touch) and a full-screen button on result pictures in `sm-stage` or `sm-gallery` and on any element marked `data-stillmade-expand` (the same value makes one set of pictures, `off` removes it); `data-stillmade-player="native"` keeps the browser's controls, and a `<video>` without `controls` is the Block's own and is never touched. A picture or clip that cannot show here (kept on another device, or it did not open) keeps its place as a quiet `sm-media-off` tile in its own shape with the `image-off` glyph and the reason in its label, never words in its place. Drop words nobody needs; put helpful ones in a closed `sm-hint`. Mark each button `data-stillmade-action="what it does"` and label each field: Chat presses and fills them. Expose the capability, not the implementation: sensible defaults, previews, progress, clear errors, visible outputs. Show no raw JSON, internal IDs, filesystem details, provider terms or developer settings unless the Block is a developer tool. When a person chooses among options they need to hear or see (voices, music, fonts, looks, templates, images), let them preview each option before choosing: a sample or thumbnail from the Block's own files or the host's free samples, never a paid generation. Skip previews only when there is nothing to preview. Choices StillMade owns (voices, models in the run review) already show samples. Follow the host appearance (Light, Dark and White) and one elastic layout: stacked on a 320px phone with no sideways scroll (result first, action pinned), and from 860px the controls left (≤380px), the result filling the right. Short settings sit side by side, each label beside its control (`sm-field`, `sm-settings`; three or four short options as one `data-segmented` row); many items are one line each (`sm-list`) that open in place; input files are small tiles (`sm-gallery data-size="small"`); on a phone chip rows scroll sideways and long lists show three. Compacting moves controls, never deletes them.
|
|
269
273
|
|
|
270
274
|
### Shared editing
|
|
271
275
|
|
|
@@ -1020,6 +1024,9 @@ inline handlers, links, file inputs, network attributes, and raw HTML are reject
|
|
|
1020
1024
|
`await StillMade.previewMedia(reference)` opens an authorized `audio` or `video`
|
|
1021
1025
|
reference as a temporary playback copy and returns `{kind, url, mimeType, bytes}`.
|
|
1022
1026
|
Assign its URL to an existing `<audio controls>` or `<video controls>` element.
|
|
1027
|
+
StillMade plays a `<video controls>` in its own player, with full screen; leave
|
|
1028
|
+
out `controls` when the Block drives playback itself, or add
|
|
1029
|
+
`data-stillmade-player="native"` to keep the browser's controls.
|
|
1023
1030
|
The host requires an exact reference from this Block’s bound input, an explicitly
|
|
1024
1031
|
selected project asset, permitted project context, or a host-recorded output.
|
|
1025
1032
|
A URL alone is insufficient. Preview has host file pickers for audio/video inputs;
|
|
@@ -1741,6 +1748,47 @@ rest. Colors written with them follow Light, Dark and White automatically.
|
|
|
1741
1748
|
Frame views are not required to use them; the appearance check reports
|
|
1742
1749
|
hard-coded colors as advice instead of refusing the view.
|
|
1743
1750
|
|
|
1751
|
+
### Layout
|
|
1752
|
+
|
|
1753
|
+
StillMade zooms a view to fill the space its Step gives it (up to 150%), and
|
|
1754
|
+
Ctrl/Cmd +, - and 0 size the view while it has focus. It never centers a frame
|
|
1755
|
+
view; a standard view narrower than its Step is centered by its margins.
|
|
1756
|
+
|
|
1757
|
+
An app that lays itself out (a full-size canvas or WebGL, its own scroll, pan
|
|
1758
|
+
or zoom, its own Ctrl/Cmd +/- keys, as in a CAD or drawing tool) puts
|
|
1759
|
+
`data-stillmade-layout="own"` on its outermost element:
|
|
1760
|
+
|
|
1761
|
+
```html
|
|
1762
|
+
<div id="root" data-stillmade-layout="own"></div>
|
|
1763
|
+
```
|
|
1764
|
+
|
|
1765
|
+
StillMade then never centers or zooms it and leaves Ctrl/Cmd +, - and 0 to the
|
|
1766
|
+
app. Without the attribute StillMade also stays out of the way when the view
|
|
1767
|
+
looks like an app: no page padding, a clipped page, a root as tall as the frame,
|
|
1768
|
+
fixed over half of it or scrolling over half of it, a canvas, SVG or
|
|
1769
|
+
`touch-action: none` surface over 40% of it, or a canvas or SVG of 300x200 or
|
|
1770
|
+
more with `touch-action: none` (as Three.js's controls set it). Mark the root
|
|
1771
|
+
anyway, in `view.html` rather than from code: StillMade reads it before the view
|
|
1772
|
+
starts, so the app never shows StillMade's size control or loses a key to it,
|
|
1773
|
+
even while it is still loading.
|
|
1774
|
+
|
|
1775
|
+
A `<video controls>` plays in StillMade's player, the same one as everywhere in
|
|
1776
|
+
StillMade: play, timeline, time, sound and full screen along the bottom, shown
|
|
1777
|
+
while the pointer is on the video, with keys on the focused video (Space or K,
|
|
1778
|
+
the arrows, M, F) and touch. Full screen goes through StillMade, right after a
|
|
1779
|
+
click or key in the view; the frame itself has no `allow="fullscreen"`. A
|
|
1780
|
+
`<video>` without `controls` is the Block's own and StillMade never touches it,
|
|
1781
|
+
so a Block that drives playback (its own timeline, an editor or CAD viewer)
|
|
1782
|
+
leaves `controls` out, and `data-stillmade-player="native"` keeps the browser's
|
|
1783
|
+
controls. Result pictures from `StillMade.previewImage` in `sm-stage` or
|
|
1784
|
+
`sm-gallery`, and any element marked `data-stillmade-expand`, get a full-screen
|
|
1785
|
+
button in the bottom-right corner while the pointer is on them; pictures with
|
|
1786
|
+
the same value (`data-stillmade-expand="shots"`) open as one set, and
|
|
1787
|
+
`data-stillmade-expand="off"` removes the button. The keyboard reaches them
|
|
1788
|
+
too: such a picture without a `tabindex` of its own joins the tab order,
|
|
1789
|
+
keyboard focus on it shows the button, Enter or Space opens the viewer, and
|
|
1790
|
+
closing the viewer gives the focus back to the picture.
|
|
1791
|
+
|
|
1744
1792
|
### Assets
|
|
1745
1793
|
|
|
1746
1794
|
Images, fonts, JSON, audio and video the view needs ship as files named by
|
|
@@ -6028,7 +6076,7 @@ export interface BlockViewBridge { connectDocument(options:import('./document-st
|
|
|
6028
6076
|
export interface SdkCompatibility { status:'supported'|'unsupported'|'invalid'; declared:unknown; runtimeVersion:string; message:string; }
|
|
6029
6077
|
export function sdkCompatibility(declared:unknown,runtimeVersion?:string):SdkCompatibility;
|
|
6030
6078
|
export type Port = { type: string; imageMode?: 'pixels'|'reference'; role?: string; context?: keyof typeof CONTEXT_FIELDS; primary?: boolean; required?: boolean; default?: unknown; min?: number; max?: number; description?: string } & Partial<import('./semantic-contracts.js').SemanticContract>;
|
|
6031
|
-
export interface Manifest { schemaVersion: 1; id: string; name: string; version: string; sdkVersion: SdkVersionRange; description: string; kind: 'task'|'workspace'|'editor-extension'|'composite'; inputs: Record<string, Port>; outputs: Record<string, Port>; runtime: 'recipe'|'javascript'|'module'|'comfyui'|'capability'; jobs?: {kind:'cooperative';version:1}; state?: {scope:'step';version:number;initial:Record<string,unknown>;migrations?:StateMigration[]}; entry?: string; permissions: { project: string[]; desktop?: DesktopPermission[]; capabilities?: ['comfyui.execute']|['text.generate']|['audio.speech']|['audio.transcribe']|['image.generate']|['video.generate']|['image.describe']|['timeline.propose']|['workspace.propose']|['connection.execute']; network?: never[]; filesystem?: never[]; secrets?: never[] }; desktopTools?:DesktopToolDeclaration[]; uiLayout?: {kind:'tabs'|'sections';groups:{id:string;label:string;inputs:string[];outputs:string[];collapsed?:boolean}[]}; ui?: ({ control: 'text'|'number'|'slider'|'checkbox'|'asset'; port: string; label?: string; when?: {port:string;equals:string|boolean} } | {control:'select'|'multiselect';port:string;options:string[];label?:string;when?:{port:string;equals:string|boolean}} | {control:'gallery';port:string;label?:string} | {control:'before-after';port:string;before:string;label?:string})[]; }
|
|
6079
|
+
export interface Manifest { schemaVersion: 1; id: string; name: string; version: string; sdkVersion: SdkVersionRange; description: string; action?: { label: string; running?: string }; kind: 'task'|'workspace'|'editor-extension'|'composite'; inputs: Record<string, Port>; outputs: Record<string, Port>; runtime: 'recipe'|'javascript'|'module'|'comfyui'|'capability'; jobs?: {kind:'cooperative';version:1}; state?: {scope:'step';version:number;initial:Record<string,unknown>;migrations?:StateMigration[]}; entry?: string; permissions: { project: string[]; desktop?: DesktopPermission[]; capabilities?: ['comfyui.execute']|['text.generate']|['audio.speech']|['audio.transcribe']|['image.generate']|['video.generate']|['image.describe']|['timeline.propose']|['workspace.propose']|['connection.execute']; network?: never[]; filesystem?: never[]; secrets?: never[] }; desktopTools?:DesktopToolDeclaration[]; uiLayout?: {kind:'tabs'|'sections';groups:{id:string;label:string;inputs:string[];outputs:string[];collapsed?:boolean}[]}; ui?: ({ control: 'text'|'number'|'slider'|'checkbox'|'asset'; port: string; label?: string; when?: {port:string;equals:string|boolean} } | {control:'select'|'multiselect';port:string;options:string[];label?:string;when?:{port:string;equals:string|boolean}} | {control:'gallery';port:string;label?:string} | {control:'before-after';port:string;before:string;label?:string})[]; }
|
|
6032
6080
|
export interface BlockView { html: string; css?: string; themedCss?: string; javascript?: string; appearance?: 'host'|'original'; }
|
|
6033
6081
|
/** A frame view: any interface code (frameworks, SVG, canvas, drag) with assets named by SHA-256. */
|
|
6034
6082
|
export interface FrameView { runtime: 'frame'; html: string; css?: string; themedCss?: string; javascript?: string; appearance?: 'host'|'original'; files?: {schemaVersion: 1; files: Record<string, {sha256: string; bytes: number; mediaType: string}>}; }
|
|
@@ -6428,7 +6476,7 @@ export * from './native-host-providers.js';
|
|
|
6428
6476
|
|
|
6429
6477
|
export {blockRemixPolicy,assertRemixReady,REMIX_AUTHORING_REQUIREMENT} from './remix-policy.js';
|
|
6430
6478
|
export interface SdkCompatibility {status:'supported'|'unsupported'|'invalid';declared:unknown;runtimeVersion:string;message:string}
|
|
6431
|
-
export interface Manifest { schemaVersion: 1; id: string; name: string; version: string; sdkVersion: SdkVersionRange; description: string; kind: 'task'|'workspace'|'editor-extension'|'composite'; inputs: Record<string, Port>; outputs: Record<string, Port>; runtime: 'recipe'|'javascript'|'module'|'comfyui'|'capability'; jobs?: {kind:'cooperative';version:1}; state?: {scope:'step';version:number;initial:Record<string,unknown>;migrations?:StateMigration[]}; entry?: string; permissions: { project: string[]; desktop?: DesktopPermission[]; capabilities?: ['comfyui.execute']|['text.generate']|['audio.speech']|['audio.transcribe']|['image.generate']|['video.generate']|['image.describe']|['timeline.propose']|['workspace.propose']|['connection.execute']; network?: never[]; filesystem?: never[]; secrets?: never[] }; uiLayout?: {kind:'tabs'|'sections';groups:{id:string;label:string;inputs:string[];outputs:string[];collapsed?:boolean}[]}; ui?: ({ control: 'text'|'number'|'slider'|'checkbox'|'asset'; port: string; label?: string; when?: {port:string;equals:string|boolean} } | {control:'select'|'multiselect';port:string;options:string[];label?:string;when?:{port:string;equals:string|boolean}} | {control:'gallery';port:string;label?:string} | {control:'before-after';port:string;before:string;label?:string})[]; }
|
|
6479
|
+
export interface Manifest { schemaVersion: 1; id: string; name: string; version: string; sdkVersion: SdkVersionRange; description: string; action?: { label: string; running?: string }; kind: 'task'|'workspace'|'editor-extension'|'composite'; inputs: Record<string, Port>; outputs: Record<string, Port>; runtime: 'recipe'|'javascript'|'module'|'comfyui'|'capability'; jobs?: {kind:'cooperative';version:1}; state?: {scope:'step';version:number;initial:Record<string,unknown>;migrations?:StateMigration[]}; entry?: string; permissions: { project: string[]; desktop?: DesktopPermission[]; capabilities?: ['comfyui.execute']|['text.generate']|['audio.speech']|['audio.transcribe']|['image.generate']|['video.generate']|['image.describe']|['timeline.propose']|['workspace.propose']|['connection.execute']; network?: never[]; filesystem?: never[]; secrets?: never[] }; uiLayout?: {kind:'tabs'|'sections';groups:{id:string;label:string;inputs:string[];outputs:string[];collapsed?:boolean}[]}; ui?: ({ control: 'text'|'number'|'slider'|'checkbox'|'asset'; port: string; label?: string; when?: {port:string;equals:string|boolean} } | {control:'select'|'multiselect';port:string;options:string[];label?:string;when?:{port:string;equals:string|boolean}} | {control:'gallery';port:string;label?:string} | {control:'before-after';port:string;before:string;label?:string})[]; }
|
|
6432
6480
|
export interface BlockPackage { portable?: PortableMetadata; manifest: Manifest; view?: BlockView|FrameView; code?: string; module?: ModuleDescriptor; comfyui?: ComfyWorkflow; capability?: ConnectedCapability|TextGenerationCapability|SpeechCapability|TranscriptionCapability|ImageGenerationCapability|VideoGenerationCapability|ImageDescriptionCapability|TimelineProposalCapability; recipe?: { schemaVersion: 1; steps: { id: string; op: string; args: Record<string, unknown> }[]; outputs: Record<string, unknown> }; tests: { name: string; input: Record<string, unknown>; expected?: Record<string, unknown>; state?: BlockState; expectedState?: BlockState; expectations?: Record<string, ConnectedResultExpectation|ComfyImageExpectation|CapabilityTextExpectation|CapabilityAudioExpectation|CapabilityTranscriptExpectation|CapabilityImageExpectation|CapabilityVideoExpectation|CapabilityTimelineExpectation> }[]; }
|
|
6433
6481
|
export type CapabilityInvocation = TextGenerationInvocation|SpeechInvocation|TranscriptionInvocation|ImageGenerationInvocation|VideoGenerationInvocation|ImageDescriptionInvocation|TimelineProposalInvocation;
|
|
6434
6482
|
export interface CapabilityResult { outputs: Record<string, unknown>; metadata?: Record<string, unknown>; mediaReceipts?: Record<string, SpeechMediaReceipt|GeneratedAudioMediaReceipt|GeneratedImageMediaReceipt|GeneratedVideoMediaReceipt>; }
|
|
@@ -7389,9 +7437,9 @@ Ask the assistant to return source files or one `.stillmade.json` package. Run t
|
|
|
7389
7437
|
|
|
7390
7438
|
<!-- builder-contract:start (generated by npm run build:sdk; do not edit) -->
|
|
7391
7439
|
|
|
7392
|
-
### Block builder contract (stillmade.block-builder@1.
|
|
7440
|
+
### Block builder contract (stillmade.block-builder@1.16.0)
|
|
7393
7441
|
|
|
7394
|
-
Contract `stillmade.block-builder@1.
|
|
7442
|
+
Contract `stillmade.block-builder@1.16.0`. Humans, coding agents, imported source, GitHub repositories and generated code all adapt to the Block platform; anything that becomes a StillMade Block obeys this contract.
|
|
7395
7443
|
|
|
7396
7444
|
### Source of truth
|
|
7397
7445
|
|
|
@@ -7453,9 +7501,13 @@ Give the Block a short, plain name of 40 characters or fewer that says what it d
|
|
|
7453
7501
|
|
|
7454
7502
|
Name each input for what the person brings, in the job's words: `sermonVideo` for a sermon clip Block, `listingPhotos` for a listing, `lessonSlides` for a lesson podcast. StillMade titles the input from that name ("Sermon video") and words its drop area from it ("Drop your sermon video here", the formats, "Choose a video"), in StillMade and the SDK preview, so never draw your own upload box for an input. Keep a bare type name (`video`, `file`) only when any file of that kind does the job. The `description` says what makes a good one.
|
|
7455
7503
|
|
|
7504
|
+
### Speak the job
|
|
7505
|
+
|
|
7506
|
+
These are StillMade's defaults: unless the person or the creator asked for something else, every screen speaks the job in its own words and adds nothing else. `manifest.action` names the Step's button, {label:"Plan the tour", running:"Planning the tour…"}, and StillMade adds the price ("Plan the tour · 1 credit"). When the Block makes a picture, video or sound with AI the label starts with Generate and says what ("Generate tour", "Generate voiceover"); one that cuts or renders the person's own media says Make ("Make 6 clips"); never "Make it", "Run", "Submit", "Process" or a bare "Generate". The main button stands out: one solid `sm-primary` in the kit's ink, never restyled to the background; everything else is `sm-quiet` or an `sm-icon`, and close is an X icon. Report progress in the job's units with `stillmade.progress(fraction, label)` ("Moving through the kitchen, 4 of 9 rooms"), never "Processing". Head the result in the job's words ("9 rooms", "Your tour · 44 s"), never "Output". Say a problem in one line with its fix beside it ("No bathroom photo. Guests look for one." and Add photo). Stay quiet: no welcome text, tips under fields, tours or banners, and at most one line of guidance on a screen, only where the next move is not obvious; anything more goes in the input's `description`, which StillMade shows behind an (i). Say nothing about how the Block works (where it runs, saving, syncing, recovery, accounts, credits) or where a file is kept: StillMade tells the person what they need as one short notification, or nothing; never a sentence on the page, and never the same line under each item. Every drop area offers "Use a reference", which fills the Step from the person's saved photos, videos and notes: media inputs fill by kind, so take `video` or `asset` where a clip works as well as a photo, and text inputs fill by plain names and labels (`productName`, `website`, `brandColors`, `fonts`, `voice`, and `details` or `notes` for the reference's note); never build your own reference picker. Days and times are picked, never typed: use the `date` type, which StillMade shows as a calendar, with a list of times when the input is about a time (`postAt`, `startsAt`); a custom view uses `<input type="date">` or `type="datetime-local"`. Posting is a connector Step of its own, and StillMade words its button from the app and action ("Post to Instagram"). Before handing the Block back, clear every Wording note that `gate` and readiness list, unless the person asked for those words.
|
|
7507
|
+
|
|
7456
7508
|
### Interface
|
|
7457
7509
|
|
|
7458
|
-
If the capability needs UI, use the Block UI SDK: generated `manifest.ui` controls first; a sandboxed custom view (`view.html`/`view.css`/`view.js`) only when the core interaction needs one. Build custom views from the Block kit the host injects (`block-kit.css`): the result in `sm-stage`, picks as pictures in `sm-choices`, one `sm-primary` naming the action (
|
|
7510
|
+
If the capability needs UI, use the Block UI SDK: generated `manifest.ui` controls first; a sandboxed custom view (`view.html`/`view.css`/`view.js`) only when the core interaction needs one. Build custom views from the Block kit the host injects (`block-kit.css`): the result in `sm-stage`, picks as pictures in `sm-choices`, the picked one in the kit's ink fill (never restyled to an outline, a tint or the page's background) so it reads at a glance, one solid `sm-primary` naming the action in the job's words ("Plan the tour", "Generate voiceover"; never "Run" or "Make it") and no price (StillMade's run button adds it), extras in a closed `sm-more`; a look the person names wins. Fit one laptop screen without scrolling: label beside control, status in a few words, files as tiles, rare tools as icons, (i) on unclear controls. These compact rules are for a job or an ingredient. Size the view to the Block's tier (block-tier.js): an app, a workspace a person works in for a while (video editor, 3D configurator, CAD or drawing tool), looks and works like that kind of app instead of a compact page: its canvas or stage fills the view, with the panels, toolbars, inspector or timeline such an app has, direct manipulation (select, drag, zoom), keyboard shortcuts and undo; it keeps the host appearance and Block kit controls, its panels may scroll, and on a phone its tools fold into sheets while the canvas stays usable. Never shrink an app into a form of fields and one button. StillMade centers a standard view narrower than its Step and zooms a view to fill its space; an app that lays itself out (full-size canvas or WebGL, its own scroll, pan or zoom, its own Ctrl/Cmd +/- keys) puts `data-stillmade-layout="own"` on its outermost element, and StillMade then never centers, zooms or takes those keys. StillMade draws one player for every `<video controls>` (play, timeline, time, sound and full screen, shown while the pointer is on the video, with keys and touch) and a full-screen button on result pictures in `sm-stage` or `sm-gallery` and on any element marked `data-stillmade-expand` (the same value makes one set of pictures, `off` removes it); `data-stillmade-player="native"` keeps the browser's controls, and a `<video>` without `controls` is the Block's own and is never touched. A picture or clip that cannot show here (kept on another device, or it did not open) keeps its place as a quiet `sm-media-off` tile in its own shape with the `image-off` glyph and the reason in its label, never words in its place. Drop words nobody needs; put helpful ones in a closed `sm-hint`. Mark each button `data-stillmade-action="what it does"` and label each field: Chat presses and fills them. Expose the capability, not the implementation: sensible defaults, previews, progress, clear errors, visible outputs. Show no raw JSON, internal IDs, filesystem details, provider terms or developer settings unless the Block is a developer tool. When a person chooses among options they need to hear or see (voices, music, fonts, looks, templates, images), let them preview each option before choosing: a sample or thumbnail from the Block's own files or the host's free samples, never a paid generation. Skip previews only when there is nothing to preview. Choices StillMade owns (voices, models in the run review) already show samples. Follow the host appearance (Light, Dark and White) and one elastic layout: stacked on a 320px phone with no sideways scroll (result first, action pinned), and from 860px the controls left (≤380px), the result filling the right. Short settings sit side by side, each label beside its control (`sm-field`, `sm-settings`; three or four short options as one `data-segmented` row); many items are one line each (`sm-list`) that open in place; input files are small tiles (`sm-gallery data-size="small"`); on a phone chip rows scroll sideways and long lists show three. Compacting moves controls, never deletes them.
|
|
7459
7511
|
|
|
7460
7512
|
### Shared editing
|
|
7461
7513
|
|
|
@@ -7625,7 +7677,7 @@ Optional custom view interfaces are supported, but generated manifest.ui control
|
|
|
7625
7677
|
|
|
7626
7678
|
*When:* StillMade's builder adds this section when the person asks for an interface, preview or controls, or refines a Block that has one.
|
|
7627
7679
|
|
|
7628
|
-
A custom interface is the optional package-level view:{html,css?,themedCss?,javascript?}; when refining, preserve and refine base.view. Design it by StillMade's interface principles, in order: Function first: unless the person asks for a design direction, build from the Block kit (`sm-block`, `sm-stage`, `sm-choices`, `sm-actions`, `sm-more`) and ship little or no CSS of your own. A direction the person names wins over the kit. Show the thing being made: the preview, media or result gets the largest area (`sm-stage`). A picture or clip the Block makes fills it in its own shape, as large as fits; several fill it as a grid, each big enough to watch. Small tiles are for the files a person gives the Block, never for what it makes. Never a JSON dump, source editor, manifest or diagnostic panel unless the task is about source. One obvious next action
|
|
7680
|
+
A custom interface is the optional package-level view:{html,css?,themedCss?,javascript?}; when refining, preserve and refine base.view. Design it by StillMade's interface principles, in order: Function first: unless the person asks for a design direction, build from the Block kit (`sm-block`, `sm-stage`, `sm-choices`, `sm-actions`, `sm-more`) and ship little or no CSS of your own. A direction the person names wins over the kit. Show the thing being made: the preview, media or result gets the largest area (`sm-stage`). A picture or clip the Block makes fills it in its own shape, as large as fits; several fill it as a grid, each big enough to watch. Small tiles are for the files a person gives the Block, never for what it makes. A clip is a `<video controls>`, which StillMade plays in its own player with full screen, and a picture in `sm-stage` or `sm-gallery` (or marked `data-stillmade-expand`) gets StillMade's full-screen button; leave out `controls` only when the Block drives playback itself. Never a JSON dump, source editor, manifest or diagnostic panel unless the task is about source. One obvious next action: one solid `sm-primary` in the kit's ink, never restyled to the background or a ghost outline; peers are `sm-quiet` buttons or named icons, and close is an X icon. Seven or fewer choices in view. Speak the job unless the person or creator asks otherwise. The action button names what it does in the job's words (`manifest.action`: "Plan the tour"; AI pictures, video and sound start with Generate and say what, the person's own media cut or rendered says Make: "Generate voiceover", "Make 6 clips"), never "Make it", "Run", "Run step", "Submit", "Process" or a bare "Generate"; progress counts the job's units ("4 of 9 rooms"), never "Processing"; results and problems use its words in one line. Show no credit numbers: StillMade puts the price beside the verb on its own run button ("Write · 1 credit"), with a chip for the model, quality or count when they can change. Pressing it runs at that price; a confirmation appears only when the server price is higher than the one shown. Pictures over words: choices people see or hear are thumbnails, swatches, samples or glyphs (`sm-choices`), not word lists. Icons carry an accessible name and tooltip; never emoji. A picked option reads at a glance: keep the kit's ink fill on an `sm-choices` pick, never restyled to an outline, a tint or the page's background. Media that cannot show here (on another device, or it did not open) keeps its place as a quiet `sm-media-off` tile in its own shape, never words in its place. Words only when needed. Drop what nobody needs to finish the task (intros, "how it works", restating the Block name). Words that might help start collapsed (`sm-hint`, `sm-more`). Errors, spending approvals, stale inputs and destructive steps stay visible, in few words. Strong defaults; secondary settings go in `sm-more`, closed. Compact: the whole Block fits one laptop screen without scrolling. A short setting is one row, its label beside the control; no card around a single control. Status is a dot or a few words ("No narration yet"), never a paragraph; the reason sits behind an `sm-hint`. Files are tiles: a saved file is a thumbnail or chip and adding one is a + tile. Never the bare browser file picker, and no size limits in view until a file is too big. Rare tools (update, schedule, history, reload) are named icon buttons beside the action, never sections under the work. An (i) beside anything a newcomer could misread: a setting, status or number whose effect is not obvious from its label gets a closed `sm-hint` with one or two sentences. Give every input that needs one a `description`; StillMade shows it as that (i). Obvious controls get none. One workspace: no cards inside cards, no second title, step counter or Back/Next bar; the host owns navigation. Status sits beside the action it describes (`sm-status`), in a few words. Keep the page in normal scroll flow; no sticky media or control strips unless the editing task needs them. Use the width: from 860px wide the kit puts the controls on the left at a reading width (300–380px) and the result (`sm-stage`) fills the right, in its real shape; under that everything stacks with the result first and the action within reach. Extra width goes to the result, never to wider text fields. Before there is a result, the stage previews what will be made from the inputs. `data-layout="stack"` opts out. Size with the kit, never fixed sizes: no fixed pixel widths or heights for the workspace or stage, no 100vh, no position:fixed panels. StillMade zooms a Block's screen to fill the space it has (up to 150%, never down to a phone layout on a computer), so a Block laid out with the kit's spacing fills its Step without empty space, and it centers a standard view narrower than its Step. An app that lays itself out (full-size canvas or WebGL, its own scroll, pan or zoom, its own Ctrl/Cmd +/- keys) puts `data-stillmade-layout="own"` on its outermost element, and StillMade then never centers, zooms or takes those keys. Settings sit side by side (`sm-settings`), next to what they change. Three or four short options are one segmented row (`data-segmented`), not a row of big tiles. Lists fill the width at a small size: input files are small tiles (`sm-gallery data-size="small"`), many items are one line each (`sm-list`): a thumbnail, one line of text, a short fact. Tapping an item opens all of its fields in place. Extra width means more items per row, never bigger cards. On a phone chip and segment rows scroll sideways instead of wrapping; long lists show their first three with "N more" (`data-peek`) and long text five lines until tapped (`sm-clamp`). Nothing is lost when a Block gets smaller: every control stays on the screen, behind an (i), in `sm-more`, or inside the item it belongs to. Compacting moves controls; it never deletes them. Text scene descriptions are planning notes, never a storyboard or an approved frame. Say nothing about how the Block works: no notes on where it runs (this device, StillMade Desktop, the cloud), saving, syncing, recovery, accounts, credits or where a file is kept. StillMade tells the person what they need as one short notification, or nothing; never a sentence on the page, and never the same line under each item. References fill your inputs: every drop area in StillMade offers "Use a reference", and the person's saved photos, videos and notes fill the Step with no typing. Media inputs fill by kind, so take `video` or `asset` wherever a clip works as well as a photo; text inputs fill by plain names and labels (`productName`, `website`, `brandColors`, `fonts`, `voice`, and `details` or `notes` for the reference's note). Never build your own reference picker or library upload. Days and times are picked, never typed: a `date` input is a calendar, with a list of times when it is about a time (`postAt`, `startsAt`, a label with Time, When or Starts). In a custom view use `<input type="date">` or `type="datetime-local"`, never a text box for a date. Posting is its own Step: sending a result to Instagram, TikTok, email or any app is a connector Step after the Block, worded by StillMade ("Post to Instagram"). A Block never posts from inside itself. Its DOM controller is separate from manifest runtime code. The view may also declare appearance:"original" or "host". For an imported design, preserve its colors with appearance:"original" and view.css; no themed replacement is required. Preserve base.view.appearance when refining unless the user requests a change. Omitted/host appearance retains the existing Light, Dark and White requirement: supply semantic colors in view.css or a complete replacement view.themedCss. An original-style view may optionally supply valid themedCss for a StillMade appearance preview. Use StillMade variables (--bg,--fg,--fg-muted,--border-tok,--r-3) only when opting into host styling; do not redefine host tokens in the themed variant. Appearance never relaxes sandbox constraints: no CSS escapes/filters/blending, imports/url(), or element.style mutations in JS. Use classes for UI state; media pixels retain their colors. Both CSS fields have the same 32 KiB limit; all existing shared-state, security and permission checks still apply. Declare elements in html, bind with document.getElementById/querySelector and addEventListener; use literal property access, array methods, textContent, input.value, button.disabled and canvas. Initial values: StillMade.onInput(values=>{...}); await StillMade.run(inputBindings) returns validated output bindings from the isolated package runtime; catch errors and show results. No computation in the DOM controller; put it in code/recipe. Disable the action button while pending.
|
|
7629
7681
|
Standard custom view code (no `view.config.json` frame runtime) is checked before it runs. These rules come straight from the validator; frame views run in their own sandbox and may build the page with ordinary DOM calls such as `createElement`:
|
|
7630
7682
|
|
|
7631
7683
|
- **HTML elements:** only `div`, `section`, `article`, `header`, `footer`, `main`, `aside`, `nav`, `h1`, `h2`, `h3`, `h4`, `p`, `span`, `strong`, `em`, `i`, `small`, `br`, `hr`, `label`, `input`, `textarea`, `button`, `select`, `option`, `optgroup`, `fieldset`, `legend`, `output`, `progress`, `meter`, `ul`, `ol`, `li`, `dl`, `dt`, `dd`, `figure`, `figcaption`, `img`, `video`, `audio`, `source`, `canvas`, `table`, `thead`, `tbody`, `tfoot`, `tr`, `th`, `td`, `pre`, `code`, `details`, `summary`. No scripts, iframes, SVG, forms, comments or inline event attributes; media URLs must be `data:` or `blob:`.
|
|
@@ -8317,7 +8369,8 @@ exact permission, such as `context.versions.read`.
|
|
|
8317
8369
|
`ui` is an array of `{ "control": "...", "port": "inputName" }` objects.
|
|
8318
8370
|
Control must be one of `text`, `number`, `slider`, `checkbox`, `asset`, `select`,
|
|
8319
8371
|
`multiselect`, `file`, `date`, `color`, `url`, `richtext`, `list` or `grid`, bound to an
|
|
8320
|
-
existing input.
|
|
8372
|
+
existing input. A field's label is its `ui` entry's `label` when given, in the job's
|
|
8373
|
+
words ("When to post"), else its port name; its (i) is the port's `description`. For a numeric slider,
|
|
8321
8374
|
give its input `type`, `min`, `max`, and `default`. Use `asset` for an image input.
|
|
8322
8375
|
For a custom visual interface, add the optional `view` object below. Do not supply React components, external dependencies, or a hosted UI URL.
|
|
8323
8376
|
|
|
@@ -9695,7 +9748,9 @@ still owns specialized workspace layout. A 320 CSS-pixel phone viewport leaves
|
|
|
9695
9748
|
less than 320 pixels inside the host's preview gutters. Size from the embedded
|
|
9696
9749
|
view's actual container, avoid a 320-pixel minimum width, wrap long labels, and
|
|
9697
9750
|
isolate intentional canvas/timeline panning from
|
|
9698
|
-
the surrounding toolbar.
|
|
9751
|
+
the surrounding toolbar. A `<video controls>` gets StillMade's player, whose
|
|
9752
|
+
44-pixel controls a tap shows for 3 seconds (a first tap never starts playback),
|
|
9753
|
+
and a result picture's full-screen button shows for 3 seconds after a tap on it. Provide visible buttons or menus for actions otherwise
|
|
9699
9754
|
available by hover, drag, right-click, or keyboard shortcut. Label fields and
|
|
9700
9755
|
announce loading, errors, and completed output with `role="status"`,
|
|
9701
9756
|
`role="alert"`, or `aria-live` as appropriate. For deterministic custom-view
|
|
@@ -9803,7 +9858,7 @@ piece in Light, Dark and White.
|
|
|
9803
9858
|
</div>
|
|
9804
9859
|
|
|
9805
9860
|
<div class="sm-actions">
|
|
9806
|
-
<button type="button" class="sm-primary" id="run" data-stillmade-action="
|
|
9861
|
+
<button type="button" class="sm-primary" id="run" data-stillmade-action="make the clip">Make the clip</button>
|
|
9807
9862
|
<p class="sm-status" id="status" role="status"></p>
|
|
9808
9863
|
</div>
|
|
9809
9864
|
|
|
@@ -9819,7 +9874,7 @@ piece in Light, Dark and White.
|
|
|
9819
9874
|
| `sm-block` | The one workspace. `data-layout="split"` puts the stage beside the controls on wide screens. |
|
|
9820
9875
|
| `sm-stage` | The thing being made: preview, media or result. `data-ratio="16:9"`, `"9:16"` or `"1:1"`. |
|
|
9821
9876
|
| `sm-empty` | An empty stage: a glyph, at most five words, one action. |
|
|
9822
|
-
| `sm-choices` | Picks shown as pictures (`img`, `.sm-swatch`, `.sm-glyph`) and one or two words. `data-compact` for short text chips, `data-segmented` for one connected row of three or four short options. Chips and segments scroll sideways on a phone. Give the `fieldset` an `id` and `data-stillmade-share` so teammates see the same pick. |
|
|
9877
|
+
| `sm-choices` | Picks shown as pictures (`img`, `.sm-swatch`, `.sm-glyph`) and one or two words. `data-compact` for short text chips, `data-segmented` for one connected row of three or four short options. The pick is filled with the kit's ink, so it reads at a glance; a `disabled` fieldset keeps its pick and fades the rest. Chips and segments scroll sideways on a phone. Give the `fieldset` an `id` and `data-stillmade-share` so teammates see the same pick. |
|
|
9823
9878
|
| `sm-field`, `sm-fields` | One short setting on one row, its label beside the control; a responsive group of them. On a phone the control wraps under its label only when both do not fit. A textarea, picture choices, file tiles or a list keep the label above. |
|
|
9824
9879
|
| `sm-settings` | Short settings side by side, each label beside its control; a narrow cell wraps the control under its label. |
|
|
9825
9880
|
| `sm-list` | Many items, one line each: a thumbnail, one line of text, a short fact. An item that opens in place is an `li` holding a `details`. `data-peek` shows three on a phone, with a last `li.sm-list-more` button that sets `data-open`. |
|
|
@@ -9829,7 +9884,8 @@ piece in Light, Dark and White.
|
|
|
9829
9884
|
| `sm-more` | A closed `<details>` for secondary settings. |
|
|
9830
9885
|
| `sm-hint` | A closed `<details>` info toggle for an explanation that might help. |
|
|
9831
9886
|
| `sm-gallery` | A grid of results or media. `data-size="small"` for input files: more tiles per row as the screen widens. |
|
|
9832
|
-
| `sm-
|
|
9887
|
+
| `sm-media-off` | A picture or clip that cannot show here (on another device, or it did not open): a quiet tile in its own shape (`--sm-photo-ratio`, the tile's shape in a gallery) holding the `image-off` glyph, the reason in `aria-label` and `title`, no words inside. |
|
|
9888
|
+
| `sm-glyph` | A small icon in `currentColor`: `play`, `pause`, `plus`, `close`, `check`, `chevron`, `upload`, `image`, `image-off`, `video`, `audio`, `text`, `spark`, `info`, `warning`, `spinner`. Works in standard views, which cannot use SVG. |
|
|
9833
9889
|
|
|
9834
9890
|
**Function first.** When the person building a Block does not ask for a look,
|
|
9835
9891
|
use the kit as is: they want it to work and be easy to use. When they name a
|
|
@@ -9845,8 +9901,9 @@ designs keep `appearance: "original"`.
|
|
|
9845
9901
|
| might help some people (what a setting does, a format limit) | Put them in a closed `sm-hint`, or secondary settings in a closed `sm-more`. |
|
|
9846
9902
|
| report an error, a spending approval, a stale input or a destructive step | Keep them visible, in few words. Say what to do next. |
|
|
9847
9903
|
|
|
9848
|
-
Buttons say the action in one to
|
|
9849
|
-
|
|
9904
|
+
Buttons say the action in the job's words, one to four of them ("Plan the tour",
|
|
9905
|
+
"Make 6 clips", "Export"), never "Make it". Status says the state in one to four
|
|
9906
|
+
words ("Making the clip", "Ready", "Needs approval").
|
|
9850
9907
|
|
|
9851
9908
|
The button that makes something names what it makes ("Write", "Generate image",
|
|
9852
9909
|
"Make video"), never "Run", "Run step", "Submit" or "Review cost", and says the
|
|
@@ -9860,7 +9917,56 @@ the same single priced button. Pressing a priced button runs at that price; a
|
|
|
9860
9917
|
confirmation appears only when the server's price is higher than the one shown.
|
|
9861
9918
|
Do not write credit numbers in the Block.
|
|
9862
9919
|
|
|
9863
|
-
### 3.
|
|
9920
|
+
### 3. Speak the job
|
|
9921
|
+
|
|
9922
|
+
These are StillMade's defaults for every Block, and they apply wherever the
|
|
9923
|
+
person or the creator has not asked for something else. What they ask for wins.
|
|
9924
|
+
|
|
9925
|
+
- **The job's words everywhere.** Bringing ("Your listing photos"), starting
|
|
9926
|
+
("Plan the tour"), working ("Moving through the kitchen, 4 of 9 rooms"),
|
|
9927
|
+
done ("Your tour · 44 s") and problems ("No bathroom photo. Guests look for
|
|
9928
|
+
one." with Add photo beside it). Never "Make it", "Run", "Submit",
|
|
9929
|
+
"Process", "Processing", "Output" or "Result".
|
|
9930
|
+
- **Name the Step's button in `manifest.action`**:
|
|
9931
|
+
`{"label":"Plan the tour","running":"Planning the tour…"}`. StillMade adds the
|
|
9932
|
+
price ("Plan the tour · 1 credit"). A picture, video or sound made with AI
|
|
9933
|
+
starts with Generate and says what ("Generate tour", "Generate voiceover");
|
|
9934
|
+
cutting or rendering the person's own media says Make ("Make 6 clips").
|
|
9935
|
+
Bare "Generate" or "Make" is not enough.
|
|
9936
|
+
- **The main button stands out.** One solid `sm-primary` per screen, in the
|
|
9937
|
+
kit's ink, never restyled to the page's background or a ghost outline; every
|
|
9938
|
+
other button is `sm-quiet` or an `sm-icon`. Close is an X icon, not the word.
|
|
9939
|
+
- **Quiet.** At most one line of guidance on a screen, only where the next
|
|
9940
|
+
move is not obvious. No welcome text, tips under fields, tours or banners.
|
|
9941
|
+
Anything more goes in the input's `description`, which StillMade shows
|
|
9942
|
+
behind an (i).
|
|
9943
|
+
- **Say nothing about how the Block works.** No notes on where it runs (this
|
|
9944
|
+
device, StillMade Desktop, the cloud), saving, syncing, recovery, accounts,
|
|
9945
|
+
credits or where a file is kept: StillMade says what a person needs, as one
|
|
9946
|
+
short notification, or nothing. Never a sentence on the page, and never the
|
|
9947
|
+
same line under each item.
|
|
9948
|
+
- **References fill your inputs.** Every drop area in StillMade offers "Use a
|
|
9949
|
+
reference": the person's saved photos, videos and notes fill the Step's
|
|
9950
|
+
fields with no typing. Media inputs fill by kind, so take `video` or `asset`
|
|
9951
|
+
wherever a clip works as well as a photo. Text inputs fill by their name and
|
|
9952
|
+
label: name them plainly (`productName`, `website`, `brandColors`, `fonts`,
|
|
9953
|
+
`voice`), and give the one that takes a reference's note a name such as
|
|
9954
|
+
`details`, `notes` or `listingDetails`; when a note has to be split across
|
|
9955
|
+
several fields StillMade does it free. Never build your own reference
|
|
9956
|
+
picker or library upload.
|
|
9957
|
+
- **Days and times are picked, never typed.** Use the `date` type. StillMade
|
|
9958
|
+
shows a calendar, and a list of times as well when the input is about a time
|
|
9959
|
+
(a name such as `postAt` or `startsAt`, a label with Time, When or Starts, or
|
|
9960
|
+
a value with a time). In a custom view use `<input type="date">` or
|
|
9961
|
+
`type="datetime-local"`, never a text box for a date.
|
|
9962
|
+
- **Posting is its own Step.** Sending a result to Instagram, TikTok, email or
|
|
9963
|
+
any app is a connector Step after the Block, and StillMade words its button
|
|
9964
|
+
("Post to Instagram"). A Block never posts from inside itself.
|
|
9965
|
+
- **Chat can do all of it.** Every button carries `data-stillmade-action`
|
|
9966
|
+
naming what it does and every field a label, so the project's Chat can press
|
|
9967
|
+
and fill them.
|
|
9968
|
+
|
|
9969
|
+
### 4. Rules
|
|
9864
9970
|
|
|
9865
9971
|
These are requirements for every author, person or model. Not all are checked
|
|
9866
9972
|
automatically. An explicit request from the person can authorize a named
|
|
@@ -9912,7 +10018,16 @@ exception, never unrelated technical UI.
|
|
|
9912
10018
|
within reach. Extra width goes to the result, never to wider text
|
|
9913
10019
|
fields. Before there is a result, the stage previews what will be made
|
|
9914
10020
|
from the inputs given so far, not an empty box. `data-layout="stack"`
|
|
9915
|
-
keeps one column.
|
|
10021
|
+
keeps one column. StillMade zooms a view to fill its space and centers a
|
|
10022
|
+
standard view narrower than its Step (by its margins only, so a margin
|
|
10023
|
+
the view sets wins). An app that lays itself out (full-size canvas or
|
|
10024
|
+
WebGL, its own scroll, pan or zoom, its own Ctrl/Cmd +/- keys) puts
|
|
10025
|
+
`data-stillmade-layout="own"` on its outermost element, and StillMade
|
|
10026
|
+
then never centers, zooms or takes those keys. StillMade plays every
|
|
10027
|
+
`<video controls>` in its own player with full screen, and puts a
|
|
10028
|
+
full-screen button on result pictures in `sm-stage` or `sm-gallery` and
|
|
10029
|
+
on anything marked `data-stillmade-expand`; a `<video>` without
|
|
10030
|
+
`controls` is the Block's own and is never touched.
|
|
9916
10031
|
17. Settings sit side by side, next to what they change. Short settings are
|
|
9917
10032
|
an `sm-settings` grid, and three or four short options (Low / Med /
|
|
9918
10033
|
High, 16:9 / 9:16 / 1:1) are one `data-segmented` row, not big tiles.
|
|
@@ -9927,8 +10042,24 @@ exception, never unrelated technical UI.
|
|
|
9927
10042
|
20. Nothing is lost when a Block gets smaller. Every control stays on the
|
|
9928
10043
|
screen, behind an (i), in `sm-more`, or inside the item it belongs to.
|
|
9929
10044
|
Compacting moves controls; it never deletes them.
|
|
9930
|
-
|
|
9931
|
-
|
|
10045
|
+
21. A picked option reads at a glance. The kit fills an `sm-choices` pick with
|
|
10046
|
+
its ink (`--fg` behind `--bg` words, the same inversion as every
|
|
10047
|
+
segmented control in StillMade); never restyle it to an outline, a tint or
|
|
10048
|
+
the page's background. A locked row (`disabled`, or a person who can only
|
|
10049
|
+
view) keeps its pick filled, fades the other options and does not react to
|
|
10050
|
+
the pointer.
|
|
10051
|
+
22. Media that cannot show here (kept on another device, or it did not open)
|
|
10052
|
+
keeps its place as a quiet `sm-media-off` tile in its own shape with the
|
|
10053
|
+
`image-off` glyph, the reason in its `aria-label` and `title`. Never words
|
|
10054
|
+
in its place:
|
|
10055
|
+
|
|
10056
|
+
```html
|
|
10057
|
+
<span class="sm-media-off" role="img" aria-label="On another device" title="On another device" style="--sm-photo-ratio:3/2">
|
|
10058
|
+
<span class="sm-glyph" data-glyph="image-off" aria-hidden="true"></span>
|
|
10059
|
+
</span>
|
|
10060
|
+
```
|
|
10061
|
+
|
|
10062
|
+
### 5. What StillMade checks
|
|
9932
10063
|
|
|
9933
10064
|
- Admission rejects a primary textarea of 12 or more rows when no task
|
|
9934
10065
|
presentation (stage, media, list or `StillMade.render`) is detected
|
|
@@ -9952,6 +10083,17 @@ exception, never unrelated technical UI.
|
|
|
9952
10083
|
(`blockKitProblems`; the failing rules are `BLOCK_KIT_READINESS_RULES`). StillMade's own Block builder also sends back a custom
|
|
9953
10084
|
view that is not built from `sm-block`, unless the person asked for their
|
|
9954
10085
|
own look (`appearance: "original"`).
|
|
10086
|
+
- Admission warns, and readiness lists a "Wording" limitation, when a button
|
|
10087
|
+
says "Make it", "Generate", "Create", "Process" or "Do it"; when progress
|
|
10088
|
+
says "Processing", "Loading" or "Working"; when a visible line explains where
|
|
10089
|
+
the Block runs or how it saves; when a date is typed into a text box; when
|
|
10090
|
+
the CSS turns `sm-primary` into a background-coloured button; when the CSS
|
|
10091
|
+
takes the ink fill off a pick (`.sm-choices label:has(input:checked)` with a
|
|
10092
|
+
transparent or page-coloured background, or the ink as its text colour); and
|
|
10093
|
+
when the page or a string in its code says where a file is kept ("Only on
|
|
10094
|
+
this device", "Not on this device"). Clear
|
|
10095
|
+
every one before you hand the Block back, unless the person asked for those
|
|
10096
|
+
words. They never refuse a release.
|
|
9955
10097
|
- The host supplies the Project Type step bar and omits its own title and frame
|
|
9956
10098
|
around custom views, and does not add a "Technical result" disclosure.
|
|
9957
10099
|
- HTML, JavaScript, permission and appearance validation are separate checks.
|
|
@@ -12541,7 +12683,7 @@ Music, sound effects and catalog voices are stored as the provider's measured MP
|
|
|
12541
12683
|
| `document` | Presents a `document` or Markdown `text` output as formatted text. |
|
|
12542
12684
|
| `chart` | Draws a `table` (optional `x` and `y` column names) or `number[]` output as a `bar` or `line` chart (`chart`). |
|
|
12543
12685
|
| `code` | Presents a `text`, `json` or `object` output as code with a copy button (optional `language`). |
|
|
12544
|
-
| `player` | Plays an `audio` or `video` output (or a list of them). |
|
|
12686
|
+
| `player` | Plays an `audio` or `video` output (or a list of them); a video plays in StillMade's player, with full screen. |
|
|
12545
12687
|
| `download` | Offers a `file`, `file[]` or `file-bundle` output as a download through the host export policy. |
|
|
12546
12688
|
|
|
12547
12689
|
## First-party Blocks
|
|
@@ -12714,7 +12856,7 @@ Optional custom view interfaces are supported, but generated manifest.ui control
|
|
|
12714
12856
|
|
|
12715
12857
|
*When:* StillMade's builder adds this section when the person asks for an interface, preview or controls, or refines a Block that has one.
|
|
12716
12858
|
|
|
12717
|
-
A custom interface is the optional package-level view:{html,css?,themedCss?,javascript?}; when refining, preserve and refine base.view. Design it by StillMade's interface principles, in order: Function first: unless the person asks for a design direction, build from the Block kit (`sm-block`, `sm-stage`, `sm-choices`, `sm-actions`, `sm-more`) and ship little or no CSS of your own. A direction the person names wins over the kit. Show the thing being made: the preview, media or result gets the largest area (`sm-stage`). A picture or clip the Block makes fills it in its own shape, as large as fits; several fill it as a grid, each big enough to watch. Small tiles are for the files a person gives the Block, never for what it makes. Never a JSON dump, source editor, manifest or diagnostic panel unless the task is about source. One obvious next action
|
|
12859
|
+
A custom interface is the optional package-level view:{html,css?,themedCss?,javascript?}; when refining, preserve and refine base.view. Design it by StillMade's interface principles, in order: Function first: unless the person asks for a design direction, build from the Block kit (`sm-block`, `sm-stage`, `sm-choices`, `sm-actions`, `sm-more`) and ship little or no CSS of your own. A direction the person names wins over the kit. Show the thing being made: the preview, media or result gets the largest area (`sm-stage`). A picture or clip the Block makes fills it in its own shape, as large as fits; several fill it as a grid, each big enough to watch. Small tiles are for the files a person gives the Block, never for what it makes. A clip is a `<video controls>`, which StillMade plays in its own player with full screen, and a picture in `sm-stage` or `sm-gallery` (or marked `data-stillmade-expand`) gets StillMade's full-screen button; leave out `controls` only when the Block drives playback itself. Never a JSON dump, source editor, manifest or diagnostic panel unless the task is about source. One obvious next action: one solid `sm-primary` in the kit's ink, never restyled to the background or a ghost outline; peers are `sm-quiet` buttons or named icons, and close is an X icon. Seven or fewer choices in view. Speak the job unless the person or creator asks otherwise. The action button names what it does in the job's words (`manifest.action`: "Plan the tour"; AI pictures, video and sound start with Generate and say what, the person's own media cut or rendered says Make: "Generate voiceover", "Make 6 clips"), never "Make it", "Run", "Run step", "Submit", "Process" or a bare "Generate"; progress counts the job's units ("4 of 9 rooms"), never "Processing"; results and problems use its words in one line. Show no credit numbers: StillMade puts the price beside the verb on its own run button ("Write · 1 credit"), with a chip for the model, quality or count when they can change. Pressing it runs at that price; a confirmation appears only when the server price is higher than the one shown. Pictures over words: choices people see or hear are thumbnails, swatches, samples or glyphs (`sm-choices`), not word lists. Icons carry an accessible name and tooltip; never emoji. A picked option reads at a glance: keep the kit's ink fill on an `sm-choices` pick, never restyled to an outline, a tint or the page's background. Media that cannot show here (on another device, or it did not open) keeps its place as a quiet `sm-media-off` tile in its own shape, never words in its place. Words only when needed. Drop what nobody needs to finish the task (intros, "how it works", restating the Block name). Words that might help start collapsed (`sm-hint`, `sm-more`). Errors, spending approvals, stale inputs and destructive steps stay visible, in few words. Strong defaults; secondary settings go in `sm-more`, closed. Compact: the whole Block fits one laptop screen without scrolling. A short setting is one row, its label beside the control; no card around a single control. Status is a dot or a few words ("No narration yet"), never a paragraph; the reason sits behind an `sm-hint`. Files are tiles: a saved file is a thumbnail or chip and adding one is a + tile. Never the bare browser file picker, and no size limits in view until a file is too big. Rare tools (update, schedule, history, reload) are named icon buttons beside the action, never sections under the work. An (i) beside anything a newcomer could misread: a setting, status or number whose effect is not obvious from its label gets a closed `sm-hint` with one or two sentences. Give every input that needs one a `description`; StillMade shows it as that (i). Obvious controls get none. One workspace: no cards inside cards, no second title, step counter or Back/Next bar; the host owns navigation. Status sits beside the action it describes (`sm-status`), in a few words. Keep the page in normal scroll flow; no sticky media or control strips unless the editing task needs them. Use the width: from 860px wide the kit puts the controls on the left at a reading width (300–380px) and the result (`sm-stage`) fills the right, in its real shape; under that everything stacks with the result first and the action within reach. Extra width goes to the result, never to wider text fields. Before there is a result, the stage previews what will be made from the inputs. `data-layout="stack"` opts out. Size with the kit, never fixed sizes: no fixed pixel widths or heights for the workspace or stage, no 100vh, no position:fixed panels. StillMade zooms a Block's screen to fill the space it has (up to 150%, never down to a phone layout on a computer), so a Block laid out with the kit's spacing fills its Step without empty space, and it centers a standard view narrower than its Step. An app that lays itself out (full-size canvas or WebGL, its own scroll, pan or zoom, its own Ctrl/Cmd +/- keys) puts `data-stillmade-layout="own"` on its outermost element, and StillMade then never centers, zooms or takes those keys. Settings sit side by side (`sm-settings`), next to what they change. Three or four short options are one segmented row (`data-segmented`), not a row of big tiles. Lists fill the width at a small size: input files are small tiles (`sm-gallery data-size="small"`), many items are one line each (`sm-list`): a thumbnail, one line of text, a short fact. Tapping an item opens all of its fields in place. Extra width means more items per row, never bigger cards. On a phone chip and segment rows scroll sideways instead of wrapping; long lists show their first three with "N more" (`data-peek`) and long text five lines until tapped (`sm-clamp`). Nothing is lost when a Block gets smaller: every control stays on the screen, behind an (i), in `sm-more`, or inside the item it belongs to. Compacting moves controls; it never deletes them. Text scene descriptions are planning notes, never a storyboard or an approved frame. Say nothing about how the Block works: no notes on where it runs (this device, StillMade Desktop, the cloud), saving, syncing, recovery, accounts, credits or where a file is kept. StillMade tells the person what they need as one short notification, or nothing; never a sentence on the page, and never the same line under each item. References fill your inputs: every drop area in StillMade offers "Use a reference", and the person's saved photos, videos and notes fill the Step with no typing. Media inputs fill by kind, so take `video` or `asset` wherever a clip works as well as a photo; text inputs fill by plain names and labels (`productName`, `website`, `brandColors`, `fonts`, `voice`, and `details` or `notes` for the reference's note). Never build your own reference picker or library upload. Days and times are picked, never typed: a `date` input is a calendar, with a list of times when it is about a time (`postAt`, `startsAt`, a label with Time, When or Starts). In a custom view use `<input type="date">` or `type="datetime-local"`, never a text box for a date. Posting is its own Step: sending a result to Instagram, TikTok, email or any app is a connector Step after the Block, worded by StillMade ("Post to Instagram"). A Block never posts from inside itself. Its DOM controller is separate from manifest runtime code. The view may also declare appearance:"original" or "host". For an imported design, preserve its colors with appearance:"original" and view.css; no themed replacement is required. Preserve base.view.appearance when refining unless the user requests a change. Omitted/host appearance retains the existing Light, Dark and White requirement: supply semantic colors in view.css or a complete replacement view.themedCss. An original-style view may optionally supply valid themedCss for a StillMade appearance preview. Use StillMade variables (--bg,--fg,--fg-muted,--border-tok,--r-3) only when opting into host styling; do not redefine host tokens in the themed variant. Appearance never relaxes sandbox constraints: no CSS escapes/filters/blending, imports/url(), or element.style mutations in JS. Use classes for UI state; media pixels retain their colors. Both CSS fields have the same 32 KiB limit; all existing shared-state, security and permission checks still apply. Declare elements in html, bind with document.getElementById/querySelector and addEventListener; use literal property access, array methods, textContent, input.value, button.disabled and canvas. Initial values: StillMade.onInput(values=>{...}); await StillMade.run(inputBindings) returns validated output bindings from the isolated package runtime; catch errors and show results. No computation in the DOM controller; put it in code/recipe. Disable the action button while pending.
|
|
12718
12860
|
Standard custom view code (no `view.config.json` frame runtime) is checked before it runs. These rules come straight from the validator; frame views run in their own sandbox and may build the page with ordinary DOM calls such as `createElement`:
|
|
12719
12861
|
|
|
12720
12862
|
- **HTML elements:** only `div`, `section`, `article`, `header`, `footer`, `main`, `aside`, `nav`, `h1`, `h2`, `h3`, `h4`, `p`, `span`, `strong`, `em`, `i`, `small`, `br`, `hr`, `label`, `input`, `textarea`, `button`, `select`, `option`, `optgroup`, `fieldset`, `legend`, `output`, `progress`, `meter`, `ul`, `ol`, `li`, `dl`, `dt`, `dd`, `figure`, `figcaption`, `img`, `video`, `audio`, `source`, `canvas`, `table`, `thead`, `tbody`, `tfoot`, `tr`, `th`, `td`, `pre`, `code`, `details`, `summary`. No scripts, iframes, SVG, forms, comments or inline event attributes; media URLs must be `data:` or `blob:`.
|
package/UI_AESTHETIC.md
CHANGED
|
@@ -239,6 +239,18 @@ before/after examples from an Image Panels project (Voiceover 1,210 px to about
|
|
|
239
239
|
"6 more", long text shows five lines. Kit: `sm-settings`,
|
|
240
240
|
`sm-choices[data-segmented]`, `sm-gallery[data-size="small"]`, `sm-list`,
|
|
241
241
|
`sm-clamp`.
|
|
242
|
+
- A picked option reads at a glance (November 2, 2026; owner, of a Step's Kind
|
|
243
|
+
and Voice rows: "there is like no separation and I can't tell what's going
|
|
244
|
+
on"). In every choice row, chip row, picture tile and segmented control the
|
|
245
|
+
pick is the foreground/background inversion (`--fg` fill, `--bg` words), as
|
|
246
|
+
Credits & plans, the Block Builder's toolbar and the Home filters already do;
|
|
247
|
+
never an outline alone, a tint, or `--bg-elev-2` over `--bg-elev-1`. Hover
|
|
248
|
+
never paints the picked option. A locked row (view only, or while a run works)
|
|
249
|
+
keeps its pick filled, fades the other options and drops the hover and the
|
|
250
|
+
pointer cursor. When a label sits beside the options, wrapped options stay in
|
|
251
|
+
their own column, never under the label. Kit: `sm-choices` (Block views and
|
|
252
|
+
the app), the Step page (`stepWorkspaceKit.css`) and the run popover
|
|
253
|
+
(`sm-run-tiles`).
|
|
242
254
|
- Nothing is lost when a screen gets smaller: every control stays, behind an
|
|
243
255
|
(i), in a one-tap menu, or inside the item it belongs to. The dealership
|
|
244
256
|
Steps with every control accounted for: `docs/ui-review/wide-steps.html`.
|
|
@@ -255,11 +267,16 @@ accessible name and a tooltip; retain visible text when the meaning would be unc
|
|
|
255
267
|
## Run buttons say what they do and what they cost
|
|
256
268
|
|
|
257
269
|
- The button that starts a Step, Block or job never says "Run step", "Run",
|
|
258
|
-
"Run in project" or "Review cost". It names what happens: Write,
|
|
259
|
-
|
|
260
|
-
|
|
270
|
+
"Run in project" or "Review cost". It names what happens: Write, Transcribe,
|
|
271
|
+
Research, Post to Instagram. Whatever AI makes as a picture, video or sound says
|
|
272
|
+
Generate, then what: "Generate image", "Generate video", "Generate voiceover"
|
|
273
|
+
(November 2, 2026). Media made on the device from the person's own files says
|
|
274
|
+
Make ("Make video", "Make 6 clips"). A Block's own `manifest.action`
|
|
275
|
+
({label:"Plan the tour", running:"Planning the tour…"}) wins over these.
|
|
276
|
+
While it works it says so ("Writing…") with Stop beside it; afterwards it offers
|
|
277
|
+
the same action again.
|
|
261
278
|
- When the run costs credits, the price is part of the button:
|
|
262
|
-
"Write · 1 credit", "Generate · 28 credits". Paid with the person's own key it
|
|
279
|
+
"Write · 1 credit", "Generate image · 28 credits". Paid with the person's own key it
|
|
263
280
|
reads "Write · your key". When the price is not known before a quote, the button
|
|
264
281
|
shows only the action and the quote opens the review.
|
|
265
282
|
- When the model, quality or count can change, one chip with a caret sits right
|
|
@@ -273,6 +290,71 @@ accessible name and a tooltip; retain visible text when the meaning would be unc
|
|
|
273
290
|
- Steps use `StepRunControls` and `client/src/blocks/runAction.js` for the verb
|
|
274
291
|
and price; reuse them instead of writing new run buttons.
|
|
275
292
|
|
|
293
|
+
## Speak the job (November 2, 2026)
|
|
294
|
+
|
|
295
|
+
These are defaults for anything nobody specified; when the creator or the person
|
|
296
|
+
asks for something else, that wins. Mockups: `docs/ui-review/job-words-journeys.html`
|
|
297
|
+
(three Project Types end to end) and `docs/ui-review/history-modal.html`.
|
|
298
|
+
|
|
299
|
+
- Every screen says, in the job's own words, what to bring, what the button makes,
|
|
300
|
+
what is happening, what came back and what is off, and adds nothing else.
|
|
301
|
+
"Drop your listing photos here", "Plan the tour · 1 credit", "Moving through the
|
|
302
|
+
kitchen, 4 of 9 rooms", "Your tour · 44 s", "No bathroom photo. Guests look for
|
|
303
|
+
one." beside Add photo. Never "Choose file", "Run", "Processing", "Output" or an
|
|
304
|
+
error code. Step names are the job's too ("Plan the tour", not "Block 2").
|
|
305
|
+
- Quiet by default: no welcome text, tips under fields, tours or banners. At most
|
|
306
|
+
one line of guidance on a screen, only where the next move is not obvious; more
|
|
307
|
+
goes behind an (i). A problem is one line with its fix beside it.
|
|
308
|
+
- Inputs are named for what the person brings (`sermonVideo`); StillMade words the
|
|
309
|
+
drop area from the name. The readiness report notes a button that would read
|
|
310
|
+
"Make it" or "Run" and inputs named only by type; it never refuses a Block for it.
|
|
311
|
+
- Buttons you act on stand out from the page. The main one is solid ink, whether
|
|
312
|
+
it costs credits or not; every other action button is white (`--bg-elev-1`) with a
|
|
313
|
+
strong edge (`--border-strong`). None is the page's own colour. Gold stays for
|
|
314
|
+
small accents.
|
|
315
|
+
- Posting is a connector Step of its own, and its button says what it sends and
|
|
316
|
+
where ("Post to Instagram", "Schedule post"), never "Send".
|
|
317
|
+
- Saved references fill Steps: "Use a reference" sits in the drop area beside
|
|
318
|
+
"Choose". It opens every saved reference, photos, videos and notes, named or not,
|
|
319
|
+
and picking one fills every field it fits. Types and names match with no model;
|
|
320
|
+
only a paragraph that has to be split across fields goes to a quick, cheap model,
|
|
321
|
+
free to the person.
|
|
322
|
+
- Days and times are picked from a calendar and a list of times, never typed.
|
|
323
|
+
- History is one icon in the project bar. A Step has no row of tool icons of its own.
|
|
324
|
+
- Chat can do everything these screens do: pick a reference, fill fields, pick a
|
|
325
|
+
time, post, and bring back an earlier version.
|
|
326
|
+
|
|
327
|
+
## Media playback and full screen (November 2, 2026)
|
|
328
|
+
|
|
329
|
+
Owner, November 2, 2026: "implement A absolutely universally, like in app, platform, sdk, just everywhere", with the
|
|
330
|
+
full-screen button in the bottom-right corner. Every user-facing video and result picture in the app, on public pages
|
|
331
|
+
and in Block views (old releases included) uses one player and one viewer, option A "Cream blocks"
|
|
332
|
+
(`packages/design-system/media-player.js` and `media-player.css`; `MediaPlayer`, `MediaViewer` and `MediaExpandButton`
|
|
333
|
+
in React; `client/public/stillmade-media.js` on server pages; `client/src/blocks/sandboxMedia.js` in Block views).
|
|
334
|
+
|
|
335
|
+
- Controls, left to right along the bottom: play, timeline, time, sound, full screen. Full screen is last, in the
|
|
336
|
+
bottom-right corner. Each button is a 44 px solid cream rounded square (`--r-3`) with an ink icon from the app set;
|
|
337
|
+
never a circle. The time is the display face, italic 200. The chrome sits on the picture, so it is the same in Light,
|
|
338
|
+
Dark and White; the letterbox is ink.
|
|
339
|
+
- Hover only. Owner: "make sure I have to hover over the video for it to appear". The controls and their shade show
|
|
340
|
+
only while the pointer is over the video, paused or playing, before the first play too; they fade 2 s after the last
|
|
341
|
+
move while a video plays. Keyboard focus shows them. On touch a tap shows them for 3 s and never starts playback.
|
|
342
|
+
- Photos get one full-screen button, the video's square in the same corner: 44 px on pictures at least 240 px wide and
|
|
343
|
+
160 px tall, 32 px on smaller ones. Owner: "if I hover over it, it appears; hover out of it, it disappears". Only on
|
|
344
|
+
results, listing and gallery pictures; never on icons, avatars, picker thumbnails, editor canvases or drag sources. A
|
|
345
|
+
picture that already opens its own viewer (versions, Edit image) hands the button's click to it.
|
|
346
|
+
- The viewer is a modal dialog on ink: the picture contained, Close top right, Previous and Next at the middle of the
|
|
347
|
+
sides, the count in the display face ("2 of 4") and the name below. Esc closes only the viewer.
|
|
348
|
+
- A file that cannot open here (kept on another device, or it did not open) is a quiet tile in its own shape with an
|
|
349
|
+
image-off icon and no words, the reason in its label and tooltip (owner, November 2, 2026, of four tiles each saying
|
|
350
|
+
"Only on the device it was added from": "if it's a notification make it a notification"). What the person needs to
|
|
351
|
+
know is one toast for the group, or nothing ("notices, not prose"); never a sentence on the page and never the same
|
|
352
|
+
line under each item. App: `MediaOffTile`; Block views: the kit's `sm-media-off` tile with the `image-off` glyph.
|
|
353
|
+
- Bare previews stay bare: thumbnails, covers, hover-play tiles, editor transports and canvas previews.
|
|
354
|
+
- A Block view's `<video>` without `controls` is the Block's own and is never touched;
|
|
355
|
+
`data-stillmade-player="native"` keeps the browser's controls. Full screen in a Block view is the host's: the frame
|
|
356
|
+
fills the screen only right after a click or key in the view.
|
|
357
|
+
|
|
276
358
|
## Dialog placement and dismissal
|
|
277
359
|
|
|
278
360
|
- Center search and other transient dialogs in the viewport, independent of the
|