@repobit/dex-system-design 0.5.0 → 0.7.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.
Files changed (58) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/package.json +4 -3
  3. package/src/assets/images/bd-header-img.jpg +0 -0
  4. package/src/assets/images/bd-header-us.jpg +0 -0
  5. package/src/components/Button/Button.js +115 -3
  6. package/src/components/Button/button.css.js +80 -43
  7. package/src/components/Button/button.stories.js +83 -7
  8. package/src/components/FAQ/faq.css.js +26 -15
  9. package/src/components/FAQ/faq.js +23 -114
  10. package/src/components/FAQ/faq.stories.js +41 -20
  11. package/src/components/Input/Input.js +2 -2
  12. package/src/components/anchor/anchor-nav.css.js +92 -0
  13. package/src/components/anchor/anchor-nav.js +121 -0
  14. package/src/components/anchor/anchor.stories.js +134 -0
  15. package/src/components/badge/badge.css.js +27 -0
  16. package/src/components/badge/badge.js +30 -0
  17. package/src/components/badge/badge.stories.js +36 -0
  18. package/src/components/carousel/carousel.css.js +35 -18
  19. package/src/components/carousel/carousel.js +149 -99
  20. package/src/components/carousel/carousel.stories.js +202 -46
  21. package/src/components/checkbox/checkbox.css.js +132 -0
  22. package/src/components/checkbox/checkbox.js +130 -0
  23. package/src/components/checkbox/checkbox.stories.js +63 -0
  24. package/src/components/divider/divider-horizontal.js +29 -0
  25. package/src/components/divider/divider-vertical.js +32 -0
  26. package/src/components/divider/divider.css.js +0 -0
  27. package/src/components/divider/divider.stories.js +77 -0
  28. package/src/components/header/header.css.js +248 -0
  29. package/src/components/header/header.js +87 -0
  30. package/src/components/header/header.stories.js +57 -0
  31. package/src/components/highlight/highlight-s.css.js +88 -0
  32. package/src/components/highlight/highlight-s.js +35 -0
  33. package/src/components/highlight/highlight-s.stories.js +22 -0
  34. package/src/components/highlight/highlight.css.js +119 -0
  35. package/src/components/highlight/highlight.js +60 -0
  36. package/src/components/highlight/highlight.stories.js +53 -0
  37. package/src/components/light-carousel/light-carousel.css.js +18 -10
  38. package/src/components/light-carousel/light-carousel.js +29 -16
  39. package/src/components/light-carousel/light-carousel.stories.js +9 -7
  40. package/src/components/pricing-cards/pricing-card.css.js +137 -2
  41. package/src/components/pricing-cards/pricing-card.js +63 -82
  42. package/src/components/pricing-cards/pricing-card.stories.js +1 -0
  43. package/src/components/radio/radio.css.js +168 -0
  44. package/src/components/radio/radio.js +222 -0
  45. package/src/components/radio/radio.stories.js +103 -0
  46. package/src/components/tabs/tabs.css.js +25 -7
  47. package/src/components/tabs/tabs.js +19 -12
  48. package/src/components/termsOfUse/terms.css.js +6 -0
  49. package/src/tokens/fonts.stories.js +73 -0
  50. package/src/tokens/spacing.stories.js +56 -0
  51. package/src/tokens/tokens-grid.stories.js +83 -0
  52. package/src/tokens/tokens.css +116 -1
  53. package/src/tokens/tokens.stories.js +67 -0
  54. package/src/tokens/typography.stories.js +69 -0
  55. package/src/tokens/tokens.js +0 -206
  56. /package/src/assets/{icons → images}/tabs-img1.png +0 -0
  57. /package/src/assets/{icons → images}/tabs-img2.png +0 -0
  58. /package/src/assets/{icons → images}/tabs-img3.png +0 -0
@@ -0,0 +1,36 @@
1
+ import { html } from 'lit';
2
+ import './badge.js';
3
+
4
+ export default {
5
+ title: 'Atoms/Badge',
6
+ component: 'bd-badge',
7
+ argTypes: {
8
+ text: {
9
+ control: 'text',
10
+ description: 'Textul afișat în badge',
11
+ defaultValue: 'Badge',
12
+ },
13
+ color: {
14
+ control: 'color',
15
+ description: 'Culoarea de fundal a badge-ului',
16
+ defaultValue: '#026DFF',
17
+ },
18
+ },
19
+ parameters: {
20
+ docs: {
21
+ description: {
22
+ component: 'Un badge simplu care afișează un text cu o culoare de fundal configurabilă.',
23
+ },
24
+ },
25
+ },
26
+ };
27
+
28
+ const Template = ({ text, color }) => html`
29
+ <bd-badge text="${text}" color="${color}"></bd-badge>
30
+ `;
31
+
32
+ export const Default = Template.bind({});
33
+ Default.args = {
34
+ text: 'Badge',
35
+ color: '#026DFF',
36
+ };
@@ -6,6 +6,7 @@ export default css`
6
6
  --background-card-grey: var(--color-neutral-25);
7
7
  --border-card-grey: var(--color-neutral-50);
8
8
  --bd-blue-color: var(--color-blue-500);
9
+ --bd-accesibility-focus: var(--color-blue-800);
9
10
  }
10
11
 
11
12
  .bd-carousel {
@@ -16,7 +17,11 @@ export default css`
16
17
  max-width: 100%;
17
18
  flex-direction: column;
18
19
  }
19
-
20
+ .bd-carousel-track.dragging {
21
+ cursor: grabbing;
22
+ user-select: none;
23
+ }
24
+
20
25
  .bd-section-title {
21
26
  font-family: var(--font-family-sans);
22
27
  font-weight: var(--font-weight-sans-semibold);
@@ -24,7 +29,17 @@ export default css`
24
29
  }
25
30
  div.bd-arrow {
26
31
  padding: var(--size-2);
32
+ visibility: visible;
33
+ }
34
+
35
+ .bd-box:focus-visible,
36
+ .bd-arrow:focus-visible,
37
+ .bd-plus-button:focus-visible,
38
+ .bd-modal-content button:focus-visible {
39
+ outline: var(--size-2) solid var(--bd-accesibility-focus);
40
+ outline-offset: var(--size-2);
27
41
  }
42
+
28
43
  .bd-header-carousel {
29
44
  display: block;
30
45
  align-items: center;
@@ -57,42 +72,42 @@ export default css`
57
72
  }
58
73
 
59
74
  .bd-left-arrow {
60
- content: url("src/assets/icons/left_normal.png");
75
+ content: url("icons/left_normal.png");
61
76
  }
62
77
 
63
78
  .bd-left-arrow:hover {
64
- content: url("src/assets/icons/left_hover.png");
79
+ content: url("icons/left_hover.png");
65
80
  }
66
81
 
67
82
  .bd-left-arrow:active {
68
- content: url("src/assets/icons/left_clicked.png");
83
+ content: url("icons/left_clicked.png");
69
84
  }
70
85
 
71
86
  .bd-left-arrow:disabled {
72
- content: url("src/assets/icons/left_disabled.png");
87
+ content: url("icons/left_disabled.png");
73
88
  }
74
89
 
75
90
  .bd-right-arrow {
76
- content: url("src/assets/icons/right_normal.png");
91
+ content: url("icons/right_normal.png");
77
92
  }
78
93
 
79
94
  .bd-right-arrow:hover {
80
- content: url("src/assets/icons/right_hover.png");
95
+ content: url("icons/right_hover.png");
81
96
  }
82
97
 
83
98
  .bd-right-arrow:active {
84
- content: url("src/assets/icons/right_clicked.png");
99
+ content: url("icons/right_clicked.png");
85
100
  }
86
101
 
87
102
  .bd-right-arrow:disabled {
88
- content: url("src/assets/icons/right_disabled.png");
103
+ content: url("icons/right_disabled.png");
89
104
  }
90
105
  .bd-right-arrow.bd-disabled {
91
- content: url("src/assets/icons/right_disabled.png");
106
+ content: url("icons/right_disabled.png");
92
107
  cursor: not-allowed;
93
108
  }
94
109
  .bd-left-arrow.bd-disabled {
95
- content: url("src/assets/icons/left_disabled.png");
110
+ content: url("icons/left_disabled.png");
96
111
  cursor: not-allowed;
97
112
  }
98
113
  .bd-disabled {
@@ -112,14 +127,12 @@ export default css`
112
127
  .bd-carousel-track {
113
128
  display: flex;
114
129
  gap: 2em;
115
- scroll-behavior: smooth;
116
130
  flex: 1;
117
131
  padding: var(--size-0) var(--size-20);
118
132
  position: relative;
119
133
  overflow-x: hidden;
120
134
  overflow-y: hidden;
121
135
  z-index: 1;
122
- scroll-behavior: smooth;
123
136
  scroll-snap-type: x mandatory;
124
137
  -webkit-overflow-scrolling: touch;
125
138
  transition: scroll-snap-align 0.6s cubic-bezier(0.23, 1, 0.32, 1);
@@ -127,7 +140,6 @@ export default css`
127
140
 
128
141
  .bd-carousel-icon {
129
142
  position: relative;
130
- bottom: 30px;
131
143
  max-width: 100%;
132
144
  height: var(--size-40);
133
145
  width: var(--size-40);
@@ -155,7 +167,7 @@ export default css`
155
167
  text-align: start;
156
168
  cursor: pointer;
157
169
  transition: transform 0.2s ease-in-out;
158
-
170
+ font-family: var(--font-family-sans);
159
171
  position: relative;
160
172
  z-index: 2;
161
173
  }
@@ -222,7 +234,7 @@ export default css`
222
234
  }
223
235
 
224
236
  .bd-plus-button {
225
- content: url("src/assets/icons/more_normal.png");
237
+ content: url("icons/more_normal.png");
226
238
  position: absolute;
227
239
  bottom: var(--size-10);
228
240
  right: var(--size-10);
@@ -238,10 +250,15 @@ export default css`
238
250
  cursor: pointer;
239
251
  }
240
252
  .bd-plus-button:hover {
241
- content: url("src/assets/icons/more_hover.png");
253
+ content: url("icons/more_hover.png");
242
254
  }
255
+
256
+ bd-carousel-item::part(content) {
257
+ font-family: var(--font-family-sans);
258
+ }
259
+
243
260
  .bd-plus-button:active {
244
- content: url("src/assets/icons/more_pressed.png");
261
+ content: url("icons/more_pressed.png");
245
262
  }
246
263
 
247
264
  .bd-left-arrow {
@@ -1,20 +1,31 @@
1
1
  import { LitElement, html } from "lit";
2
2
  import carouselCSS from "../carousel/carousel.css.js";
3
3
 
4
- class CarouselItem extends LitElement {
4
+ export class CarouselItem extends LitElement {
5
5
  static properties = {
6
+ icon: { type: String },
6
7
  title: { type: String },
7
- subTitle: { type: String },
8
8
  modalText: { type: String },
9
- icon: { type: String },
10
9
  };
11
10
 
12
- constructor() {
13
- super();
14
- this.title = "";
15
- this.subTitle = "";
16
- this.modalText = "";
17
- this.icon = "";
11
+ _onKeydown(event) {
12
+ if (event.key === "Enter" || event.key === " ") {
13
+ this._openModal();
14
+ }
15
+ }
16
+
17
+ _openModal() {
18
+ this.dispatchEvent(
19
+ new CustomEvent("open-modal", {
20
+ detail: {
21
+ title: this.title,
22
+ modalText: this.modalText,
23
+ icon: this.icon,
24
+ },
25
+ bubbles: true,
26
+ composed: true,
27
+ })
28
+ );
18
29
  }
19
30
 
20
31
  render() {
@@ -23,53 +34,52 @@ class CarouselItem extends LitElement {
23
34
  ${this.icon
24
35
  ? html`<img src="${this.icon}" alt="icon" class="bd-carousel-icon" />`
25
36
  : ""}
26
- ${this.title ? html`<h3>${this.title}</h3>` : ""}
27
- ${this.subTitle ? html`<p>${this.subTitle}</p>` : ""}
37
+ <div class="bd-content">
38
+ <slot></slot>
39
+ </div>
28
40
  <div
29
41
  class="bd-plus-button"
30
- @click="${() =>
31
- this.dispatchEvent(
32
- new CustomEvent("open-modal", {
33
- detail: {
34
- title: this.title,
35
- modalText: this.modalText,
36
- icon: this.icon,
37
- },
38
- bubbles: true,
39
- composed: true,
40
- })
41
- )}"
42
- ></div>
42
+ role="button"
43
+ aria-label="Open modal for ${this.title}"
44
+ @click="${this._openModal}"
45
+ @keydown="${this._onKeydown}"
46
+ tabindex="0"
47
+ >
48
+ +
49
+ </div>
43
50
  </div>
44
51
  `;
45
52
  }
53
+
54
+ static styles = [carouselCSS];
46
55
  }
47
56
 
48
57
  class CustomCarousel extends LitElement {
49
58
  static properties = {
59
+ title: { type: String },
50
60
  selectedItem: { type: Object },
51
61
  };
52
62
 
53
63
  constructor() {
54
64
  super();
55
65
  this.selectedItem = null;
66
+ this.title = "";
56
67
  }
57
68
 
58
69
  firstUpdated() {
59
- const track = this.shadowRoot.querySelector(".bd-carousel-track");
60
- const slot = this.shadowRoot.querySelector("slot");
70
+ this.track = this.shadowRoot.querySelector(".bd-carousel-track");
71
+ this.slotElement = this.shadowRoot.querySelector("slot");
72
+ this.leftArrow = this.shadowRoot.querySelector(".bd-left-arrow");
73
+ this.rightArrow = this.shadowRoot.querySelector(".bd-right-arrow");
61
74
 
62
- // Ascultă scroll ca actualizezi săgețile
63
- track.addEventListener("scroll", () => this.updateArrowStates());
75
+ this.track.addEventListener("scroll", () => this.updateArrowStates());
64
76
 
65
- // Ascultă schimbările din slot
66
- slot.addEventListener("slotchange", () => {
77
+ this.slotElement.addEventListener("slotchange", () => {
67
78
  this.waitForImagesToLoad().then(() => {
68
79
  this.updateArrowStates();
69
80
  });
70
81
  });
71
82
 
72
- // Așteaptă un layout complet înainte de prima verificare
73
83
  setTimeout(() => {
74
84
  this.waitForImagesToLoad().then(() => {
75
85
  this.updateArrowStates();
@@ -78,92 +88,65 @@ class CustomCarousel extends LitElement {
78
88
 
79
89
  const arrows = this.shadowRoot.querySelectorAll(".bd-arrow");
80
90
  arrows.forEach((arrow) => {
81
- arrow.addEventListener("mousedown", () =>
82
- arrow.classList.add("bd-active")
83
- );
84
- arrow.addEventListener("mouseup", () =>
85
- arrow.classList.remove("bd-active")
86
- );
87
- arrow.addEventListener("mouseleave", () =>
88
- arrow.classList.remove("bd-active")
89
- );
91
+ arrow.addEventListener("mousedown", () => arrow.classList.add("bd-active"));
92
+ arrow.addEventListener("mouseup", () => arrow.classList.remove("bd-active"));
93
+ arrow.addEventListener("mouseleave", () => arrow.classList.remove("bd-active"));
94
+ arrow.addEventListener("keydown", (e) => this._onArrowKeydown(e, arrow));
90
95
  });
91
96
 
92
97
  this.addEventListener("open-modal", (e) => this.openModal(e.detail));
98
+ this.enableDragAndTouchScroll(this.track);
93
99
  }
94
100
 
95
101
  waitForImagesToLoad() {
96
- const assignedElements = this.shadowRoot
97
- .querySelector("slot")
98
- .assignedElements({ flatten: true });
99
-
102
+ const assignedElements = this.slotElement.assignedElements({ flatten: true });
100
103
  const images = assignedElements
101
104
  .map((el) => el.shadowRoot?.querySelector("img"))
102
105
  .filter((img) => img);
103
-
104
106
  const promises = images.map(
105
107
  (img) =>
106
108
  new Promise((resolve) => {
107
- if (img.complete) {
108
- resolve();
109
- } else {
109
+ if (img.complete) resolve();
110
+ else {
110
111
  img.addEventListener("load", resolve, { once: true });
111
- img.addEventListener("error", resolve, { once: true }); // în caz de eroare de încărcare
112
+ img.addEventListener("error", resolve, { once: true });
112
113
  }
113
114
  })
114
115
  );
115
-
116
116
  return Promise.all(promises);
117
117
  }
118
118
 
119
119
  scrollCarousel(direction) {
120
- const slot = this.shadowRoot.querySelector("slot");
121
- const assignedElements = slot.assignedElements({ flatten: true });
122
-
123
- if (!assignedElements.length) {
124
- console.warn("No items found in slot!");
125
- return;
126
- }
127
-
120
+ const assignedElements = this.slotElement.assignedElements({ flatten: true });
121
+ if (!assignedElements.length) return;
128
122
  const itemWidth = assignedElements[0].offsetWidth || 300;
129
- const track = this.shadowRoot.querySelector(".bd-carousel-track");
130
-
131
- if (!track) {
132
- console.warn("No track found!");
133
- return;
134
- }
123
+ if (!this.track) return;
135
124
 
136
- if (direction === "left") {
137
- track.scrollBy({ left: -itemWidth, behavior: "smooth" });
138
- } else if (direction === "right") {
139
- track.scrollBy({ left: itemWidth, behavior: "smooth" });
140
- }
125
+ this.track.scrollBy({
126
+ left: direction === "left" ? -itemWidth : itemWidth,
127
+ behavior: "smooth",
128
+ });
141
129
 
142
- // Așteaptă animația scroll-ului și actualizează săgețile
143
130
  setTimeout(() => this.updateArrowStates(), 300);
144
131
  }
145
132
 
146
133
  updateArrowStates() {
147
- const track = this.shadowRoot.querySelector(".bd-carousel-track");
148
- const trackWidth = track.offsetWidth;
149
- const totalWidth = track.scrollWidth;
150
- const scrollPosition = track.scrollLeft;
151
-
152
- const leftArrow = this.shadowRoot.querySelector(".bd-left-arrow");
153
- const rightArrow = this.shadowRoot.querySelector(".bd-right-arrow");
154
-
155
- if (!leftArrow || !rightArrow) return;
156
-
157
- if (scrollPosition <= 0) {
158
- leftArrow.classList.add("bd-disabled");
159
- } else {
160
- leftArrow.classList.remove("bd-disabled");
161
- }
134
+ const trackWidth = this.track.offsetWidth;
135
+ const totalWidth = this.track.scrollWidth;
136
+ const scrollPosition = this.track.scrollLeft;
137
+ if (!this.leftArrow || !this.rightArrow) return;
138
+
139
+ this.leftArrow.classList.toggle("bd-disabled", scrollPosition <= 0);
140
+ this.rightArrow.classList.toggle(
141
+ "bd-disabled",
142
+ scrollPosition + trackWidth >= totalWidth - 1
143
+ );
144
+ }
162
145
 
163
- if (scrollPosition + trackWidth >= totalWidth - 1) {
164
- rightArrow.classList.add("bd-disabled");
165
- } else {
166
- rightArrow.classList.remove("bd-disabled");
146
+ _onArrowKeydown(e, arrow) {
147
+ if (e.key === "Enter" || e.key === " ") {
148
+ e.preventDefault();
149
+ arrow.click();
167
150
  }
168
151
  }
169
152
 
@@ -175,52 +158,119 @@ class CustomCarousel extends LitElement {
175
158
  this.selectedItem = null;
176
159
  }
177
160
 
161
+ enableDragAndTouchScroll(element) {
162
+ let isDown = false;
163
+ let startX;
164
+ let scrollLeft;
165
+
166
+ element.addEventListener("mousedown", (e) => {
167
+ isDown = true;
168
+ element.classList.add("dragging");
169
+ startX = e.pageX - element.offsetLeft;
170
+ scrollLeft = element.scrollLeft;
171
+ });
172
+
173
+ element.addEventListener("mouseleave", () => {
174
+ isDown = false;
175
+ element.classList.remove("dragging");
176
+ });
177
+
178
+ element.addEventListener("mouseup", () => {
179
+ isDown = false;
180
+ element.classList.remove("dragging");
181
+ });
182
+
183
+ element.addEventListener("mousemove", (e) => {
184
+ if (!isDown) return;
185
+ e.preventDefault();
186
+ const x = e.pageX - element.offsetLeft;
187
+ const walk = (x - startX) * 1.5;
188
+ element.scrollLeft = scrollLeft - walk;
189
+ });
190
+
191
+ element.addEventListener("touchstart", (e) => {
192
+ isDown = true;
193
+ startX = e.touches[0].pageX - element.offsetLeft;
194
+ scrollLeft = element.scrollLeft;
195
+ });
196
+
197
+ element.addEventListener("touchend", () => {
198
+ isDown = false;
199
+ });
200
+
201
+ element.addEventListener("touchmove", (e) => {
202
+ if (!isDown) return;
203
+ const x = e.touches[0].pageX - element.offsetLeft;
204
+ const walk = (x - startX) * 1.5;
205
+ element.scrollLeft = scrollLeft - walk;
206
+ });
207
+ }
208
+
178
209
  render() {
179
210
  return html`
180
211
  <div class="bd-carousel">
181
- <div class="bd-header-carousel">
182
- <h1 class="bd-section-title">${this.title}</h1>
183
- </div>
212
+ ${this.title
213
+ ? html`<div class="bd-header-carousel">
214
+ <h1 class="bd-section-title">${this.title}</h1>
215
+ </div>`
216
+ : ""}
217
+
184
218
  <img
219
+ src="left-arrow.svg"
185
220
  alt="Left Arrow"
186
221
  class="bd-arrow bd-left-arrow"
222
+ role="button"
223
+ aria-label="Scroll left"
187
224
  @click="${() => this.scrollCarousel("left")}"
225
+ tabindex="0"
188
226
  />
189
227
  <div class="bd-carousel-track">
190
228
  <slot></slot>
191
229
  </div>
192
230
  <img
231
+ src="right-arrow.svg"
193
232
  alt="Right Arrow"
194
233
  class="bd-arrow bd-right-arrow"
234
+ role="button"
235
+ aria-label="Scroll right"
195
236
  @click="${() => this.scrollCarousel("right")}"
237
+ tabindex="0"
196
238
  />
197
239
  </div>
198
240
 
199
241
  ${this.selectedItem
200
242
  ? html`
201
- <div class="bd-modal" @click="${this.closeModal}" ?open="${true}">
243
+ <div
244
+ class="bd-modal"
245
+ @click="${this.closeModal}"
246
+ aria-hidden="${!this.selectedItem}"
247
+ ?open="${true}"
248
+ >
202
249
  <div
203
250
  class="bd-modal-content"
204
251
  @click="${(e) => e.stopPropagation()}"
252
+ aria-labelledby="modal-title"
253
+ aria-describedby="modal-description"
205
254
  >
206
255
  <img
207
256
  src="${this.selectedItem.icon}"
208
257
  alt="icon"
209
258
  class="bd-carousel-modal-icon"
210
259
  />
211
- <h2>${this.selectedItem.title}</h2>
212
- <p>${this.selectedItem.modalText}</p>
213
- <button @click="${this.closeModal}">Close</button>
260
+ <h2 id="modal-title">${this.selectedItem.title}</h2>
261
+ <p id="modal-description">${this.selectedItem.modalText}</p>
262
+ <button @click="${this.closeModal}" aria-label="Close modal">
263
+ Close
264
+ </button>
214
265
  </div>
215
266
  </div>
216
267
  `
217
268
  : ""}
218
269
  `;
219
270
  }
220
- }
221
271
 
222
- CarouselItem.styles = [carouselCSS];
223
- CustomCarousel.styles = [carouselCSS];
272
+ static styles = [carouselCSS];
273
+ }
224
274
 
225
275
  customElements.define("bd-carousel-item", CarouselItem);
226
276
  customElements.define("bd-carousel-section", CustomCarousel);