@ongov/ontario-design-system-component-library 4.3.0 → 5.0.0-alpha.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.
Files changed (148) hide show
  1. package/dist/cjs/index-88d5cf20.js +2 -2
  2. package/dist/cjs/loader.cjs.js +1 -1
  3. package/dist/cjs/{ontario-accordion_43.cjs.entry.js → ontario-accordion_44.cjs.entry.js} +738 -296
  4. package/dist/cjs/ontario-accordion_44.cjs.entry.js.map +1 -0
  5. package/dist/cjs/ontario-design-system-components.cjs.js +1 -1
  6. package/dist/collection/collection-manifest.json +1 -0
  7. package/dist/collection/components/ontario-card/ontario-card-types.js +29 -2
  8. package/dist/collection/components/ontario-card/ontario-card-types.js.map +1 -1
  9. package/dist/collection/components/ontario-card/ontario-card.css +257 -31
  10. package/dist/collection/components/ontario-card/ontario-card.js +104 -80
  11. package/dist/collection/components/ontario-card/ontario-card.js.map +1 -1
  12. package/dist/collection/components/ontario-card/test/ontario-cards.spec.js +23 -13
  13. package/dist/collection/components/ontario-card/test/ontario-cards.spec.js.map +1 -1
  14. package/dist/collection/components/ontario-header/ontario-header.js +17 -3
  15. package/dist/collection/components/ontario-header/ontario-header.js.map +1 -1
  16. package/dist/collection/components/ontario-header/service-ontario-header.css +0 -3
  17. package/dist/collection/components/ontario-header/test/ontario-header.spec.js +3 -3
  18. package/dist/collection/components/ontario-header/test/ontario-header.spec.js.map +1 -1
  19. package/dist/collection/components/ontario-language-toggle/ontario-language-toggle.js +193 -47
  20. package/dist/collection/components/ontario-language-toggle/ontario-language-toggle.js.map +1 -1
  21. package/dist/collection/components/ontario-language-toggle/test/ontario-language-toggle.spec.js +16 -3
  22. package/dist/collection/components/ontario-language-toggle/test/ontario-language-toggle.spec.js.map +1 -1
  23. package/dist/collection/components/ontario-search-box/assets/ontario-icon-close.svg +1 -0
  24. package/dist/collection/components/ontario-search-box/assets/ontario-logo--mobile.svg +6 -0
  25. package/dist/collection/components/ontario-search-box/ontario-search-box.css +823 -0
  26. package/dist/collection/components/ontario-search-box/ontario-search-box.js +584 -0
  27. package/dist/collection/components/ontario-search-box/ontario-search-box.js.map +1 -0
  28. package/dist/collection/components/ontario-search-box/test/ontario-search-box.e2e.js +20 -0
  29. package/dist/collection/components/ontario-search-box/test/ontario-search-box.e2e.js.map +1 -0
  30. package/dist/collection/components/ontario-search-box/test/ontario-search-box.spec.js +19 -0
  31. package/dist/collection/components/ontario-search-box/test/ontario-search-box.spec.js.map +1 -0
  32. package/dist/collection/components/ontario-step-indicator/ontario-step-indicator.js +5 -5
  33. package/dist/collection/components/ontario-table/ontario-table.js +5 -5
  34. package/dist/collection/components/ontario-textarea/ontario-textarea.js +3 -3
  35. package/dist/collection/i18n/global.i18n.json +172 -162
  36. package/dist/collection/utils/common/input/input.js +3 -0
  37. package/dist/collection/utils/common/input/input.js.map +1 -1
  38. package/dist/collection/utils/common/input-caption/input-caption.js +5 -3
  39. package/dist/collection/utils/common/input-caption/input-caption.js.map +1 -1
  40. package/dist/collection/utils/common/language-types.js +1 -1
  41. package/dist/collection/utils/common/language-types.js.map +1 -1
  42. package/dist/collection/utils/helper/utils-types.js +2 -0
  43. package/dist/collection/utils/helper/utils-types.js.map +1 -0
  44. package/dist/collection/utils/helper/utils.js +26 -0
  45. package/dist/collection/utils/helper/utils.js.map +1 -1
  46. package/dist/components/error-message.js +1 -324
  47. package/dist/components/error-message.js.map +1 -1
  48. package/dist/components/event-handler.js +330 -0
  49. package/dist/components/event-handler.js.map +1 -0
  50. package/dist/components/global.i18n.js +184 -173
  51. package/dist/components/global.i18n.js.map +1 -1
  52. package/dist/components/input.js +3 -0
  53. package/dist/components/input.js.map +1 -1
  54. package/dist/components/ontario-card.js +118 -66
  55. package/dist/components/ontario-card.js.map +1 -1
  56. package/dist/components/ontario-checkboxes.js +2 -1
  57. package/dist/components/ontario-checkboxes.js.map +1 -1
  58. package/dist/components/ontario-date-input.js +2 -1
  59. package/dist/components/ontario-date-input.js.map +1 -1
  60. package/dist/components/ontario-dropdown-list.js +2 -1
  61. package/dist/components/ontario-dropdown-list.js.map +1 -1
  62. package/dist/components/ontario-header.js +13 -7
  63. package/dist/components/ontario-header.js.map +1 -1
  64. package/dist/components/ontario-icon-search2.js +6 -0
  65. package/dist/components/ontario-icon-search2.js.map +1 -0
  66. package/dist/components/ontario-input.js +2 -1
  67. package/dist/components/ontario-input.js.map +1 -1
  68. package/dist/components/ontario-language-toggle2.js +180 -37
  69. package/dist/components/ontario-language-toggle2.js.map +1 -1
  70. package/dist/components/ontario-radio-buttons.js +2 -1
  71. package/dist/components/ontario-radio-buttons.js.map +1 -1
  72. package/dist/components/ontario-search-box.d.ts +11 -0
  73. package/dist/components/ontario-search-box.js +269 -0
  74. package/dist/components/ontario-search-box.js.map +1 -0
  75. package/dist/components/ontario-step-indicator.js +5 -5
  76. package/dist/components/ontario-table.js +5 -5
  77. package/dist/components/ontario-textarea.js +5 -4
  78. package/dist/components/ontario-textarea.js.map +1 -1
  79. package/dist/components/utils.js +28 -0
  80. package/dist/components/utils.js.map +1 -1
  81. package/dist/esm/index-603026f7.js +2 -2
  82. package/dist/esm/loader.js +1 -1
  83. package/dist/esm/{ontario-accordion_43.entry.js → ontario-accordion_44.entry.js} +738 -296
  84. package/dist/esm/ontario-accordion_44.entry.js.map +1 -0
  85. package/dist/esm/ontario-design-system-components.js +1 -1
  86. package/dist/ontario-design-system-components/i18n/global.i18n.json +172 -162
  87. package/dist/ontario-design-system-components/ontario-design-system-components.esm.js +1 -1
  88. package/dist/ontario-design-system-components/ontario-design-system-components.esm.js.map +1 -1
  89. package/dist/ontario-design-system-components/{p-cff41424.entry.js → p-9c3a1be9.entry.js} +2204 -1918
  90. package/dist/ontario-design-system-components/p-9c3a1be9.entry.js.map +1 -0
  91. package/dist/types/components/ontario-card/ontario-card-types.d.ts +4 -4
  92. package/dist/types/components/ontario-card/ontario-card.d.ts +40 -29
  93. package/dist/types/components/ontario-header/ontario-header.d.ts +13 -2
  94. package/dist/types/components/ontario-language-toggle/ontario-language-toggle.d.ts +75 -8
  95. package/dist/types/components/ontario-search-box/ontario-search-box.d.ts +180 -0
  96. package/dist/types/components.d.ts +211 -22
  97. package/dist/types/utils/common/input/input.d.ts +2 -1
  98. package/dist/types/utils/common/input-caption/input-caption.d.ts +7 -1
  99. package/dist/types/utils/common/language-types.d.ts +2 -1
  100. package/dist/types/utils/helper/utils-types.d.ts +2 -0
  101. package/dist/types/utils/helper/utils.d.ts +21 -0
  102. package/package.json +3 -3
  103. package/src/components/ontario-card/ontario-card-types.tsx +33 -4
  104. package/src/components/ontario-card/ontario-card.scss +59 -38
  105. package/src/components/ontario-card/ontario-card.tsx +98 -70
  106. package/src/components/ontario-card/readme.md +57 -27
  107. package/src/components/ontario-card/test/__snapshots__/ontario-cards.spec.tsx.snap +66 -0
  108. package/src/components/ontario-card/test/ontario-cards.spec.tsx +27 -13
  109. package/src/components/ontario-card-collection/readme.md +13 -13
  110. package/src/components/ontario-checkbox/ontario-checkboxes.scss +0 -1
  111. package/src/components/ontario-header/ontario-header.tsx +13 -4
  112. package/src/components/ontario-header/service-ontario-header.scss +0 -4
  113. package/src/components/ontario-header/test/ontario-header.spec.tsx +3 -3
  114. package/src/components/ontario-hint-text/readme.md +2 -0
  115. package/src/components/ontario-language-toggle/ontario-language-toggle.tsx +192 -45
  116. package/src/components/ontario-language-toggle/readme.md +10 -10
  117. package/src/components/ontario-language-toggle/test/__snapshots__/ontario-language-toggle.spec.tsx.snap +1 -1
  118. package/src/components/ontario-language-toggle/test/ontario-language-toggle.spec.tsx +17 -3
  119. package/src/components/ontario-radio-buttons/ontario-radio-buttons.scss +0 -1
  120. package/src/components/ontario-search-box/assets/ontario-icon-close.svg +1 -0
  121. package/src/components/ontario-search-box/assets/ontario-logo--mobile.svg +6 -0
  122. package/src/components/ontario-search-box/ontario-search-box.scss +141 -0
  123. package/src/components/ontario-search-box/ontario-search-box.tsx +341 -0
  124. package/src/components/ontario-search-box/readme.md +132 -0
  125. package/src/components/ontario-search-box/test/__snapshots__/ontario-search-box.spec.tsx.snap +35 -0
  126. package/src/components/ontario-search-box/test/ontario-search-box.e2e.ts +21 -0
  127. package/src/components/ontario-search-box/test/ontario-search-box.spec.tsx +22 -0
  128. package/src/components.d.ts +211 -22
  129. package/src/french.html +37 -0
  130. package/src/index.html +292 -38
  131. package/src/translations/global.i18n.json +172 -162
  132. package/src/utils/common/input/input.tsx +4 -1
  133. package/src/utils/common/input-caption/input-caption.tsx +9 -3
  134. package/src/utils/common/language-types.ts +2 -1
  135. package/src/utils/helper/utils-types.ts +2 -0
  136. package/src/utils/helper/utils.ts +30 -0
  137. package/www/build/ontario-design-system-components.esm.js +1 -1
  138. package/www/build/ontario-design-system-components.esm.js.map +1 -1
  139. package/www/build/{p-b61db0f6.js → p-84035ac3.js} +1 -1
  140. package/www/build/{p-cff41424.entry.js → p-9c3a1be9.entry.js} +2204 -1918
  141. package/www/build/p-9c3a1be9.entry.js.map +1 -0
  142. package/www/french.html +37 -0
  143. package/www/i18n/global.i18n.json +172 -162
  144. package/www/index.html +266 -38
  145. package/dist/cjs/ontario-accordion_43.cjs.entry.js.map +0 -1
  146. package/dist/esm/ontario-accordion_43.entry.js.map +0 -1
  147. package/dist/ontario-design-system-components/p-cff41424.entry.js.map +0 -1
  148. package/www/build/p-cff41424.entry.js.map +0 -1
