Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Playground death loop #480

Closed
brunnerh opened this issue Oct 20, 2024 · 4 comments · Fixed by sveltejs/svelte#13927
Closed

Playground death loop #480

brunnerh opened this issue Oct 20, 2024 · 4 comments · Fixed by sveltejs/svelte#13927

Comments

@brunnerh
Copy link
Member

This code (from a user question) will kill the playground:

<button class="shiny-cta">
  <span>Prøv Oss!</span>
</button>

<style>
  @import url("https://use.typekit.net/tzv3rms.css");

  :root {
      --shiny-cta-bg: #000000;
      --shiny-cta-bg-subtle: #1a1818;
      --shiny-cta-fg: #ffffff;
      --shiny-cta-highlight: #3772ff;
      --shiny-cta-highlight-subtle: #1a243e;
  }

  @property --gradient-angle {
      syntax: "<angle>";
      initial-value: 0deg;
      inherits: false;
  }

  @property --gradient-angle-offset {
      syntax: "<angle>";
      initial-value: 0deg;
      inherits: false;
  }

  @property --gradient-percent {
      syntax: "<percentage>";
      initial-value: 5%;
      inherits: false;
  }

  @property --gradient-shine {
      syntax: "<color>";
      initial-value: white;
      inherits: false;
  }

  .shiny-cta {
      --animation: gradient-angle linear infinite;
      --duration: 3s;
      --shadow-size: 2px;
      isolation: isolate;
      position: relative;
      overflow: hidden;
      cursor: pointer;
      outline-offset: 4px;
      padding: 1.25rem 2.5rem;
      font-family: inherit;
      font-size: 1.125rem;
      line-height: 1.2;
      border: 1px solid transparent;
      border-radius: 360px;
      color: var(--shiny-cta-fg);
      background: linear-gradient(var(--shiny-cta-bg), var(--shiny-cta-bg))
          padding-box,
      conic-gradient(
          from calc(var(--gradient-angle) - var(--gradient-angle-offset)),
          transparent,
          var(--shiny-cta-highlight) var(--gradient-percent),
          var(--gradient-shine) calc(var(--gradient-percent) * 2),
          var(--shiny-cta-highlight) calc(var(--gradient-percent) * 3),
          transparent calc(var(--gradient-percent) * 4)
      )
      border-box;
      box-shadow: inset 0 0 0 1px var(--shiny-cta-bg-subtle);
  }

  .shiny-cta::before,
  .shiny-cta::after,
  .shiny-cta span::before {
      content: "";
      pointer-events: none;
      position: absolute;
      inset-inline-start: 50%;
      inset-block-start: 50%;
      translate: -50% -50%;
      z-index: -1;
  } 

  .shiny-cta:active {
      translate: 0 1px;
  }

  .shiny-cta::before {
      --size: calc(100% - var(--shadow-size) * 3);
      --position: 2px;
      --space: calc(var(--position) * 2);
      width: var(--size);
      height: var(--size);
      background: radial-gradient(
          circle at var(--position) var(--position),
          white calc(var(--position) / 4),
          transparent 0
      )
      padding-box;
      background-size: var(--space) var(--space);
      background-repeat: space;
      mask-image: conic-gradient(
          from calc(var(--gradient-angle) + 45deg),
          black,
          transparent 10% 90%,
          black
      );
      border-radius: inherit;
      opacity: 0.4;
      z-index: -1;
  }

  .shiny-cta::after {
      --animation: shimmer linear infinite;
      width: 100%;
      aspect-ratio: 1;
      background: linear-gradient(
          -50deg,
          transparent,
          var(--shiny-cta-highlight),
          transparent
      );
      mask-image: radial-gradient(circle at bottom, transparent 40%, black);
      opacity: 0.6;
  }

  .shiny-cta span {
      z-index: 1;
  }

  .shiny-cta span::before {
      --size: calc(100% + 1rem);
      width: var(--size);
      height: var(--size);
      box-shadow: inset 0 -1ex 2rem 4px var(--shiny-cta-highlight);
      opacity: 0;
  }

  .shiny-cta {
      --transition: 800ms cubic-bezier(0.25, 1, 0.5, 1);
      transition: var(--transition);
      transition-property: --gradient-angle-offset, --gradient-percent,
      --gradient-shine;
  }

  .shiny-cta,
  .shiny-cta::before,
  .shiny-cta::after {
      animation: var(--animation) var(--duration),
      var(--animation) calc(var(--duration) / 0.4) reverse paused;
      animation-composition: add;
  }

  .shiny-cta span::before {
      transition: opacity var(--transition);
      animation: calc(var(--duration) * 1.5) breathe linear infinite;
  }

  .shiny-cta:is(:hover, :focus-visible) {
      --gradient-percent: 20%;
      --gradient-angle-offset: 95deg;
      --gradient-shine: var(--shiny-cta-highlight-subtle);
  }

  .shiny-cta:is(:hover, :focus-visible),
  .shiny-cta:is(:hover, :focus-visible)::before,
  .shiny-cta:is(:hover, :focus-visible)::after {
      animation-play-state: running;
  }

  .shiny-cta:is(:hover, :focus-visible) span::before {
      opacity: 1;
  }

  @keyframes gradient-angle {
      to {
          --gradient-angle: 360deg;
      }
  }

  @keyframes shimmer {
      to {
          rotate: 360deg;
      }
  }

  @keyframes breathe {
      from,
      to {
          scale: 1;
      }
      50% {
          scale: 1.2;
      }
  }
</style>
@brunnerh
Copy link
Member Author

Found another thing that sends it spinning - tried to add :global() around the input selector:

<label>
	<input type="checkbox" />
	<span>hi</span>
</label>

<style>
	label:has(input) span {
		color:red
	}
</style>

Playground

I.e. start typing :global in front of input.

@dummdidumm
Copy link
Member

I started debugging this and it seems neither the workers nor the editor syntax highlighting is the problem.

@dummdidumm
Copy link
Member

dummdidumm commented Oct 24, 2024

So it seems the AST output is the culprit. Trying to find out why now.

Edit: May actually be a bug within Svelte. The metadata object on complex selectors inside pseudo classes is not removed for some reason, seems like zimmerframe's walk doesn't reach it. No idea why.

@andirady
Copy link

Found another thing that sends it spinning - tried to add :global() around the input selector:

<label>
	<input type="checkbox" />
	<span>hi</span>
</label>

<style>
	label:has(input) span {
		color:red
	}
</style>

Playground

I.e. start typing :global in front of input.

The playground will slow down whenever you introduce :global. It's worse if you typed :global(body).

dummdidumm added a commit to sveltejs/svelte that referenced this issue Oct 25, 2024
Besides being private API that shouldn't be exposed, they caused our AST explorer on the Svelte site to traverse endlessly

fixes sveltejs/svelte.dev#480
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants