@grantcodes/ui 2.0.0-beta4 → 2.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.
Files changed (310) hide show
  1. package/CHANGELOG.md +111 -0
  2. package/README.md +6 -8
  3. package/custom-elements.json +4273 -0
  4. package/package.json +80 -89
  5. package/src/components/app-bar/app-bar.component.js +90 -0
  6. package/src/components/app-bar/app-bar.js +8 -0
  7. package/src/components/app-bar/app-bar.stories.js +84 -0
  8. package/src/components/app-bar/app-bar.styles.js +227 -0
  9. package/src/components/app-bar/app-bar.test.js +174 -0
  10. package/src/components/app-bar/index.js +3 -0
  11. package/src/components/avatar/avatar.component.js +78 -0
  12. package/src/components/avatar/avatar.js +18 -0
  13. package/src/components/avatar/avatar.stories.js +45 -0
  14. package/src/components/avatar/avatar.styles.js +42 -0
  15. package/src/components/avatar/avatar.test.js +85 -0
  16. package/src/components/avatar/index.js +13 -0
  17. package/src/components/badge/badge.component.js +36 -0
  18. package/src/components/badge/badge.js +8 -0
  19. package/src/components/badge/badge.stories.js +46 -0
  20. package/src/components/badge/badge.styles.js +94 -0
  21. package/src/components/badge/badge.test.js +70 -0
  22. package/src/components/badge/index.js +3 -0
  23. package/src/components/breadcrumb/breadcrumb.component.js +110 -0
  24. package/src/components/breadcrumb/breadcrumb.js +12 -0
  25. package/src/components/breadcrumb/breadcrumb.stories.js +25 -0
  26. package/src/components/breadcrumb/breadcrumb.styles.js +96 -0
  27. package/src/components/breadcrumb/breadcrumb.test.js +144 -0
  28. package/src/components/breadcrumb/index.js +3 -0
  29. package/src/components/button/button.component.js +64 -0
  30. package/src/components/button/button.js +6 -0
  31. package/src/components/button/button.stories.js +78 -0
  32. package/src/components/button/button.styles.js +97 -0
  33. package/src/components/button/button.test.js +98 -0
  34. package/src/components/button/index.js +1 -0
  35. package/src/components/button-group/button-group.component.js +27 -0
  36. package/src/components/button-group/button-group.js +6 -0
  37. package/src/components/button-group/button-group.stories.js +33 -0
  38. package/src/components/button-group/button-group.styles.js +43 -0
  39. package/src/components/button-group/button-group.test.js +57 -0
  40. package/src/components/button-group/index.js +1 -0
  41. package/src/components/card/card.component.js +17 -0
  42. package/src/components/card/card.js +6 -0
  43. package/src/components/card/card.stories.js +36 -0
  44. package/src/components/card/card.styles.js +128 -0
  45. package/src/components/card/card.test.js +59 -0
  46. package/src/components/card/index.js +1 -0
  47. package/src/components/code-preview/code-preview.component.js +53 -0
  48. package/src/components/code-preview/code-preview.js +7 -0
  49. package/src/components/code-preview/code-preview.stories.js +67 -0
  50. package/src/components/code-preview/code-preview.styles.js +18 -0
  51. package/src/components/code-preview/code-preview.test.js +118 -0
  52. package/src/components/code-preview/index.js +1 -0
  53. package/src/components/container/container.component.js +38 -0
  54. package/src/components/container/container.js +7 -0
  55. package/src/components/container/container.stories.js +59 -0
  56. package/src/components/container/container.styles.js +43 -0
  57. package/src/components/container/container.test.js +84 -0
  58. package/src/components/container/index.js +1 -0
  59. package/src/components/dialog/dialog.component.js +78 -0
  60. package/src/components/dialog/dialog.js +7 -0
  61. package/src/components/dialog/dialog.stories.js +43 -0
  62. package/src/components/dialog/dialog.styles.js +74 -0
  63. package/src/components/dialog/dialog.test.js +97 -0
  64. package/src/components/dialog/index.js +1 -0
  65. package/src/components/dropdown/dropdown.component.js +225 -0
  66. package/src/components/dropdown/dropdown.js +12 -0
  67. package/src/components/dropdown/dropdown.stories.js +107 -0
  68. package/src/components/dropdown/dropdown.styles.js +128 -0
  69. package/src/components/dropdown/dropdown.test.js +144 -0
  70. package/src/components/dropdown/index.js +3 -0
  71. package/src/components/dropzone/dropzone.component.js +141 -0
  72. package/src/components/dropzone/dropzone.js +6 -0
  73. package/src/components/dropzone/dropzone.stories.js +41 -0
  74. package/src/components/dropzone/dropzone.styles.js +64 -0
  75. package/src/components/dropzone/dropzone.test.js +112 -0
  76. package/src/components/dropzone/index.js +1 -0
  77. package/src/components/footer/footer-column.component.js +15 -0
  78. package/src/components/footer/footer-column.styles.js +51 -0
  79. package/src/components/footer/footer.component.js +38 -0
  80. package/src/components/footer/footer.js +9 -0
  81. package/src/components/footer/footer.stories.js +143 -0
  82. package/src/components/footer/footer.styles.js +90 -0
  83. package/src/components/footer/footer.test.js +107 -0
  84. package/src/components/footer/index.js +2 -0
  85. package/src/components/form-field/form-field.component.js +173 -0
  86. package/src/components/form-field/form-field.js +7 -0
  87. package/src/components/form-field/form-field.stories.js +104 -0
  88. package/src/components/form-field/form-field.styles.js +47 -0
  89. package/src/components/form-field/form-field.test.js +118 -0
  90. package/src/components/form-field/index.js +1 -0
  91. package/src/components/gallery/gallery-image.component.js +52 -0
  92. package/src/components/gallery/gallery-image.js +7 -0
  93. package/src/components/gallery/gallery.component.js +25 -0
  94. package/src/components/gallery/gallery.js +7 -0
  95. package/src/components/gallery/gallery.stories.js +60 -0
  96. package/src/components/gallery/gallery.styles.js +56 -0
  97. package/src/components/gallery/gallery.test.js +58 -0
  98. package/src/components/gallery/index.js +2 -0
  99. package/src/components/icon/icon.component.js +14 -0
  100. package/src/components/icon/icon.js +7 -0
  101. package/src/components/icon/icon.stories.js +26 -0
  102. package/src/components/icon/icon.styles.js +28 -0
  103. package/src/components/icon/icon.test.js +57 -0
  104. package/src/components/icon/index.js +1 -0
  105. package/src/components/loading/index.js +1 -0
  106. package/src/components/loading/loading.component.js +21 -0
  107. package/src/components/loading/loading.js +7 -0
  108. package/src/components/loading/loading.stories.js +25 -0
  109. package/src/components/loading/loading.styles.js +43 -0
  110. package/src/components/loading/loading.test.js +57 -0
  111. package/src/components/notice/index.js +1 -0
  112. package/src/components/notice/notice.component.js +77 -0
  113. package/src/components/notice/notice.js +7 -0
  114. package/src/components/notice/notice.stories.js +122 -0
  115. package/src/components/notice/notice.styles.js +72 -0
  116. package/src/components/notice/notice.test.js +146 -0
  117. package/src/components/pagination/index.js +1 -0
  118. package/src/components/pagination/pagination.component.js +62 -0
  119. package/src/components/pagination/pagination.js +7 -0
  120. package/src/components/pagination/pagination.stories.js +34 -0
  121. package/src/components/pagination/pagination.styles.js +19 -0
  122. package/src/components/pagination/pagination.test.js +98 -0
  123. package/src/components/sidebar/index.js +3 -0
  124. package/src/components/sidebar/sidebar.component.js +165 -0
  125. package/src/components/sidebar/sidebar.js +8 -0
  126. package/src/components/sidebar/sidebar.stories.js +155 -0
  127. package/src/components/sidebar/sidebar.styles.js +192 -0
  128. package/src/components/sidebar/sidebar.test.js +196 -0
  129. package/src/components/tabs/index.js +2 -0
  130. package/src/components/tabs/internal/tabs-button.component.js +39 -0
  131. package/src/components/tabs/internal/tabs-button.js +7 -0
  132. package/src/components/tabs/internal/tabs-item.component.js +39 -0
  133. package/src/components/tabs/tab.component.js +20 -0
  134. package/src/components/tabs/tab.js +7 -0
  135. package/src/components/tabs/tabs.component.js +130 -0
  136. package/src/components/tabs/tabs.js +7 -0
  137. package/src/components/tabs/tabs.stories.js +39 -0
  138. package/src/components/tabs/tabs.styles.js +88 -0
  139. package/src/components/tabs/tabs.test.js +148 -0
  140. package/src/components/toast/index.js +3 -0
  141. package/src/components/toast/toast.component.js +187 -0
  142. package/src/components/toast/toast.js +9 -0
  143. package/src/components/toast/toast.stories.js +169 -0
  144. package/src/components/toast/toast.styles.js +207 -0
  145. package/src/components/toast/toast.test.js +196 -0
  146. package/src/components/tooltip/index.js +1 -0
  147. package/src/components/tooltip/tooltip.component.js +70 -0
  148. package/src/components/tooltip/tooltip.js +7 -0
  149. package/src/components/tooltip/tooltip.stories.js +33 -0
  150. package/src/components/tooltip/tooltip.styles.js +78 -0
  151. package/src/components/tooltip/tooltip.test.js +150 -0
  152. package/src/css/all.css +1 -0
  153. package/src/css/base.css +31 -0
  154. package/src/css/colors.stories.js +192 -0
  155. package/src/css/elements/a.css +50 -0
  156. package/src/css/elements/forms/button.css +15 -0
  157. package/src/css/elements/forms/input.css +183 -0
  158. package/src/css/elements/forms/label.css +5 -0
  159. package/src/css/elements/media/image.css +3 -0
  160. package/src/css/elements.css +5 -0
  161. package/src/css/elements.stories.js +108 -0
  162. package/src/css/helpers.css +16 -0
  163. package/src/css/themes/grantcodes.css +3 -0
  164. package/src/css/themes/todomap.css +2 -0
  165. package/src/css/themes/wireframe.css +2 -0
  166. package/src/css/tokens.stories.js +183 -0
  167. package/src/css/typography.css +64 -0
  168. package/src/css/typography.stories.js +179 -0
  169. package/src/css/util/functions.css +16 -0
  170. package/src/css/util/index.css +2 -0
  171. package/src/css/util/mixins.css +63 -0
  172. package/src/icons.js +3 -0
  173. package/src/lib/classnames.js +61 -0
  174. package/src/lib/generate-id.js +10 -0
  175. package/src/main.js +17 -0
  176. package/src/test-utils/assert-helpers.js +150 -0
  177. package/src/test-utils/events.js +88 -0
  178. package/src/test-utils/fixture.js +77 -0
  179. package/src/test-utils/index.js +7 -0
  180. package/dist/components/avatar/avatar.component.js +0 -3
  181. package/dist/components/avatar/avatar.js +0 -1
  182. package/dist/components/avatar/avatar.react.js +0 -1
  183. package/dist/components/avatar/avatar.scss.js +0 -1
  184. package/dist/components/avatar/index.js +0 -1
  185. package/dist/components/button/button.component.js +0 -5
  186. package/dist/components/button/button.js +0 -1
  187. package/dist/components/button/button.react.js +0 -1
  188. package/dist/components/button/button.scss.js +0 -1
  189. package/dist/components/button/index.js +0 -1
  190. package/dist/components/button-group/button-group.component.js +0 -5
  191. package/dist/components/button-group/button-group.js +0 -1
  192. package/dist/components/button-group/button-group.react.js +0 -1
  193. package/dist/components/button-group/button-group.scss.js +0 -1
  194. package/dist/components/button-group/index.js +0 -1
  195. package/dist/components/card/card.component.js +0 -8
  196. package/dist/components/card/card.js +0 -1
  197. package/dist/components/card/card.react.js +0 -1
  198. package/dist/components/card/card.scss.js +0 -1
  199. package/dist/components/card/index.js +0 -1
  200. package/dist/components/code-preview/code-preview.component.js +0 -1
  201. package/dist/components/code-preview/code-preview.js +0 -1
  202. package/dist/components/code-preview/code-preview.react.js +0 -1
  203. package/dist/components/code-preview/code-preview.scss.js +0 -1
  204. package/dist/components/code-preview/index.js +0 -1
  205. package/dist/components/container/container.component.js +0 -5
  206. package/dist/components/container/container.js +0 -1
  207. package/dist/components/container/container.react.js +0 -1
  208. package/dist/components/container/container.scss.js +0 -1
  209. package/dist/components/container/index.js +0 -1
  210. package/dist/components/dialog/dialog.component.js +0 -23
  211. package/dist/components/dialog/dialog.js +0 -1
  212. package/dist/components/dialog/dialog.react.js +0 -1
  213. package/dist/components/dialog/dialog.scss.js +0 -1
  214. package/dist/components/dialog/index.js +0 -1
  215. package/dist/components/dropzone/dropzone.component.js +0 -11
  216. package/dist/components/dropzone/dropzone.js +0 -1
  217. package/dist/components/dropzone/dropzone.react.js +0 -1
  218. package/dist/components/dropzone/dropzone.scss.js +0 -1
  219. package/dist/components/dropzone/index.js +0 -1
  220. package/dist/components/form-field/form-field.component.js +0 -22
  221. package/dist/components/form-field/form-field.js +0 -1
  222. package/dist/components/form-field/form-field.react.js +0 -1
  223. package/dist/components/form-field/form-field.scss.js +0 -1
  224. package/dist/components/form-field/index.js +0 -1
  225. package/dist/components/gallery/gallery-image.component.js +0 -14
  226. package/dist/components/gallery/gallery-image.js +0 -1
  227. package/dist/components/gallery/gallery.component.js +0 -5
  228. package/dist/components/gallery/gallery.js +0 -1
  229. package/dist/components/gallery/gallery.react.js +0 -1
  230. package/dist/components/gallery/gallery.scss.js +0 -1
  231. package/dist/components/gallery/index.js +0 -1
  232. package/dist/components/icon/icon.component.js +0 -1
  233. package/dist/components/icon/icon.js +0 -1
  234. package/dist/components/icon/icon.react.js +0 -1
  235. package/dist/components/icon/icon.scss.js +0 -1
  236. package/dist/components/icon/index.js +0 -1
  237. package/dist/components/loading/index.js +0 -1
  238. package/dist/components/loading/loading.component.js +0 -5
  239. package/dist/components/loading/loading.js +0 -1
  240. package/dist/components/loading/loading.react.js +0 -1
  241. package/dist/components/loading/loading.scss.js +0 -1
  242. package/dist/components/notice/index.js +0 -1
  243. package/dist/components/notice/notice.component.js +0 -17
  244. package/dist/components/notice/notice.js +0 -1
  245. package/dist/components/notice/notice.react.js +0 -1
  246. package/dist/components/notice/notice.scss.js +0 -1
  247. package/dist/components/pagination/index.js +0 -1
  248. package/dist/components/pagination/pagination.component.js +0 -13
  249. package/dist/components/pagination/pagination.js +0 -1
  250. package/dist/components/pagination/pagination.react.js +0 -1
  251. package/dist/components/pagination/pagination.scss.js +0 -1
  252. package/dist/components/tabs/index.js +0 -1
  253. package/dist/components/tabs/tab.component.js +0 -1
  254. package/dist/components/tabs/tab.js +0 -1
  255. package/dist/components/tabs/tabs-item.component.js +0 -1
  256. package/dist/components/tabs/tabs-panel.component.js +0 -10
  257. package/dist/components/tabs/tabs-panel.js +0 -1
  258. package/dist/components/tabs/tabs-tab.component.js +0 -12
  259. package/dist/components/tabs/tabs-tab.js +0 -1
  260. package/dist/components/tabs/tabs.component.js +0 -28
  261. package/dist/components/tabs/tabs.js +0 -1
  262. package/dist/components/tabs/tabs.react.js +0 -1
  263. package/dist/components/tabs/tabs.scss.js +0 -1
  264. package/dist/components/tooltip/index.js +0 -1
  265. package/dist/components/tooltip/tooltip.component.js +0 -10
  266. package/dist/components/tooltip/tooltip.js +0 -1
  267. package/dist/components/tooltip/tooltip.react.js +0 -1
  268. package/dist/components/tooltip/tooltip.scss.js +0 -1
  269. package/dist/css/base.css +0 -1
  270. package/dist/css/themes/grantcodes.css +0 -1
  271. package/dist/fonts/greycliff-bold-oblique.woff +0 -0
  272. package/dist/fonts/greycliff-bold-oblique.woff2 +0 -0
  273. package/dist/fonts/greycliff-bold.woff +0 -0
  274. package/dist/fonts/greycliff-bold.woff2 +0 -0
  275. package/dist/fonts/greycliff-demi-bold-oblique.woff +0 -0
  276. package/dist/fonts/greycliff-demi-bold-oblique.woff2 +0 -0
  277. package/dist/fonts/greycliff-demi-bold.woff +0 -0
  278. package/dist/fonts/greycliff-demi-bold.woff2 +0 -0
  279. package/dist/fonts/greycliff-extra-bold-oblique.woff +0 -0
  280. package/dist/fonts/greycliff-extra-bold-oblique.woff2 +0 -0
  281. package/dist/fonts/greycliff-extra-bold.woff +0 -0
  282. package/dist/fonts/greycliff-extra-bold.woff2 +0 -0
  283. package/dist/fonts/greycliff-extra-light-oblique.woff +0 -0
  284. package/dist/fonts/greycliff-extra-light-oblique.woff2 +0 -0
  285. package/dist/fonts/greycliff-extra-light.woff +0 -0
  286. package/dist/fonts/greycliff-extra-light.woff2 +0 -0
  287. package/dist/fonts/greycliff-heavy-oblique.woff +0 -0
  288. package/dist/fonts/greycliff-heavy-oblique.woff2 +0 -0
  289. package/dist/fonts/greycliff-heavy.woff +0 -0
  290. package/dist/fonts/greycliff-heavy.woff2 +0 -0
  291. package/dist/fonts/greycliff-light-oblique.woff +0 -0
  292. package/dist/fonts/greycliff-light-oblique.woff2 +0 -0
  293. package/dist/fonts/greycliff-light.woff +0 -0
  294. package/dist/fonts/greycliff-light.woff2 +0 -0
  295. package/dist/fonts/greycliff-medium-oblique.woff +0 -0
  296. package/dist/fonts/greycliff-medium-oblique.woff2 +0 -0
  297. package/dist/fonts/greycliff-medium.woff +0 -0
  298. package/dist/fonts/greycliff-medium.woff2 +0 -0
  299. package/dist/fonts/greycliff-regular-oblique.woff +0 -0
  300. package/dist/fonts/greycliff-regular-oblique.woff2 +0 -0
  301. package/dist/fonts/greycliff-regular.woff +0 -0
  302. package/dist/fonts/greycliff-regular.woff2 +0 -0
  303. package/dist/fonts/greycliff-thin-oblique.woff +0 -0
  304. package/dist/fonts/greycliff-thin-oblique.woff2 +0 -0
  305. package/dist/fonts/greycliff-thin.woff +0 -0
  306. package/dist/fonts/greycliff-thin.woff2 +0 -0
  307. package/dist/icons.js +0 -1
  308. package/dist/lib/generate-id.js +0 -1
  309. package/dist/main.js +0 -1
  310. package/dist/react.js +0 -1
