@neovici/cosmoz-button 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,29 @@
1
+ export type ButtonVariant = 'primary' | 'secondary' | 'tertiary' | 'destructive' | 'link';
2
+ export type ButtonSize = 'sm' | 'md' | 'lg' | 'xl';
3
+ export type ButtonType = 'button' | 'submit' | 'reset';
4
+ export interface CosmozButtonElement extends HTMLElement {
5
+ variant: ButtonVariant;
6
+ size: ButtonSize;
7
+ disabled: boolean;
8
+ 'full-width': boolean;
9
+ type: ButtonType;
10
+ }
11
+ /**
12
+ * A customizable button component using Untitled UI design tokens.
13
+ *
14
+ * @element cosmoz-button
15
+ *
16
+ * @attr {string} variant - Button style variant: primary (default), secondary, tertiary, destructive, link
17
+ * @attr {string} size - Button size: sm, md (default), lg, xl
18
+ * @attr {boolean} disabled - Disables the button
19
+ * @attr {boolean} full-width - Makes the button 100% width
20
+ * @attr {string} type - Button type: button (default), submit, reset
21
+ *
22
+ * @slot - Default slot for button text content
23
+ * @slot prefix - Slot for prefix icon (before text)
24
+ * @slot suffix - Slot for suffix icon (after text)
25
+ *
26
+ * @csspart button - The native button element
27
+ */
28
+ declare const CosmozButton: (host: CosmozButtonElement) => import("lit-html").TemplateResult<1>;
29
+ export { CosmozButton };
@@ -0,0 +1,44 @@
1
+ import { normalize } from '@neovici/cosmoz-tokens/normalize';
2
+ import { component, html } from '@pionjs/pion';
3
+ import { styles } from './styles';
4
+ const observedAttributes = [
5
+ 'variant',
6
+ 'size',
7
+ 'disabled',
8
+ 'full-width',
9
+ 'type',
10
+ ];
11
+ /**
12
+ * A customizable button component using Untitled UI design tokens.
13
+ *
14
+ * @element cosmoz-button
15
+ *
16
+ * @attr {string} variant - Button style variant: primary (default), secondary, tertiary, destructive, link
17
+ * @attr {string} size - Button size: sm, md (default), lg, xl
18
+ * @attr {boolean} disabled - Disables the button
19
+ * @attr {boolean} full-width - Makes the button 100% width
20
+ * @attr {string} type - Button type: button (default), submit, reset
21
+ *
22
+ * @slot - Default slot for button text content
23
+ * @slot prefix - Slot for prefix icon (before text)
24
+ * @slot suffix - Slot for suffix icon (after text)
25
+ *
26
+ * @csspart button - The native button element
27
+ */
28
+ const CosmozButton = (host) => {
29
+ const disabled = host.hasAttribute('disabled');
30
+ const type = host.getAttribute('type') || 'button';
31
+ return html `
32
+ <button type=${type} class="button" ?disabled=${disabled} part="button">
33
+ <slot name="prefix"></slot>
34
+ <slot></slot>
35
+ <slot name="suffix"></slot>
36
+ </button>
37
+ `;
38
+ };
39
+ customElements.define('cosmoz-button', component(CosmozButton, {
40
+ observedAttributes,
41
+ styleSheets: [normalize, styles],
42
+ shadowRootInit: { mode: 'open', delegatesFocus: true },
43
+ }));
44
+ export { CosmozButton };
@@ -0,0 +1 @@
1
+ export { CosmozButton, type ButtonSize, type ButtonVariant, type CosmozButtonElement, } from './cosmoz-button';
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export { CosmozButton, } from './cosmoz-button';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Button styles using cosmoz-tokens design system
3
+ * Based on Untitled UI button component specifications
4
+ */
5
+ export declare const styles: string;
package/dist/styles.js ADDED
@@ -0,0 +1,239 @@
1
+ import { skeumorphicHighlight } from '@neovici/cosmoz-tokens/skeumorphic';
2
+ import { css } from '@pionjs/pion';
3
+ /**
4
+ * Button styles using cosmoz-tokens design system
5
+ * Based on Untitled UI button component specifications
6
+ */
7
+ export const styles = css `
8
+ :host {
9
+ display: inline-flex;
10
+ }
11
+
12
+ :host([full-width]) {
13
+ display: flex;
14
+ width: 100%;
15
+ }
16
+
17
+ :host([hidden]) {
18
+ display: none;
19
+ }
20
+
21
+ /* ========================================
22
+ * SIZE VARIANTS
23
+ * ======================================== */
24
+
25
+ :host([size='sm']) .button {
26
+ height: 36px;
27
+ padding: calc(var(--cz-spacing) * 2) calc(var(--cz-spacing) * 3.5);
28
+ font-size: var(--cz-text-sm);
29
+ line-height: var(--cz-text-sm-line-height);
30
+ border-radius: var(--cz-radius-md);
31
+ }
32
+
33
+ :host([size='sm']) ::slotted(svg) {
34
+ width: 16px;
35
+ height: 16px;
36
+ }
37
+
38
+ :host([size='lg']) .button {
39
+ height: 44px;
40
+ padding: calc(var(--cz-spacing) * 2.5) calc(var(--cz-spacing) * 4.5);
41
+ font-size: var(--cz-text-base);
42
+ line-height: var(--cz-text-base-line-height);
43
+ border-radius: var(--cz-radius-md);
44
+ }
45
+
46
+ :host([size='xl']) .button {
47
+ height: 48px;
48
+ padding: calc(var(--cz-spacing) * 3) calc(var(--cz-spacing) * 5);
49
+ font-size: var(--cz-text-base);
50
+ line-height: var(--cz-text-base-line-height);
51
+ border-radius: var(--cz-radius-md);
52
+ }
53
+
54
+ /* ========================================
55
+ * BUTTON BASE STYLES (Primary - default)
56
+ * ======================================== */
57
+
58
+ .button {
59
+ display: inline-flex;
60
+ align-items: center;
61
+ justify-content: center;
62
+ gap: 8px;
63
+ cursor: pointer;
64
+ font-family: var(--cz-font-body);
65
+ font-weight: var(--cz-font-weight-semibold);
66
+ text-decoration: none;
67
+ transition:
68
+ background-color 0.15s ease,
69
+ box-shadow 0.15s ease;
70
+ width: 100%;
71
+
72
+ /* Medium (md) - default size */
73
+ height: 40px;
74
+ padding: calc(var(--cz-spacing) * 2.5) calc(var(--cz-spacing) * 4);
75
+ font-size: var(--cz-text-sm);
76
+ line-height: var(--cz-text-sm-line-height);
77
+ border-radius: var(--cz-radius-md);
78
+
79
+ /* Primary - default variant */
80
+ ${skeumorphicHighlight}
81
+ background-color: var(--cz-color-bg-brand-solid);
82
+ color: var(--cz-color-text-on-brand);
83
+ box-shadow: var(--cz-shadow-xs-skeumorphic);
84
+
85
+ &:hover {
86
+ background-color: var(--cz-color-bg-brand-solid-hover);
87
+ }
88
+
89
+ &:active {
90
+ background-color: var(--cz-color-brand-800);
91
+ }
92
+
93
+ &:focus-visible {
94
+ outline: none;
95
+ box-shadow: var(--cz-shadow-xs-skeumorphic), var(--cz-focus-ring);
96
+ }
97
+ }
98
+
99
+ /* ========================================
100
+ * STYLE VARIANTS
101
+ * ======================================== */
102
+
103
+ :host([variant='secondary']) .button {
104
+ background-color: var(--cz-color-bg-primary);
105
+ color: var(--cz-color-text-secondary);
106
+
107
+ &:hover {
108
+ background-color: var(--cz-color-bg-primary-hover);
109
+ color: var(--cz-color-text-secondary-hover);
110
+ }
111
+
112
+ &:active {
113
+ background-color: var(--cz-color-bg-tertiary);
114
+ }
115
+
116
+ &:focus-visible {
117
+ box-shadow: var(--cz-shadow-xs-skeumorphic), var(--cz-focus-ring);
118
+ }
119
+ }
120
+
121
+ :host([variant='tertiary']) .button {
122
+ background-color: transparent;
123
+ color: var(--cz-color-text-secondary);
124
+ box-shadow: none;
125
+
126
+ &::before {
127
+ display: none;
128
+ }
129
+
130
+ &:hover {
131
+ background-color: var(--cz-color-bg-primary-hover);
132
+ color: var(--cz-color-text-secondary-hover);
133
+ }
134
+
135
+ &:active {
136
+ background-color: var(--cz-color-bg-secondary);
137
+ }
138
+
139
+ &:focus-visible {
140
+ box-shadow: var(--cz-focus-ring);
141
+ }
142
+ }
143
+
144
+ :host([variant='destructive']) .button {
145
+ background-color: var(--cz-color-bg-error-solid);
146
+
147
+ &:hover {
148
+ background-color: var(--cz-color-bg-error-solid-hover);
149
+ }
150
+
151
+ &:active {
152
+ background-color: var(--cz-color-error-800);
153
+ }
154
+
155
+ &:focus-visible {
156
+ box-shadow: var(--cz-shadow-xs-skeumorphic), var(--cz-focus-ring-error);
157
+ }
158
+ }
159
+
160
+ :host([variant='link']) .button {
161
+ background-color: transparent;
162
+ color: var(--cz-color-text-brand);
163
+ box-shadow: none;
164
+ padding: 0;
165
+ height: auto;
166
+
167
+ &::before {
168
+ display: none;
169
+ }
170
+
171
+ &:hover {
172
+ text-decoration: underline;
173
+ color: var(--cz-color-text-brand-hover);
174
+ }
175
+
176
+ &:active {
177
+ color: var(--cz-color-brand-800);
178
+ }
179
+
180
+ &:focus-visible {
181
+ text-decoration: underline;
182
+ box-shadow: var(--cz-focus-ring);
183
+ border-radius: var(--cz-radius-xs);
184
+ }
185
+ }
186
+
187
+ /* ========================================
188
+ * DISABLED STATE
189
+ * ======================================== */
190
+
191
+ :host([disabled]) .button {
192
+ cursor: not-allowed;
193
+ pointer-events: none;
194
+
195
+ &::before {
196
+ display: none;
197
+ }
198
+ }
199
+
200
+ :host([disabled]) .button,
201
+ :host([disabled][variant='primary']) .button {
202
+ background-color: var(--cz-color-bg-disabled);
203
+ color: var(--cz-color-text-disabled);
204
+ box-shadow: none;
205
+ }
206
+
207
+ :host([disabled][variant='secondary']) .button {
208
+ background-color: var(--cz-color-bg-primary);
209
+ color: var(--cz-color-text-disabled);
210
+ box-shadow: none;
211
+ }
212
+
213
+ :host([disabled][variant='tertiary']) .button {
214
+ background-color: transparent;
215
+ color: var(--cz-color-text-disabled);
216
+ box-shadow: none;
217
+ }
218
+
219
+ :host([disabled][variant='destructive']) .button {
220
+ background-color: var(--cz-color-bg-disabled);
221
+ color: var(--cz-color-text-disabled);
222
+ box-shadow: none;
223
+ }
224
+
225
+ :host([disabled][variant='link']) .button {
226
+ background-color: transparent;
227
+ color: var(--cz-color-text-disabled);
228
+ }
229
+
230
+ /* ========================================
231
+ * ICON SLOTS
232
+ * ======================================== */
233
+
234
+ ::slotted(svg) {
235
+ width: 20px;
236
+ height: 20px;
237
+ flex-shrink: 0;
238
+ }
239
+ `;
package/package.json ADDED
@@ -0,0 +1,93 @@
1
+ {
2
+ "name": "@neovici/cosmoz-button",
3
+ "version": "1.0.0",
4
+ "description": "A customizable button web component built with Untitled UI design tokens",
5
+ "keywords": [
6
+ "web-components",
7
+ "pion",
8
+ "lit-html",
9
+ "button",
10
+ "design-system"
11
+ ],
12
+ "homepage": "https://github.com/Neovici/cosmoz-button#readme",
13
+ "bugs": {
14
+ "url": "https://github.com/Neovici/cosmoz-button/issues"
15
+ },
16
+ "repository": {
17
+ "type": "git",
18
+ "url": "git+https://github.com/Neovici/cosmoz-button.git"
19
+ },
20
+ "license": "Apache-2.0",
21
+ "author": "Neovici Development",
22
+ "main": "dist/index.js",
23
+ "type": "module",
24
+ "directories": {
25
+ "test": "test"
26
+ },
27
+ "scripts": {
28
+ "lint": "tsc && eslint --cache .",
29
+ "check:duplicates": "check-duplicate-components",
30
+ "build": "tsc -p tsconfig.build.json",
31
+ "start": "wds",
32
+ "test": "wtr --coverage",
33
+ "test:watch": "wtr --watch",
34
+ "storybook:start": "storybook dev -p 8000",
35
+ "storybook:build": "storybook build",
36
+ "storybook:deploy": "storybook-to-ghpages",
37
+ "storybook:preview": "npm run storybook:build && http-server ./storybook-static/ --silent",
38
+ "prepare": "husky"
39
+ },
40
+ "release": {
41
+ "plugins": [
42
+ "@semantic-release/commit-analyzer",
43
+ "@semantic-release/release-notes-generator",
44
+ "@semantic-release/changelog",
45
+ "@semantic-release/github",
46
+ "@semantic-release/npm",
47
+ "@semantic-release/git"
48
+ ],
49
+ "branch": "main",
50
+ "preset": "conventionalcommits"
51
+ },
52
+ "publishConfig": {
53
+ "access": "public"
54
+ },
55
+ "files": [
56
+ "dist/",
57
+ "types"
58
+ ],
59
+ "exports": {
60
+ ".": "./dist/index.js",
61
+ "./cosmoz-button": "./dist/cosmoz-button.js"
62
+ },
63
+ "dependencies": {
64
+ "@neovici/cosmoz-tokens": "^3.2.0",
65
+ "@pionjs/pion": "^2.5.2",
66
+ "lit-html": "^3.3.1"
67
+ },
68
+ "devDependencies": {
69
+ "@commitlint/cli": "^20.0.0",
70
+ "@commitlint/config-conventional": "^20.0.0",
71
+ "@neovici/cfg": "^2.8.0",
72
+ "@neovici/testing": "^2.0.0",
73
+ "@open-wc/testing": "^4.0.0",
74
+ "@semantic-release/changelog": "^6.0.0",
75
+ "@semantic-release/git": "^10.0.0",
76
+ "@storybook/addon-docs": "^10.2.3",
77
+ "@storybook/web-components-vite": "^10.0.0",
78
+ "@types/mocha": "^10.0.6",
79
+ "@types/node": "^24.0.0",
80
+ "@web/test-runner-playwright": "^0.11.1",
81
+ "eslint": "^9.0.0",
82
+ "http-server": "^14.1.1",
83
+ "husky": "^9.0.0",
84
+ "lint-staged": "^16.2.7",
85
+ "semantic-release": "^25.0.0",
86
+ "sinon": "^19.0.0",
87
+ "storybook": "^10.0.0",
88
+ "typescript": "^5.4.3"
89
+ },
90
+ "overrides": {
91
+ "conventional-changelog-conventionalcommits": ">= 8.0.0"
92
+ }
93
+ }