
Research
/Security News
Laravel Lang Compromised with RCE Backdoor Across 700+ Versions
Laravel Lang packages were compromised with an RCE backdoor across hundreds of versions, exposing cloud, CI/CD, and developer secrets.
@nectary/labs
Advanced tools
Welcome to Nectary Labs! This is the experimental playground for new components, patterns, and features that are being evaluated for inclusion in the main Nectary design system.
Welcome to Nectary Labs! This is the experimental playground for new components, patterns, and features that are being evaluated for inclusion in the main Nectary design system.
Nectary Labs is a shared component library where any team can contribute their own experimental components. When a component is requested or used by multiple teams, it becomes a candidate for promotion to the main Nectary design system by the official Nectary team.
Think of it as an incubator where teams can share components with each other, and the most useful ones graduate to become officially supported in the main Nectary repository based on cross-team adoption.
Clone the repository
git clone <repository-url>
cd nectary
Install dependencies
pnpm install
Start the docs locally
pnpm start
Create documentation page for testing
Create a documentation page in docs/latest/src/pages/labComponents/YourComponent/ to display and manually test your component. This is essential for development and validation.
// docs/latest/src/pages/labComponents/YourComponent/examples/Basic.tsx
import '@nectary/labs/your-component'
export const BasicExample = () => (
<sinch-labs-your-component
text="Hello World"
disabled={false}
/>
)
Create a new directory following the naming convention:
mkdir my-new-component
cd my-new-component
First, create a documentation page in docs/latest/src/pages/labComponents/MyComponent/ to display and manually test your component during development:
// docs/latest/src/pages/labComponents/MyComponent/examples/Basic.tsx
import '@nectary/labs/my-new-component'
export const BasicExample = () => (
<sinch-labs-my-new-component
text="Hello World"
disabled={false}
/>
)
import { defineCustomElement, NectaryElement } from '../utils'
import templateHTML from './template.html'
import type React from 'react'
const template = document.createElement('template')
template.innerHTML = templateHTML
export class MyNewComponent extends NectaryElement {
// Private fields for DOM elements
#button: HTMLButtonElement
#controller: AbortController | null = null
constructor() {
super()
const shadowRoot = this.attachShadow()
shadowRoot.appendChild(template.content.cloneNode(true))
// Query DOM elements
this.#button = shadowRoot.querySelector('#button')!
}
connectedCallback() {
super.connectedCallback()
this.#controller = new AbortController()
const { signal } = this.#controller
// Add event listeners
this.#button.addEventListener('click', this.#onClick, { signal })
this.#updateUI()
}
disconnectedCallback() {
super.disconnectedCallback()
this.#controller?.abort()
this.#controller = null
}
static get observedAttributes() {
return ['disabled', 'text']
}
attributeChangedCallback(name: string, oldVal: string | null, newVal: string | null) {
if (oldVal === newVal) return
switch (name) {
case 'disabled':
case 'text':
this.#updateUI()
break
}
}
// Properties with getters/setters
get disabled(): boolean {
return this.hasAttribute('disabled')
}
set disabled(value: boolean) {
if (value) {
this.setAttribute('disabled', '')
} else {
this.removeAttribute('disabled')
}
}
get text(): string {
return this.getAttribute('text') ?? ''
}
set text(value: string) {
this.setAttribute('text', value)
}
#updateUI() {
if (!this.isDomConnected) return
this.#button.disabled = this.disabled
this.#button.textContent = this.text
}
#onClick = () => {
this.dispatchEvent(new CustomEvent('-click'))
}
}
defineCustomElement('sinch-labs-my-new-component', MyNewComponent)
// TypeScript definitions
type Props = {
disabled?: boolean
text?: string
}
type ElementProps = Partial<{ [K in keyof Props]: Props[K] | string }>
declare global {
interface HTMLElementTagNameMap {
'sinch-labs-my-new-component': ElementProps & HTMLElement
}
}
declare module 'react' {
namespace JSX {
interface IntrinsicElements {
'sinch-labs-my-new-component': ElementProps &
React.ClassAttributes<HTMLElement> &
React.HTMLAttributes<HTMLElement>
}
}
}
<style>
:host {
display: inline-block;
}
#button {
padding: 8px 16px;
border: 1px solid var(--sinch-sys-color-border-default);
border-radius: 4px;
background: var(--sinch-sys-color-surface-default);
color: var(--sinch-sys-color-text-default);
font: var(--sinch-sys-font-body-m);
cursor: pointer;
}
#button:hover {
background: var(--sinch-sys-color-surface-hover);
}
#button:disabled {
opacity: 0.5;
cursor: not-allowed;
}
</style>
<button id="button" type="button">
Default Text
</button>
Only use primitive types (string, number, boolean) for component properties to keep components as close to native HTML as possible. For complex data structures, prefer slots/children over array props for better composability:
// ❌ Avoid complex props
<my-component config={{theme: "dark", items: [1, 2, 3]}} />
<my-component items={[{title: "Item 1"}, {title: "Item 2"}]} />
// ✅ Use primitive props and slotted children
<my-component theme="dark" count="3">
<my-item title="Item 1" />
<my-item title="Item 2" />
</my-component>
Use the - prefix for custom events:
// Dispatch custom events
this.dispatchEvent(new CustomEvent('-click'))
this.dispatchEvent(new CustomEvent('-change', { detail: newValue }))
Always reflect important properties as attributes:
get disabled(): boolean {
return this.hasAttribute('disabled')
}
set disabled(value: boolean) {
if (value) {
this.setAttribute('disabled', '')
} else {
this.removeAttribute('disabled')
}
}
Leverage design tokens for consistent styling:
:host {
color: var(--sinch-sys-color-text-default);
font: var(--sinch-sys-font-body-m);
background: var(--sinch-sys-color-surface-default);
}
Follow conventional commit format:
feat(labs): add new component for data visualization
fix(labs): resolve accessibility issue in phone preview
docs(labs): update contributing guide with new patterns
We use semantic-release for automated versioning and publishing. Your commit messages directly determine the version bump:
feat: triggers a minor version bump (e.g., 1.2.0 → 1.3.0)fix: triggers a patch version bump (e.g., 1.2.0 → 1.2.1)docs:, style:, refactor: etc. don't trigger a releaseBREAKING CHANGE: in footer) trigger a major version bump (e.g., 1.2.0 → 2.0.0)This means your commit message format is crucial for proper versioning and release notes generation.
git checkout -b feat/my-new-componentTypeScript Conflicts: If you see "Subsequent property declarations must have the same type":
.d.ts filesnpm run build to regenerate typesImport Errors: Ensure all child components are properly imported:
Styling Issues:
:host for component root styleslabs/ for patterns and examplesReady to contribute? Start by exploring existing components in the repository, then follow the patterns above to create your own experimental component that could benefit teams across the organization!
FAQs
Welcome to Nectary Labs! This is the experimental playground for new components, patterns, and features that are being evaluated for inclusion in the main Nectary design system.
The npm package @nectary/labs receives a total of 1,063 weekly downloads. As such, @nectary/labs popularity was classified as popular.
We found that @nectary/labs demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 6 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Research
/Security News
Laravel Lang packages were compromised with an RCE backdoor across hundreds of versions, exposing cloud, CI/CD, and developer secrets.

Security News
Socket found a malicious postinstall hook across 700+ GitHub repos, including PHP packages on Packagist and Node.js project repositories.

Security News
Vibe coding at scale is reshaping how packages are created, contributed, and selected across the software supply chain