@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.
- package/dist/cosmoz-button.d.ts +29 -0
- package/dist/cosmoz-button.js +44 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/styles.d.ts +5 -0
- package/dist/styles.js +239 -0
- package/package.json +93 -0
|
@@ -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 };
|
package/dist/index.d.ts
ADDED
|
@@ -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';
|
package/dist/styles.d.ts
ADDED
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
|
+
}
|