@avakhula/ui 0.0.10

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 (194) hide show
  1. package/.babelrc.json +14 -0
  2. package/.eslintrc.cjs +15 -0
  3. package/.nvmrc +1 -0
  4. package/.prettierrc.json +1 -0
  5. package/.storybook/intelliboardTheme.js +10 -0
  6. package/.storybook/main.js +25 -0
  7. package/.storybook/manager.js +7 -0
  8. package/.storybook/preview-head.html +11 -0
  9. package/.storybook/preview.js +24 -0
  10. package/.storybook/scss-loader.scss +6 -0
  11. package/.storybook/withSource.js +97 -0
  12. package/README.md +35 -0
  13. package/dist/favicon.ico +0 -0
  14. package/dist/index.mjs +19366 -0
  15. package/dist/index.umd.js +209 -0
  16. package/dist/style.css +1 -0
  17. package/index.html +21 -0
  18. package/package.json +63 -0
  19. package/public/favicon.ico +0 -0
  20. package/src/App.vue +37 -0
  21. package/src/EventEmmiter.js +19 -0
  22. package/src/assets/scss/mixins/dropdown-list-item.scss +45 -0
  23. package/src/assets/scss/mixins/tooltip-position.scss +147 -0
  24. package/src/assets/scss/mixins.scss +21 -0
  25. package/src/assets/scss/reset.scss +12 -0
  26. package/src/assets/scss/style.scss +73 -0
  27. package/src/assets/scss/typography.scss +155 -0
  28. package/src/assets/scss/variables/colors.scss +115 -0
  29. package/src/assets/scss/variables/shadows.scss +17 -0
  30. package/src/components/Accordion/Accordion.scss +94 -0
  31. package/src/components/Accordion/Accordion.stories.js +41 -0
  32. package/src/components/Accordion/Accordion.vue +104 -0
  33. package/src/components/Accordion/readme.mdx +38 -0
  34. package/src/components/Alert/Alert.stories.js +69 -0
  35. package/src/components/Alert/Alert.vue +131 -0
  36. package/src/components/Alert/alert.scss +166 -0
  37. package/src/components/Alert/constants.js +6 -0
  38. package/src/components/Alert/readme.mdx +63 -0
  39. package/src/components/Badge/Badge.stories.js +53 -0
  40. package/src/components/Badge/Badge.vue +58 -0
  41. package/src/components/Badge/readme.mdx +38 -0
  42. package/src/components/Breadcrumbs/Breadcrumbs.vue +98 -0
  43. package/src/components/Breadcrumbs/breadcrumbs.scss +77 -0
  44. package/src/components/Breadcrumbs/breadcrumbs.stories.js +37 -0
  45. package/src/components/Button/Button.stories.js +124 -0
  46. package/src/components/Button/Button.vue +165 -0
  47. package/src/components/Button/button.scss +217 -0
  48. package/src/components/Button/constants.js +8 -0
  49. package/src/components/Button/readme.mdx +118 -0
  50. package/src/components/ButtonGroup/ButtonGroup.stories.js +27 -0
  51. package/src/components/ButtonGroup/ButtonGroup.vue +24 -0
  52. package/src/components/ButtonGroup/readme.mdx +10 -0
  53. package/src/components/Dropdown/Dropdown.spec.js +90 -0
  54. package/src/components/Dropdown/Dropdown.stories.js +48 -0
  55. package/src/components/Dropdown/Dropdown.vue +313 -0
  56. package/src/components/Dropdown/DropdownDivider.vue +15 -0
  57. package/src/components/Dropdown/DropdownItem.vue +59 -0
  58. package/src/components/Dropdown/DropdownList.stories.js +174 -0
  59. package/src/components/Dropdown/DropdownList.vue +93 -0
  60. package/src/components/Dropdown/constants.js +10 -0
  61. package/src/components/Dropdown/readme.mdx +88 -0
  62. package/src/components/Form/CharactersCount.vue +55 -0
  63. package/src/components/Form/Checkbox/Checkbox.scss +226 -0
  64. package/src/components/Form/Checkbox/Checkbox.stories.js +63 -0
  65. package/src/components/Form/Checkbox/Checkbox.vue +128 -0
  66. package/src/components/Form/Checkbox/readme.mdx +69 -0
  67. package/src/components/Form/CheckboxGroup/CheckboxGroup.stories.js +64 -0
  68. package/src/components/Form/CheckboxGroup/CheckboxGroup.vue +87 -0
  69. package/src/components/Form/CheckboxGroup/readme.mdx +56 -0
  70. package/src/components/Form/DatePicker/DatePicker.scss +479 -0
  71. package/src/components/Form/DatePicker/DatePicker.stories.js +78 -0
  72. package/src/components/Form/DatePicker/DatePicker.vue +284 -0
  73. package/src/components/Form/DatePicker/Icons/chevron-back.js +5 -0
  74. package/src/components/Form/DatePicker/Icons/chevron-forward.js +5 -0
  75. package/src/components/Form/DatePicker/readme.mdx +115 -0
  76. package/src/components/Form/FormGroup/FormGroup.stories.js +48 -0
  77. package/src/components/Form/FormGroup/FormGroup.vue +61 -0
  78. package/src/components/Form/FormGroup/FormGroupSet.stories.js +32 -0
  79. package/src/components/Form/FormGroup/FormGroupSet.vue +75 -0
  80. package/src/components/Form/Input/Input.stories.js +137 -0
  81. package/src/components/Form/Input/Input.vue +231 -0
  82. package/src/components/Form/Input/constants.js +5 -0
  83. package/src/components/Form/Input/input.scss +133 -0
  84. package/src/components/Form/Input/readme.mdx +68 -0
  85. package/src/components/Form/Label/Label.stories.js +29 -0
  86. package/src/components/Form/Label/Label.vue +87 -0
  87. package/src/components/Form/Label/readme.mdx +25 -0
  88. package/src/components/Form/PhoneInput/PhoneInput.stories.js +43 -0
  89. package/src/components/Form/PhoneInput/PhoneInput.vue +105 -0
  90. package/src/components/Form/PhoneInput/phoneInput.scss +197 -0
  91. package/src/components/Form/PhoneInput/readme.mdx +37 -0
  92. package/src/components/Form/Radio/Radio.stories.js +34 -0
  93. package/src/components/Form/Radio/Radio.vue +109 -0
  94. package/src/components/Form/Radio/radio.scss +187 -0
  95. package/src/components/Form/Radio/readme.mdx +48 -0
  96. package/src/components/Form/TextEditor/TextEditor.stories.js +58 -0
  97. package/src/components/Form/TextEditor/TextEditor.vue +305 -0
  98. package/src/components/Form/TextEditor/icons/svg/chevron-down.svg +3 -0
  99. package/src/components/Form/TextEditor/icons/toolbarIcons.js +111 -0
  100. package/src/components/Form/TextEditor/plugins/alphabetList.js +43 -0
  101. package/src/components/Form/TextEditor/readme.mdx +59 -0
  102. package/src/components/Form/TextEditor/textEditor.scss +684 -0
  103. package/src/components/Form/Textarea/Textarea.spec.js +107 -0
  104. package/src/components/Form/Textarea/Textarea.stories.js +68 -0
  105. package/src/components/Form/Textarea/Textarea.vue +102 -0
  106. package/src/components/Form/Textarea/readme.mdx +45 -0
  107. package/src/components/Form/Textarea/textarea.scss +84 -0
  108. package/src/components/Form/Toggle/Toggle.stories.js +44 -0
  109. package/src/components/Form/Toggle/Toggle.vue +122 -0
  110. package/src/components/Form/Toggle/readme.mdx +39 -0
  111. package/src/components/Form/Toggle/toggle.scss +166 -0
  112. package/src/components/Icon.vue +41 -0
  113. package/src/components/IconButton/IconButton.scss +91 -0
  114. package/src/components/IconButton/IconButton.stories.js +115 -0
  115. package/src/components/IconButton/IconButton.vue +100 -0
  116. package/src/components/IconButton/constants.js +14 -0
  117. package/src/components/IconButton/readme.mdx +66 -0
  118. package/src/components/List.vue +150 -0
  119. package/src/components/Modal/Modal.stories.js +48 -0
  120. package/src/components/Modal/Modal.vue +231 -0
  121. package/src/components/Modal/readme.mdx +76 -0
  122. package/src/components/Pagination/LimitSelector.vue +73 -0
  123. package/src/components/Pagination/Pagination.stories.js +54 -0
  124. package/src/components/Pagination/Pagination.vue +227 -0
  125. package/src/components/Pagination/pagination.scss +189 -0
  126. package/src/components/Popover/Popover.stories.js +46 -0
  127. package/src/components/Popover/Popover.vue +81 -0
  128. package/src/components/Popover/constants.js +14 -0
  129. package/src/components/Popover/popover.scss +26 -0
  130. package/src/components/Popover/readme.mdx +42 -0
  131. package/src/components/ProgressBar/ProgressBar.stories.js +90 -0
  132. package/src/components/ProgressBar/ProgressBar.vue +58 -0
  133. package/src/components/ProgressBar/constants.js +6 -0
  134. package/src/components/ProgressBar/progressBar.scss +116 -0
  135. package/src/components/ProgressBar/readme.mdx +67 -0
  136. package/src/components/Sorting/Sorting.stories.js +35 -0
  137. package/src/components/Sorting/Sorting.vue +128 -0
  138. package/src/components/Sorting/constants.js +10 -0
  139. package/src/components/Sorting/sorting.scss +87 -0
  140. package/src/components/SplitButton/SplitButton.stories.js +39 -0
  141. package/src/components/SplitButton/SplitButton.vue +132 -0
  142. package/src/components/SplitButton/SplitButtonItem.vue +34 -0
  143. package/src/components/SplitButton/constants.js +4 -0
  144. package/src/components/SplitButton/readme.mdx +77 -0
  145. package/src/components/SplitButton/splitButton.scss +161 -0
  146. package/src/components/StatusIndicator/StatusIndicator.stories.js +40 -0
  147. package/src/components/StatusIndicator/StatusIndicator.vue +52 -0
  148. package/src/components/StatusIndicator/constants.js +10 -0
  149. package/src/components/StatusIndicator/icons.js +48 -0
  150. package/src/components/StatusIndicator/readme.mdx +21 -0
  151. package/src/components/Table/Cells/Cell.vue +71 -0
  152. package/src/components/Table/Cells/CheckboxCell.vue +48 -0
  153. package/src/components/Table/Row.vue +26 -0
  154. package/src/components/Table/Table.stories.js +59 -0
  155. package/src/components/Table/Table.vue +36 -0
  156. package/src/components/Tabs/Tab.vue +37 -0
  157. package/src/components/Tabs/TabDropdown.vue +93 -0
  158. package/src/components/Tabs/Tabs.stories.js +57 -0
  159. package/src/components/Tabs/Tabs.vue +94 -0
  160. package/src/components/Tabs/tabs.scss +157 -0
  161. package/src/components/TagPill/TagPill.stories.js +30 -0
  162. package/src/components/TagPill/TagPill.vue +133 -0
  163. package/src/components/TagPill/constants.js +9 -0
  164. package/src/components/TagPill/readme.mdx +37 -0
  165. package/src/components/ToggleTip/ToggleTip.stories.js +98 -0
  166. package/src/components/ToggleTip/ToggleTip.vue +112 -0
  167. package/src/components/ToggleTip/constants.js +14 -0
  168. package/src/components/ToggleTip/readme.mdx +46 -0
  169. package/src/components/ToggleTip/toggleTip.scss +55 -0
  170. package/src/components/Tooltip/Tooltip.stories.js +56 -0
  171. package/src/components/Tooltip/Tooltip.vue +49 -0
  172. package/src/components/Tooltip/readme.mdx +43 -0
  173. package/src/components/TreeSelect/Option.vue +325 -0
  174. package/src/components/TreeSelect/Select.stories.js +349 -0
  175. package/src/components/TreeSelect/Select.vue +909 -0
  176. package/src/components/TreeSelect/TreeSelect.stories.js +270 -0
  177. package/src/components/TreeSelect/scss/option.scss +204 -0
  178. package/src/components/TreeSelect/scss/select.scss +166 -0
  179. package/src/constants/events.js +2 -0
  180. package/src/constants/keyCodes.js +8 -0
  181. package/src/directives/outside/outside.js +81 -0
  182. package/src/directives/outside/outside.stories.js +29 -0
  183. package/src/directives/outside/readme.mdx +24 -0
  184. package/src/helpers/generateUID.js +3 -0
  185. package/src/helpers/getHrefFromID.js +3 -0
  186. package/src/helpers/multiLineOverflows.js +3 -0
  187. package/src/helpers/removeEvents.js +9 -0
  188. package/src/index.js +49 -0
  189. package/src/main.js +12 -0
  190. package/src/stories/link.readme.mdx +57 -0
  191. package/src/stories/link.stories.js +59 -0
  192. package/static/Logo.svg +25 -0
  193. package/static/docks/button.pdf +147566 -0
  194. package/vite.config.js +47 -0
