Skip to content

Instantly share code, notes, and snippets.

@Atulin
Last active July 20, 2025 19:52
Show Gist options
  • Select an option

  • Save Atulin/22601e96093ff200a75163ff2651c986 to your computer and use it in GitHub Desktop.

Select an option

Save Atulin/22601e96093ff200a75163ff2651c986 to your computer and use it in GitHub Desktop.
SolidElement Styled wrapper

Styled wrapper for SolidElement webcomponents

1. Create a regular ol' Solid component:

const Counter: ComponentType<{ title: string, count: number }> = (props) => {
	const [count, setCount] = createSignal(props.count);
	
	return (
		<div class="counter">
			<span class="title">{props.title}</span>
			<button class="increment" onclick={[ setCount, count() + 1 ]}>{count}</button>
		</div>
	)
};

2. Wrap it

const css = `
.counter {
	display: flex;
	flex-direction: column;
}
.title {
	font-size: 1.1rem;
}
.increment {
	cursor: pointer;
}
`;

customElement(
	"x-counter", 
	{ title: "counter", count: 0 },
	Styled(Counter, css),
);

3. Use it

<h1>Counter demo</h1>

<x-counter title="skibidi" count="69"></x-counter>
import type { ComponentOptions, FunctionComponent } from "component-register";
import type { ComponentType } from "solid-element";
import { type Component, createComponent, onMount } from "solid-js";
type SolidElementInstance = Element & { renderRoot?: Node | null };
/**
* A higher-order component function that wraps a given component and injects scoped CSS styles
* into its rendering context. The injected CSS is appended to the component's shadow DOM or
* render root during the component's mount lifecycle.
*
* @template TProps The type of the component's props.
* @param {ComponentType<TProps>} component The component to wrap and style. Can be a functional or class-based component.
* @param {string} css The CSS styles to be applied to the wrapped component.
* @returns {ComponentType<TProps>} A new component type with the specified styles applied.
*/
export const Styled = <TProps extends Record<string, unknown>>(
component: ComponentType<TProps>,
...css: string[]
): ComponentType<TProps> => {
return (props: TProps, options: ComponentOptions) => {
onMount(() => {
const styleEl = document.createElement("style");
styleEl.textContent = css.join("");
const element = options.element as unknown as SolidElementInstance;
if (element.renderRoot && element.renderRoot !== element) {
element.renderRoot.appendChild(styleEl);
} else {
element.appendChild(styleEl);
}
});
if (Object.getPrototypeOf(component).constructor === component) {
return createComponent(component as unknown as Component<TProps>, props);
}
return (component as FunctionComponent<TProps>)(props, options);
};
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment