style: Update class attribute in Highlight component
This commit is contained in:
parent
ea4fa0c342
commit
88012308d0
@ -102,10 +102,7 @@ export const Highlight: ParentComponent<Props> = (_props) => {
|
|||||||
)}
|
)}
|
||||||
|
|
||||||
<pre
|
<pre
|
||||||
class={clsx(
|
class={clsx("not-prose h-full w-full prism-code flex", languageClass())}
|
||||||
"not-prose w-full prism-code flex overflow-x-auto",
|
|
||||||
languageClass(),
|
|
||||||
)}
|
|
||||||
>
|
>
|
||||||
<code
|
<code
|
||||||
class={clsx("leading-6", props.withLineNumbers ? "px-4" : "pr-4")}
|
class={clsx("leading-6", props.withLineNumbers ? "px-4" : "pr-4")}
|
||||||
|
|||||||
@ -48,10 +48,40 @@ export function SmoothScroll(props: SmoothScrollProps) {
|
|||||||
return regex.test(navigator.userAgent);
|
return regex.test(navigator.userAgent);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const isElementScrollable = (element: HTMLElement) => {
|
||||||
|
if (!element) return false;
|
||||||
|
return element.scrollHeight > element.clientHeight;
|
||||||
|
};
|
||||||
|
|
||||||
|
const findScrollableParent = (element: HTMLElement) => {
|
||||||
|
let currentElement: HTMLElement | null = element;
|
||||||
|
|
||||||
|
while (currentElement) {
|
||||||
|
if (isElementScrollable(currentElement)) {
|
||||||
|
return currentElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentElement = currentElement.parentElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
const handleWheel = (event: WheelEvent) => {
|
const handleWheel = (event: WheelEvent) => {
|
||||||
if (isMobile()) return;
|
if (isMobile()) return;
|
||||||
|
|
||||||
|
const hoveredElement = document.elementFromPoint(
|
||||||
|
event.clientX,
|
||||||
|
event.clientY,
|
||||||
|
) as HTMLElement;
|
||||||
|
if (findScrollableParent(hoveredElement)) {
|
||||||
|
if (animationFrameId !== null) cancelAnimationFrame(animationFrameId);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
if (isScrolling()) {
|
if (isScrolling()) {
|
||||||
if (animationFrameId !== null) {
|
if (animationFrameId !== null) {
|
||||||
cancelAnimationFrame(animationFrameId);
|
cancelAnimationFrame(animationFrameId);
|
||||||
|
|||||||
@ -38,6 +38,9 @@ type SnippetProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export function Snippet(props: SnippetProps) {
|
export function Snippet(props: SnippetProps) {
|
||||||
|
let tabs: HTMLDivElement | undefined;
|
||||||
|
let nav: HTMLDivElement | undefined;
|
||||||
|
|
||||||
const [selectedTab, setSelectedTab] = createSignal<SnippetTab | CommonTab>(
|
const [selectedTab, setSelectedTab] = createSignal<SnippetTab | CommonTab>(
|
||||||
props.snippets[0],
|
props.snippets[0],
|
||||||
);
|
);
|
||||||
@ -49,6 +52,27 @@ export function Snippet(props: SnippetProps) {
|
|||||||
const selectTab = (name: string) => {
|
const selectTab = (name: string) => {
|
||||||
const tab = props.snippets.find((tab) => tab.name === name);
|
const tab = props.snippets.find((tab) => tab.name === name);
|
||||||
if (tab) setSelectedTab(tab);
|
if (tab) setSelectedTab(tab);
|
||||||
|
|
||||||
|
if (!tabs || !nav) return;
|
||||||
|
|
||||||
|
const navWidth = nav.offsetWidth || 0;
|
||||||
|
const tabsWidth = tabs.scrollWidth;
|
||||||
|
|
||||||
|
if (tabsWidth > navWidth) {
|
||||||
|
const tabElement: HTMLDivElement | null = tabs.querySelector(
|
||||||
|
`div[data-tab="${name}"]`,
|
||||||
|
);
|
||||||
|
if (!tabElement) return;
|
||||||
|
|
||||||
|
const tabOffsetLeft = tabElement.offsetLeft;
|
||||||
|
const tabWidth = tabElement.offsetWidth;
|
||||||
|
const scrollLeft = Math.max(
|
||||||
|
0,
|
||||||
|
tabOffsetLeft - navWidth / 2 + tabWidth / 2,
|
||||||
|
);
|
||||||
|
|
||||||
|
nav.scrollTo({ left: scrollLeft, behavior: "smooth" });
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const canBeSelected = (tab: SnippetTab | CommonTab) => {
|
const canBeSelected = (tab: SnippetTab | CommonTab) => {
|
||||||
@ -68,48 +92,51 @@ export function Snippet(props: SnippetProps) {
|
|||||||
<div class="pt-4 pl-4">
|
<div class="pt-4 pl-4">
|
||||||
<TrafficLightsIcon class="h-2.5 w-auto stroke-slate-500/30" />
|
<TrafficLightsIcon class="h-2.5 w-auto stroke-slate-500/30" />
|
||||||
|
|
||||||
<div class="mt-4 flex space-x-2 text-xs overflow-x-auto">
|
<nav ref={nav} class="overflow-x-auto">
|
||||||
<For each={props.snippets}>
|
<div ref={tabs} class="mt-4 flex space-x-2 text-xs w-max mb-2">
|
||||||
{(tab) => (
|
<For each={props.snippets}>
|
||||||
<div
|
{(tab) => (
|
||||||
class={clsx(
|
<div
|
||||||
"flex h-6 rounded-full",
|
data-tab={tab.name}
|
||||||
{ "cursor-pointer": canBeSelected(tab) && !isActive(tab) },
|
|
||||||
isActive(tab)
|
|
||||||
? clsx(
|
|
||||||
"bg-linear-to-r from-violet-400/30 via-violet-400 to-violet-400/30 p-px font-medium",
|
|
||||||
props.dark ? "text-violet-300" : "text-violet-600",
|
|
||||||
)
|
|
||||||
: props.dark
|
|
||||||
? "text-slate-400"
|
|
||||||
: "text-slate-500",
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
type="button"
|
|
||||||
class={clsx(
|
class={clsx(
|
||||||
"flex items-center rounded-full px-2.5",
|
"flex h-6 rounded-full",
|
||||||
isActive(tab) && {
|
{ "cursor-pointer": canBeSelected(tab) && !isActive(tab) },
|
||||||
"bg-slate-800": props.dark,
|
isActive(tab)
|
||||||
"bg-violet-100": !props.dark,
|
? clsx(
|
||||||
},
|
"bg-linear-to-r from-violet-400/30 via-violet-400 to-violet-400/30 p-px font-medium",
|
||||||
|
props.dark ? "text-violet-300" : "text-violet-600",
|
||||||
|
)
|
||||||
|
: props.dark
|
||||||
|
? "text-slate-400"
|
||||||
|
: "text-slate-500",
|
||||||
)}
|
)}
|
||||||
disabled={!canBeSelected(tab)}
|
|
||||||
onClick={() => selectTab(tab.name)}
|
|
||||||
>
|
>
|
||||||
{tab.name}
|
<button
|
||||||
</button>
|
type="button"
|
||||||
</div>
|
class={clsx(
|
||||||
)}
|
"flex items-center rounded-full px-2.5",
|
||||||
</For>
|
isActive(tab) && {
|
||||||
</div>
|
"bg-slate-800": props.dark,
|
||||||
|
"bg-violet-100": !props.dark,
|
||||||
|
},
|
||||||
|
)}
|
||||||
|
disabled={!canBeSelected(tab)}
|
||||||
|
onClick={() => selectTab(tab.name)}
|
||||||
|
>
|
||||||
|
{tab.name}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</For>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
{selectedTab() && (
|
{selectedTab() && (
|
||||||
<div class="mt-6">
|
<div class="mt-6">
|
||||||
{selectedTab().code && (
|
{selectedTab().code && (
|
||||||
<Highlight
|
<Highlight
|
||||||
class={clsx(
|
class={clsx(
|
||||||
"!pt-0 !px-1 max-h-96 overflow-auto",
|
"!pt-0 !px-1 max-h-96 overflow-auto mb-2",
|
||||||
props.dark && "dark text-white",
|
props.dark && "dark text-white",
|
||||||
)}
|
)}
|
||||||
language={(selectedTab() as SnippetTab).codeLanguage}
|
language={(selectedTab() as SnippetTab).codeLanguage}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user