Compare commits

...

3 Commits

Author SHA1 Message Date
unkn0wn 4d7c882324 feat: updating package to version 0.03.0
Publish to npm / check-and-publish (push) Successful in 21s
2026-06-09 14:32:48 +02:00
unkn0wn c508d6ae31 feat: add NumericStepper component and integrate into index page 2026-06-09 14:30:40 +02:00
unkn0wn 02ae2b143e feat: add icon support to Button component 2026-06-09 14:08:53 +02:00
7 changed files with 155 additions and 4 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
{ {
"name": "@unkn0wndo3s/nova-design-system", "name": "@unkn0wndo3s/nova-design-system",
"type": "module", "type": "module",
"version": "0.02.0", "version": "0.03.0",
"main": "./src/index.ts", "main": "./src/index.ts",
"description": "Nova Design System — Astro component library", "description": "Nova Design System — Astro component library",
"engines": { "engines": {
+3
View File
@@ -34,4 +34,7 @@
background-color: var(--nds-disabled); background-color: var(--nds-disabled);
color: var(--nds-neutral); color: var(--nds-neutral);
} }
&--icon {
padding: var(--nds-spacing-2xs) var(--nds-spacing-xs);
}
} }
+3 -2
View File
@@ -2,11 +2,12 @@
export interface Props { export interface Props {
type: 'primary' | 'secondary'; type: 'primary' | 'secondary';
disabled?: boolean; disabled?: boolean;
icon?: boolean;
} }
const { type, disabled = false } = Astro.props; const { type, disabled = false, icon = false } = Astro.props;
--- ---
<div class={`button button__${type} ${disabled ? 'button--disabled' : ''}`}> <div class={`button button__${type} ${disabled ? 'button--disabled' : ''} ${icon ? 'button--icon' : ''}`}>
<slot/> <slot/>
</div> </div>
+2 -1
View File
@@ -11,4 +11,5 @@ export { default as Link } from './Link/link.astro';
export { default as ListItem } from './ListItem/listItem.astro'; export { default as ListItem } from './ListItem/listItem.astro';
export { default as ListItemTitle } from './ListItem/listItemTitle.astro'; export { default as ListItemTitle } from './ListItem/listItemTitle.astro';
export { default as ListItemSubtitle } from './ListItem/listItemSubtitle.astro'; export { default as ListItemSubtitle } from './ListItem/listItemSubtitle.astro';
export { default as LoadingBar } from './LoadingBar/loadingBar.astro'; export { default as LoadingBar } from './LoadingBar/loadingBar.astro';
export { default as NumericStepper } from './numericStepper/numericStepper.astro';
@@ -0,0 +1,14 @@
@use '../../styles/tokens/typography' as *;
.numeric-stepper {
display: flex;
flex-direction: column;
align-items: center;
gap: var(--nds-spacing-xs);
width: fit-content;
& p {
@include text-xl;
margin: 0;
}
}
@@ -0,0 +1,117 @@
---
import Button from '../Button/button.astro';
import { Arrow2Icon } from '../Icons';
export interface Props {
id: string;
min?: number;
max?: number;
value?: number;
step?: number;
}
const { id, min, max, value = 0, step = 1 } = Astro.props;
---
<div
class="numeric-stepper"
id={id}
data-numeric-stepper
data-min={min}
data-max={max}
data-value={value}
data-step={step}
>
<span class="numeric-stepper__control" data-action="increment">
<Button type="secondary" icon={true}>
<Arrow2Icon size={24} orientation="up" />
</Button>
</span>
<p class="numeric-stepper__value">{value}</p>
<span class="numeric-stepper__control" data-action="decrement">
<Button type="secondary" icon={true}>
<Arrow2Icon size={24} orientation="down" />
</Button>
</span>
</div>
<script>
type StepperAction = 'increment' | 'decrement';
interface StepperChangeDetail {
value: number;
}
interface StepperSetDetail {
value: number;
}
interface NumericStepperElement extends HTMLElement {
setValue: (value: number) => void;
getValue: () => number;
getStep: () => number;
}
declare global {
interface HTMLElementEventMap {
'stepper:change': CustomEvent<StepperChangeDetail>;
'stepper:set': CustomEvent<StepperSetDetail>;
}
}
document.querySelectorAll<NumericStepperElement>('[data-numeric-stepper]').forEach((stepper) => {
const { min: minAttr, max: maxAttr, step: stepAttr, value: valueAttr } = stepper.dataset;
const min = minAttr !== undefined ? Number(minAttr) : -Infinity;
const max = maxAttr !== undefined ? Number(maxAttr) : Infinity;
const step = stepAttr !== undefined ? Number(stepAttr) : 1;
let current = valueAttr !== undefined ? Number(valueAttr) : 0;
const display = stepper.querySelector<HTMLParagraphElement>('.numeric-stepper__value');
function render(): void {
if (display) display.textContent = String(current);
stepper.dataset.value = String(current);
}
function setValue(newValue: number): void {
const clamped = Math.min(max, Math.max(min, newValue));
if (clamped === current) return;
current = clamped;
render();
stepper.dispatchEvent(
new CustomEvent<StepperChangeDetail>('stepper:change', {
detail: { value: current },
bubbles: true,
}),
);
}
stepper.addEventListener('click', (event: MouseEvent) => {
const target = event.target as HTMLElement;
const control = target.closest<HTMLElement>('[data-action]');
if (!control || !stepper.contains(control)) return;
const action = control.dataset.action as StepperAction | undefined;
if (action === 'increment') setValue(current + step);
else if (action === 'decrement') setValue(current - step);
});
stepper.addEventListener('stepper:set', (event) => {
setValue(event.detail.value);
});
stepper.setValue = (value: number): void => setValue(value);
stepper.getValue = (): number => current;
stepper.getStep = (): number => step;
});
</script>
<style lang="scss">
@use './numericStepper';
</style>
+15
View File
@@ -11,6 +11,7 @@ import ListItem from '../components/ListItem/listItem.astro';
import ListItemTitle from '../components/ListItem/listItemTitle.astro'; import ListItemTitle from '../components/ListItem/listItemTitle.astro';
import ListItemSubtitle from '../components/ListItem/listItemSubtitle.astro'; import ListItemSubtitle from '../components/ListItem/listItemSubtitle.astro';
import LoadingBar from '../components/LoadingBar/loadingBar.astro'; import LoadingBar from '../components/LoadingBar/loadingBar.astro';
import NumericStepper from '../components/numericStepper/numericStepper.astro';
import { import {
Arrow2Icon, BinIcon, BurgerIcon, CalendarIcon, CheckIcon, CloseIcon, Arrow2Icon, BinIcon, BurgerIcon, CalendarIcon, CheckIcon, CloseIcon,
CodeIcon, CubeIcon, DownloadIcon, FilterIcon, HelpIcon, HomeIcon, CodeIcon, CubeIcon, DownloadIcon, FilterIcon, HelpIcon, HomeIcon,
@@ -25,6 +26,20 @@ const initialChecked = true;
<Layout> <Layout>
<main> <main>
<h1>Nova Design System</h1> <h1>Nova Design System</h1>
<section>
<h2>Numeric Stepper</h2>
<div style="display: flex; flex-direction: column; gap: var(--nds-spacing-md);">
<NumericStepper min={-15} max={10} value={5} step={5} id="my-numeric-stepper"/>
</div>
</section>
<section>
<h2>Loading Bar</h2>
<div style="display: flex; flex-direction: column; gap: var(--nds-spacing-md);">
<LoadingBar type="known" percentage={75} width="500px" />
<LoadingBar type="unknown" width="500px" />
</div>
</div>
</section>
<section> <section>
<h2>Loading Bar</h2> <h2>Loading Bar</h2>
<div style="display: flex; flex-direction: column; gap: var(--nds-spacing-md);"> <div style="display: flex; flex-direction: column; gap: var(--nds-spacing-md);">