0.8.3: custom tooltips, editor-hide, pack script, settings reshuffle
Tooltips - New v-tooltip directive + TooltipHost floating panel replace the native title attribute across 95+ sites (topbar, timeline, sidebar, properties, stage overlays, fullscreen preview, export dialog, clipart drawer, modals). Styled dark card with a configurable label + optional help line for inline documentation; screen readers still get an aria-label when the panel is disabled. - Settings → Interface toggle (`ruwio:tooltipsEnabled`) hides the visual panel for users who know the app. IconButton now routes its title prop through v-tooltip so every existing call site is tooltip-aware without churn. Editor-hide + export filter - New `Layer.editorHidden` flag, eye toggle per layer row, skipped by the Konva stage and the mask-preview canvas path but honoured by exports and fullscreen preview (runtime untouched). - Export dialog gets a "Skip hidden tracks" switch that strips editor-hidden layers from every format (scene JS, runtime, example HTML, MP4, WebM) on opt-in. Disabled when the scene has no hidden layers. Button editor - `+` buttons appear on empty state slots in button-timeline rows and duplicate the nearest keyframe (prev by preference, next otherwise) onto that slot. New `duplicateKeyframeAt` store action carries props, easing, hold, and bezier handles across. Stage / interaction - Plain left-click on the empty content view pans the viewport, but only when the pointer isn't over a Konva shape — transformer handles, vertex dots, and selection boxes that extend past the canvas edge keep their drag. Settings reshuffle - Timeline tab merged into Document (Duration + FPS sit under a new "Timing" sub-heading). New Interface tab gathers three global prefs: Show tooltips, Show locked tracks, Asset thumbnails — driven by shared composables so the existing toolbar toggles stay in sync. Interface-tab CSS defensively resets the scoped label flex-column + uppercase rule that was making the toggle row look like an accident. Project identity + UX polish - Favicon wired up (moved to public/favicon.ico, linked from index.html); scripts/pack.sh packs the minimum Vue project (src, index.html, configs, public) into a tarball with the right version in the filename, and `npm run pack` drives it. - About dialog now credits Torsten Hoeltge. Test infra - Progress bar turns red mid-run on the first failure: runAll gets an onResult callback that TestOverlay uses to push each result into the reactive array incrementally. - mountComponent in the test harness registers v-tooltip on the isolated app instance so IconButton's aria-label contract actually fires under test. Regression tests - duplicateKeyframeAt: copy fidelity (props, easing, hold), collision refusal, unknown-id guards, separated-track targeting. - Shared composables: useTooltipPref and useAssetThumbsPref both return the same ref across calls and persist to localStorage. - Tooltip contract: IconButton ships `aria-label` (not title); live-DOM smoke tests match on aria-label selectors now. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
a2c8e5998a
commit
1d84c34c15
33 files changed
+1185
-128
No files matched your search
@@ -384,7 +384,7 @@ function removeKeyframeHere() {
|
||||
{{ hasKeyframeHere ? t('properties.keyframeLabel') : t('properties.interpolated') }}
|
||||
<span class="kf-time">@ {{ store.playhead.toFixed(2) }}s</span>
|
||||
</span>
|
||||
<button v-if="hasKeyframeHere" class="kf-btn" :title="t('properties.removeKeyframe')" @click="removeKeyframeHere">
|
||||
<button v-if="hasKeyframeHere" class="kf-btn" v-tooltip="t('properties.removeKeyframe')" @click="removeKeyframeHere">
|
||||
<PhX :size="12" weight="bold" />
|
||||
</button>
|
||||
</div>
|
||||
@@ -430,7 +430,7 @@ function removeKeyframeHere() {
|
||||
type="button"
|
||||
class="icon-toggle"
|
||||
:class="{ active: polygonClosed }"
|
||||
:title="t('properties.polygonClosed')"
|
||||
v-tooltip="t('properties.polygonClosed')"
|
||||
@click="polygonClosed = !polygonClosed"
|
||||
>
|
||||
<PhPolygon :size="14" :weight="polygonClosed ? 'fill' : 'regular'" />
|
||||
@@ -465,7 +465,7 @@ function removeKeyframeHere() {
|
||||
type="button"
|
||||
class="icon-toggle alpha-toggle-btn"
|
||||
:class="{ active: fillTransparent }"
|
||||
:title="t('properties.transparent')"
|
||||
v-tooltip="t('properties.transparent')"
|
||||
@click="fillTransparent = !fillTransparent"
|
||||
>
|
||||
<component :is="fillTransparent ? PhEyeSlash : PhEye" :size="13" />
|
||||
@@ -487,7 +487,7 @@ function removeKeyframeHere() {
|
||||
type="button"
|
||||
class="icon-toggle alpha-toggle-btn"
|
||||
:class="{ active: strokeTransparent }"
|
||||
:title="t('properties.transparent')"
|
||||
v-tooltip="t('properties.transparent')"
|
||||
@click="strokeTransparent = !strokeTransparent"
|
||||
>
|
||||
<component :is="strokeTransparent ? PhEyeSlash : PhEye" :size="13" />
|
||||
@@ -588,7 +588,7 @@ function removeKeyframeHere() {
|
||||
type="button"
|
||||
class="icon-toggle"
|
||||
:class="{ active: !!selected.isMask }"
|
||||
:title="t('properties.maskUse')"
|
||||
v-tooltip="t('properties.maskUse')"
|
||||
@click="store.setLayerMask(selected.id, !selected.isMask)"
|
||||
>
|
||||
<PhMaskHappy :size="14" />
|
||||
@@ -601,7 +601,7 @@ function removeKeyframeHere() {
|
||||
type="button"
|
||||
class="icon-toggle"
|
||||
:class="{ active: (selected.maskMode ?? 'negative') === 'negative', danger: (selected.maskMode ?? 'negative') === 'negative' }"
|
||||
:title="t('properties.maskNegative')"
|
||||
v-tooltip="t('properties.maskNegative')"
|
||||
@click="store.setLayerMaskMode(selected.id, 'negative')"
|
||||
>
|
||||
<PhMinus :size="13" weight="bold" />
|
||||
@@ -610,7 +610,7 @@ function removeKeyframeHere() {
|
||||
type="button"
|
||||
class="icon-toggle"
|
||||
:class="{ active: selected.maskMode === 'positive' }"
|
||||
:title="t('properties.maskPositive')"
|
||||
v-tooltip="t('properties.maskPositive')"
|
||||
@click="store.setLayerMaskMode(selected.id, 'positive')"
|
||||
>
|
||||
<PhPlus :size="13" weight="bold" />
|
||||
|
||||
Reference in new issue
Block a user