updates scrollable graphic example

This commit is contained in:
Sudev Kiyada 2026-01-13 12:12:09 +05:30
parent 74d6de2ff7
commit 0674ec24e6
Failed to extract signature
9 changed files with 158 additions and 91 deletions

View file

@ -2,7 +2,7 @@ import { Meta } from '@storybook/blocks';
import * as HorizontalScrollerStories from './HorizontalScroller.stories.svelte'; import * as HorizontalScrollerStories from './HorizontalScroller.stories.svelte';
import IllustratorScreenshot from './assets/illustrator.jpg'; import IllustratorScreenshot from './assets/illustrator.png';
<Meta of={HorizontalScrollerStories} /> <Meta of={HorizontalScrollerStories} />
@ -10,7 +10,7 @@ import IllustratorScreenshot from './assets/illustrator.jpg';
The `HorizontalScroller` component creates a horizontal scrolling section that scrolls through any child content wider than `100vw`. The `HorizontalScroller` component creates a horizontal scrolling section that scrolls through any child content wider than `100vw`.
To use `HorizontalScroller`, wrap it around the content that you want to horizontally scroll through. The scroll length is controlled by the height of the `HorizontalScroller` container, which is set by the prop `height`. `height` defaults to `200lvh`, but you can adjust this to any valid CSS height value such as `1200px` or `400lvh`. To use `HorizontalScroller`, wrap it around the content that you want to horizontally scroll through. The scroll length is controlled by the height of the `HorizontalScroller` container, which is set by the prop `height`. `height` defaults to `200lvh`, but you can adjust this to any valid CSS height value such as `1200px` or `400lvh`.
The child content inside the `HorizontalScroller` must be wider than `100vw` so that there is overflow to horizontal scroll through. By default, only the top `100lvh` of the child content is visible. You can use CSS `transform: translate()` on the child content to adjust its vertical positioning within the visible area. The child content inside the `HorizontalScroller` must be wider than `100vw` so that there is overflow to horizontal scroll through. By default, only the top `100lvh` of the child content is visible. You can use CSS `transform: translate()` on the child content to adjust its vertical positioning within the visible area.
@ -22,7 +22,10 @@ See the full list of available props under the `Controls` tab in the [demo](?pat
```svelte ```svelte
<script lang="ts"> <script lang="ts">
import { HorizontalScroller, Block } from '@reuters-graphics/graphics-components'; import {
HorizontalScroller,
Block,
} from '@reuters-graphics/graphics-components';
</script> </script>
<!-- Wrap `HorizontalScroller` in a fluid container for a full bleed experience --> <!-- Wrap `HorizontalScroller` in a fluid container for a full bleed experience -->
@ -31,11 +34,11 @@ See the full list of available props under the `Controls` tab in the [demo](?pat
<HorizontalScroller> <HorizontalScroller>
<!-- Child content wider than 100vw. Only the top 100lvh is visible. --> <!-- Child content wider than 100vw. Only the top 100lvh is visible. -->
<div style="width: 400vw; height: 100lvh;"> <div style="width: 400vw; height: 100lvh;">
<img <img
src="my-wide-image.jpg" src="my-wide-image.jpg"
alt="alt text" alt="alt text"
style="width: 100%; height: 100%; object-fit: cover; padding: 0; margin: 0;" style="width: 100%; height: 100%; object-fit: cover; padding: 0; margin: 0;"
/> />
</div> </div>
</HorizontalScroller> </HorizontalScroller>
</Block> </Block>
@ -61,36 +64,39 @@ If `scrubbed` is set to `false` and `stops` are defined, the scrolling transitio
`easing` accepts any easing function from `svelte/easing` or a custom easing function, while `duration` sets the time, in milliseconds, for each transition between stops. `easing` accepts any easing function from `svelte/easing` or a custom easing function, while `duration` sets the time, in milliseconds, for each transition between stops.
So, if the stops are at irregular intervals — for example, `[0.2, 0.9]` — the scroll to the first stop will be much quicker than the scroll to the second stop since the distance to travel is different but the duration of the transition is the same. So, if the stops are at irregular intervals — for example, `[0.2, 0.9]` — the scroll to the first stop will be much quicker than the scroll to the second stop since the distance to travel is different but the duration of the transition is the same.
By default, `duration` is set to `400` milliseconds. By default, `duration` is set to `400` milliseconds.
[Demo](?path=/story/components-graphics-horizontalscroller--with-stops) [Demo](?path=/story/components-graphics-horizontalscroller--with-stops)
```svelte ```svelte
<script lang="ts"> <script lang="ts">
import { HorizontalScroller, Block } from '@reuters-graphics/graphics-components'; import {
HorizontalScroller,
Block,
} from '@reuters-graphics/graphics-components';
import { quartInOut } from 'svelte/easing'; import { quartInOut } from 'svelte/easing';
</script> </script>
<!-- Wrap `HorizontalScroller` in a fluid container for a full bleed experience --> <!-- Wrap `HorizontalScroller` in a fluid container for a full bleed experience -->
<Block width="fluid"> <Block width="fluid">
<HorizontalScroller <HorizontalScroller
stops={[0.2, 0.5, 0.9]} stops={[0.2, 0.5, 0.9]}
duration={400} duration={400}
scrubbed={false} scrubbed={false}
easing={quartInOut} easing={quartInOut}
showDebugInfo={true} showDebugInfo={true}
> >
<!-- Child content wider than 100vw. Only the top 100lvh is visible. --> <!-- Child content wider than 100vw. Only the top 100lvh is visible. -->
<div style="width: 200vw; height: 100lvh;"> <div style="width: 200vw; height: 100lvh;">
<img <img
src="my-wide-image.jpg" src="my-wide-image.jpg"
alt="alt text" alt="alt text"
style="width: 100%; height: 100%; object-fit: cover; padding: 0; margin: 0;" style="width: 100%; height: 100%; object-fit: cover; padding: 0; margin: 0;"
/> />
</div> </div>
</HorizontalScroller> </HorizontalScroller>
</Block> </Block>
``` ```
@ -106,12 +112,16 @@ If using custom `mappedStart` and `mappedEnd` values, you must also set `stops`
```svelte ```svelte
<script lang="ts"> <script lang="ts">
import { HorizontalScroller, Block } from '@reuters-graphics/graphics-components'; import {
HorizontalScroller,
Block,
} from '@reuters-graphics/graphics-components';
import { quartInOut } from 'svelte/easing'; import { quartInOut } from 'svelte/easing';
</script> </script>
<!-- Wrap `HorizontalScroller` in a fluid container for a full bleed experience --> <!-- Wrap `HorizontalScroller` in a fluid container for a full bleed experience -->
<Block width="fluid"> <Block width="fluid">
<HorizontalScroller <HorizontalScroller
mappedStart={-0.5} mappedStart={-0.5}
mappedEnd={1.5} mappedEnd={1.5}
stops={[0, 1]} stops={[0, 1]}
@ -119,7 +129,7 @@ If using custom `mappedStart` and `mappedEnd` values, you must also set `stops`
easing={quartInOut} easing={quartInOut}
> >
<!-- Child content wider than 100vw. Only the top 100lvh is visible. --> <!-- Child content wider than 100vw. Only the top 100lvh is visible. -->
<div style="width: 200vw; height: 100lvh;"> <div style="width: 200vw; height: 100lvh;">
<img <img
src="my-wide-image.jpg" src="my-wide-image.jpg"
alt="alt text" alt="alt text"
@ -154,7 +164,10 @@ allow_overflow: true
```svelte ```svelte
<script lang="ts"> <script lang="ts">
import { HorizontalScroller, Block } from '@reuters-graphics/graphics-components'; import {
HorizontalScroller,
Block,
} from '@reuters-graphics/graphics-components';
import AiGraphic from './ai2svelte/ai-graphic.svelte'; import AiGraphic from './ai2svelte/ai-graphic.svelte';
// If using with the graphics kit // If using with the graphics kit
@ -166,11 +179,7 @@ allow_overflow: true
<!-- Wrap `HorizontalScroller` in a fluid container for a full bleed experience --> <!-- Wrap `HorizontalScroller` in a fluid container for a full bleed experience -->
<Block width="fluid"> <Block width="fluid">
<HorizontalScroller <HorizontalScroller height="800lvh" easing={sineInOut} showDebugInfo>
height="800lvh"
easing={sineInOut}
showDebugInfo
>
<AiGraphic assetsPath={assets} /> <AiGraphic assetsPath={assets} />
</HorizontalScroller> </HorizontalScroller>
</Block> </Block>
@ -184,7 +193,7 @@ The demo below has 2 advanced interactions: fade in/out of caption boxes based o
### Captions fading in/out ### Captions fading in/out
Caption boxes are exported as `htext` [tagged layers](https://reuters-graphics.github.io/ai2svelte/users/tagged-layers/) in ai2svelte. In this example, we use the `handleScroll()` function to check the position of each caption box relative to the viewport width and set its opacity to `1` (visible) or `0` (hidden) based on whether the caption box is within the `threshold` of the viewport. Caption boxes are exported as `htext` [tagged layers](https://reuters-graphics.github.io/ai2svelte/users/tagged-layers/) in ai2svelte. In this example, we use the `handleScroll()` function to check the position of each caption box relative to the viewport width and set its opacity to `1` (visible) or `0` (hidden) based on whether the caption box is within the `threshold` of the viewport. Set `override_text: true` in the ai2svelte export settings to allow custom HTML content in tagged text layers.
### Parallax effect with png layer ### Parallax effect with png layer
@ -194,7 +203,10 @@ This demo has a tagged `png` [layer](https://reuters-graphics.github.io/ai2svelt
```svelte ```svelte
<script lang="ts"> <script lang="ts">
import { HorizontalScroller, Block } from '@reuters-graphics/graphics-components'; import {
HorizontalScroller,
Block,
} from '@reuters-graphics/graphics-components';
import AiGraphic from './ai2svelte/ai-graphic.svelte'; import AiGraphic from './ai2svelte/ai-graphic.svelte';
import { sineInOut } from 'svelte/easing'; import { sineInOut } from 'svelte/easing';
@ -211,7 +223,7 @@ This demo has a tagged `png` [layer](https://reuters-graphics.github.io/ai2svelt
function handleScroll() { function handleScroll() {
// Create a parallax movement for the foreground png layer // Create a parallax movement for the foreground png layer
if (pngLayer) { if (pngLayer) {
pngLayer.style.transform = `translateX(${map(progress, 0, 1, -400, 400)}px)`; pngLayer.style.transform = `scale(1.5) translateX(${map(progress, 0, 1, -15, 85)}%)`;
} }
// For each caption, checks if position of the caption is below the threshold. // For each caption, checks if position of the caption is below the threshold.
@ -247,6 +259,9 @@ This demo has a tagged `png` [layer](https://reuters-graphics.github.io/ai2svelt
window.addEventListener('scroll', handleScroll, { window.addEventListener('scroll', handleScroll, {
passive: true, passive: true,
}); });
// to translate overlay layer on initial load
handleScroll();
} }
} }
</script> </script>
@ -259,21 +274,24 @@ This demo has a tagged `png` [layer](https://reuters-graphics.github.io/ai2svelt
easing={sineInOut} easing={sineInOut}
showDebugInfo={true} showDebugInfo={true}
> >
<AiGraphic assetsPath={assets} {onArtboardChange} <AiGraphic
taggedText={{ assetsPath={assets}
htext: { {onArtboardChange}
captions: { taggedText={{
caption1: htext: {
'<div class="scroller-caption"><strong>Caption 1!</strong><br/>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>', captions: {
caption2: caption1:
'<div class="scroller-caption"><strong>Caption 2!</strong><br/>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>', '<div class="scroller-caption"><strong>Caption 1!</strong><br/>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>',
caption3: caption2:
'<div class="scroller-caption"><strong>Caption 3!</strong><br/>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>', '<div class="scroller-caption"><strong>Caption 2!</strong><br/>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>',
caption4: caption3:
'<div class="scroller-caption"><strong>Caption 4!</strong><br/>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>', '<div class="scroller-caption"><strong>Caption 3!</strong><br/>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>',
caption4:
'<div class="scroller-caption"><strong>Caption 4!</strong><br/>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>',
},
}, },
}, }}
}} /> />
</HorizontalScroller> </HorizontalScroller>
</Block> </Block>
@ -281,14 +299,14 @@ This demo has a tagged `png` [layer](https://reuters-graphics.github.io/ai2svelt
:global(.scroller-caption) { :global(.scroller-caption) {
padding: 1rem; padding: 1rem;
margin: 0; margin: 0;
background-color: rgba(255, 255, 255, 0.8); background-color: rgba(0, 0, 0, 0.8);
border-radius: 8px; border-radius: 8px;
color: white;
filter: drop-shadow(0px 2px 16px rgba(0, 0, 0, 0.2)); filter: drop-shadow(0px 2px 16px rgba(0, 0, 0, 0.2));
} }
</style> </style>
``` ```
## With custom child components ## With custom child components
You can create a custom horizontal layout with any component and pass it as a child to the `HorizontalScroller`. Here's an example with `DatawrapperChart`, `Headline` and ai2svelte components laid out in a horizontal scroll. You can create a custom horizontal layout with any component and pass it as a child to the `HorizontalScroller`. Here's an example with `DatawrapperChart`, `Headline` and ai2svelte components laid out in a horizontal scroll.
@ -355,6 +373,7 @@ You can create a custom horizontal layout with any component and pass it as a ch
You can also integrate HorizontalScroller with `ScrollerBase` for a horizontal scroll with vertical captions. You can also integrate HorizontalScroller with `ScrollerBase` for a horizontal scroll with vertical captions.
When using `HorizontalScroller` with `ScrollerBase` or other scrollers, you must: When using `HorizontalScroller` with `ScrollerBase` or other scrollers, you must:
- Create a `progress` state variable and bind it to both `ScrollerBase` and `HorizontalScroller` - Create a `progress` state variable and bind it to both `ScrollerBase` and `HorizontalScroller`
- Set `HorizontalScroller`'s `height` to `100lvh` - Set `HorizontalScroller`'s `height` to `100lvh`
- Set `handleScroll` to `false` - Set `handleScroll` to `false`
@ -366,12 +385,12 @@ When using `HorizontalScroller` with `ScrollerBase` or other scrollers, you must
import { import {
HorizontalScroller, HorizontalScroller,
ScrollerBase, ScrollerBase,
Block Block,
} from '@reuters-graphics/graphics-components'; } from '@reuters-graphics/graphics-components';
import AiGraphic from './ai2svelte/ai-graphic.svelte'; import AiGraphic from './ai2svelte/ai-graphic.svelte';
import { circInOut } from 'svelte/easing'; import { circInOut } from 'svelte/easing';
// Optional: Bind your own variables to use them in your code. // Optional: Bind your own variables to use them in your code.
let progress = $state(0); let progress = $state(0);
</script> </script>
@ -379,15 +398,15 @@ When using `HorizontalScroller` with `ScrollerBase` or other scrollers, you must
{#snippet backgroundSnippet()} {#snippet backgroundSnippet()}
<!-- Wrap `HorizontalScroller` in a fluid container for a full bleed experience --> <!-- Wrap `HorizontalScroller` in a fluid container for a full bleed experience -->
<Block width="fluid"> <Block width="fluid">
<HorizontalScroller <HorizontalScroller
bind:progress bind:progress
height="100lvh" height="100lvh"
handleScroll={false} handleScroll={false}
showDebugInfo={true} showDebugInfo={true}
> >
<AiGraphic /> <AiGraphic />
</HorizontalScroller> </HorizontalScroller>
</Block> </Block>
{/snippet} {/snippet}
{#snippet foregroundSnippet()} {#snippet foregroundSnippet()}
<!-- Add custom foreground HTML or component --> <!-- Add custom foreground HTML or component -->

Binary file not shown.

Before

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 574 KiB

View file

@ -18,7 +18,7 @@
function handleScroll() { function handleScroll() {
if (pngLayer) { if (pngLayer) {
pngLayer.style.transform = `translateX(${map(progress, 0, 1, -400, 400)}px)`; pngLayer.style.transform = `scale(1.5) translateX(${map(progress, 0, 1, -15, 85)}%)`;
} }
if (captions?.length) { if (captions?.length) {
@ -51,6 +51,9 @@
window.addEventListener('scroll', handleScroll, { window.addEventListener('scroll', handleScroll, {
passive: true, passive: true,
}); });
// to translate overlay layer on initial load
handleScroll();
} }
} }
</script> </script>
@ -68,7 +71,6 @@
> >
<Demo <Demo
{onArtboardChange} {onArtboardChange}
debugTaggedText
taggedText={{ taggedText={{
htext: { htext: {
captions: { captions: {
@ -93,8 +95,9 @@
:global(.scroller-caption) { :global(.scroller-caption) {
padding: 1rem; padding: 1rem;
margin: 0; margin: 0;
background-color: rgba(255, 255, 255, 0.8); background-color: rgba(0, 0, 0, 0.8);
border-radius: 8px; border-radius: 8px;
color: white;
filter: drop-shadow(0px 2px 16px rgba(0, 0, 0, 0.2)); filter: drop-shadow(0px 2px 16px rgba(0, 0, 0, 0.2));
} }
</style> </style>

View file

@ -1,4 +1,4 @@
<script lang="ts"> <script>
// For demo purposes only, hard-wiring img paths from Vite // For demo purposes only, hard-wiring img paths from Vite
// @ts-ignore img // @ts-ignore img
import imageXl from '../imgs/demo-xl.jpg'; import imageXl from '../imgs/demo-xl.jpg';
@ -6,8 +6,11 @@
import imageLg from '../imgs/demo-lg.jpg'; import imageLg from '../imgs/demo-lg.jpg';
// @ts-ignore img // @ts-ignore img
import imagePngOverlayXl from '../imgs/layer-overlay-xl.png'; import imagePngOverlayXl from '../imgs/layer-overlay-xl.png';
// @ts-ignore img
import imagePngOverlayLg from '../imgs/layer-overlay-lg.png';
let { let {
assetsPath = '/',
onAiMounted = () => {}, onAiMounted = () => {},
onArtboardChange = () => {}, onArtboardChange = () => {},
taggedText = { text: {}, htext: {} }, taggedText = { text: {}, htext: {} },
@ -15,15 +18,15 @@
artboardWidth = $bindable(undefined), artboardWidth = $bindable(undefined),
} = $props(); } = $props();
import { onMount, untrack } from 'svelte'; import { onMount, untrack } from 'svelte';
let aiBox: HTMLDivElement | undefined = $state(undefined); let aiBox;
let screenWidth = $state(0); let screenWidth = $state(0);
let aiBoxWidth = $derived(artboardWidth ?? screenWidth); let aiBoxWidth = $derived(artboardWidth ?? screenWidth);
let activeArtboard: Element | undefined = $state(undefined); let activeArtboard = $state(undefined);
onMount(() => { onMount(() => {
onAiMounted(); onAiMounted();
}); });
$effect(() => { $effect(() => {
if (aiBoxWidth && aiBox) { if (aiBoxWidth) {
const currentArtboard = aiBox.querySelectorAll('.g-artboard')[0]; const currentArtboard = aiBox.querySelectorAll('.g-artboard')[0];
if (currentArtboard?.id !== activeArtboard?.id) { if (currentArtboard?.id !== activeArtboard?.id) {
activeArtboard = untrack(() => currentArtboard); activeArtboard = untrack(() => currentArtboard);
@ -40,47 +43,61 @@
class="ai2svelte" class="ai2svelte"
bind:this={aiBox} bind:this={aiBox}
style:--debug-tagged-text={debugTaggedText ? 'visible' : 'hidden'} style:--debug-tagged-text={debugTaggedText ? 'visible' : 'hidden'}
style:--debug-stroke={debugTaggedText ? '2px' : '0px'}
> >
<!-- Artboard: lg --> <!-- Artboard: lg -->
{#if aiBoxWidth && aiBoxWidth >= 0 && aiBoxWidth < 800} {#if aiBoxWidth && aiBoxWidth >= 0 && aiBoxWidth < 1200}
<div <div
id="g-demo-lg" id="g-demo-lg"
class="g-artboard" class="g-artboard"
style="max-width: 799px;aspect-ratio: 2.75483870967742;" style="max-width: 1199px;aspect-ratio: 2.75483870967742;"
data-aspect-ratio="2.755" data-aspect-ratio="2.755"
data-min-width="0" data-min-width="0"
data-max-width="799" data-max-width="1199"
> >
<div <div
id="g-demo-lg-img" id="g-demo-lg-img"
class="g-demo-lg-img g-aiImg" class="g-demo-lg-img g-aiImg"
alt=""
style="background-image: url({imageLg});" style="background-image: url({imageLg});"
loading="lazy"
></div>
<div
id="g-png-layer-overlay-lg"
class="g-png-layer-overlay g-aiImg"
alt=""
style="opacity:1;;background-image: url({imagePngOverlayLg});"
loading="lazy"
></div> ></div>
</div> </div>
{/if} {/if}
<!-- Artboard: xl --> <!-- Artboard: xl -->
{#if aiBoxWidth && aiBoxWidth >= 800} {#if aiBoxWidth && aiBoxWidth >= 1200}
<div <div
id="g-demo-xl" id="g-demo-xl"
class="g-artboard" class="g-artboard"
style="min-width: 800px;aspect-ratio: 6.6758064516129;" style="min-width: 1200px;aspect-ratio: 4.80806451612903;"
data-aspect-ratio="6.676" data-aspect-ratio="4.808"
data-min-width="800" data-min-width="1200"
> >
<div <div
id="g-demo-xl-img" id="g-demo-xl-img"
class="g-demo-xl-img g-aiImg" class="g-demo-xl-img g-aiImg"
alt=""
style="background-image: url({imageXl});" style="background-image: url({imageXl});"
loading="lazy"
></div> ></div>
<div <div
id="g-png-layer-overlay-xl" id="g-png-layer-overlay-xl"
class="g-png-layer-overlay g-aiImg" class="g-png-layer-overlay g-aiImg"
alt=""
style="opacity:1;;background-image: url({imagePngOverlayXl});" style="opacity:1;;background-image: url({imagePngOverlayXl});"
loading="lazy"
></div> ></div>
<div <div
id="g-caption2" id="g-caption2"
class="g-captions g-aiAbs" class="g-captions g-aiAbs"
style="top:38.5484%;left:23.6715%;width:5.2428%;" style="top:14.3548%;left:34.8126%;width:7.2794%;"
> >
<p <p
class="g-pstyle0 g-taggedText g-htext" class="g-pstyle0 g-taggedText g-htext"
@ -93,7 +110,7 @@
<div <div
id="g-caption3" id="g-caption3"
class="g-captions g-aiAbs" class="g-captions g-aiAbs"
style="top:38.5484%;left:49.4749%;width:5.2428%;" style="top:14.3548%;left:60.6764%;width:7.2794%;"
> >
<p <p
class="g-pstyle0 g-taggedText g-htext" class="g-pstyle0 g-taggedText g-htext"
@ -106,7 +123,7 @@
<div <div
id="g-caption4" id="g-caption4"
class="g-captions g-aiAbs" class="g-captions g-aiAbs"
style="top:38.5484%;left:83.976%;width:5.2428%;" style="top:14.3548%;left:84.0914%;width:7.2794%;"
> >
<p <p
class="g-pstyle0 g-taggedText g-htext" class="g-pstyle0 g-taggedText g-htext"
@ -119,7 +136,7 @@
<div <div
id="g-caption1" id="g-caption1"
class="g-captions g-aiAbs" class="g-captions g-aiAbs"
style="top:38.5484%;left:2.966%;width:3.4791%;" style="top:14.3548%;left:4.1182%;width:4.8306%;"
> >
<p <p
class="g-pstyle0 g-taggedText g-htext" class="g-pstyle0 g-taggedText g-htext"
@ -137,7 +154,7 @@
TAGGED TEXT PROPS TAGGED TEXT PROPS
taggedText={{ taggedText={
{ {
"text": { "text": {
@ -151,12 +168,12 @@ taggedText={{
} }
} }
} }
}} }
--> -->
<!-- End ai2svelte - 2026-01-07 11:23 --> <!-- End ai2svelte - 2026-01-13 11:12 -->
<!-- Generated by ai2svelte v1.0.3 - 2026-01-07 11:23 --> <!-- Generated by ai2svelte v1.0.3 - 2026-01-13 11:12 -->
<!-- ai file: demo.ai --> <!-- ai file: demo.ai -->
<style lang="scss"> <style lang="scss">
#g-demo-box, #g-demo-box,
@ -187,6 +204,13 @@ taggedText={{
background-size: contain; background-size: contain;
background-repeat: no-repeat; background-repeat: no-repeat;
} }
#g-demo-box .g-aiSymbol {
position: absolute;
box-sizing: border-box;
}
#g-demo-box .g-aiPointText p {
white-space: nowrap;
}
#g-demo-box { #g-demo-box {
height: 100%; height: 100%;
} }
@ -225,8 +249,9 @@ taggedText={{
content: attr(data-tagged-type); content: attr(data-tagged-type);
padding: 0px 4px; padding: 0px 4px;
font-size: 0.6rem; font-size: 0.6rem;
font-style: normal;
color: #fff; color: #fff;
background-color: black; background-color: #ee0000;
display: block; display: block;
font-weight: 800; font-weight: 800;
visibility: var(--debug-tagged-text, hidden); visibility: var(--debug-tagged-text, hidden);
@ -236,14 +261,34 @@ taggedText={{
content: attr(data-tagged-prop); content: attr(data-tagged-prop);
padding: 0px 4px; padding: 0px 4px;
font-size: 0.8rem; font-size: 0.8rem;
font-style: normal;
color: #fff; color: #fff;
font-weight: 500; font-weight: 500;
visibility: var(--debug-tagged-text, hidden); visibility: var(--debug-tagged-text, hidden);
} }
.g-taggedText:empty { .g-taggedText:empty {
background-color: #00000088; background-color: #440000;
outline: 2px solid black; outline: 2px solid #ee0000;
visibility: var(--debug-tagged-text, hidden); visibility: var(--debug-tagged-text, hidden);
} }
.g-taggedText:not(:empty)::before {
content: attr(data-tagged-type);
position: absolute;
width: calc(100% + 4px);
transform: translateY(-100%) translateX(-2px);
padding: 0px 4px;
font-size: 0.6rem;
font-style: normal;
color: #fff;
background-color: black;
display: block;
font-weight: 800;
visibility: var(--debug-tagged-text, hidden);
}
.g-taggedText {
outline: var(--debug-stroke, 0px) solid black;
}
</style> </style>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1 MiB

After

Width:  |  Height:  |  Size: 881 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 MiB

After

Width:  |  Height:  |  Size: 1.4 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 MiB

After

Width:  |  Height:  |  Size: 1.2 MiB