@@ -67,6 +67,7 @@ Promise<string | undefined>
67
67
  - [ontario-dropdown-list](../ontario-dropdown-list)
68
68
  - [ontario-input](../ontario-input)
69
69
  - [ontario-radio-buttons](../ontario-radio-buttons)
70
+ - [ontario-search-box](../ontario-search-box)
70
71
  - [ontario-textarea](../ontario-textarea)
71
72
 
72
73
  ### Graph
@@ -77,6 +78,7 @@ graph TD;
77
78
  ontario-dropdown-list --> ontario-hint-text
78
79
  ontario-input --> ontario-hint-text
79
80
  ontario-radio-buttons --> ontario-hint-text
81
+ ontario-search-box --> ontario-hint-text
80
82
  ontario-textarea --> ontario-hint-text
81
83
  style ontario-hint-text fill:#f9f,stroke:#333,stroke-width:4px
82
84
  ```
@@ -1,10 +1,12 @@
1
1
  import { Component, Prop, State, Event, EventEmitter, Watch, h, Fragment } from '@stencil/core';
2
2
 
3
- import { Language } from '../../utils/common/language-types';
4
- import { validateLanguage } from '../../utils/validation/validation-functions';
3
+ import { supportedLanguages, Language } from '../../utils/common/language-types';
5
4
 
6
5
  import { default as translations } from '../../translations/global.i18n.json';
7
6
  import { HeaderLanguageToggleEventDetails } from '../../utils/events/common-events.interface';
7
+ import { validateValueAgainstArray } from '../../utils/validation/validation-functions';
8
+ import { ConsoleMessageClass } from '../../utils/console-message/console-message';
9
+ import { printArray, getRootHTMLElement } from '../../utils/helper/utils';
8
10
 
9
11
  @Component({
10
12
  tag: 'ontario-language-toggle',
@@ -12,7 +14,14 @@ import { HeaderLanguageToggleEventDetails } from '../../utils/events/common-even
12
14
  shadow: true,
13
15
  })
14
16
  export class OntarioLanguageToggle {
15
- @Prop({ mutable: true }) language: Language | string;
17
+ /**
18
+ * The language of the component.
19
+ *
20
+ * In most cases, the language toggle should be the source of truth for determining the site language.
21
+ *
22
+ * Only pass a language value here if necessary.
23
+ */
24
+ @Prop({ mutable: true }) language?: Language;
16
25
 
17
26
  /**
18
27
  * The size of the language toggle button.
@@ -38,89 +47,227 @@ export class OntarioLanguageToggle {
38
47
  @State() translations: any = translations;
39
48
 
40
49
  /**
41
- * An event to set the Document's HTML lang property, and emit the toggled language to other components.
50
+ * Internal state used as the source of truth for component language.
51
+ */
52
+ @State() private languageState: Language;
53
+
54
+ /**
55
+ * Internal state used to render the text on the language toggle UI.
56
+ */
57
+ @State() private oppositeLanguageLabel: { fullWord: string; abbreviation: Language } | undefined = undefined;
58
+
59
+ /**
60
+ * Updates the language and languageState props when changes to the language prop are detected.
42
61
  */
43
- @Event() setAppLanguage: EventEmitter<string>;
44
- setAppLanguageHandler() {
45
- let lang: string | Language;
62
+ @Watch('language')
63
+ updateLanguage() {
46
64
  if (this.language) {
47
- lang = this.language;
48
- } else if (document.documentElement.lang) {
49
- lang = document.documentElement.lang;
50
- } else {
51
- lang = 'en';
65
+ if (!validateValueAgainstArray(this.language, supportedLanguages)) {
66
+ this.showLanguageWarning(this.language);
67
+ this.language = this.translations.siteLanguage.abbreviation.en as Language;
68
+ }
69
+ this.languageState = this.language;
52
70
  }
71
+ this.setAppLanguageHandler();
72
+ }
73
+
74
+ /**
75
+ * Event that fires during the setAppLanguageHandler() method.
76
+ *
77
+ * The event contains the current language (after language logic has already occurred).
78
+ */
79
+ @Event() setAppLanguage: EventEmitter<Language>;
80
+
81
+ /**
82
+ * Event that fires when the language toggle is pressed/clicked.
83
+ *
84
+ * The event contains the oldLanguage along with the newLanguage.
85
+ */
86
+ @Event() headerLanguageToggled: EventEmitter<HeaderLanguageToggleEventDetails>;
87
+
88
+ /**
89
+ * This function sets the languageState (if not already set).
90
+ *
91
+ * It also emits the setAppLanguage() event, updates the component language label, and
92
+ * updates the <html> tag lang attribute with the languageState value.
93
+ *
94
+ * It gets called by the connectedCallback() component lifecycle hook, and by the
95
+ * updateLanguage() method, which is fired on the watch for the language prop.
96
+ */
97
+ private setAppLanguageHandler() {
98
+ const defaultLang = this.translations.siteLanguage.abbreviation.en;
99
+ const rootLang = getRootHTMLElement()?.lang;
100
+
101
+ // If languageState is not set, set it equal to the following cadence:
102
+ // language prop value, <html> tag lang attribute, or default to "en"
103
+ if (!this.languageState) {
104
+ if (this.language) {
105
+ this.languageState = this.language;
106
+ } else if (rootLang) {
107
+ if (validateValueAgainstArray(rootLang, supportedLanguages)) {
108
+ this.languageState = rootLang as Language;
109
+ } else {
110
+ this.showLanguageWarning(rootLang, 'document');
111
+ this.languageState = defaultLang;
112
+ }
113
+ } else {
114
+ this.languageState = defaultLang;
115
+ }
116
+ }
117
+
118
+ this.setAppLanguage.emit(this.languageState);
53
119
 
54
- this.language = lang;
55
- this.setAppLanguage.emit(lang);
120
+ this.oppositeLanguageLabel = {
121
+ fullWord: this.getOppositeLanguageFullWord(),
122
+ abbreviation: this.getOppositeLanguageAbbrievation(),
123
+ };
56
124
 
57
- this.updateHTMLLang(lang);
125
+ this.updateHTMLLang();
58
126
  }
59
127
 
60
128
  /**
61
129
  * An event that emits to other components that the language toggle button has been toggled.
130
+ *
131
+ * @param {Language} oldLanguage - The language prior to the language toggle being pressed.
132
+ * @param {globalThis.Event} event - event that triggered the function (e.g. onclick).
62
133
  */
63
- @Event() headerLanguageToggled: EventEmitter<HeaderLanguageToggleEventDetails>;
64
- handleHeaderLanguageToggled(language: string, event?: globalThis.Event) {
65
- const toggledLanguage = language === 'en' ? 'fr' : 'en';
66
- this.language = toggledLanguage;
134
+ private handleHeaderLanguageToggled(oldLanguage: Language, event?: globalThis.Event) {
135
+ this.languageState =
136
+ oldLanguage === this.translations.siteLanguage.abbreviation.en
137
+ ? this.translations.siteLanguage.abbreviation.fr
138
+ : this.translations.siteLanguage.abbreviation.en;
67
139
 
68
- this.headerLanguageToggled.emit({ oldLanguage: language, newLanguage: toggledLanguage });
140
+ this.headerLanguageToggled.emit({ oldLanguage: oldLanguage, newLanguage: this.languageState });
69
141
 
70
- this.updateHTMLLang(toggledLanguage);
142
+ this.updateHTMLLang();
71
143
 
72
144
  if (this.customLanguageToggle && event) {
73
145
  this.customLanguageToggle(event);
74
146
  }
75
147
  }
76
148
 
77
- @Watch('language')
78
- updateLanguage() {
79
- this.language = validateLanguage(this.language);
80
- this.setAppLanguageHandler();
149
+ /**
150
+ * Prints a warning message to the console about using an incorrect language for the component.
151
+ *
152
+ * @param {string} lang - The incorrect language that was received.
153
+ * @param {string} type - prop/document | Where the incorrect language is coming from.
154
+ */
155
+ private showLanguageWarning(lang: string, type: 'prop' | 'document' = 'prop') {
156
+ const propOrDocumentMessage =
157
+ type === 'prop' ? `The language prop value of ${lang} ` : `The HTML document lang attribute value of ${lang} `;
158
+ const message = new ConsoleMessageClass();
159
+ message
160
+ .addDesignSystemTag()
161
+ .addRegularText(propOrDocumentMessage)
162
+ .addRegularText('is not a valid language value for the ')
163
+ .addMonospaceText(' <ontario-language-toggle> ')
164
+ .addRegularText(`component. Valid language values are ${printArray([...supportedLanguages])}. `)
165
+ .addRegularText(`A default language value of ${this.translations.siteLanguage.abbreviation.en} will be applied.`)
166
+ .printMessage();
81
167
  }
82
168
 
83
- updateHTMLLang = (lang: string) => {
84
- const htmlElement = document.firstElementChild;
169
+ /**
170
+ * Returns abbreviated text for the opposite language.
171
+ *
172
+ * @returns {Language}
173
+ */
174
+ private getOppositeLanguageAbbrievation(): Language {
175
+ return this.languageState === this.translations.siteLanguage.abbreviation.en
176
+ ? this.translations.siteLanguage.abbreviation.fr
177
+ : this.translations.siteLanguage.abbreviation.en;
178
+ }
85
179
 
86
- if (htmlElement?.tagName.toLowerCase() === 'html') {
87
- if (lang) {
88
- htmlElement.setAttribute('lang', lang);
89
- } else {
90
- htmlElement.setAttribute('lang', 'en');
91
- }
92
- }
180
+ /**
181
+ * Returns full word text for the opposite language.
182
+ *
183
+ * @returns {string}
184
+ */
185
+ private getOppositeLanguageFullWord(): string {
186
+ return this.languageState === this.translations.siteLanguage.abbreviation.en
187
+ ? this.translations.siteLanguage.fullWord.fr
188
+ : this.translations.siteLanguage.fullWord.en;
189
+ }
190
+
191
+ /*
192
+ * Updates the <html> lang attribute based on component languageState.
193
+ */
194
+ private updateHTMLLang = () => {
195
+ const htmlElement = getRootHTMLElement();
93
196
 
94
- return;
197
+ if (htmlElement) {
198
+ htmlElement.setAttribute('lang', this.languageState);
199
+ }
95
200
  };
96
201
 
202
+ /**
203
+ * Component life cycle hook.
204
+ *
205
+ * https://stenciljs.com/docs/component-lifecycle#connectedcallback
206
+ */
97
207
  connectedCallback() {
98
- this.updateLanguage();
208
+ this.setAppLanguageHandler();
99
209
  }
100
210
 
101
- render() {
102
- const language = this.language === 'en' ? 'Français' : 'English';
103
- const abbreviatedLanguage = this.language === 'en' ? 'FR' : 'EN';
211
+ /**
212
+ * Component life cycle hook.
213
+ *
214
+ * https://stenciljs.com/docs/component-lifecycle#componentdidload
215
+ */
216
+ componentDidLoad() {
217
+ /**
218
+ * Creates a MutationObserver (a type of watch) on the <html> tag lang attribute.
219
+ *
220
+ * When changes occur, the oppositeLanguageLabel state variable regenerates.
221
+ *
222
+ * This is to act as a form of callback and create a subtle delay between page content
223
+ * updating and the language toggle label updating.
224
+ */
225
+ const observer = new MutationObserver((mutations) => {
226
+ mutations.forEach((mutation) => {
227
+ switch (mutation.type) {
228
+ case 'attributes':
229
+ switch (mutation.attributeName) {
230
+ case 'lang':
231
+ this.oppositeLanguageLabel = {
232
+ fullWord: this.getOppositeLanguageFullWord(),
233
+ abbreviation: this.getOppositeLanguageAbbrievation(),
234
+ };
235
+ break;
236
+ }
237
+ break;
238
+ }
239
+ });
240
+ });
104
241
 
242
+ // Only create/trigger the MutationObserver if the <html> element exists.
243
+ if (getRootHTMLElement()) {
244
+ const options = { attributes: true };
245
+ observer.observe(getRootHTMLElement(), options);
246
+ }
247
+ }
248
+
249
+ render() {
105
250
  return (
106
251
  <a
252
+ aria-label={this.translations.languageToggle.ariaLabel[`${this.oppositeLanguageLabel?.abbreviation}`]}
107
253
  class={
108
254
  this.size === 'default'
109
255
  ? 'ontario-language-toggler ontario-language-toggler--default'
110
256
  : 'ontario-language-toggler ontario-language-toggler--small'
111
257
  }
112
258
  href={this.url ? this.url : '#'}
113
- aria-label={this.translations.languageToggle.ariaLabel[`${this.language}`]}
114
- onClick={(e) => this.handleHeaderLanguageToggled(this.language, e)}
259
+ hreflang={this.oppositeLanguageLabel?.abbreviation}
260
+ lang={this.oppositeLanguageLabel?.abbreviation}
261
+ onClick={(e) => this.handleHeaderLanguageToggled(this.languageState, e)}
115
262
  >
116
263
  {this.size === 'small' ? (
117
- <span>{language}</span>
264
+ <span>{this.oppositeLanguageLabel?.fullWord}</span>
118
265
  ) : (
119
266
  <Fragment>
120
- <abbr title={language} class="ontario-show-for-small-only">
121
- {abbreviatedLanguage}
267
+ <abbr title={this.oppositeLanguageLabel?.fullWord} class="ontario-show-for-small-only">
268
+ {this.oppositeLanguageLabel?.abbreviation.toUpperCase()}
122
269
  </abbr>
123
- <span class="ontario-show-for-medium">{language}</span>
270
+ <span class="ontario-show-for-medium">{this.oppositeLanguageLabel?.fullWord}</span>
124
271
  </Fragment>
125
272
  )}
126
273
  </a>
@@ -10,19 +10,19 @@ It is used in the ontario-header component.
10
10
 
11
11
  ## Properties
12
12
 
13
- | Property | Attribute | Description | Type | Default |
14
- | ---------------------- | ---------- | --------------------------------------------------------------------------------------------------- | --------------------------------------- | ----------- |
15
- | `customLanguageToggle` | -- | A custom function to pass to the language toggle button. This is optional. | `((event: Event) => void) \| undefined` | `undefined` |
16
- | `language` | `language` | | `string` | `undefined` |
17
- | `size` | `size` | The size of the language toggle button. If no prop is passed, it will be set to the `default` size. | `"default" \| "small" \| undefined` | `'default'` |
18
- | `url` | `url` | The URL to change to when the language toggle button is clicked. This is optional. | `string \| undefined` | `undefined` |
13
+ | Property | Attribute | Description | Type | Default |
14
+ | ---------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------- | ----------- |
15
+ | `customLanguageToggle` | -- | A custom function to pass to the language toggle button. This is optional. | `((event: Event) => void) \| undefined` | `undefined` |
16
+ | `language` | `language` | The language of the component. In most cases, the language toggle should be the source of truth for determining the site language. Only pass a language value here if necessary. | `"en" \| "fr" \| undefined` | `undefined` |
17
+ | `size` | `size` | The size of the language toggle button. If no prop is passed, it will be set to the `default` size. | `"default" \| "small" \| undefined` | `'default'` |
18
+ | `url` | `url` | The URL to change to when the language toggle button is clicked. This is optional. | `string \| undefined` | `undefined` |
19
19
 
20
20
  ## Events
21
21
 
22
- | Event | Description | Type |
23
- | ----------------------- | ----------------------------------------------------------------------------------------------------- | ----------------------------------------------- |
24
- | `headerLanguageToggled` | An event that emits to other components that the language toggle button has been toggled. | `CustomEvent<HeaderLanguageToggleEventDetails>` |
25
- | `setAppLanguage` | An event to set the Document's HTML lang property, and emit the toggled language to other components. | `CustomEvent<string>` |
22
+ | Event | Description | Type |
23
+ | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------- |
24
+ | `headerLanguageToggled` | Event that fires when the language toggle is pressed/clicked. The event contains the oldLanguage along with the newLanguage. | `CustomEvent<HeaderLanguageToggleEventDetails>` |
25
+ | `setAppLanguage` | Event that fires during the setAppLanguageHandler() method. The event contains the current language (after language logic has already occurred). | `CustomEvent<"en" \| "fr">` |
26
26
 
27
27
  ## Dependencies
28
28
 
@@ -3,7 +3,7 @@
3
3
  exports[`ontario-language-toggle snapshot should render the expected html 1`] = `
