Skip to content

Commit 7664635

Browse files
committed
Improve styled editor TPS object authoring
1 parent fdc511c commit 7664635

11 files changed

Lines changed: 712 additions & 84 deletions

File tree

AGENTS.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,14 @@ Rule format:
9494
- TPS authoring completeness must be checked against the upstream `managedcode/TPS` README, not only the currently shipped editor menus, so new editor support stays aligned with the full spec for emotions, delivery, pauses, speed, pronunciation, and related cues.
9595
- Editor TPS command surfaces must expose the full currently supported TPS authoring set consistently across top toolbar menus, floating-toolbar menus, and Monaco assistance; do not ship partial or differently grouped command taxonomies between those surfaces.
9696
- The editor must support multiple authoring views: `Raw` is the canonical TPS source editor with tags, and `Editor` is the WYSIWYG-style styled-text editor that hides raw Markdown/TPS syntax while preserving text styling for non-technical authors. Do not label the styled authoring tab as `Rendered`; it is still an editor, and card or storyboard concepts must be separate modes when explicitly requested.
97+
- The styled `Editor` authoring view must open by default for normal editor entry; `Raw` remains available as the canonical TPS source view for technical editing.
9798
- The styled `Editor` authoring view must be a full Monaco-backed editing surface with cursor, selection, keyboard editing, find behavior, and undo/redo parity with `Raw`; rendered styling should be applied through Monaco decorations or equivalent editor-native layers, not by replacing the editor with a static preview or separate non-editable DOM.
99+
- Technical TPS objects such as headers, metadata chips, edit points, cuts, pauses, breath marks, pronunciation guides, and timing controls must be visually distinguished from spoken script text in both `Raw` and styled `Editor`, and should offer object-like hover/edit affordances instead of looking like ordinary words.
98100
- Styled `Editor` TPS hover tooltips must be compact, readable, and viewport-safe; they should explain what the hovered cue/header element means and how it affects authoring without giant clipped Monaco popovers.
99101
- Styled `Editor` header metadata must not dominate the authoring surface or expose vague labels such as `Header metadata`; speaker, WPM, emotion, timing, and archetype parts need clear semantic labels and should stay visually subordinate to the actual script text.
100102
- Styled `Editor` Monaco performance must avoid redundant hidden overlay rendering and unnecessary full-document decoration work while typing; optimize the editor-native decoration path before adding more DOM layers or broad scans.
101103
- TPS cue semantics must be visually represented across both the editor and live reader surfaces: emotions, delivery, voice, pace, energy, pauses or breath marks, pronunciation, phonetics, stress, staccato, legato, emphasis, highlight, aside, rhetorical, building, sarcasm, loud, soft, whisper, and related cues need visible affordances that help the user read intent without inspecting raw TPS tags.
104+
- TPS cue visual language must be shared across Raw editor, styled `Editor`, and Teleprompter reader surfaces; colors, typography, cue marks, and motion metaphors should come from one canonical style contract so the same TPS element reads the same way everywhere.
102105
- TPS word and emotion treatments should use tasteful word-level CSS effects such as gradients, shadows, underline textures, and constrained animation when they make the cue more legible and interesting; do not limit cue rendering to flat color changes, but never let effects reduce readability or cause word overlap.
103106
- TPS emotion cue colors must be meaningfully distinguishable from each other and should be grounded in color/emotion theory where possible; do not ship a set of near-identical pastel tints that users cannot tell apart while reading.
104107
- TPS cue rendering work must start from an explicit design note that maps each supported TPS style to its reader/editor visual treatment, animation, and test expectation before implementation, so the product does not grow one-off cue styling.

src/PrompterOne.Shared/Editor/Components/EditorSourcePanel.razor.css

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,6 +465,55 @@ body.theme-light .ed-main ::deep .efb-menu-item:hover {
465465
opacity:.82;
466466
padding:0 3px;
467467
}
468+
.ed-main--styled-text ::deep .po-pause-short,
469+
.ed-main--styled-text ::deep .po-pause-long,
470+
.ed-main--styled-text ::deep .po-pause-timed{
471+
color:transparent !important;
472+
font-size:0 !important;
473+
opacity:0 !important;
474+
text-shadow:none !important;
475+
}
476+
.ed-main--styled-text ::deep .po-object-chip::before{
477+
content:"cue";
478+
display:inline-flex;
479+
align-items:center;
480+
justify-content:center;
481+
min-width:0;
482+
height:1.35em;
483+
margin:0 .28em 0 .12em;
484+
padding:0 .5em;
485+
border:1px solid color-mix(in srgb, var(--ed-object-color, #D4B070) 46%, transparent);
486+
border-radius:999px;
487+
background:linear-gradient(180deg, color-mix(in srgb, var(--ed-object-color, #D4B070) 18%, transparent), color-mix(in srgb, var(--ed-object-color, #D4B070) 8%, transparent));
488+
box-shadow:inset 0 1px 0 rgba(255,255,255,.07),0 .08em .45em rgba(0,0,0,.12);
489+
color:color-mix(in srgb, var(--ed-object-color, #D4B070) 74%, #FFFFFF);
490+
font-family:var(--font-sans);
491+
font-size:11px;
492+
font-weight:700;
493+
letter-spacing:.02em;
494+
line-height:1;
495+
text-transform:uppercase;
496+
vertical-align:.12em;
497+
}
498+
.ed-main--styled-text ::deep .po-object-tag-close::before{content:"end";--ed-object-color:#6A7E78;color:#94A49E;}
499+
.ed-main--styled-text ::deep .po-object-pause::before{content:"pause";--ed-object-color:#E0C070;}
500+
.ed-main--styled-text ::deep .po-object-pause-long::before{content:"pause+";}
501+
.ed-main--styled-text ::deep .po-object-breath::before{content:"breath";--ed-object-color:#EEDB96;}
502+
.ed-main--styled-text ::deep .po-object-cut::before{content:"cut";--ed-object-color:#FFD060;}
503+
.ed-main--styled-text ::deep .po-object-pronunciation::before{content:"pron";--ed-object-color:#D88AFF;}
504+
.ed-main--styled-text ::deep .po-object-phonetic::before{content:"ipa";--ed-object-color:#8EDCFF;}
505+
.ed-main--styled-text ::deep .po-object-highlight::before{content:"highlight";--ed-object-color:#FFE87A;}
506+
.ed-main--styled-text ::deep .po-object-emphasis::before{content:"emphasis";--ed-object-color:#F2C18B;}
507+
.ed-main--styled-text ::deep .po-object-stress::before{content:"stress";--ed-object-color:#FFD060;}
508+
.ed-main--styled-text ::deep .po-object-energy::before{content:"energy";--ed-object-color:#CEFF66;}
509+
.ed-main--styled-text ::deep .po-object-melody::before{content:"melody";--ed-object-color:#91D2FF;}
510+
.ed-main--styled-text ::deep .po-object-cue::before{content:"cue";--ed-object-color:#9ED6FF;}
511+
.ed-main--styled-text ::deep .po-object-chip[class*="po-tag-volume-"]::before{content:"voice";--ed-object-color:#C7DDF5;}
512+
.ed-main--styled-text ::deep .po-object-chip[class*="po-tag-delivery-"]::before{content:"delivery";--ed-object-color:#F0D48D;}
513+
.ed-main--styled-text ::deep .po-object-chip[class*="po-tag-articulation-"]::before{content:"articulation";--ed-object-color:#8DD5E2;}
514+
.ed-main--styled-text ::deep .po-object-chip[class*="po-tag-speed-"]::before{content:"pace";--ed-object-color:#8ECFFF;}
515+
.ed-main--styled-text ::deep .po-object-chip[class*="po-tag-emotion-"]::before{content:"emotion";--ed-object-color:#FFB86A;}
516+
.ed-main--styled-text ::deep .po-object-chip.po-object-tag-close::before{content:"end";--ed-object-color:#6A7E78;color:#94A49E;}
468517
.ed-main ::deep .monaco-editor .line-numbers.active-line-number{
469518
color:#90A39C !important;
470519
font-size:14px !important;
@@ -640,6 +689,49 @@ body.theme-light .ed-main ::deep .monaco-editor .line-numbers.active-line-number
640689
.ed-main ::deep .po-inline-pronunciation{color:#D88AFF;background-image:linear-gradient(180deg, transparent 62%, rgba(216,138,255,.12) 62%);box-shadow:inset 0 -1px 0 rgba(216,138,255,.28);}
641690
.ed-main ::deep .mk-phonetic-word{border-bottom:2px dashed rgba(216,138,255,.4);}
642691
.ed-main ::deep .po-inline-pronunciation-word{border-bottom:2px dashed rgba(216,138,255,.4);}
692+
.ed-main ::deep .monaco-editor [class*="tps-"]{font-weight:inherit;letter-spacing:inherit;margin:0;padding:0;}
693+
.ed-main ::deep .monaco-editor .tps-highlight{background:transparent;border-radius:0;}
694+
.ed-main ::deep .po-inline-loud.tps-loud{color:#F2C18B;text-shadow:0 1px 0 rgba(0,0,0,.18),0 0 10px rgba(245,200,139,.18);}
695+
.ed-main ::deep .po-inline-soft.tps-soft{color:#C7DDF5;opacity:.86;text-shadow:0 0 8px rgba(199,221,245,.12);}
696+
.ed-main ::deep .po-inline-whisper.tps-whisper{color:#CFCBD7;font-style:italic;opacity:.76;text-decoration-line:underline;text-decoration-style:dotted;text-decoration-color:rgba(207,203,215,.24);text-decoration-thickness:1px;text-underline-offset:.32em;}
697+
.ed-main ::deep .po-inline-delivery-aside.tps-aside{color:#D8C29B;font-style:italic;opacity:.88;}
698+
.ed-main ::deep .po-inline-delivery-rhetorical.tps-rhetorical{color:#CDB3E9;text-shadow:0 0 8px rgba(205,179,233,.12);}
699+
.ed-main ::deep .po-inline-delivery-sarcasm.tps-sarcasm{color:#E2B6C7;opacity:.92;}
700+
.ed-main ::deep .po-inline-delivery-building.tps-building{color:#F0D48D;text-shadow:0 0 calc(5px + (12px * var(--tps-build-progress, .42))) rgba(240,212,141, calc(.08 + (.16 * var(--tps-build-progress, .42))));}
701+
.ed-main ::deep .po-inline-highlight.tps-highlight{background:none;box-shadow:none;color:#FFE87A;isolation:isolate;position:relative;}
702+
.ed-main ::deep .po-inline-highlight.tps-highlight::before{content:"";position:absolute;z-index:-1;inset:.1em -.06em .14em;border-radius:.16em;background:linear-gradient(180deg, rgba(255,232,148,.2), rgba(238,173,69,.18)),linear-gradient(90deg, rgba(255,235,180,.06), rgba(255,214,77,.18), rgba(255,235,180,.06));box-shadow:inset 0 0 0 1px rgba(255,224,102,.18),0 .08em .34em rgba(0,0,0,.12);pointer-events:none;}
703+
.ed-main ::deep .po-inline-emphasis.tps-emphasis{color:rgba(255,228,162,.94);text-decoration-line:none;text-shadow:0 0 10px rgba(255,210,128,.18),0 0 16px rgba(232,170,80,.1);}
704+
.ed-main ::deep .po-inline-articulation-legato.tps-legato{color:#8DD5E2;position:relative;text-decoration-line:none;}
705+
.ed-main ::deep .po-inline-articulation-legato.tps-legato::before{content:"";position:absolute;left:-.04em;right:-.04em;bottom:-.16em;height:.22em;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 22' preserveAspectRatio='none' fill='none'%3E%3Cpath d='M4 5 Q 50 18 96 5' stroke='%238DD5E2' stroke-opacity='.72' stroke-width='2.4' stroke-linecap='round'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:center;background-size:100% 100%;pointer-events:none;}
706+
.ed-main ::deep .po-inline-articulation-staccato.tps-staccato{color:#ECB5D8;position:relative;text-decoration-line:none;}
707+
.ed-main ::deep .po-inline-articulation-staccato.tps-staccato::before{content:"";position:absolute;left:50%;top:-.18em;width:.2em;height:.2em;min-width:6px;min-height:6px;transform:translateX(-50%);background:currentColor;opacity:.74;border-radius:50%;pointer-events:none;}
708+
.ed-main ::deep .po-inline-stress.tps-stress{color:#FFD060;padding-inline:.04em;position:relative;text-decoration-line:none;}
709+
.ed-main ::deep .po-inline-stress.tps-stress::before{content:"";position:absolute;left:50%;top:-.5em;width:.5em;height:.28em;transform:translateX(-50%);background:currentColor;opacity:.78;-webkit-mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 22' fill='none' preserveAspectRatio='none'%3E%3Cpath d='M4 3 L34 11 L4 19' stroke='%23000' stroke-width='3.6' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3C/svg%3E");mask-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 22' fill='none' preserveAspectRatio='none'%3E%3Cpath d='M4 3 L34 11 L4 19' stroke='%23000' stroke-width='3.6' stroke-linecap='round' stroke-linejoin='round' fill='none'/%3E%3C/svg%3E");-webkit-mask-size:100% 100%;mask-size:100% 100%;pointer-events:none;}
710+
.ed-main ::deep .po-inline-energy.tps-energy{color:hsl(calc(74 + (12 * var(--tps-energy, .16))) 100% calc(78% - (10% * var(--tps-energy, .16))));text-shadow:0 0 calc(8px + (18px * var(--tps-energy, .16))) rgba(216,255,114, calc(.12 + (.24 * var(--tps-energy, .16)))),0 0 calc(12px + (22px * var(--tps-energy, .16))) rgba(255,214,82, calc(.04 + (.12 * var(--tps-energy, .16))));filter:saturate(calc(1.04 + (.24 * var(--tps-energy, .16)))) brightness(calc(.98 + (.12 * var(--tps-energy, .16))));}
711+
.ed-main ::deep .po-inline-melody.tps-melody{color:hsl(calc(202 + (8 * var(--tps-melody, .16))) 100% calc(84% - (10% * var(--tps-melody, .16))));position:relative;text-decoration-line:none;text-shadow:0 0 calc(4px + (10px * var(--tps-melody, .16))) rgba(125,219,255, calc(.06 + (.12 * var(--tps-melody, .16))));}
712+
.ed-main ::deep .po-inline-melody.tps-melody::after{content:"";position:absolute;left:-.04em;right:-.04em;bottom:calc(-.12em - (.08em * var(--tps-melody, .16)));height:calc(.14em + (.16em * var(--tps-melody, .16)));background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 160 28' preserveAspectRatio='none' fill='none'%3E%3Cpath d='M2 14 C10 6 18 22 26 14 S42 6 50 14 S66 22 74 14 S90 6 98 14 S114 22 122 14 S138 6 146 14 S154 22 158 14' stroke='%2391D2FF' stroke-opacity='.92' stroke-width='2.3' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");background-repeat:no-repeat;background-position:center;background-size:100% 100%;opacity:calc(.38 + (.42 * var(--tps-melody, .16)));pointer-events:none;}
713+
.ed-main ::deep .po-inline-pronunciation-word.tps-pronunciation{border-bottom:0;color:rgba(239,232,255,.98);text-shadow:0 0 12px rgba(194,169,255,.18);}
714+
.ed-main ::deep .po-inline-pronunciation-word.tps-phonetic{border-bottom:0;color:rgba(226,247,255,.98);text-shadow:0 0 12px rgba(127,219,255,.18);}
715+
.ed-main ::deep .po-energy-level-1{--tps-energy:.16;}
716+
.ed-main ::deep .po-energy-level-2{--tps-energy:.253;}
717+
.ed-main ::deep .po-energy-level-3{--tps-energy:.347;}
718+
.ed-main ::deep .po-energy-level-4{--tps-energy:.44;}
719+
.ed-main ::deep .po-energy-level-5{--tps-energy:.533;}
720+
.ed-main ::deep .po-energy-level-6{--tps-energy:.627;}
721+
.ed-main ::deep .po-energy-level-7{--tps-energy:.72;}
722+
.ed-main ::deep .po-energy-level-8{--tps-energy:.813;}
723+
.ed-main ::deep .po-energy-level-9{--tps-energy:.907;}
724+
.ed-main ::deep .po-energy-level-10{--tps-energy:1;}
725+
.ed-main ::deep .po-melody-level-1{--tps-melody:.16;}
726+
.ed-main ::deep .po-melody-level-2{--tps-melody:.253;}
727+
.ed-main ::deep .po-melody-level-3{--tps-melody:.347;}
728+
.ed-main ::deep .po-melody-level-4{--tps-melody:.44;}
729+
.ed-main ::deep .po-melody-level-5{--tps-melody:.533;}
730+
.ed-main ::deep .po-melody-level-6{--tps-melody:.627;}
731+
.ed-main ::deep .po-melody-level-7{--tps-melody:.72;}
732+
.ed-main ::deep .po-melody-level-8{--tps-melody:.813;}
733+
.ed-main ::deep .po-melody-level-9{--tps-melody:.907;}
734+
.ed-main ::deep .po-melody-level-10{--tps-melody:1;}
643735
.ed-main ::deep .mk-special{color:#E0C070;background-image:linear-gradient(180deg, transparent 60%, rgba(224,192,112,.12) 60%);box-shadow:inset 0 -1px 0 rgba(224,192,112,.22);}
644736
.ed-main ::deep .mk-edit{color:#FFD060;background-image:linear-gradient(180deg, transparent 60%, rgba(255,208,96,.1) 60%);box-shadow:inset 0 -1px 0 rgba(255,208,96,.3);}
645737
.ed-main ::deep .ed-src-line-segment{color:#F2E1AA;background:linear-gradient(90deg, rgba(255,224,102,.08), rgba(255,224,102,0) 42%);box-shadow:inset 3px 0 0 rgba(255,224,102,.38);border-radius:6px;}

src/PrompterOne.Shared/Editor/Pages/EditorPage.razor.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ public partial class EditorPage
6767
private IReadOnlyList<EditorLocalRevisionViewModel> _localHistory = [];
6868
private DateTimeOffset? _lastLocalSaveAt;
6969
private EditorMetadataRailTab _metadataRailSelectedTab = EditorMetadataRailTab.Metadata;
70-
private EditorWorkspaceTab _workspaceTab = EditorWorkspaceTab.Source;
70+
private EditorWorkspaceTab _workspaceTab = EditorWorkspaceTab.Editor;
7171
private IDisposable? _aiSpotlightEditRegistration;
7272
private string _profile = DefaultProfileActor;
7373
private bool _preserveHistoryOnNextLoad;

0 commit comments

Comments
 (0)