@boostdev/design-system-components 2.7.0 → 2.7.1
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/AGENTS.md +102 -2
- package/dist/client.cjs +52 -52
- package/dist/client.css +548 -548
- package/dist/client.js +52 -52
- package/dist/index.cjs +52 -52
- package/dist/index.css +548 -548
- package/dist/index.js +52 -52
- package/dist/web-components/{chunk-T6AETZRP.js → chunk-3GFWLSLS.js} +1 -1
- package/dist/web-components/{chunk-N6IMUOY4.js → chunk-65JXQOBA.js} +3 -3
- package/dist/web-components/{chunk-ZTC6GRP7.js → chunk-BKIHQYJR.js} +1 -0
- package/dist/web-components/{chunk-X3FKVHLK.js → chunk-CM3KYZ6Z.js} +1 -1
- package/dist/web-components/{chunk-QLZ2362S.js → chunk-CZBIVR4V.js} +1 -1
- package/dist/web-components/{chunk-GER5UJOF.js → chunk-F5E3IT7G.js} +1 -3
- package/dist/web-components/{chunk-UFFCKVZE.js → chunk-FXURM6D5.js} +1 -1
- package/dist/web-components/{chunk-HHHRF2PS.js → chunk-IYGF6CD5.js} +1 -1
- package/dist/web-components/{chunk-OCODKRVZ.js → chunk-KUI55GFB.js} +2 -2
- package/dist/web-components/{chunk-ZNKEZIYE.js → chunk-NCPQ7AF3.js} +3 -2
- package/dist/web-components/{chunk-RTOS7LLG.js → chunk-PC3IOQAH.js} +3 -8
- package/dist/web-components/{chunk-JUKB3BUP.js → chunk-PXZWYO6Z.js} +1 -1
- package/dist/web-components/{chunk-EBJM3VD4.js → chunk-QBB6ZX4R.js} +1 -1
- package/dist/web-components/{chunk-ECW3HHWA.js → chunk-TQ7IQ4GZ.js} +7 -2
- package/dist/web-components/{chunk-AJSXNDAP.js → chunk-X46KL5BK.js} +19 -18
- package/dist/web-components/{chunk-XNA6WTXG.js → chunk-Y3POAKGS.js} +1 -1
- package/dist/web-components/{chunk-HGBNDR22.js → chunk-Y7V7LM6R.js} +1 -1
- package/dist/web-components/index.js +23 -19
- package/dist/web-components/interaction/bds-accordion-item.js +1 -1
- package/dist/web-components/interaction/bds-accordion.js +1 -1
- package/dist/web-components/interaction/bds-button.js +1 -1
- package/dist/web-components/interaction/bds-dialog.js +1 -1
- package/dist/web-components/interaction/bds-drawer.js +1 -1
- package/dist/web-components/interaction/bds-popover.js +1 -1
- package/dist/web-components/interaction/bds-tooltip.js +1 -1
- package/dist/web-components/interaction/form/bds-checkbox.js +1 -1
- package/dist/web-components/interaction/form/bds-combobox.js +1 -1
- package/dist/web-components/interaction/form/bds-number-input.js +1 -1
- package/dist/web-components/interaction/form/bds-radio.js +1 -1
- package/dist/web-components/interaction/form/bds-select.js +1 -1
- package/dist/web-components/interaction/form/bds-switch.js +1 -1
- package/dist/web-components/interaction/form/bds-textarea.js +1 -1
- package/dist/web-components/ui/bds-alert.js +1 -1
- package/dist/web-components/ui/bds-card.d.ts +3 -9
- package/dist/web-components/ui/bds-card.js +1 -1
- package/dist/web-components/ui/bds-notification-banner.js +1 -1
- package/package.json +2 -1
- package/src/components/layout/IconWrapper/IconWrapper.module.css +2 -2
- package/src/test/token-contract.spec.ts +86 -0
- package/src/web-components/interaction/bds-accordion-item.ts +1 -1
- package/src/web-components/interaction/bds-accordion.ts +1 -0
- package/src/web-components/interaction/bds-button.ts +1 -3
- package/src/web-components/interaction/bds-dialog.ts +3 -3
- package/src/web-components/interaction/bds-drawer.ts +2 -2
- package/src/web-components/interaction/bds-popover.ts +7 -2
- package/src/web-components/interaction/bds-tooltip.ts +1 -1
- package/src/web-components/interaction/form/bds-checkbox.ts +1 -1
- package/src/web-components/interaction/form/bds-combobox.ts +1 -1
- package/src/web-components/interaction/form/bds-form-input.ts +1 -1
- package/src/web-components/interaction/form/bds-number-input.ts +1 -1
- package/src/web-components/interaction/form/bds-radio.ts +1 -1
- package/src/web-components/interaction/form/bds-select.ts +1 -1
- package/src/web-components/interaction/form/bds-switch.ts +1 -1
- package/src/web-components/interaction/form/bds-textarea.ts +1 -1
- package/src/web-components/ui/BdsCard.mdx +4 -3
- package/src/web-components/ui/BdsCard.stories.tsx +7 -11
- package/src/web-components/ui/BdsSkeleton.stories.tsx +4 -4
- package/src/web-components/ui/bds-alert.ts +3 -2
- package/src/web-components/ui/bds-card.spec.ts +3 -5
- package/src/web-components/ui/bds-card.ts +5 -12
- package/src/web-components/ui/bds-notification-banner.ts +19 -18
- package/src/web-components/ui/bds-pagination.ts +1 -1
- package/src/web-components/ui/bds-table.ts +4 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { describe, it, expect } from 'vitest';
|
|
2
|
+
import { readdirSync, readFileSync, statSync } from 'node:fs';
|
|
3
|
+
import { join, relative } from 'node:path';
|
|
4
|
+
import { extractFoundationRefs, extractTokens } from '../../mcp/extract.ts';
|
|
5
|
+
|
|
6
|
+
function collectFiles(dir: string, ext: string): string[] {
|
|
7
|
+
const results: string[] = [];
|
|
8
|
+
for (const entry of readdirSync(dir)) {
|
|
9
|
+
const full = join(dir, entry);
|
|
10
|
+
if (statSync(full).isDirectory()) {
|
|
11
|
+
results.push(...collectFiles(full, ext));
|
|
12
|
+
} else if (full.endsWith(ext)) {
|
|
13
|
+
results.push(full);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
return results;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function loadDeclaredTokens(): Set<string> {
|
|
20
|
+
const tokensDir = join(__dirname, '../../node_modules/@boostdev/design-system-foundation/src/tokens');
|
|
21
|
+
const propertiesFile = join(tokensDir, 'properties.css');
|
|
22
|
+
const declared = new Set<string>();
|
|
23
|
+
|
|
24
|
+
for (const file of collectFiles(tokensDir, '.css')) {
|
|
25
|
+
const css = readFileSync(file, 'utf-8');
|
|
26
|
+
for (const token of extractTokens(css, 'all')) {
|
|
27
|
+
declared.add(token.name);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// @property declarations aren't captured by extractTokens — parse them separately
|
|
32
|
+
if (statSync(propertiesFile).isFile()) {
|
|
33
|
+
const css = readFileSync(propertiesFile, 'utf-8');
|
|
34
|
+
for (const [, name] of css.matchAll(/@property\s+(--bds-[\w-]+)/g)) {
|
|
35
|
+
declared.add(name);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Also include deprecated aliases (they resolve to real tokens)
|
|
40
|
+
const deprecatedFile = join(tokensDir, 'deprecated.css');
|
|
41
|
+
const deprecatedCss = readFileSync(deprecatedFile, 'utf-8');
|
|
42
|
+
for (const [, name] of deprecatedCss.matchAll(/^\s*(--bds-[\w-]+)\s*:/gm)) {
|
|
43
|
+
declared.add(name);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
return declared;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Component-local tokens that were incorrectly given the --bds-* prefix.
|
|
50
|
+
// Kept as deprecated fallbacks for backwards compatibility — remove in next major.
|
|
51
|
+
const DEPRECATED_BDS_ALIASES = new Set([
|
|
52
|
+
'--bds-on-icon-wrapper-color',
|
|
53
|
+
]);
|
|
54
|
+
|
|
55
|
+
describe('token contract', () => {
|
|
56
|
+
const declared = loadDeclaredTokens();
|
|
57
|
+
const srcRoot = join(__dirname, '../');
|
|
58
|
+
const componentCssFiles = collectFiles(join(srcRoot, 'components'), '.module.css');
|
|
59
|
+
const bdcFile = join(srcRoot, 'css/bdc.css');
|
|
60
|
+
|
|
61
|
+
it('has a non-empty set of declared foundation tokens', () => {
|
|
62
|
+
expect(declared.size).toBeGreaterThan(50);
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('resolves every var(--bds-*) reference in component CSS to a declared token', () => {
|
|
66
|
+
const undeclared: { file: string; token: string }[] = [];
|
|
67
|
+
|
|
68
|
+
for (const file of [...componentCssFiles, bdcFile]) {
|
|
69
|
+
const css = readFileSync(file, 'utf-8');
|
|
70
|
+
for (const ref of extractFoundationRefs(css)) {
|
|
71
|
+
if (!declared.has(ref) && !DEPRECATED_BDS_ALIASES.has(ref)) {
|
|
72
|
+
undeclared.push({ file: relative(srcRoot, file), token: ref });
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (undeclared.length > 0) {
|
|
78
|
+
const report = undeclared
|
|
79
|
+
.map(({ file, token }) => ` ${token} in ${file}`)
|
|
80
|
+
.join('\n');
|
|
81
|
+
expect.fail(
|
|
82
|
+
`Found ${undeclared.length} reference(s) to undeclared foundation tokens:\n${report}`,
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
});
|
|
@@ -69,7 +69,7 @@ export class BdsAccordionItem extends LitElement {
|
|
|
69
69
|
|
|
70
70
|
@media (hover: hover) and (pointer: fine) {
|
|
71
71
|
.trigger:not(:disabled):hover {
|
|
72
|
-
background-color: var(--bds-color_bg--subtle);
|
|
72
|
+
background-color: var(--accordion_trigger-bg--hover, var(--bds-color_bg--subtle));
|
|
73
73
|
}
|
|
74
74
|
}
|
|
75
75
|
|
|
@@ -26,6 +26,7 @@ export class BdsAccordion extends LitElement {
|
|
|
26
26
|
static styles = css`
|
|
27
27
|
:host {
|
|
28
28
|
display: block;
|
|
29
|
+
border: var(--accordion_border, none);
|
|
29
30
|
--bdc_color: var(--bds-color_bg--subtle);
|
|
30
31
|
--bdc-outline_radius: var(--bds-border_radius--s);
|
|
31
32
|
border-radius: var(--accordion_radius, var(--bdc-outline_radius));
|
|
@@ -56,7 +56,7 @@ export class BdsButton extends LitElement {
|
|
|
56
56
|
padding-inline: var(--bds-space_l);
|
|
57
57
|
display: inline-flex;
|
|
58
58
|
gap: var(--bds-space_xs);
|
|
59
|
-
border-radius: var(--
|
|
59
|
+
border-radius: var(--button_radius, var(--bds-border_radius--full));
|
|
60
60
|
align-items: center;
|
|
61
61
|
cursor: pointer;
|
|
62
62
|
justify-content: center;
|
|
@@ -102,7 +102,6 @@ export class BdsButton extends LitElement {
|
|
|
102
102
|
.button.small {
|
|
103
103
|
--button_height: 2.25em;
|
|
104
104
|
--button_font-size: var(--bds-font_size--body--s);
|
|
105
|
-
--button_border_radius--s: var(--bds-border_radius--xs);
|
|
106
105
|
padding-inline: var(--bds-space_m);
|
|
107
106
|
}
|
|
108
107
|
|
|
@@ -113,7 +112,6 @@ export class BdsButton extends LitElement {
|
|
|
113
112
|
|
|
114
113
|
.button.large {
|
|
115
114
|
--button_font-size: var(--bds-font_size--heading-3);
|
|
116
|
-
--button_border_radius--s: var(--bds-border_radius--m);
|
|
117
115
|
padding-inline: var(--bds-space_xl);
|
|
118
116
|
}
|
|
119
117
|
|
|
@@ -34,7 +34,7 @@ export class BdsDialog extends LitElement {
|
|
|
34
34
|
.dialog {
|
|
35
35
|
font-size: var(--bds-font_size--body--s);
|
|
36
36
|
border: var(--dialog_border, none);
|
|
37
|
-
--bdc_color: currentcolor;
|
|
37
|
+
--bdc_color: var(--dialog_border-color, currentcolor);
|
|
38
38
|
--bdc-outline_radius: var(--bds-border_radius--m);
|
|
39
39
|
|
|
40
40
|
border-radius: var(--dialog_radius, var(--bdc-outline_radius));
|
|
@@ -66,11 +66,11 @@ export class BdsDialog extends LitElement {
|
|
|
66
66
|
display: flex;
|
|
67
67
|
align-items: center;
|
|
68
68
|
justify-content: center;
|
|
69
|
-
border-radius:
|
|
69
|
+
border-radius: var(--dialog_close-radius, var(--bds-border_radius--circle));
|
|
70
70
|
background-color: var(--bds-color_bg);
|
|
71
71
|
color: currentcolor;
|
|
72
72
|
border: var(--dialog_close-border, none);
|
|
73
|
-
--bdc_color: currentcolor;
|
|
73
|
+
--bdc_color: var(--dialog_close-border-color, currentcolor);
|
|
74
74
|
|
|
75
75
|
box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color);
|
|
76
76
|
cursor: pointer;
|
|
@@ -119,7 +119,7 @@ export class BdsDrawer extends LitElement {
|
|
|
119
119
|
justify-content: center;
|
|
120
120
|
inline-size: 2rem;
|
|
121
121
|
block-size: 2rem;
|
|
122
|
-
border-radius:
|
|
122
|
+
border-radius: var(--drawer_close-radius, var(--bds-border_radius--circle));
|
|
123
123
|
cursor: pointer;
|
|
124
124
|
transition: var(--bds-animation_transition);
|
|
125
125
|
}
|
|
@@ -136,7 +136,7 @@ export class BdsDrawer extends LitElement {
|
|
|
136
136
|
|
|
137
137
|
@media (hover: hover) and (pointer: fine) {
|
|
138
138
|
.close-button:hover {
|
|
139
|
-
background-color: var(--bds-color_bg--subtle);
|
|
139
|
+
background-color: var(--drawer_close-bg--hover, var(--bds-color_bg--subtle));
|
|
140
140
|
}
|
|
141
141
|
}
|
|
142
142
|
|
|
@@ -50,10 +50,15 @@ export class BdsPopover extends LitElement {
|
|
|
50
50
|
overflow-y: auto;
|
|
51
51
|
z-index: var(--popover_z-index, 100);
|
|
52
52
|
min-width: 12rem;
|
|
53
|
+
max-width: var(--popover_max-width, 20rem);
|
|
54
|
+
max-height: var(--popover_max-height, 80dvh);
|
|
53
55
|
padding: var(--bds-space_m);
|
|
54
|
-
border
|
|
56
|
+
border: var(--popover_border, none);
|
|
57
|
+
--bdc_color: currentcolor;
|
|
58
|
+
--bdc-outline_radius: var(--bds-border_radius--s);
|
|
59
|
+
border-radius: var(--popover_radius, var(--bdc-outline_radius));
|
|
55
60
|
background-color: var(--popover_color, var(--bds-color_bg));
|
|
56
|
-
box-shadow: var(--popover_shadow, var(--bds-shadow_m));
|
|
61
|
+
box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color), var(--popover_shadow, var(--bds-shadow_m));
|
|
57
62
|
color: var(--popover_on-color, var(--bds-color_on-bg));
|
|
58
63
|
font-size: var(--bds-font_size--body);
|
|
59
64
|
}
|
|
@@ -37,7 +37,7 @@ export class BdsTooltip extends LitElement {
|
|
|
37
37
|
position: absolute;
|
|
38
38
|
z-index: var(--bds-z-index_popover, 200);
|
|
39
39
|
padding: var(--bds-space_xxs) var(--bds-space_xs);
|
|
40
|
-
border-radius: var(--bds-border_radius--
|
|
40
|
+
border-radius: var(--tooltip_radius, var(--bds-border_radius--full));
|
|
41
41
|
background-color: var(--tooltip_bg, var(--bds-color_on-bg));
|
|
42
42
|
color: var(--tooltip_text, var(--bds-color_bg));
|
|
43
43
|
font-size: var(--bds-font_size--body--s);
|
|
@@ -49,7 +49,7 @@ export class BdsCheckbox extends LitElement {
|
|
|
49
49
|
inline-size: var(--inputSize);
|
|
50
50
|
block-size: var(--inputSize);
|
|
51
51
|
flex-shrink: 0;
|
|
52
|
-
--bdc_color: currentcolor;
|
|
52
|
+
--bdc_color: var(--checkbox_border-color, currentcolor);
|
|
53
53
|
--bdc-outline_radius: var(--bds-border_radius--xs);
|
|
54
54
|
|
|
55
55
|
border-radius: var(--checkbox_radius, var(--bdc-outline_radius));
|
|
@@ -54,7 +54,7 @@ export class BdsCombobox extends LitElement {
|
|
|
54
54
|
padding: var(--bds-space_s);
|
|
55
55
|
padding-inline-end: var(--bds-space_xl);
|
|
56
56
|
border: none;
|
|
57
|
-
--bdc_color: currentcolor;
|
|
57
|
+
--bdc_color: var(--combobox_border-color, currentcolor);
|
|
58
58
|
--bdc-outline_radius: var(--bds-border_radius--xs);
|
|
59
59
|
|
|
60
60
|
border-radius: var(--combobox_radius, var(--bdc-outline_radius));
|
|
@@ -58,7 +58,7 @@ export class BdsFormInput extends LitElement {
|
|
|
58
58
|
position: relative;
|
|
59
59
|
display: flex;
|
|
60
60
|
align-items: center;
|
|
61
|
-
--bdc_color: currentcolor;
|
|
61
|
+
--bdc_color: var(--formInput_border-color, currentcolor);
|
|
62
62
|
--bdc-outline_radius: var(--bds-border_radius--xs);
|
|
63
63
|
|
|
64
64
|
border-radius: var(--formInput_radius, var(--bdc-outline_radius));
|
|
@@ -42,7 +42,7 @@ export class BdsNumberInput extends LitElement {
|
|
|
42
42
|
font-size: var(--bds-font_size--body);
|
|
43
43
|
padding: var(--bds-space_s);
|
|
44
44
|
border: none;
|
|
45
|
-
--bdc_color: currentcolor;
|
|
45
|
+
--bdc_color: var(--number-input_border-color, currentcolor);
|
|
46
46
|
--bdc-outline_radius: var(--bds-border_radius--xs);
|
|
47
47
|
|
|
48
48
|
border-radius: var(--number-input_radius, var(--bdc-outline_radius));
|
|
@@ -47,7 +47,7 @@ export class BdsRadio extends LitElement {
|
|
|
47
47
|
inline-size: var(--inputSize);
|
|
48
48
|
block-size: var(--inputSize);
|
|
49
49
|
flex-shrink: 0;
|
|
50
|
-
--bdc_color: currentcolor;
|
|
50
|
+
--bdc_color: var(--radio_border-color, currentcolor);
|
|
51
51
|
--bdc-outline_radius: 50%;
|
|
52
52
|
|
|
53
53
|
border-radius: 50%;
|
|
@@ -55,7 +55,7 @@ export class BdsSelect extends LitElement {
|
|
|
55
55
|
padding: var(--bds-space_s);
|
|
56
56
|
padding-inline-end: var(--bds-space_xl);
|
|
57
57
|
border: none;
|
|
58
|
-
--bdc_color: currentcolor;
|
|
58
|
+
--bdc_color: var(--select_border-color, currentcolor);
|
|
59
59
|
--bdc-outline_radius: var(--bds-border_radius--xs);
|
|
60
60
|
|
|
61
61
|
border-radius: var(--select_radius, var(--bdc-outline_radius));
|
|
@@ -46,7 +46,7 @@ export class BdsSwitch extends LitElement {
|
|
|
46
46
|
block-size: 1.5rem;
|
|
47
47
|
border-radius: 999px;
|
|
48
48
|
background-color: var(--switch_color_bg, var(--bds-color_bg--subtle));
|
|
49
|
-
--bdc_color: currentcolor;
|
|
49
|
+
--bdc_color: var(--switch_border-color, currentcolor);
|
|
50
50
|
|
|
51
51
|
box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color);
|
|
52
52
|
transition: background-color 0.2s ease;
|
|
@@ -41,7 +41,7 @@ export class BdsTextarea extends LitElement {
|
|
|
41
41
|
line-height: var(--bds-font_line-height--body);
|
|
42
42
|
padding: var(--bds-space_s);
|
|
43
43
|
border: none;
|
|
44
|
-
--bdc_color: currentcolor;
|
|
44
|
+
--bdc_color: var(--textarea_border-color, currentcolor);
|
|
45
45
|
--bdc-outline_radius: var(--bds-border_radius--xs);
|
|
46
46
|
|
|
47
47
|
border-radius: var(--textarea_radius, var(--bdc-outline_radius));
|
|
@@ -5,7 +5,7 @@ import * as Stories from './BdsCard.stories';
|
|
|
5
5
|
|
|
6
6
|
# <bds-card>
|
|
7
7
|
|
|
8
|
-
Framework-agnostic Card layout custom element. A versatile container with three visual variants,
|
|
8
|
+
Framework-agnostic Card layout custom element. A versatile container with three visual variants, text alignment, and an optional clickable mode. Padding is controlled via the `--card_padding` CSS custom property.
|
|
9
9
|
|
|
10
10
|
> **Status: experimental** — API may change before stable release.
|
|
11
11
|
|
|
@@ -46,7 +46,6 @@ import '@boostdev/design-system-components/web-components';
|
|
|
46
46
|
| Attribute | Type | Default | Description |
|
|
47
47
|
|-----------|------|---------|-------------|
|
|
48
48
|
| `variant` | `"default" \| "elevated" \| "outlined"` | `"default"` | Shadow and border style |
|
|
49
|
-
| `padding` | `"none" \| "small" \| "medium" \| "large"` | `"medium"` | Inner padding |
|
|
50
49
|
| `text-align` | `"start" \| "center" \| "end"` | `"start"` | Text alignment |
|
|
51
50
|
| `clickable` | boolean | `false` | Renders the card as a `<button>` with hover/active effects |
|
|
52
51
|
| `aria-label` | string | — | Accessible label (recommended when `clickable` is set) |
|
|
@@ -67,13 +66,15 @@ import '@boostdev/design-system-components/web-components';
|
|
|
67
66
|
|
|
68
67
|
| Property | Description |
|
|
69
68
|
|----------|-------------|
|
|
69
|
+
| `--card_padding` | Inner padding (default: `var(--bds-space_m)`) |
|
|
70
70
|
| `--card_color` | Card background colour |
|
|
71
71
|
| `--card_on-color` | Card text/foreground colour |
|
|
72
|
+
| `--card_border` | Border on outlined variant (default: `none`) |
|
|
72
73
|
|
|
73
74
|
## Usage in plain HTML
|
|
74
75
|
|
|
75
76
|
```html
|
|
76
|
-
<bds-card variant="elevated"
|
|
77
|
+
<bds-card variant="elevated" style="--card_padding: var(--bds-space_l)">
|
|
77
78
|
<p>Card content</p>
|
|
78
79
|
</bds-card>
|
|
79
80
|
|
|
@@ -1,18 +1,16 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
-
import type { CardVariant,
|
|
3
|
+
import type { CardVariant, CardTextAlign } from './bds-card';
|
|
4
4
|
import '../index'; // auto-registers all custom elements
|
|
5
5
|
|
|
6
6
|
function BdsCard({
|
|
7
7
|
variant = 'default',
|
|
8
|
-
padding = 'medium',
|
|
9
8
|
textAlign = 'start',
|
|
10
9
|
clickable,
|
|
11
10
|
ariaLabel,
|
|
12
11
|
children,
|
|
13
12
|
}: {
|
|
14
13
|
variant?: CardVariant;
|
|
15
|
-
padding?: CardPadding;
|
|
16
14
|
textAlign?: CardTextAlign;
|
|
17
15
|
clickable?: boolean;
|
|
18
16
|
ariaLabel?: string;
|
|
@@ -22,7 +20,6 @@ function BdsCard({
|
|
|
22
20
|
'bds-card',
|
|
23
21
|
{
|
|
24
22
|
variant,
|
|
25
|
-
padding,
|
|
26
23
|
'text-align': textAlign,
|
|
27
24
|
clickable: clickable || undefined,
|
|
28
25
|
'aria-label': ariaLabel,
|
|
@@ -38,7 +35,6 @@ const meta = {
|
|
|
38
35
|
parameters: { layout: 'centered' },
|
|
39
36
|
argTypes: {
|
|
40
37
|
variant: { control: 'select', options: ['default', 'elevated', 'outlined'] },
|
|
41
|
-
padding: { control: 'select', options: ['none', 'small', 'medium', 'large'] },
|
|
42
38
|
textAlign: { control: 'select', options: ['start', 'center', 'end'] },
|
|
43
39
|
clickable: { control: 'boolean' },
|
|
44
40
|
},
|
|
@@ -47,19 +43,19 @@ const meta = {
|
|
|
47
43
|
export default meta;
|
|
48
44
|
type Story = StoryObj<typeof meta>;
|
|
49
45
|
|
|
50
|
-
export const Default: Story = { args: { variant: 'default',
|
|
51
|
-
export const Elevated: Story = { args: { variant: 'elevated',
|
|
52
|
-
export const Outlined: Story = { args: { variant: 'outlined',
|
|
46
|
+
export const Default: Story = { args: { variant: 'default', children: 'Card content goes here.' } };
|
|
47
|
+
export const Elevated: Story = { args: { variant: 'elevated', children: 'Elevated card.' } };
|
|
48
|
+
export const Outlined: Story = { args: { variant: 'outlined', children: 'Outlined card.' } };
|
|
53
49
|
export const Clickable: Story = {
|
|
54
|
-
args: { variant: 'default',
|
|
50
|
+
args: { variant: 'default', clickable: true, ariaLabel: 'Open details', children: 'Clickable card — hover me.' },
|
|
55
51
|
};
|
|
56
52
|
|
|
57
53
|
export const AllVariants: Story = {
|
|
58
54
|
render: () => (
|
|
59
55
|
<div style={{ display: 'flex', gap: 16, flexWrap: 'wrap', maxWidth: 600 }}>
|
|
60
56
|
{(['default', 'elevated', 'outlined'] as const).map(v =>
|
|
61
|
-
React.createElement('bds-card', { key: v, variant: v,
|
|
62
|
-
React.createElement('p', { style:
|
|
57
|
+
React.createElement('bds-card', { key: v, variant: v, style: { width: 160 } },
|
|
58
|
+
React.createElement('p', { style: { margin: 0 } }, v),
|
|
63
59
|
),
|
|
64
60
|
)}
|
|
65
61
|
</div>
|
|
@@ -41,10 +41,10 @@ export const Avatar: Story = {
|
|
|
41
41
|
export const ContentBlock: Story = {
|
|
42
42
|
render: () => (
|
|
43
43
|
<div style={{ display: 'flex', flexDirection: 'column', gap: 8, width: 300 }}>
|
|
44
|
-
{React.createElement('bds-skeleton', { style:
|
|
45
|
-
{React.createElement('bds-skeleton', { style:
|
|
46
|
-
{React.createElement('bds-skeleton', { style:
|
|
47
|
-
{React.createElement('bds-skeleton', { style:
|
|
44
|
+
{React.createElement('bds-skeleton', { style: { width: '100%', height: '1.5rem' } })}
|
|
45
|
+
{React.createElement('bds-skeleton', { style: { width: '80%', height: '1rem' } })}
|
|
46
|
+
{React.createElement('bds-skeleton', { style: { width: '90%', height: '1rem' } })}
|
|
47
|
+
{React.createElement('bds-skeleton', { style: { width: '60%', height: '1rem' } })}
|
|
48
48
|
</div>
|
|
49
49
|
),
|
|
50
50
|
};
|
|
@@ -112,7 +112,8 @@ export class BdsAlert extends LitElement {
|
|
|
112
112
|
cursor: pointer;
|
|
113
113
|
color: currentcolor;
|
|
114
114
|
transition: var(--bds-animation_transition);
|
|
115
|
-
border
|
|
115
|
+
border: var(--alert_dismiss-border, none);
|
|
116
|
+
border-radius: var(--alert_dismiss-radius, var(--bds-border_radius--circle));
|
|
116
117
|
--bdc_color: currentcolor;
|
|
117
118
|
box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color);
|
|
118
119
|
}
|
|
@@ -129,7 +130,7 @@ export class BdsAlert extends LitElement {
|
|
|
129
130
|
|
|
130
131
|
@media (hover: hover) and (pointer: fine) {
|
|
131
132
|
.dismiss:hover {
|
|
132
|
-
opacity: 0.7;
|
|
133
|
+
opacity: var(--alert_dismiss-opacity--hover, 0.7);
|
|
133
134
|
}
|
|
134
135
|
}
|
|
135
136
|
`;
|
|
@@ -6,10 +6,9 @@ describe('bds-card', () => {
|
|
|
6
6
|
expect(customElements.get('bds-card')).toBe(BdsCard);
|
|
7
7
|
});
|
|
8
8
|
|
|
9
|
-
it('defaults to variant="default",
|
|
9
|
+
it('defaults to variant="default", text-align="start"', async () => {
|
|
10
10
|
const el = await fixture('<bds-card>Content</bds-card>') as BdsCard;
|
|
11
11
|
expect(el.getAttribute('variant')).toBe('default');
|
|
12
|
-
expect(el.getAttribute('padding')).toBe('medium');
|
|
13
12
|
expect(el.getAttribute('text-align')).toBe('start');
|
|
14
13
|
cleanup(el);
|
|
15
14
|
});
|
|
@@ -45,11 +44,10 @@ describe('bds-card', () => {
|
|
|
45
44
|
cleanup(el);
|
|
46
45
|
});
|
|
47
46
|
|
|
48
|
-
it('applies variant
|
|
49
|
-
const el = await fixture('<bds-card variant="elevated"
|
|
47
|
+
it('applies variant and text-align classes to the card element', async () => {
|
|
48
|
+
const el = await fixture('<bds-card variant="elevated" text-align="center">Content</bds-card>');
|
|
50
49
|
const card = el.shadowRoot!.querySelector('.card')!;
|
|
51
50
|
expect(card.classList.contains('--elevated')).toBe(true);
|
|
52
|
-
expect(card.classList.contains('--padding-large')).toBe(true);
|
|
53
51
|
expect(card.classList.contains('--text-center')).toBe(true);
|
|
54
52
|
cleanup(el);
|
|
55
53
|
});
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { LitElement, css, html, nothing } from 'lit';
|
|
2
2
|
|
|
3
3
|
export type CardVariant = 'default' | 'elevated' | 'outlined';
|
|
4
|
-
export type CardPadding = 'none' | 'small' | 'medium' | 'large';
|
|
5
4
|
export type CardTextAlign = 'start' | 'center' | 'end';
|
|
6
5
|
|
|
7
6
|
/**
|
|
@@ -9,7 +8,7 @@ export type CardTextAlign = 'start' | 'center' | 'end';
|
|
|
9
8
|
*
|
|
10
9
|
* Attributes:
|
|
11
10
|
* variant — "default" (default) | "elevated" | "outlined"
|
|
12
|
-
*
|
|
11
|
+
* --card_padding — CSS custom property to override padding (default: var(--bds-space_m))
|
|
13
12
|
* text-align — "start" (default) | "center" | "end"
|
|
14
13
|
* clickable — boolean; renders as a <button> with hover/active effects
|
|
15
14
|
* aria-label — accessible label (useful when clickable)
|
|
@@ -21,7 +20,7 @@ export type CardTextAlign = 'start' | 'center' | 'end';
|
|
|
21
20
|
* bds-click — fired (bubbles, composed) when the card button is clicked
|
|
22
21
|
*
|
|
23
22
|
* @example
|
|
24
|
-
* <bds-card variant="elevated"
|
|
23
|
+
* <bds-card variant="elevated" style="--card_padding: var(--bds-space_l)">
|
|
25
24
|
* <p>Card content</p>
|
|
26
25
|
* </bds-card>
|
|
27
26
|
*
|
|
@@ -43,9 +42,11 @@ export class BdsCard extends LitElement {
|
|
|
43
42
|
position: relative;
|
|
44
43
|
box-sizing: border-box;
|
|
45
44
|
inline-size: 100%;
|
|
45
|
+
block-size: 100%;
|
|
46
46
|
text-align: inherit;
|
|
47
47
|
font: inherit;
|
|
48
48
|
border: none;
|
|
49
|
+
padding: var(--card_padding, var(--bds-space_m));
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
/* Resting shadows — consumers can override per-variant via
|
|
@@ -54,15 +55,11 @@ export class BdsCard extends LitElement {
|
|
|
54
55
|
.card.--elevated { box-shadow: var(--card_shadow--elevated, var(--bds-shadow_m)); }
|
|
55
56
|
|
|
56
57
|
.card.--outlined {
|
|
58
|
+
border: var(--card_border, none);
|
|
57
59
|
--bdc_color: currentcolor;
|
|
58
60
|
box-shadow: var(--card_shadow--outlined, inset 0 0 0 var(--bdc-outline_width) var(--bdc_color), var(--bds-shadow_s));
|
|
59
61
|
}
|
|
60
62
|
|
|
61
|
-
.card.--padding-none { padding: 0; }
|
|
62
|
-
.card.--padding-small { padding: var(--bds-space_s); }
|
|
63
|
-
.card.--padding-medium { padding: var(--bds-space_m); }
|
|
64
|
-
.card.--padding-large { padding: var(--bds-space_l); }
|
|
65
|
-
|
|
66
63
|
.card.--text-start { text-align: start; }
|
|
67
64
|
.card.--text-center { text-align: center; }
|
|
68
65
|
.card.--text-end { text-align: end; }
|
|
@@ -96,14 +93,12 @@ export class BdsCard extends LitElement {
|
|
|
96
93
|
|
|
97
94
|
static properties = {
|
|
98
95
|
variant: { type: String, reflect: true },
|
|
99
|
-
padding: { type: String, reflect: true },
|
|
100
96
|
textAlign: { type: String, attribute: 'text-align', reflect: true },
|
|
101
97
|
clickable: { type: Boolean, reflect: true },
|
|
102
98
|
ariaLabel: { type: String, attribute: 'aria-label' },
|
|
103
99
|
};
|
|
104
100
|
|
|
105
101
|
declare variant: CardVariant;
|
|
106
|
-
declare padding: CardPadding;
|
|
107
102
|
declare textAlign: CardTextAlign;
|
|
108
103
|
declare clickable: boolean;
|
|
109
104
|
declare ariaLabel: string;
|
|
@@ -111,7 +106,6 @@ export class BdsCard extends LitElement {
|
|
|
111
106
|
constructor() {
|
|
112
107
|
super();
|
|
113
108
|
this.variant = 'default';
|
|
114
|
-
this.padding = 'medium';
|
|
115
109
|
this.textAlign = 'start';
|
|
116
110
|
this.clickable = false;
|
|
117
111
|
this.ariaLabel = '';
|
|
@@ -125,7 +119,6 @@ export class BdsCard extends LitElement {
|
|
|
125
119
|
const classes = [
|
|
126
120
|
'card',
|
|
127
121
|
`--${this.variant}`,
|
|
128
|
-
`--padding-${this.padding}`,
|
|
129
122
|
`--text-${this.textAlign}`,
|
|
130
123
|
this.clickable ? '--clickable' : '',
|
|
131
124
|
].filter(Boolean).join(' ');
|
|
@@ -34,9 +34,9 @@ export class BdsNotificationBanner extends LitElement {
|
|
|
34
34
|
align-items: center;
|
|
35
35
|
gap: var(--bds-space_m);
|
|
36
36
|
padding: var(--bds-space_s) var(--bds-space_m);
|
|
37
|
-
background-color: var(--banner_bg, var(--bds-color_blue--subtle));
|
|
38
|
-
color: var(--banner_text, var(--bds-color_on-blue--subtle));
|
|
39
|
-
border-block-end: 3px solid var(--banner_border, var(--bds-color_blue));
|
|
37
|
+
background-color: var(--banner_bg, var(--banner_bg--variant, var(--bds-color_blue--subtle)));
|
|
38
|
+
color: var(--banner_text, var(--banner_text--variant, var(--bds-color_on-blue--subtle)));
|
|
39
|
+
border-block-end: 3px solid var(--banner_border, var(--banner_border--variant, var(--bds-color_blue)));
|
|
40
40
|
font-size: var(--bds-font_size--body);
|
|
41
41
|
line-height: var(--bds-font_line-height--body);
|
|
42
42
|
inline-size: 100%;
|
|
@@ -44,27 +44,27 @@ export class BdsNotificationBanner extends LitElement {
|
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
:host([variant='info']) .banner {
|
|
47
|
-
--banner_bg: var(--bds-color_blue--subtle);
|
|
48
|
-
--banner_text: var(--bds-color_on-blue--subtle);
|
|
49
|
-
--banner_border: var(--bds-color_blue);
|
|
47
|
+
--banner_bg--variant: var(--banner_bg--info, var(--bds-color_blue--subtle));
|
|
48
|
+
--banner_text--variant: var(--banner_text--info, var(--bds-color_on-blue--subtle));
|
|
49
|
+
--banner_border--variant: var(--banner_border--info, var(--bds-color_blue));
|
|
50
50
|
}
|
|
51
51
|
|
|
52
52
|
:host([variant='success']) .banner {
|
|
53
|
-
--banner_bg: var(--bds-color_success--subtle);
|
|
54
|
-
--banner_text: var(--bds-color_on-success--subtle);
|
|
55
|
-
--banner_border: var(--bds-color_success);
|
|
53
|
+
--banner_bg--variant: var(--banner_bg--success, var(--bds-color_success--subtle));
|
|
54
|
+
--banner_text--variant: var(--banner_text--success, var(--bds-color_on-success--subtle));
|
|
55
|
+
--banner_border--variant: var(--banner_border--success, var(--bds-color_success));
|
|
56
56
|
}
|
|
57
57
|
|
|
58
58
|
:host([variant='warning']) .banner {
|
|
59
|
-
--banner_bg: var(--bds-color_orange--subtle);
|
|
60
|
-
--banner_text: var(--bds-color_on-orange--subtle);
|
|
61
|
-
--banner_border: var(--bds-color_warning);
|
|
59
|
+
--banner_bg--variant: var(--banner_bg--warning, var(--bds-color_orange--subtle));
|
|
60
|
+
--banner_text--variant: var(--banner_text--warning, var(--bds-color_on-orange--subtle));
|
|
61
|
+
--banner_border--variant: var(--banner_border--warning, var(--bds-color_warning));
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
:host([variant='error']) .banner {
|
|
65
|
-
--banner_bg: rgb(from var(--bds-color_error) r g b / 12%);
|
|
66
|
-
--banner_text: var(--bds-color_on-bg);
|
|
67
|
-
--banner_border: var(--bds-color_error);
|
|
65
|
+
--banner_bg--variant: var(--banner_bg--error, rgb(from var(--bds-color_error) r g b / 12%));
|
|
66
|
+
--banner_text--variant: var(--banner_text--error, var(--bds-color_on-bg));
|
|
67
|
+
--banner_border--variant: var(--banner_border--error, var(--bds-color_error));
|
|
68
68
|
}
|
|
69
69
|
|
|
70
70
|
.content {
|
|
@@ -88,9 +88,10 @@ export class BdsNotificationBanner extends LitElement {
|
|
|
88
88
|
flex-shrink: 0;
|
|
89
89
|
cursor: pointer;
|
|
90
90
|
color: currentcolor;
|
|
91
|
-
border-radius:
|
|
91
|
+
border-radius: var(--banner_dismiss-radius, var(--bds-border_radius--circle));
|
|
92
|
+
border: var(--banner_dismiss-border, none);
|
|
92
93
|
transition: var(--bds-animation_transition);
|
|
93
|
-
--bdc_color: currentcolor;
|
|
94
|
+
--bdc_color: var(--notification-banner_dismiss-border-color, currentcolor);
|
|
94
95
|
box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color);
|
|
95
96
|
}
|
|
96
97
|
|
|
@@ -106,7 +107,7 @@ export class BdsNotificationBanner extends LitElement {
|
|
|
106
107
|
|
|
107
108
|
@media (hover: hover) and (pointer: fine) {
|
|
108
109
|
.dismiss:hover {
|
|
109
|
-
opacity: 0.7;
|
|
110
|
+
opacity: var(--banner_dismiss-opacity--hover, 0.7);
|
|
110
111
|
}
|
|
111
112
|
}
|
|
112
113
|
`;
|
|
@@ -65,7 +65,7 @@ export class BdsPagination extends LitElement {
|
|
|
65
65
|
cursor: pointer;
|
|
66
66
|
color: var(--bds-color_on-bg);
|
|
67
67
|
transition: var(--bds-animation_transition);
|
|
68
|
-
--bdc_color: transparent;
|
|
68
|
+
--bdc_color: var(--pagination_border-color, transparent);
|
|
69
69
|
--bdc-outline_radius: var(--bds-border_radius--xs);
|
|
70
70
|
box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color), var(--bdc-outline_shadow);
|
|
71
71
|
}
|
|
@@ -29,6 +29,10 @@ export class BdsTable extends LitElement {
|
|
|
29
29
|
.wrapper {
|
|
30
30
|
overflow-inline: auto;
|
|
31
31
|
-webkit-overflow-scrolling: touch;
|
|
32
|
+
border: var(--table_border, none);
|
|
33
|
+
border-radius: var(--table_radius, var(--bds-border_radius--s));
|
|
34
|
+
--bdc_color: var(--bds-color_bg--subtle);
|
|
35
|
+
box-shadow: inset 0 0 0 var(--bdc-outline_width) var(--bdc_color);
|
|
32
36
|
}
|
|
33
37
|
|
|
34
38
|
::slotted(table) {
|