4
4
  <ontario-language-toggle>
5
5
  <mock:shadow-root>
6
- <a aria-label="Click to switch language to French" class="ontario-language-toggler ontario-language-toggler--default" href="#">
6
+ <a aria-label="Cliquez pour changer la langue en français" class="ontario-language-toggler ontario-language-toggler--default" href="#" hreflang="fr" lang="fr">
7
7
  <abbr class="ontario-show-for-small-only" title="Français">
8
8
  FR
9
9
  </abbr>
@@ -1,5 +1,8 @@
1
1
  import { newSpecPage } from '@stencil/core/testing';
2
2
  import { OntarioLanguageToggle } from '../ontario-language-toggle';
3
+ import { mutationObserverMock } from '../../../utils/tests/mutation-observer.mock';
4
+
5
+ global.MutationObserver = mutationObserverMock;
3
6
 
4
7
  describe('ontario-language-toggle', () => {
5
8
  describe('snapshot', () => {
@@ -22,7 +25,7 @@ describe('ontario-language-toggle', () => {
22
25
  expect(page.root).toEqualHtml(`
23
26
  <ontario-language-toggle>
24
27
  <mock:shadow-root>
25
- <a aria-label="Click to switch language to French" class="ontario-language-toggler ontario-language-toggler--default" href="#">
28
+ <a aria-label="Cliquez pour changer la langue en français" class="ontario-language-toggler ontario-language-toggler--default" href="#" hreflang="fr" lang="fr">
26
29
  <abbr class="ontario-show-for-small-only" title="Français">
27
30
  FR
28
31
  </abbr>
@@ -36,7 +39,18 @@ describe('ontario-language-toggle', () => {
36
39
  expect(page.rootInstance.size).toBe('default');
37
40
  });
38
41
 
39
- it('should render a default language of English if no language prop is passed', async () => {
42
+ /**
43
+ * TODO: Determine if this is testable.
44
+ *
45
+ * Not sure how to properly test against this, seems to be a race condition.
46
+ *
47
+ * Takes a few processes before the html lang attribute is updated.
48
+ *
49
+ * Using setTimeout() leads to a false positive.
50
+ *
51
+ * Using page.waitForChanges() or autoApplyChanges: true seem to have no effect.
52
+ */
53
+ it.skip('should render a default language of English on the <html> tag if no language prop is passed', async () => {
40
54
  const page = await newSpecPage({
41
55
  components: [OntarioLanguageToggle],
42
56
  html: `<ontario-language-toggle></ontario-language-toggle>`,
@@ -54,7 +68,7 @@ describe('ontario-language-toggle', () => {
54
68
  expect(page.root).toEqualHtml(`
55
69
  <ontario-language-toggle size="small" url="/en" language="fr">
56
70
  <mock:shadow-root>
57
- <a aria-label="Cliquez pour changer de langue en anglais" class="ontario-language-toggler ontario-language-toggler--small" href="/en">
71
+ <a aria-label="Click to switch the language to English" class="ontario-language-toggler ontario-language-toggler--small" href="/en" hreflang="en" lang="en">
58
72
  <span>
59
73
  English
60
74
  </span>
@@ -19,7 +19,6 @@
19
19
  $ontario-radios-size: 32px;
20
20
  $ontario-radios-size-mobile: 36px;
21
21
  $ontario-input-offset: math.div((globalVariables.$touch-target-size - $ontario-radios-size), 2);
22
- $ontario-input-border-width: 0.125rem;
23
22
 
24
23
  .ontario-radios__item {
25
24
  position: relative;
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="none"><path d="M19 6.4L17.6 5 12 10.6 6.4 5 5 6.4l5.6 5.6L5 17.6 6.4 19l5.6-5.6 5.6 5.6 1.4-1.4-5.6-5.6L19 6.4z" fill="#000"/></svg>
@@ -0,0 +1,6 @@
1
+ <svg width="46" height="46" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 46 46" fill="none" xmlns:v="https://vecta.io/nano" tabindex="-1">
2
+ <path d="M23 0C7.36 0 0 7.36 0 23s7.36 23 23 23 23-7.36 23-23S38.64 0 23 0" fill="#fff" />
3
+ <path fill-rule="evenodd"
4
+ d="M23 13.223c4.728-3.178 10.58-3.613 15.69-1.153l.18.128-.026.18a16.08 16.08 0 0 1-2.07 6.765c-1.405 2.41-3.4 4.408-5.8 5.79h-.025a15.71 15.71 0 0 0-.365.191c-.188.1-.38.203-.58.296.383 5.69-2.172 10.994-6.85 14.197L23 39.72l-.153-.102a15.76 15.76 0 0 1-4.805-5.176 16.12 16.12 0 0 1-2.095-7.944v-.026c0-.333.025-.692.05-1.05-5.086-2.51-8.382-7.38-8.817-13.043l-.026-.18.153-.077c2.147-1.05 4.523-1.59 6.874-1.59 2.786 0 5.494.743 7.897 2.127h.026a17.21 17.21 0 0 1 .895.564zm5.93 8.56c1.763-1.025 3.27-2.46 4.37-4.33.51-.897.894-1.82 1.176-2.69-2.888-.666-5.8-.23-8.433 1.204.23.307.383.64.537 1.076s.18 1.025.05 1.512c-.05.205-.153.4-.256.615h0c-.51.87-1.584 1.512-2.913 1.922.51-1.59-.307-2.998-1.33-3.895-.51-.46-1.1-.846-1.687-1.204a12.29 12.29 0 0 0-5.929-1.614 12.52 12.52 0 0 0-2.964.359c.894 2.844 2.71 5.15 5.265 6.714.153-.36.358-.64.664-1s.792-.666 1.278-.794a2.94 2.94 0 0 1 .664-.077c.997 0 2.096.615 3.118 1.563-1.6.36-2.428 1.768-2.683 3.1-.128.692-.204 1.384-.204 2.076 0 2.024.486 4.075 1.56 5.945.486.87 1.125 1.69 1.79 2.383 2.02-2.204 3.092-4.946 3.17-7.944-.41.05-.74 0-1.2-.077s-.97-.384-1.33-.718c-.153-.154-.307-.333-.41-.538-.51-.897-.51-2.153-.204-3.51 1.124 1.23 2.734 1.256 4.012.794a10.52 10.52 0 0 0 1.891-.871z"
5
+ fill="#000" />
6
+ </svg>
@@ -0,0 +1,141 @@
1
+ @use 'sass:math';
2
+ @use '@ongov/ontario-design-system-global-styles/dist/styles/scss/1-variables/global.variables' as globalVariables;
3
+ @use '@ongov/ontario-design-system-global-styles/dist/styles/scss/1-variables/spacing.variables' as spacing;
4
+ @use '@ongov/ontario-design-system-global-styles/dist/styles/scss/1-variables/colours.variables' as colours;
5
+ @use '@ongov/ontario-design-system-global-styles/dist/styles/scss/1-variables/breakpoints.variables' as breakpoints;
6
+ @use '@ongov/ontario-design-system-global-styles/dist/styles/scss/1-variables/typography.variables' as typography;
7
+ @use '@ongov/ontario-design-system-global-styles/dist/styles/scss/1-variables/line-heights.variables' as lineheight;
8
+ @use '@ongov/ontario-design-system-global-styles/dist/styles/scss/1-variables/font-weights.variables' as fontWeights;
9
+ @use '@ongov/ontario-design-system-global-styles/dist/styles/scss/2-tools/functions/global.functions' as globalFunctions;
10
+ @use '@ongov/ontario-design-system-global-styles/dist/styles/scss/2-tools/placeholder/focus.placeholders' as
11
+ focusPlaceholders;
12
+ @use '@ongov/ontario-design-system-global-styles/dist/styles/scss/4-elements/_global.elements.scss';
13
+ @use '../../styles/form.scss';
14
+
15
+ $ontario-input-height: globalFunctions.px-to-rem(48);
16
+ $ontario-search-icon-size: 2rem;
17
+ $ontario-reset-icon-size: 1.5rem;
18
+ $ontario-search-button-width: 5rem;
19
+ $ontario-search-button-width--mobile: 3rem;
20
+ $ontario-search-input-padding: 8.5rem;
21
+ $ontario-search-input-padding--mobile: 7.75rem;
22
+ $ontario-search-desktop-width: 34rem;
23
+ $ontario-search-mobile-width: 20.5rem;
24
+
25
+ .ontario-search__container {
26
+ max-width: $ontario-search-desktop-width;
27
+ margin-bottom: spacing.$spacing-7;
28
+ }
29
+
30
+ .ontario-search__input-container {
31
+ position: relative;
32
+ }
33
+
34
+ .ontario-search__input.ontario-input {
35
+ border: 2px solid colours.$ontario-colour-black;
36
+ margin-bottom: spacing.$spacing-0;
37
+ height: $ontario-input-height;
38
+ padding-left: spacing.$spacing-3;
39
+ padding-right: $ontario-search-input-padding;
40
+ width: 100%;
41
+
42
+ &:invalid + input[type='reset'] {
43
+ display: none;
44
+ }
45
+
46
+ &:focus {
47
+ @extend %ontario-focus;
48
+ }
49
+ }
50
+
51
+ input[type='reset'].ontario-search__reset {
52
+ position: absolute;
53
+ display: flex;
54
+ align-items: center;
55
+ top: spacing.$spacing-3;
56
+ right: $ontario-search-button-width + spacing.$spacing-4;
57
+ height: $ontario-reset-icon-size;
58
+ width: $ontario-reset-icon-size;
59
+ color: colours.$ontario-colour-black;
60
+ margin: spacing.$spacing-0;
61
+ padding: spacing.$spacing-1;
62
+ background-size: $ontario-reset-icon-size;
63
+ background-image: url(data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIgZmlsbD0ibm9uZSI+PHBhdGggZD0iTTE5IDYuNEwxNy42IDUgMTIgMTAuNiA2LjQgNSA1IDYuNGw1LjYgNS42TDUgMTcuNiA2LjQgMTlsNS42LTUuNiA1LjYgNS42IDEuNC0xLjQtNS42LTUuNkwxOSA2LjR6IiBmaWxsPSIjMDAwIi8+PC9zdmc+);
64
+ background-position: center center;
65
+ background-repeat: no-repeat;
66
+ background-color: transparent;
67
+ outline: none;
68
+ border: none;
69
+ cursor: pointer;
70
+
71
+ &:focus {
72
+ box-shadow: inset 0 0 0 globalVariables.$global-radius colours.$ontario-colour-focus;
73
+ }
74
+
75
+ @media screen and (max-width: breakpoints.$small-breakpoint) {
76
+ right: $ontario-search-button-width--mobile + spacing.$spacing-7;
77
+ }
78
+ }
79
+
80
+ .ontario-search__submit {
81
+ border: 0;
82
+ border-radius: 0 3px 3px 0;
83
+ background-color: colours.$ontario-colour-link;
84
+ color: colours.$ontario-colour-black;
85
+
86
+ display: flex;
87
+ justify-content: center;
88
+ align-items: center;
89
+
90
+ font-family: typography.$ontario-font-open-sans;
91
+ font-weight: fontWeights.$ontario-font-weights-semi-bold;
92
+ font-size: 1.125rem;
93
+ width: $ontario-search-button-width;
94
+ line-height: lineheight.$ontario-line-height-8;
95
+
96
+ position: absolute;
97
+ right: spacing.$spacing-0;
98
+ bottom: spacing.$spacing-0;
99
+ top: spacing.$spacing-0;
100
+ cursor: pointer;
101
+
102
+ &:hover {
103
+ background-color: colours.$ontario-colour-link--hover;
104
+ color: colours.$ontario-colour-white;
105
+ }
106
+
107
+ &:focus {
108
+ outline: none;
109
+ box-shadow: 0 0 0 globalVariables.$global-radius colours.$ontario-colour-focus;
110
+ background-color: colours.$ontario-colour-link--hover;
111
+ color: colours.$ontario-colour-white;
112
+ }
113
+
114
+ &:active {
115
+ background-color: colours.$ontario-colour-link--active;
116
+ color: colours.$ontario-colour-white;
117
+ }
118
+
119
+ svg {
120
+ fill: colours.$ontario-colour-white;
121
+ margin-right: spacing.$spacing-0;
122
+ margin-bottom: spacing.$spacing-0;
123
+ width: $ontario-search-icon-size;
124
+ height: $ontario-search-icon-size;
125
+ display: inline-block;
126
+ vertical-align: middle;
127
+ overflow: hidden;
128
+ }
129
+
130
+ @media screen and (max-width: breakpoints.$small-breakpoint) {
131
+ width: $ontario-search-button-width--mobile;
132
+ }
133
+ }
134
+
135
+ // remove default cancel button for input with type="search"
136
+ input[type='search'].ontario-search__input::-webkit-search-decoration,
137
+ input[type='search'].ontario-search__input::-webkit-search-cancel-button,
138
+ input[type='search'].ontario-search__input::-webkit-search-results-button,
139
+ input[type='search'].ontario-search__input::-webkit-search-results-decoration {
140
+ -webkit-appearance: none;
141
+ }