portofolio/src/lib/components/molecules/CodeBlock.svelte
2025-06-05 22:17:05 +03:00

129 lines
2.5 KiB
Svelte

<script lang="ts">
export let filename: string;
export let lang: string;
export let fullBleed: boolean | undefined = undefined;
let codeContent: HTMLElement;
let isCopied = false;
// Copy the code inside the slot
async function copyCode() {
if (codeContent) {
const codeText = codeContent.textContent?.trim() || '';
try {
await navigator.clipboard.writeText(codeText);
isCopied = true;
// Reset copy state after 2 seconds
setTimeout(() => (isCopied = false), 2000);
} catch (error) {
alert('Failed to copy code.');
}
}
}
</script>
<div class="code-block" class:full-bleed={fullBleed}>
{#if filename}
<div class="filename">{filename}</div>
{/if}
{#if lang}
<div class="lang">{lang}</div>
{/if}
<!-- Copy button -->
<button class="copy-button" on:click={copyCode}>
{#if isCopied}
Copied!
{:else}
📋
{/if}
</button>
<!-- Slot containing the code -->
<div bind:this={codeContent} class="code-container">
<slot />
</div>
</div>
<style lang="scss">
.code-block {
display: block;
position: relative;
background-color: var(--color--code-background);
color: var(--color--code-text);
font-family: var(--font--mono);
font-size: 1rem;
line-height: 1.33em;
border-radius: 8px;
box-shadow: var(--card-shadow);
padding: 30px 15px;
margin: 30px 0;
:global(pre) {
overflow-x: auto;
scrollbar-color: var(--color--primary) var(--color--primary-tint);
scrollbar-width: thin;
padding-bottom: 5px;
&::-webkit-scrollbar {
height: 8px;
}
&::-webkit-scrollbar-thumb {
background: var(--color--primary);
&:hover {
background: var(--color--primary-shade);
}
}
}
.lang {
position: absolute;
right: 0;
top: -15px;
background: inherit;
border-radius: 8px;
padding: 5px 10px;
z-index: 2;
font-size: 0.85em;
min-width: 40px;
text-align: center;
}
.filename {
background: inherit;
border-top-left-radius: 8px;
border-top-right-radius: 8px;
margin-bottom: -2px;
padding: 5px 10px;
position: absolute;
left: 0px;
top: -15px;
z-index: 1;
}
.code-container {
position: relative;
overflow-x: auto;
}
.copy-button {
position: absolute;
right: 10px;
top: 25px;
background: var(--color--code-background);
color: white;
border: none;
border-radius: 6px;
padding: 5px 8px;
font-size: 0.8rem;
cursor: pointer;
transition: all 0.2s ease;
opacity: 0.7;
z-index: 1;
&:hover {
background: var(--color--primary-shade);
opacity: 1;
}
}
}
</style>