@@ -0,0 +1,57 @@
1
+ import { describe, it, afterEach } from "node:test";
2
+ import { strict as assert } from "node:assert";
3
+ import { fixture, cleanup } from "../../test-utils/index.js";
4
+ import "./loading.js";
5
+
6
+ describe("Loading Component", () => {
7
+ let element;
8
+
9
+ afterEach(() => {
10
+ cleanup(element);
11
+ });
12
+
13
+ it("should render with default properties", async () => {
14
+ element = await fixture("grantcodes-loading");
15
+ assert.ok(element, "Element should be created");
16
+ assert.ok(element.shadowRoot, "Element should have shadow root");
17
+ });
18
+
19
+ it("should have loading wrapper span", async () => {
20
+ element = await fixture("grantcodes-loading");
21
+ const loadingSpan = element.shadowRoot.querySelector(".loading");
22
+ assert.ok(loadingSpan, "Loading span should exist");
23
+ });
24
+
25
+ it("should have slot for content", async () => {
26
+ element = await fixture("grantcodes-loading");
27
+ const slot = element.shadowRoot.querySelector("slot");
28
+ assert.ok(slot, "Slot should exist");
29
+ });
30
+
31
+ it("should render slotted content", async () => {
32
+ element = await fixture("grantcodes-loading");
33
+ element.textContent = "Loading...";
34
+
35
+ await element.updateComplete;
36
+
37
+ assert.strictEqual(
38
+ element.textContent,
39
+ "Loading...",
40
+ "Slotted text should be present",
41
+ );
42
+ });
43
+
44
+ it("should support custom loading indicators", async () => {
45
+ element = await fixture("grantcodes-loading");
46
+ const spinner = document.createElement("div");
47
+ spinner.className = "custom-spinner";
48
+ element.appendChild(spinner);
49
+
50
+ await element.updateComplete;
51
+
52
+ const customSpinner = element.querySelector(".custom-spinner");
53
+ assert.ok(customSpinner, "Custom spinner should be slotted");
54
+ });
55
+ });
56
+
57
+
@@ -0,0 +1 @@
1
+ export * from "./notice";
@@ -0,0 +1,77 @@
1
+ import { LitElement } from "lit";
2
+ import { html } from "lit/static-html.js";
3
+ import { unsafeHTML } from "lit/directives/unsafe-html.js";
4
+ import { cx } from "../../lib/classnames.js";
5
+ import { noticeStyles } from "./notice.styles.js";
6
+ import { GrantCodesIcon } from "../icon/icon.component.js";
7
+ import { AlertCircle, Info, CheckCircle2, XCircle, X } from "../../icons.js";
8
+
9
+ const ICONS = {
10
+ info: Info,
11
+ success: CheckCircle2,
12
+ warning: AlertCircle,
13
+ error: XCircle,
14
+ };
15
+
16
+ export class GrantCodesNotice extends LitElement {
17
+ static dependencies = { "grancodes-icon": GrantCodesIcon };
18
+ // Styles are scoped to this element: they won't conflict with styles
19
+ // on the main page or in other components. Styling API can be exposed
20
+ // via CSS custom properties.
21
+ static styles = [noticeStyles];
22
+
23
+ // Define reactive properties--updating a reactive property causes
24
+ // the component to update.
25
+ // @property() label = 'Button Label'
26
+ static properties = {
27
+ variant: { type: String },
28
+ title: { type: String },
29
+ dismissable: { type: Boolean },
30
+ };
31
+
32
+ constructor() {
33
+ super();
34
+
35
+ this.variant = "info";
36
+ this.title = "";
37
+ this.dismissable = false;
38
+ }
39
+
40
+ onDismiss(_e) {
41
+ if (document.startViewTransition) {
42
+ document.startViewTransition(() => {
43
+ this.remove();
44
+ });
45
+ } else {
46
+ this.remove();
47
+ }
48
+ }
49
+
50
+ renderDismiss() {
51
+ if (this.dismissable) {
52
+ return html`
53
+ <button class="notice__close" @click=${this.onDismiss}>
54
+ <grantcodes-icon title="Close Notice">${unsafeHTML(X)}</grantcodes-icon>
55
+ </button>
56
+ `;
57
+ }
58
+ return html``;
59
+ }
60
+
61
+ render() {
62
+ const icon = ICONS[this.variant];
63
+
64
+ return html`
65
+ <aside class="${cx("notice", `notice--${this.variant}`)}">
66
+ <grantcodes-icon class="notice__icon">${unsafeHTML(icon)}</grantcodes-icon>
67
+
68
+ <div class="notice__content">
69
+ ${this.title && html`<h2 class="notice__title">${this.title}</h2>`}
70
+ <p><slot></slot></p>
71
+ </div>
72
+
73
+ ${this.renderDismiss()}
74
+ </aside>
75
+ `;
76
+ }
77
+ }
@@ -0,0 +1,7 @@
1
+ import { GrantCodesNotice } from "./notice.component.js";
2
+
3
+ export * from "./notice.component.js";
4
+ export default GrantCodesNotice;
5
+
6
+ customElements.define("grantcodes-notice", GrantCodesNotice);
7
+
@@ -0,0 +1,122 @@
1
+ import { html } from "lit/static-html.js";
2
+ import { getStorybookHelpers } from "@wc-toolkit/storybook-helpers";
3
+ const { events, args, argTypes, template } =
4
+ getStorybookHelpers("grantcodes-notice");
5
+ import "./notice.js";
6
+
7
+ const meta = {
8
+ title: "Components/Notice",
9
+ component: "grantcodes-notice",
10
+ args: {
11
+ ...args,
12
+ text: "This is the notice content",
13
+ title: "Notice title",
14
+ variant: "info",
15
+ dismissable: false,
16
+ },
17
+ argTypes: {
18
+ ...argTypes,
19
+ variant: {
20
+ type: "string",
21
+ },
22
+ },
23
+ render: (args) => template(args, html`${args.text}`),
24
+ parameters: {
25
+ actions: {
26
+ handles: events,
27
+ },
28
+ },
29
+ };
30
+
31
+ export default meta;
32
+
33
+ /**
34
+ * Informational notice with info variant and icon.
35
+ * Use for general information that doesn't require immediate action.
36
+ */
37
+ export const InfoNotice = {};
38
+
39
+ /**
40
+ * Success notice indicating a successful operation.
41
+ * Use after successful form submissions, saves, or completions.
42
+ */
43
+ export const SuccessNotice = {
44
+ args: {
45
+ variant: "success",
46
+ title: "Success",
47
+ text: "Your changes have been saved successfully.",
48
+ },
49
+ };
50
+
51
+ /**
52
+ * Warning notice for non-critical issues.
53
+ * Use to alert users about potential problems that don't block their workflow.
54
+ */
55
+ export const WarningNotice = {
56
+ args: {
57
+ variant: "warning",
58
+ title: "Warning",
59
+ text: "Your session will expire in 5 minutes.",
60
+ },
61
+ };
62
+
63
+ /**
64
+ * Error notice for critical issues.
65
+ * Use when an operation fails or there's a blocking error.
66
+ */
67
+ export const ErrorNotice = {
68
+ args: {
69
+ variant: "error",
70
+ title: "Error",
71
+ text: "Failed to save changes. Please try again.",
72
+ },
73
+ };
74
+
75
+ /**
76
+ * Dismissable notice that can be closed by the user.
77
+ * The notice will be removed from the DOM when dismissed.
78
+ */
79
+ export const Dismissable = {
80
+ args: {
81
+ variant: "info",
82
+ title: "Dismissable Notice",
83
+ text: "You can close this notice by clicking the X button.",
84
+ dismissable: true,
85
+ },
86
+ };
87
+
88
+ /**
89
+ * Notice without a title, showing only the message.
90
+ */
91
+ export const NoTitle = {
92
+ args: {
93
+ variant: "info",
94
+ title: "",
95
+ text: "This is a notice without a title, just the content message.",
96
+ },
97
+ };
98
+
99
+ /**
100
+ * All notice variants displayed together for comparison.
101
+ */
102
+ export const AllVariants = {
103
+ render: () => html`
104
+ <div style="display: flex; flex-direction: column; gap: 1rem;">
105
+ <grantcodes-notice variant="info" title="Information">
106
+ This is an informational message for general updates.
107
+ </grantcodes-notice>
108
+ <grantcodes-notice variant="success" title="Success">
109
+ Operation completed successfully!
110
+ </grantcodes-notice>
111
+ <grantcodes-notice variant="warning" title="Warning">
112
+ Please review this warning before continuing.
113
+ </grantcodes-notice>
114
+ <grantcodes-notice variant="error" title="Error">
115
+ An error occurred. Please contact support.
116
+ </grantcodes-notice>
117
+ <grantcodes-notice variant="info" dismissable>
118
+ This notice can be dismissed by clicking the close button.
119
+ </grantcodes-notice>
120
+ </div>
121
+ `,
122
+ };
@@ -0,0 +1,72 @@
1
+ import { css } from "lit";
2
+
3
+ export const noticeStyles = css`
4
+
5
+ .notice {
6
+ display: flex;
7
+ flex-direction: row;
8
+ align-items: flex-start;
9
+ gap: 1rem;
10
+ padding: 1rem;
11
+ border-radius: 0.25rem;
12
+ view-transition-name: notice;
13
+ transition: opacity 0.5s;
14
+ }
15
+
16
+ .notice--info {
17
+ color: var(--g-color-utility-blue-900);
18
+ background-color: var(--g-color-utility-blue-100);
19
+ }
20
+
21
+ .notice--success {
22
+ color: var(--g-color-utility-green-900);
23
+ background-color: var(--g-color-utility-green-100);
24
+ }
25
+
26
+ .notice--warning {
27
+ color: var(--g-color-utility-yellow-900);
28
+ background-color: var(--g-color-utility-yellow-100);
29
+ }
30
+
31
+ .notice--error {
32
+ color: var(--g-color-utility-red-900);
33
+ background-color: var(--g-color-utility-red-100);
34
+ }
35
+
36
+ .notice__title {
37
+ font-size: 1rem;
38
+ margin: 0;
39
+ }
40
+
41
+ .notice__icon {
42
+ font-size: calc(var(--g-theme-typography-body-default-line-height) * 1em);
43
+ }
44
+
45
+ .notice__content {
46
+ flex-grow: 1;
47
+ }
48
+
49
+ .notice__close {
50
+ background: none;
51
+ color: inherit;
52
+ opacity: 0.5;
53
+ transition: 0.2s;
54
+ font-size: calc(var(--g-theme-typography-body-default-line-height) * 1em);
55
+ line-height: 1;
56
+ padding: 0.5rem;
57
+ margin: -0.5rem -0.5rem 0 0;
58
+ border: 0;
59
+
60
+ &:hover,
61
+ &:focus-visible {
62
+ background: none;
63
+ color: inherit;
64
+ opacity: 1;
65
+ }
66
+ }
67
+
68
+ .notice p {
69
+ margin: 0;
70
+ }
71
+
72
+ `;
@@ -0,0 +1,146 @@
1
+ import { describe, it, afterEach } from "node:test";
2
+ import { strict as assert } from "node:assert";
3
+ import { fixture, cleanup, click } from "../../test-utils/index.js";
4
+ import "./notice.js";
5
+
6
+ describe("Notice Component", () => {
7
+ let element;
8
+
9
+ afterEach(() => {
10
+ cleanup(element);
11
+ });
12
+
13
+ it("should render with default properties", async () => {
14
+ element = await fixture("grantcodes-notice");
15
+ assert.ok(element, "Element should be created");
16
+ assert.ok(element.shadowRoot, "Element should have shadow root");
17
+ });
18
+
19
+ it("should have info variant by default", async () => {
20
+ element = await fixture("grantcodes-notice");
21
+ assert.strictEqual(element.variant, "info", "Default variant should be info");
22
+ });
23
+
24
+ it("should render with info variant class", async () => {
25
+ element = await fixture("grantcodes-notice", {
26
+ variant: "info",
27
+ });
28
+
29
+ const notice = element.shadowRoot.querySelector(".notice--info");
30
+ assert.ok(notice, "Notice should have info class");
31
+ });
32
+
33
+ it("should render with success variant class", async () => {
34
+ element = await fixture("grantcodes-notice", {
35
+ variant: "success",
36
+ });
37
+
38
+ const notice = element.shadowRoot.querySelector(".notice--success");
39
+ assert.ok(notice, "Notice should have success class");
40
+ });
41
+
42
+ it("should render with warning variant class", async () => {
43
+ element = await fixture("grantcodes-notice", {
44
+ variant: "warning",
45
+ });
46
+
47
+ const notice = element.shadowRoot.querySelector(".notice--warning");
48
+ assert.ok(notice, "Notice should have warning class");
49
+ });
50
+
51
+ it("should render with error variant class", async () => {
52
+ element = await fixture("grantcodes-notice", {
53
+ variant: "error",
54
+ });
55
+
56
+ const notice = element.shadowRoot.querySelector(".notice--error");
57
+ assert.ok(notice, "Notice should have error class");
58
+ });
59
+
60
+ it("should display title when provided", async () => {
61
+ element = await fixture("grantcodes-notice", {
62
+ title: "Important Notice",
63
+ });
64
+
65
+ const title = element.shadowRoot.querySelector(".notice__title");
66
+ assert.ok(title, "Title element should exist");
67
+ assert.strictEqual(title.textContent, "Important Notice", "Title text should match");
68
+ });
69
+
70
+ it("should not display title when not provided", async () => {
71
+ element = await fixture("grantcodes-notice");
72
+
73
+ const title = element.shadowRoot.querySelector(".notice__title");
74
+ assert.ok(!title, "Title element should not exist");
75
+ });
76
+
77
+ it("should not be dismissable by default", async () => {
78
+ element = await fixture("grantcodes-notice");
79
+ assert.strictEqual(element.dismissable, false, "Should not be dismissable by default");
80
+ });
81
+
82
+ it("should render dismiss button when dismissable", async () => {
83
+ element = await fixture("grantcodes-notice", {
84
+ dismissable: true,
85
+ });
86
+
87
+ const closeButton = element.shadowRoot.querySelector(".notice__close");
88
+ assert.ok(closeButton, "Close button should exist");
89
+ });
90
+
91
+ it("should not render dismiss button when not dismissable", async () => {
92
+ element = await fixture("grantcodes-notice", {
93
+ dismissable: false,
94
+ });
95
+
96
+ const closeButton = element.shadowRoot.querySelector(".notice__close");
97
+ assert.ok(!closeButton, "Close button should not exist");
98
+ });
99
+
100
+ it("should render appropriate icon for variant", async () => {
101
+ element = await fixture("grantcodes-notice", {
102
+ variant: "success",
103
+ });
104
+
105
+ const icon = element.shadowRoot.querySelector(".notice__icon");
106
+ assert.ok(icon, "Icon should be present");
107
+ });
108
+
109
+ it("should have content slot", async () => {
110
+ element = await fixture("grantcodes-notice");
111
+ const slot = element.shadowRoot.querySelector("slot");
112
+ assert.ok(slot, "Slot should exist for content");
113
+ });
114
+
115
+ it("should render slotted content", async () => {
116
+ element = await fixture("grantcodes-notice");
117
+ element.textContent = "This is a notice message";
118
+
119
+ await element.updateComplete;
120
+
121
+ assert.strictEqual(
122
+ element.textContent,
123
+ "This is a notice message",
124
+ "Slotted content should be present",
125
+ );
126
+ });
127
+
128
+ it("should remove element when dismissed", async () => {
129
+ element = await fixture("grantcodes-notice", {
130
+ dismissable: true,
131
+ });
132
+
133
+ const closeButton = element.shadowRoot.querySelector(".notice__close");
134
+ const parentBeforeDismiss = element.parentNode;
135
+
136
+ assert.ok(parentBeforeDismiss, "Element should have a parent");
137
+
138
+ // Note: In actual tests, the element removal via view transitions might need special handling
139
+ click(closeButton);
140
+
141
+ // Give time for the dismiss handler to execute
142
+ await new Promise((resolve) => setTimeout(resolve, 10));
143
+ });
144
+ });
145
+
146
+
@@ -0,0 +1 @@
1
+ export * from "./pagination";
@@ -0,0 +1,62 @@
1
+ import { LitElement } from "lit";
2
+ import { html } from "lit/static-html.js";
3
+ import { paginationStyles } from "./pagination.styles.js";
4
+ import { GrantCodesButton } from "../button/button.component.js";
5
+ import "../button/button.js";
6
+
7
+ export class GrantCodesPagination extends LitElement {
8
+ // Styles are scoped to this element: they won't conflict with styles
9
+ // on the main page or in other components. Styling API can be exposed
10
+ // via CSS custom properties.
11
+ static styles = [paginationStyles];
12
+
13
+ static dependencies = { "grantcodes-button": GrantCodesButton };
14
+
15
+ static properties = {
16
+ previousHref: { attribute: "previous-href" },
17
+ nextHref: { attribute: "next-href" },
18
+ page: { type: Number },
19
+ pages: { type: Number },
20
+ };
21
+
22
+ constructor() {
23
+ super();
24
+
25
+ this.previousHref = "";
26
+ this.nextHref = "";
27
+ this.page = 1;
28
+ this.pages = 1;
29
+ }
30
+
31
+ nextTemplate() {
32
+ if (!this.nextHref) {
33
+ return html``;
34
+ }
35
+
36
+ return html`
37
+ <grantcodes-button class="pagination__next" href=${this.nextHref}
38
+ >Next</grantcodes-button
39
+ >
40
+ `;
41
+ }
42
+
43
+ previousTemplate() {
44
+ if (!this.previousHref) {
45
+ return html``;
46
+ }
47
+
48
+ return html`
49
+ <grantcodes-button class="pagination__previous" href=${this.previousHref}
50
+ >Previous</grantcodes-button
51
+ >
52
+ `;
53
+ }
54
+
55
+ render() {
56
+ return html`
57
+ <nav class="pagination" aria-label="Pagination navigation">
58
+ ${this.previousTemplate()} ${this.nextTemplate()}
59
+ </nav>
60
+ `;
61
+ }
62
+ }
@@ -0,0 +1,7 @@
1
+ import { GrantCodesPagination } from "./pagination.component.js";
2
+ import "../button/button.js";
3
+
4
+ export * from "./pagination.component.js";
5
+ export default GrantCodesPagination;
6
+
7
+ customElements.define("grantcodes-pagination", GrantCodesPagination);
@@ -0,0 +1,34 @@
1
+ import { html } from "lit/static-html.js";
2
+ import { getStorybookHelpers } from "@wc-toolkit/storybook-helpers";
3
+ const { events, args, argTypes } = getStorybookHelpers(
4
+ "grantcodes-pagination",
5
+ );
6
+ import "./pagination.js";
7
+
8
+ const meta = {
9
+ title: "Components/Pagination",
10
+ component: "grantcodes-pagination",
11
+ args: {
12
+ ...args,
13
+ previousHref: "#1",
14
+ nextHref: "#3",
15
+ },
16
+ argTypes,
17
+ render: (args) => html`
18
+ <grantcodes-pagination
19
+ .previousHref=${args.previousHref}
20
+ .nextHref=${args.nextHref}
21
+ .page=${args.page ?? 1}
22
+ .pages=${args.pages ?? 1}
23
+ ></grantcodes-pagination>
24
+ `,
25
+ parameters: {
26
+ actions: {
27
+ handles: events,
28
+ },
29
+ },
30
+ };
31
+
32
+ export default meta;
33
+
34
+ export const Pagination = {};
@@ -0,0 +1,19 @@
1
+ import { css } from "lit";
2
+
3
+ export const paginationStyles = css`
4
+
5
+ .pagination {
6
+ display: flex;
7
+ flex-direction: row;
8
+ align-items: center;
9
+ }
10
+
11
+ .pagination__next {
12
+ margin-inline-start: auto;
13
+ }
14
+
15
+ .pagination__previous {
16
+ margin-inline-end: auto;
17
+ }
18
+
19
+ `;