@@ -0,0 +1,107 @@
1
+ import { mount } from "@vue/test-utils";
2
+ import { describe, it, expect } from "vitest";
3
+ import Textarea from "./Textarea.vue";
4
+
5
+ const ERROR_CLASS = "error";
6
+ const CHARACTER_COUNT_CLASS = "character-count";
7
+ const VAL_LENGTH_CLASS = "val-length";
8
+ const CHARACTER_LIMIT_CLASS = "val-limit";
9
+ const VALUE_OVER_LIMIT_CLASS = "character-count";
10
+
11
+ const createComponent = (props = {}, slots) => {
12
+ return mount(Textarea, {
13
+ slots: slots,
14
+ propsData: props,
15
+ attachTo: document.body,
16
+ });
17
+ };
18
+
19
+ describe("Textarea", () => {
20
+ it("Default", () => {
21
+ const wrapper = createComponent();
22
+
23
+ expect(wrapper.find("textarea").exists()).toBe(true);
24
+ expect(wrapper.find(VAL_LENGTH_CLASS).exists()).toBe(false);
25
+ expect(wrapper.find(CHARACTER_LIMIT_CLASS).exists()).toBe(false);
26
+ });
27
+
28
+ it("disables textarea when disabled prop is true", () => {
29
+ const wrapper = createComponent({ disabled: true });
30
+ expect(wrapper.find("textarea").isDisabled()).toBe(true);
31
+ });
32
+
33
+ it("adds error class when error prop is true", () => {
34
+ const wrapper = createComponent({ error: true });
35
+ expect(wrapper.find("textarea").classes()).toContain(ERROR_CLASS);
36
+ });
37
+
38
+ it("displays error message when errorMessage is set", () => {
39
+ const errorMessage = "This is an error message";
40
+ const wrapper = createComponent({ errorMessage });
41
+
42
+ const alert = wrapper.findComponent({ name: "IbAlert" });
43
+ expect(alert.exists()).toBe(true);
44
+ expect(alert.text()).toBe(errorMessage);
45
+ expect(wrapper.find("textarea").classes()).toContain(ERROR_CLASS);
46
+ });
47
+
48
+ it("emits input event with the updated value when user types", async () => {
49
+ const VALUE = "test";
50
+ const wrapper = createComponent();
51
+
52
+ const textarea = wrapper.find("textarea");
53
+ await textarea.setValue(VALUE);
54
+
55
+ expect(wrapper.emitted("input")).toBeTruthy();
56
+ expect(wrapper.emitted().input[0]).toEqual([VALUE]);
57
+ });
58
+
59
+ it('emits "blur" event with input value on blur', () => {
60
+ const wrapper = createComponent();
61
+
62
+ const textarea = wrapper.find("textarea");
63
+ const inputText = "testing";
64
+
65
+ textarea.setValue(inputText);
66
+ textarea.trigger("blur");
67
+ expect(wrapper.emitted("blur")).toBeTruthy();
68
+ expect(wrapper.emitted("blur")[0]).toEqual([inputText]);
69
+ });
70
+
71
+ it("limits the number of characters to the provided characterLimit", async () => {
72
+ const VALUE = "test";
73
+ const VALUE_OVER_LIMIT = "test_test_test_test";
74
+
75
+ const LIMIT = 10;
76
+ const wrapper = createComponent({ characterLimit: LIMIT });
77
+ const textarea = wrapper.find("textarea");
78
+
79
+ const characterCountNode = wrapper.find(`.${CHARACTER_COUNT_CLASS}`);
80
+ let characterLimitNode = wrapper.find(`.${CHARACTER_LIMIT_CLASS}`);
81
+ let valueNode = wrapper.find(`.${VAL_LENGTH_CLASS}`);
82
+
83
+ expect(characterCountNode.exists()).toBe(true);
84
+ expect(characterLimitNode.exists()).toBe(true);
85
+ expect(characterLimitNode.html()).toContain(LIMIT);
86
+
87
+ expect(valueNode.exists()).toBe(false);
88
+
89
+ await textarea.setValue(VALUE);
90
+
91
+ valueNode = wrapper.find(`.${VAL_LENGTH_CLASS}`);
92
+ expect(valueNode.exists()).toBe(true);
93
+ expect(valueNode.text()).toBe(
94
+ (LIMIT - textarea.element.value.length).toString()
95
+ );
96
+
97
+ await textarea.setValue(VALUE_OVER_LIMIT);
98
+ const characterOverLimitNode = wrapper.find(`.${VALUE_OVER_LIMIT_CLASS}`);
99
+ characterLimitNode = wrapper.find(`.${CHARACTER_LIMIT_CLASS}`);
100
+
101
+ expect(characterLimitNode.exists()).toBe(false);
102
+ expect(characterOverLimitNode.exists()).toBe(true);
103
+ expect(characterOverLimitNode.text()).toBe(
104
+ (LIMIT - textarea.element.value.length).toString()
105
+ );
106
+ });
107
+ });
@@ -0,0 +1,68 @@
1
+ import IbTextarea from "./Textarea.vue";
2
+ import IbFormGroup from "../FormGroup/FormGroup.vue";
3
+ import IbLabel from "../Label/Label.vue";
4
+ import readme from "./readme.mdx";
5
+ export default {
6
+ title: "Form/Textarea",
7
+ component: IbTextarea,
8
+ parameters: {
9
+ docs: {
10
+ page: readme,
11
+ },
12
+ },
13
+ };
14
+
15
+ const Template = (args) => ({
16
+ components: { IbTextarea },
17
+ setup() {
18
+ return { args };
19
+ },
20
+ template: '<ib-textarea placeholder="Placeholder text" v-bind="args" />',
21
+ });
22
+
23
+ export const Default = Template.bind({});
24
+ Default.decorators = [
25
+ () => ({
26
+ template:
27
+ '<div style="display: flex; align-items:center; justify-content: center; width: 400px; height: 400px; margin: 0 auto"><story /></div>',
28
+ }),
29
+ ];
30
+ const TemplateWidthContent = (args) => ({
31
+ components: { IbTextarea },
32
+ setup() {
33
+ return { args };
34
+ },
35
+ template: '<ib-textarea value="Sample content" v-bind="args" />',
36
+ });
37
+
38
+ export const Disabled = TemplateWidthContent.bind({});
39
+ Disabled.args = {
40
+ disabled: true,
41
+ };
42
+ Disabled.decorators = [
43
+ () => ({
44
+ template:
45
+ '<div style="display: flex; align-items:center; justify-content: center; width: 400px; height: 400px; margin: 0 auto"><story /></div>',
46
+ }),
47
+ ];
48
+
49
+ const TemplateWidthFormGroup = (args) => ({
50
+ components: { IbTextarea, IbFormGroup, IbLabel },
51
+ setup() {
52
+ return { args };
53
+ },
54
+ template: `
55
+ <ib-form-group :disable="args.disabled" support-text="Supporting text">
56
+ <ib-label required id="description">Description</ib-label>
57
+ <ib-textarea required for="description" v-bind="args" placeholder="Placeholder Text" />
58
+ </ib-form-group>
59
+ `,
60
+ });
61
+
62
+ export const WidthFormGroup = TemplateWidthFormGroup.bind({});
63
+ WidthFormGroup.decorators = [
64
+ () => ({
65
+ template:
66
+ '<div style="display: flex; align-items:center; justify-content: center; width: 400px; height: 400px; margin: 0 auto"><story /></div>',
67
+ }),
68
+ ];
@@ -0,0 +1,102 @@
1
+ <template>
2
+ <div class="textarea-wrapper" :class="{ disabled: disabled }">
3
+ <ib-character-count
4
+ v-if="characterLimit"
5
+ :character-limit="characterLimit"
6
+ :character-length="val.length"
7
+ />
8
+
9
+ <ib-alert v-show="errorMessage.length">{{ errorMessage }}</ib-alert>
10
+ <ib-alert v-show="characterLimitErrorMessage.length && characterOverLimit">
11
+ {{ characterLimitErrorMessage }}
12
+ </ib-alert>
13
+
14
+ <textarea
15
+ v-bind="$attrs"
16
+ v-model="val"
17
+ @input="onInput"
18
+ @blur="onBlur"
19
+ class="ib-textarea"
20
+ :class="classes"
21
+ :disabled="disabled"
22
+ ></textarea>
23
+ </div>
24
+ </template>
25
+
26
+ <script>
27
+ import generateUID from "../../../helpers/generateUID";
28
+ import IbAlert from "../../Alert/Alert.vue";
29
+ import IbCharacterCount from "../CharactersCount.vue";
30
+
31
+ export default {
32
+ name: "IbTextarea",
33
+ props: {
34
+ disabled: {
35
+ type: Boolean,
36
+ default: false,
37
+ },
38
+ id: {
39
+ type: String,
40
+ default() {
41
+ return generateUID();
42
+ },
43
+ },
44
+ error: {
45
+ type: Boolean,
46
+ default: false,
47
+ },
48
+ characterLimit: {
49
+ type: Number,
50
+ default: null,
51
+ },
52
+ errorMessage: {
53
+ type: String,
54
+ default: "",
55
+ },
56
+ characterLimitErrorMessage: {
57
+ type: String,
58
+ default: "",
59
+ },
60
+ },
61
+ data() {
62
+ return {
63
+ val: "",
64
+ };
65
+ },
66
+ methods: {
67
+ onInput() {
68
+ if (!this.characterOverLimit) {
69
+ this.$emit("input", this.val);
70
+ }
71
+ },
72
+ onBlur() {
73
+ if (!this.characterOverLimit) {
74
+ this.$emit("blur", this.val);
75
+ }
76
+ },
77
+ },
78
+ computed: {
79
+ characterOverLimit() {
80
+ return !!this.characterLimit && this.val.length > this.characterLimit;
81
+ },
82
+ classes() {
83
+ const classList = ["ib-textarea"];
84
+
85
+ if (this.error || this.errorMessage.length || this.characterOverLimit) {
86
+ classList.push("error");
87
+ }
88
+
89
+ return classList;
90
+ },
91
+ },
92
+ components: {
93
+ IbAlert,
94
+ IbCharacterCount,
95
+ },
96
+ inheritAttrs: false,
97
+ };
98
+ </script>
99
+
100
+ <style lang="scss" scoped>
101
+ @import "./textarea.scss";
102
+ </style>
@@ -0,0 +1,45 @@
1
+ # IbTextArea
2
+
3
+ import { Story, Canvas } from "@storybook/addon-docs";
4
+
5
+ The IbTextarea component is a customizable textarea input that provides additional features such as character count and error messages. It can be used to receive and display large amounts of text input from the user.
6
+
7
+ ### Default
8
+
9
+ <Canvas>
10
+ <Story id="form-textarea--default" />
11
+ </Canvas>
12
+
13
+ ### Props
14
+
15
+ | Name | type | Default Value | Description |
16
+ | -------------------------- | ------- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ |
17
+ | disabled | Boolean | false | Disables the textarea. |
18
+ | id | String | auto-generated | Sets the unique ID for the textarea. |
19
+ | error | Boolean | false | Sets the textarea to an error state. |
20
+ | characterLimit | Number | null | Sets the character limit for the input. If set, the component will display the character count and limit the user input to the specified amount. |
21
+ | characterLimitErrorMessage | String | '' | Show error message to be displayed when the user has exceeded the character limit. |
22
+ | errorMessage | String | '' | Sets the textarea to an error state and show error message. |
23
+
24
+ ### Slots
25
+
26
+ This component has no slots.
27
+
28
+ ### Events
29
+
30
+ | Event name | Parameters | Description |
31
+ | ---------- | ---------- | --------------------------------------------------------------------------- |
32
+ | input | String | Emitted on every input change. The payload is the current input value. |
33
+ | blur | String | Emitted when the input loses focus. The payload is the current input value. |
34
+
35
+ ### Disabled
36
+
37
+ <Canvas>
38
+ <Story id="form-textarea--disabled" />
39
+ </Canvas>
40
+
41
+ ### Width Form Group
42
+
43
+ <Canvas>
44
+ <Story id="form-textarea--width-form-group" />
45
+ </Canvas>
@@ -0,0 +1,84 @@
1
+ @import "../../../assets/scss/variables/colors.scss";
2
+ @import "../../../assets/scss/mixins.scss";
3
+ @import "../../../assets/scss/typography.scss";
4
+
5
+ $textarea-bg: $gray-100;
6
+ $textarea-text-color: $neutral-900;
7
+ $textarea-border-color: $gray-500;
8
+ $textarea-placeholder-color: $neutral-600;
9
+ $textarea-disabled-text-color: $neutral-500;
10
+ $textarea-disabled-bg: $gray-100;
11
+ $textarea-disabled-border-color: $gray-500;
12
+ $textarea-hover-bg: $blue-100;
13
+ $textarea-hover-border-color: $blue-700;
14
+ $textarea-error-outline-color: $red-800;
15
+
16
+ .textarea-wrapper {
17
+ width: fit-content;
18
+ position: relative;
19
+
20
+ .character-count {
21
+ position: absolute;
22
+ right: 0;
23
+ bottom: calc(100% + 5px);
24
+ }
25
+
26
+ .ib-alert {
27
+ margin-bottom: 5px;
28
+ }
29
+
30
+ &.disabled {
31
+ .character-count {
32
+ color: $neutral-500;
33
+ }
34
+ }
35
+ }
36
+
37
+ textarea.ib-textarea {
38
+ @include Ib-H4-regular;
39
+ height: 80px;
40
+ min-height: 36px;
41
+ border: none;
42
+ background-color: $textarea-bg;
43
+ color: $textarea-text-color;
44
+ padding: 10px 15px;
45
+ resize: vertical;
46
+ border-radius: 4px 4px 0px 0px;
47
+ border-bottom: 1px solid $textarea-border-color;
48
+ transition: background-color 0.3s, border-color 0.3s, border-radius 0.3s,
49
+ color 0.3s;
50
+
51
+ &::placeholder {
52
+ @include Ib-H4-regular-italic;
53
+ color: $textarea-placeholder-color;
54
+ }
55
+
56
+ &:hover {
57
+ background-color: $textarea-hover-bg;
58
+ border-bottom-color: $textarea-hover-border-color;
59
+ }
60
+
61
+ &:focus {
62
+ border-radius: 4px;
63
+ border-bottom-color: transparent;
64
+ @include focus(0px);
65
+ }
66
+
67
+ &:disabled {
68
+ background-color: $textarea-disabled-bg;
69
+ color: $textarea-disabled-text-color;
70
+ border-bottom-color: $textarea-disabled-border-color;
71
+ cursor: not-allowed;
72
+ resize: none;
73
+
74
+ &::placeholder {
75
+ color: $textarea-disabled-text-color;
76
+ }
77
+ }
78
+
79
+ &.error {
80
+ border-radius: 4px;
81
+ border-bottom-color: transparent;
82
+ @include outline(0px, $textarea-error-outline-color);
83
+ }
84
+ }
@@ -0,0 +1,44 @@
1
+ import IbToggle from "./Toggle.vue";
2
+ import readme from "./readme.mdx";
3
+
4
+ export default {
5
+ title: "Form/Toggle",
6
+ component: IbToggle,
7
+ argTypes: {
8
+ onInput: {},
9
+ labelPosition: {
10
+ control: { type: "select" },
11
+ options: ["right", "left"],
12
+ },
13
+ },
14
+ parameters: {
15
+ docs: {
16
+ page: readme,
17
+ },
18
+ },
19
+ };
20
+
21
+ const Template = (args) => ({
22
+ components: { IbToggle },
23
+ setup() {
24
+ return { args };
25
+ },
26
+ template: "<ib-toggle style='width: fit-content;' v-bind='args'></ib-toggle>",
27
+ });
28
+
29
+ export const Default = Template.bind({});
30
+ Default.args = {
31
+ label: "Label",
32
+ };
33
+
34
+ export const HasTooltip = Template.bind({});
35
+ HasTooltip.args = {
36
+ helpMessage: "Enable pull requests",
37
+ };
38
+ // TODO: move this to storybook helpers
39
+ HasTooltip.decorators = [
40
+ () => ({
41
+ template:
42
+ '<div style="display: flex; align-items:center; justify-content: center; width: 400px; height: 400px; margin: 0 auto"><story /></div>',
43
+ }),
44
+ ];
@@ -0,0 +1,122 @@
1
+ <template>
2
+ <label
3
+ :class="classes"
4
+ @keypress.space.prevent="onChange"
5
+ :tabindex="disabled ? -1 : 0"
6
+ >
7
+ <div class="toggle-wrapper" ref="wrapper">
8
+ <div class="toggle" ref="toggle">
9
+ <input
10
+ tabindex="-1"
11
+ type="checkbox"
12
+ value="1"
13
+ :name="name"
14
+ :checked="checked"
15
+ :id="id"
16
+ :disabled="disabled"
17
+ @click="onChange"
18
+ @input.stop
19
+ />
20
+ <span class="toggle-slider round"></span>
21
+ <ib-icon class="checked-icon" name="checkmark"></ib-icon>
22
+ <ib-icon class="unchecked-icon" name="close" />
23
+ </div>
24
+ </div>
25
+
26
+ <span v-if="label.length" class="toggle-label">{{ label }}</span>
27
+ <ib-tooltip
28
+ v-if="helpMessage.length"
29
+ :text="
30
+ checked
31
+ ? helpMessage
32
+ : helpMessageOff.length
33
+ ? helpMessageOff
34
+ : helpMessage
35
+ "
36
+ ></ib-tooltip>
37
+ </label>
38
+ </template>
39
+
40
+ <script>
41
+ import generateUID from "../../../helpers/generateUID";
42
+ import IbIcon from "../../Icon.vue";
43
+ import IbTooltip from "../../Tooltip/Tooltip.vue";
44
+
45
+ export default {
46
+ name: "IbToggle",
47
+ model: {
48
+ prop: "isChecked",
49
+ event: "input",
50
+ },
51
+ props: {
52
+ isChecked: {
53
+ type: Boolean,
54
+ required: false,
55
+ },
56
+ id: {
57
+ type: String,
58
+ default: () => generateUID(),
59
+ },
60
+ disabled: {
61
+ type: Boolean,
62
+ default: false,
63
+ },
64
+ name: {
65
+ type: String,
66
+ default: "active",
67
+ },
68
+ label: {
69
+ type: String,
70
+ default: "",
71
+ },
72
+ error: {
73
+ type: Boolean,
74
+ default: false,
75
+ },
76
+ labelPosition: {
77
+ type: String,
78
+ default: "right",
79
+ },
80
+ helpMessage: {
81
+ type: String,
82
+ default: "",
83
+ },
84
+ helpMessageOff: {
85
+ type: String,
86
+ default: "",
87
+ },
88
+ },
89
+ watch: {
90
+ isChecked(value) {
91
+ this.checked = value;
92
+ },
93
+ },
94
+ data() {
95
+ return {
96
+ checked: this.isChecked,
97
+ };
98
+ },
99
+ methods: {
100
+ onChange() {
101
+ this.checked = !this.checked;
102
+ this.$emit("input", this.checked);
103
+ },
104
+ },
105
+ computed: {
106
+ classes() {
107
+ return {
108
+ "ib-toggle-container": true,
109
+ "has-error": this.error,
110
+ "toggle-on": this.checked,
111
+ "toggle-disabled": this.disabled,
112
+ "label-position-left": this.labelPosition === "left",
113
+ };
114
+ },
115
+ },
116
+ components: { IbIcon, IbTooltip },
117
+ };
118
+ </script>
119
+
120
+ <style lang="scss">
121
+ @import "./toggle.scss";
122
+ </style>
@@ -0,0 +1,39 @@
1
+ # IbToogle
2
+
3
+ import { Story, Canvas } from "@storybook/addon-docs";
4
+
5
+ A toggle is used to quickly switch between two possible states. They are commonly used for “on/off” switches.
6
+
7
+ ## Overview
8
+
9
+ Toggle is a control that is used to quickly switch between two possible states. Toggles are only used for these binary actions that occur immediately after the user “flips the switch”. They are commonly used for “on/off” switches.
10
+
11
+ ### Default
12
+
13
+ <Canvas>
14
+ <Story id="form-toggle--default" />
15
+ </Canvas>
16
+
17
+ ### Props
18
+
19
+ | Prop name | Type | Default | Description |
20
+ | -------------- | ------- | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
21
+ | isChecked | Boolean | false | The initial state of the toggle switch. |
22
+ | id | String | auto-generated unique ID | The ID of the toggle switch. |
23
+ | disabled | Boolean | auto-generated unique ID | Determines if a component is disabled. |
24
+ | name | String | 'active' | The name of the toggle switch. |
25
+ | label | String | '' | The label text that appears next to the toggle switch. |
26
+ | error | Nollean | false | Determines the toggle switch has an error state or not. |
27
+ | labelPosition | String | 'left' | The position of the label relative to the toggle switch. Possible values are "left" and "right". |
28
+ | helpMessage | String | '' | The help message that appears in the tooltip when the toggle switch is in the "on" state. |
29
+ | helpMessageOff | String | '' | The help message that appears in the tooltip when the toggle switch is in the "off" state. If this prop is not set, the helpMessage prop will be used instead. |
30
+
31
+ ### Slots
32
+
33
+ The component has no named slots, but you can place any content inside the component, and it will be displayed before or after the checkbox and the label, depending on the value of the labelPosition prop.
34
+
35
+ ### Events
36
+
37
+ | Event name | Parameters | Description |
38
+ | ---------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
39
+ | input | Boolean | The event emitted when the toggle is changes, and the checked state changes. The event is emitted with the new value of the checked property. |