@returnless/focus-ui 0.0.2 → 0.0.3

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 (186) hide show
  1. package/dist/focus-ui.js +10851 -0
  2. package/dist/focus-ui.umd.cjs +26 -0
  3. package/dist/style.css +1 -0
  4. package/package.json +11 -7
  5. package/src/build-utils/generate-component-meta.ts +5 -1
  6. package/src/build-utils/update-component-list.ts +1 -1
  7. package/src/components/Accordion/AccordionContent.vue +34 -5
  8. package/src/components/Accordion/AccordionItem.vue +5 -2
  9. package/src/components/Accordion/AccordionTrigger.vue +5 -2
  10. package/src/components/Accordion/README.md +1 -1
  11. package/src/components/ActionList/ActionList.vue +9 -0
  12. package/src/components/ActionList/ActionListBody.vue +11 -0
  13. package/src/components/ActionList/ActionListItem.vue +37 -0
  14. package/src/components/ActionList/ActionListSection.vue +7 -0
  15. package/src/components/ActionList/ActionListTrigger.vue +9 -0
  16. package/src/components/ActionList/README.md +113 -0
  17. package/src/components/ActionList/index.ts +5 -0
  18. package/src/components/Alert/Alert.vue +23 -10
  19. package/src/components/Alert/AlertDescription.vue +13 -1
  20. package/src/components/Alert/AlertTitle.vue +1 -1
  21. package/src/components/Alert/DismissableAlertButton.vue +6 -4
  22. package/src/components/Alert/README.md +31 -2
  23. package/src/components/Alert/index.ts +2 -0
  24. package/src/components/Alert/types.ts +1 -0
  25. package/src/components/AlertDialog/AlertDialog.vue +10 -1
  26. package/src/components/AlertDialog/AlertDialogActionButton.vue +9 -2
  27. package/src/components/AlertDialog/AlertDialogCancelButton.vue +1 -1
  28. package/src/components/AlertDialog/AlertDialogDescription.vue +7 -1
  29. package/src/components/AlertDialog/AlertDialogTitle.vue +11 -3
  30. package/src/components/AlertDialog/README.md +15 -16
  31. package/src/components/AspectRatio/AspectRatio.vue +19 -0
  32. package/src/components/AspectRatio/README.md +36 -0
  33. package/src/components/AspectRatio/index.ts +1 -0
  34. package/src/components/Avatar/Avatar.vue +57 -13
  35. package/src/components/Avatar/README.md +3 -9
  36. package/src/components/Badge/Badge.vue +1 -1
  37. package/src/components/Badge/README.md +9 -9
  38. package/src/components/BarChart/BarChart.vue +80 -0
  39. package/src/components/{MetricCard/MetricCardHeader.vue → BarChart/BarChartContainer.vue} +1 -1
  40. package/src/components/BarChart/BarChartStacked.vue +93 -0
  41. package/src/components/BarChart/README.md +83 -0
  42. package/src/components/BarChart/index.ts +3 -0
  43. package/src/components/Breadcrumbs/Breadcrumb.vue +7 -0
  44. package/src/components/Breadcrumbs/BreadcrumbEllipsis.vue +12 -0
  45. package/src/components/{MetricCard/MetricCardValue.vue → Breadcrumbs/BreadcrumbItem.vue} +2 -2
  46. package/src/components/Breadcrumbs/BreadcrumbLink.vue +13 -0
  47. package/src/components/Breadcrumbs/BreadcrumbList.vue +8 -0
  48. package/src/components/Breadcrumbs/BreadcrumbPage.vue +13 -0
  49. package/src/components/Breadcrumbs/BreadcrumbSeparator.vue +12 -0
  50. package/src/components/Breadcrumbs/README.md +91 -0
  51. package/src/components/Breadcrumbs/index.ts +7 -0
  52. package/src/components/Button/Button.vue +53 -41
  53. package/src/components/Button/ButtonContent.vue +1 -1
  54. package/src/components/Button/ButtonIcon.vue +28 -3
  55. package/src/components/Button/README.md +32 -29
  56. package/src/components/Button/index.ts +2 -0
  57. package/src/components/Button/types.ts +30 -0
  58. package/src/components/ButtonGroup/README.md +1 -1
  59. package/src/components/Card/CardHelp.vue +23 -0
  60. package/src/components/Card/CardSection.vue +17 -2
  61. package/src/components/Card/CardTitle.vue +6 -3
  62. package/src/components/Card/README.md +97 -10
  63. package/src/components/Card/index.ts +2 -1
  64. package/src/components/Checkbox/Checkbox.vue +29 -5
  65. package/src/components/Checkbox/README.md +34 -5
  66. package/src/components/DatePicker/DatePicker.vue +7 -27
  67. package/src/components/DatePicker/README.md +1 -1
  68. package/src/components/DescriptionList/DescriptionList.vue +1 -1
  69. package/src/components/DescriptionList/DescriptionListItem.vue +1 -1
  70. package/src/components/DescriptionList/README.md +2 -2
  71. package/src/components/Dialog/README.md +2 -0
  72. package/src/components/Dialog/index.ts +0 -0
  73. package/src/components/DropZone/DropZone.vue +105 -0
  74. package/src/components/DropZone/README.md +48 -0
  75. package/src/components/DropZone/index.ts +1 -0
  76. package/src/components/EmptyState/README.md +1 -1
  77. package/src/components/Feed/FeedItem.vue +4 -1
  78. package/src/components/Feed/FeedItemBlock.vue +4 -1
  79. package/src/components/Feed/README.md +1 -1
  80. package/src/components/FileUploadButton/FileUploadButton.vue +62 -0
  81. package/src/components/FileUploadButton/index.ts +1 -0
  82. package/src/components/Form/Form.vue +7 -2
  83. package/src/components/Form/README.md +1 -1
  84. package/src/components/FormLayout/FormLayout.vue +20 -2
  85. package/src/components/FormLayout/README.md +39 -1
  86. package/src/components/Heading/Heading.vue +32 -0
  87. package/src/components/Heading/index.ts +3 -0
  88. package/src/components/Heading/types.ts +3 -0
  89. package/src/components/Image/Image.vue +30 -0
  90. package/src/components/Image/index.ts +1 -0
  91. package/src/components/InertiaLink/InertiaLink.vue +11 -0
  92. package/src/components/InertiaLink/index.ts +1 -0
  93. package/src/components/InlineError/InlineError.vue +21 -0
  94. package/src/components/InlineError/README.md +63 -0
  95. package/src/components/InlineError/index.ts +1 -0
  96. package/src/components/KPICard/KPICard.vue +28 -0
  97. package/src/components/KPICard/KPICardSection.vue +30 -0
  98. package/src/components/KPICard/README.md +124 -0
  99. package/src/components/KPICard/index.ts +2 -0
  100. package/src/components/Legend/Legend.vue +7 -0
  101. package/src/components/Legend/LegendItem.vue +34 -0
  102. package/src/components/Legend/README.md +32 -0
  103. package/src/components/Legend/index.ts +2 -0
  104. package/src/components/Link/Link.vue +4 -4
  105. package/src/components/Link/README.md +1 -1
  106. package/src/components/Navigation/Navigation.vue +2 -2
  107. package/src/components/Navigation/NavigationItem.vue +14 -10
  108. package/src/components/Navigation/NavigationSecondarySection.vue +12 -0
  109. package/src/components/Navigation/NavigationSection.vue +1 -1
  110. package/src/components/Navigation/README.md +10 -15
  111. package/src/components/Navigation/index.ts +1 -0
  112. package/src/components/Page/Page.vue +2 -33
  113. package/src/components/Page/PageBody.vue +36 -0
  114. package/src/components/Page/PageTitle.vue +6 -3
  115. package/src/components/Page/README.md +45 -39
  116. package/src/components/Page/index.ts +1 -0
  117. package/src/components/Pagination/README.md +1 -1
  118. package/src/components/PinInput/README.md +1 -1
  119. package/src/components/Popover/Popover.vue +18 -0
  120. package/src/components/Popover/PopoverBody.vue +11 -0
  121. package/src/components/Popover/PopoverTrigger.vue +9 -0
  122. package/src/components/Popover/README.md +34 -6
  123. package/src/components/Popover/index.ts +3 -0
  124. package/src/components/Popper/Popper.vue +91 -0
  125. package/src/components/Popper/PopperBody.vue +19 -0
  126. package/src/components/Popper/PopperTrigger.vue +14 -0
  127. package/src/components/Popper/README.md +42 -0
  128. package/src/components/Popper/index.ts +3 -0
  129. package/src/components/ProgressBar/ProgressBar.vue +24 -6
  130. package/src/components/RadioButton/README.md +1 -1
  131. package/src/components/RadioButton/RadioButton.vue +3 -2
  132. package/src/components/ResourceList/README.md +160 -0
  133. package/src/components/ResourceList/ResourceList.vue +7 -0
  134. package/src/components/ResourceList/ResourceListItem.vue +7 -0
  135. package/src/components/ResourceList/ResourceListItemContent.vue +7 -0
  136. package/src/components/ResourceList/index.ts +3 -0
  137. package/src/components/Select/README.md +1 -1
  138. package/src/components/Select/Select.vue +1 -1
  139. package/src/components/Separator/README.md +5 -1
  140. package/src/components/Separator/Separator.vue +20 -3
  141. package/src/components/Spinner/README.md +1 -1
  142. package/src/components/Spinner/Spinner.vue +10 -4
  143. package/src/components/StatusIndicator/README.md +2 -2
  144. package/src/components/StatusIndicator/StatusIndicator.vue +11 -5
  145. package/src/components/Stepper/README.md +38 -0
  146. package/src/components/Stepper/Stepper.vue +104 -0
  147. package/src/components/Stepper/index.ts +1 -0
  148. package/src/components/Tabs/README.md +1 -1
  149. package/src/components/Tabs/TabTrigger.vue +5 -4
  150. package/src/components/Tabs/Tabs.vue +4 -1
  151. package/src/components/Tag/Tag.vue +45 -0
  152. package/src/components/Tag/index.ts +1 -0
  153. package/src/components/TextField/README.md +24 -6
  154. package/src/components/TextField/TextField.vue +25 -5
  155. package/src/components/TextField/TextFieldIcon.vue +19 -0
  156. package/src/components/TextStyle/README.md +1 -1
  157. package/src/components/TextStyle/TextStyle.vue +1 -1
  158. package/src/components/Toast/DismissToastAction.vue +1 -1
  159. package/src/components/Toast/README.md +1 -1
  160. package/src/components/Toggle/README.md +1 -1
  161. package/src/components/Toggle/Toggle.vue +8 -5
  162. package/src/components/Tooltip/README.md +1 -1
  163. package/src/components/Tooltip/Tooltip.vue +15 -41
  164. package/src/components/TopBar/TopBarSearch.vue +2 -2
  165. package/src/components/index.ts +68 -12
  166. package/src/components/types.ts +5 -0
  167. package/src/composables/useTheme.ts +13 -1
  168. package/src/composables/useToastNotifications.ts +1 -1
  169. package/src/composables/useUniqueId.ts +4 -3
  170. package/src/index.css +17 -13
  171. package/src/index.ts +0 -11
  172. package/dist/focus-ui.es.js +0 -33
  173. package/dist/types/components/Accordion/Accordion.vue.d.ts +0 -32
  174. package/dist/types/components/Accordion/AccordionItem.vue.d.ts +0 -2
  175. package/dist/types/components/Accordion/index.d.ts +0 -2
  176. package/dist/types/components/index.d.ts +0 -1
  177. package/dist/types/index.d.ts +0 -7
  178. package/src/components/CategoryBar/CategoryBar.vue +0 -25
  179. package/src/components/CategoryBar/CategoryBarItem.vue +0 -34
  180. package/src/components/CategoryBar/README.md +0 -17
  181. package/src/components/CategoryBar/index.ts +0 -2
  182. package/src/components/MetricCard/MetricCard.vue +0 -11
  183. package/src/components/MetricCard/MetricCardLabel.vue +0 -9
  184. package/src/components/MetricCard/MetricCardSection.vue +0 -11
  185. package/src/components/MetricCard/README.md +0 -53
  186. package/src/components/MetricCard/index.ts +0 -5
@@ -1,38 +1,7 @@
1
- <script lang="ts" setup>
2
- import { Component, computed, h, useSlots } from 'vue';
3
-
4
- const props = defineProps<{
5
- /** Navigation component to render in the left column */
6
- navigation?: Component;
7
- }>();
8
-
9
- const slots = useSlots();
10
-
11
- const hasNavigation = computed(() => props.navigation || !!slots['page-navigation']);
12
-
13
- const PageNavigation = props.navigation
14
- ? h(props.navigation)
15
- : h('div');
16
-
17
- const contentClassList = computed(() => {
18
- return hasNavigation.value ? 'col-span-9' : 'col-span-12';
19
- });
20
- </script>
1
+ <script lang="ts" setup></script>
21
2
 
22
3
  <template>
23
4
  <div class="mx-auto max-w-8xl p-8">
24
- <div class="grid grid-cols-12 gap-x-4">
25
- <div
26
- v-if="hasNavigation"
27
- class="col-span-3"
28
- >
29
- <PageNavigation />
30
- <slot name="page-navigation" />
31
- </div>
32
-
33
- <div :class="contentClassList">
34
- <slot />
35
- </div>
36
- </div>
5
+ <slot />
37
6
  </div>
38
7
  </template>
@@ -0,0 +1,36 @@
1
+ <script lang="ts" setup>
2
+ import { Component, computed, h, useSlots } from 'vue';
3
+
4
+ const props = defineProps<{
5
+ /** Navigation component to render in the left column */
6
+ navigation?: Component;
7
+ }>();
8
+
9
+ const slots = useSlots();
10
+
11
+ const hasNavigation = computed((): boolean | Component => props.navigation || !!slots['page-navigation']);
12
+
13
+ const PageNavigation = props.navigation
14
+ ? h(props.navigation)
15
+ : h('div');
16
+
17
+ const contentClassList = computed((): string => {
18
+ return hasNavigation.value ? 'col-span-9' : 'col-span-12';
19
+ });
20
+ </script>
21
+
22
+ <template>
23
+ <div class="grid grid-cols-12 gap-x-4">
24
+ <div
25
+ v-if="hasNavigation"
26
+ class="col-span-3"
27
+ >
28
+ <PageNavigation />
29
+ <slot name="page-navigation" />
30
+ </div>
31
+
32
+ <div :class="contentClassList">
33
+ <slot />
34
+ </div>
35
+ </div>
36
+ </template>
@@ -1,9 +1,12 @@
1
1
  <script lang="ts" setup>
2
-
2
+ import { Heading } from '../Heading';
3
3
  </script>
4
4
 
5
5
  <template>
6
- <h1 class="text-2xl font-semibold leading-none">
6
+ <Heading
7
+ level="h1"
8
+ size="2xl"
9
+ >
7
10
  <slot />
8
- </h1>
11
+ </Heading>
9
12
  </template>
@@ -8,6 +8,7 @@ import {
8
8
  CardDescription,
9
9
  CardSection,
10
10
  Page,
11
+ PageBody,
11
12
  PageDescription,
12
13
  PageHeader,
13
14
  PageTitle,
@@ -64,7 +65,7 @@ import {
64
65
  PageDescription,
65
66
  PageHeader,
66
67
  PageTitle,
67
- } from 'focus-ui';
68
+ } from '@returnless/focus-ui';
68
69
  </script>
69
70
 
70
71
  <template>
@@ -96,15 +97,6 @@ import {
96
97
 
97
98
  <ComponentWrapper>
98
99
  <Page>
99
- <template #page-navigation>
100
- <Navigation>
101
- <NavigationSection>
102
- <NavigationItem active>Navigation item 1</NavigationItem>
103
- <NavigationItem>Navigation item 2</NavigationItem>
104
- <NavigationItem>Navigation item 3</NavigationItem>
105
- </NavigationSection>
106
- </Navigation>
107
- </template>
108
100
  <PageHeader :back-action="{ content: 'Overview', href: '#' }">
109
101
  <PageTitle>The page title</PageTitle>
110
102
  <PageDescription>The page title</PageDescription>
@@ -115,15 +107,26 @@ import {
115
107
  </ButtonGroup>
116
108
  </template>
117
109
  </PageHeader>
118
- <Card>
119
- <CardHeader>
120
- <CardTitle>Notifications</CardTitle>
121
- <CardDescription>You have 3 unread messages.</CardDescription>
122
- </CardHeader>
123
- <CardSection>
124
- <div>Card content</div>
125
- </CardSection>
126
- </Card>
110
+ <PageBody>
111
+ <template #page-navigation>
112
+ <Navigation>
113
+ <NavigationSection>
114
+ <NavigationItem active href="#">Navigation item 1</NavigationItem>
115
+ <NavigationItem href="#">Navigation item 2</NavigationItem>
116
+ <NavigationItem href="#">Navigation item 3</NavigationItem>
117
+ </NavigationSection>
118
+ </Navigation>
119
+ </template>
120
+ <Card>
121
+ <CardHeader>
122
+ <CardTitle>Notifications</CardTitle>
123
+ <CardDescription>You have 3 unread messages.</CardDescription>
124
+ </CardHeader>
125
+ <CardSection>
126
+ <div>Card content</div>
127
+ </CardSection>
128
+ </Card>
129
+ </PageBody>
127
130
  </Page>
128
131
  </ComponentWrapper>
129
132
 
@@ -140,27 +143,19 @@ import {
140
143
  CardDescription,
141
144
  CardSection,
142
145
  Page,
146
+ PageBody,
143
147
  PageDescription,
144
148
  PageHeader,
145
149
  PageTitle,
146
150
  Navigation,
147
151
  NavigationItem,
148
152
  NavigationSection,
149
- } from 'focus-ui';
153
+ } from '@returnless/focus-ui';
150
154
  </script>
151
155
 
152
156
  <template>
153
157
  <Page>
154
- <template v-slot:page-navigation>
155
- <Navigation>
156
- <NavigationSection>
157
- <NavigationItem active>Navigation item 1</NavigationItem>
158
- <NavigationItem>Navigation item 2</NavigationItem>
159
- <NavigationItem>Navigation item 3</NavigationItem>
160
- </NavigationSection>
161
- </Navigation>
162
- </template>
163
- <PageHeader v-bind:back-action="{ content: 'Overview', href: '#' }">
158
+ <PageHeader :back-action="{ content: 'Overview', href: '#' }">
164
159
  <PageTitle>The page title</PageTitle>
165
160
  <PageDescription>The page title</PageDescription>
166
161
  <template v-slot:page-header-actions>
@@ -170,15 +165,26 @@ import {
170
165
  </ButtonGroup>
171
166
  </template>
172
167
  </PageHeader>
173
- <Card>
174
- <CardHeader>
175
- <CardTitle>Notifications</CardTitle>
176
- <CardDescription>You have 3 unread messages.</CardDescription>
177
- </CardHeader>
178
- <CardSection>
179
- <div>Card content</div>
180
- </CardSection>
181
- </Card>
168
+ <PageBody>
169
+ <template #page-navigation>
170
+ <Navigation>
171
+ <NavigationSection>
172
+ <NavigationItem active>Navigation item 1</NavigationItem>
173
+ <NavigationItem>Navigation item 2</NavigationItem>
174
+ <NavigationItem>Navigation item 3</NavigationItem>
175
+ </NavigationSection>
176
+ </Navigation>
177
+ </template>
178
+ <Card>
179
+ <CardHeader>
180
+ <CardTitle>Notifications</CardTitle>
181
+ <CardDescription>You have 3 unread messages.</CardDescription>
182
+ </CardHeader>
183
+ <CardSection>
184
+ <div>Card content</div>
185
+ </CardSection>
186
+ </Card>
187
+ </PageBody>
182
188
  </Page>
183
189
  </template>
184
190
  ```
@@ -1,4 +1,5 @@
1
1
  export { default as Page } from './Page.vue';
2
+ export { default as PageBody } from './PageBody.vue';
2
3
  export { default as PageDescription } from './PageDescription.vue';
3
4
  export { default as PageHeader } from './PageHeader.vue';
4
5
  export { default as PageTitle } from './PageTitle.vue';
@@ -25,7 +25,7 @@ import {
25
25
  Pagination,
26
26
  PaginationPreviousButton,
27
27
  PaginationNextButton,
28
- } from 'focus-ui';
28
+ } from '@returnless/focus-ui';
29
29
  </script>
30
30
 
31
31
  <template>
@@ -26,7 +26,7 @@ user to enter a pin code, such as a 2FA forms.
26
26
 
27
27
  ```js-vue
28
28
  <script lang="ts" setup>
29
- import { PinInput } from 'focus-ui';
29
+ import { PinInput } from '@returnless/focus-ui';
30
30
  </script>
31
31
 
32
32
  <template>
@@ -0,0 +1,18 @@
1
+ <script lang="ts" setup>
2
+ import { Popper } from '../Popper';
3
+ import { Alignment } from '@floating-ui/vue';
4
+
5
+ defineProps<{
6
+ /** The alignment of the popover */
7
+ alignment: Alignment;
8
+ }>();
9
+ </script>
10
+
11
+ <template>
12
+ <Popper
13
+ trigger="click"
14
+ :placement="`bottom-${alignment}`"
15
+ >
16
+ <slot />
17
+ </Popper>
18
+ </template>
@@ -0,0 +1,11 @@
1
+ <script lang="ts" setup>
2
+ import { PopperBody } from '../Popper';
3
+ </script>
4
+
5
+ <template>
6
+ <PopperBody>
7
+ <div class="overflow-hidden rounded-md border bg-white shadow-lg">
8
+ <slot />
9
+ </div>
10
+ </PopperBody>
11
+ </template>
@@ -0,0 +1,9 @@
1
+ <script lang="ts" setup>
2
+ import { PopperTrigger } from '../Popper';
3
+ </script>
4
+
5
+ <template>
6
+ <PopperTrigger>
7
+ <slot />
8
+ </PopperTrigger>
9
+ </template>
@@ -1,8 +1,36 @@
1
+ <script lang="ts" setup>
2
+ import {
3
+ Button,
4
+ PopoverBody,
5
+ Popover,
6
+ PopoverTrigger,
7
+ } from '../../src/components';
8
+ import api from '../component-meta/Popover.json';
9
+ </script>
10
+
1
11
  # Popover
2
12
 
3
13
  Popovers are small overlays that open on demand. They let users access additional content and actions without cluttering
4
14
  the page.
5
15
 
16
+ <ComponentApi :api="api" />
17
+
18
+ ## Usage
19
+
20
+ <ComponentWrapper>
21
+ <Popover alignment="start">
22
+ <PopoverTrigger>
23
+ <Button>Popper trigger</Button>
24
+ </PopoverTrigger>
25
+ <PopoverBody>
26
+ <div class="p-4">
27
+ Popover body content here
28
+ </div>
29
+ </PopoverBody>
30
+ </Popover>
31
+ </ComponentWrapper>
32
+
33
+
6
34
  ## Best practices
7
35
 
8
36
  Popovers should:
@@ -33,19 +61,19 @@ If the popover includes a series of navigational links, each item should:
33
61
 
34
62
  Popovers usually contain an `option list` or `action list`, but can also contain other controls or content.
35
63
 
36
- To assist screen readers with sending focus to an `action list`, pass `autofocusTarget="first-node"` to the
37
- `Popover`. This will avoid known issues a screen reader may have with keyboard support once focus is moved off the
64
+ To assist screen readers with sending focus to an `action list`, pass `autofocusTarget="first-node"` to the
65
+ `Popover`. This will avoid known issues a screen reader may have with keyboard support once focus is moved off the
38
66
  activator.
39
67
 
40
- Web browsers assign a default value of `menu` to the `aria-haspopup` role. You can use the prop `ariaHaspopup` to
41
- specify a value. Screen readers may fail to send focus to the `Popover` content when they expect the content to be
42
- adjacent to the element with `aria-haspopup` in the DOM tree. In this scenario, it is recommended not to provide
68
+ Web browsers assign a default value of `menu` to the `aria-haspopup` role. You can use the prop `ariaHaspopup` to
69
+ specify a value. Screen readers may fail to send focus to the `Popover` content when they expect the content to be
70
+ adjacent to the element with `aria-haspopup` in the DOM tree. In this scenario, it is recommended not to provide
43
71
  the `ariaHaspopup` prop.
44
72
 
45
73
  ### Keyboard support
46
74
 
47
75
  - When a popover opens, focus moves to the first focusable element or to the popover container.
48
- - Once focus is in the popover, users can access controls in the popover using the tab key (and shift + tab
76
+ - Once focus is in the popover, users can access controls in the popover using the tab key (and shift + tab
49
77
  backwards) and standard keystrokes for interacting.
50
78
  - Users can dismiss the popover by tabbing out of it, pressing the esc key, or clicking outside of it.
51
79
  - When the popover is closed, focus returns to the element that launched it.
@@ -0,0 +1,3 @@
1
+ export { default as Popover } from './Popover.vue';
2
+ export { default as PopoverBody } from './PopoverBody.vue';
3
+ export { default as PopoverTrigger } from './PopoverTrigger.vue';
@@ -0,0 +1,91 @@
1
+ <script lang="ts" setup>
2
+ import { useUniqueId } from '../../composables';
3
+ import { onMounted, provide, ref } from 'vue';
4
+ import { type ReferenceElement, computePosition, flip, shift, offset, Placement } from '@floating-ui/vue';
5
+ import { onClickOutside } from '@vueuse/core';
6
+
7
+ const props = defineProps<{
8
+ /** The trigger event of the popper */
9
+ trigger: 'click' | 'hover';
10
+
11
+ /** The placement of the popper */
12
+ placement: Placement;
13
+ }>();
14
+
15
+ const popperBodyId = useUniqueId('popperBody');
16
+ const popperTriggerId = useUniqueId('popperTrigger');
17
+
18
+ const popperBodyVisible = ref(false);
19
+
20
+ const $popperWrapper = ref<HTMLElement>()!;
21
+ const $popperTrigger = ref<HTMLElement>();
22
+ const $popperBody = ref<HTMLElement>();
23
+
24
+ provide('popperBodyId', popperBodyId);
25
+ provide('popperTriggerId', popperTriggerId);
26
+ provide('popperBodyVisible', popperBodyVisible);
27
+
28
+ function computePopperPosition(): void {
29
+ computePosition($popperTrigger.value as ReferenceElement, $popperBody.value!, {
30
+ placement: props.placement,
31
+ middleware: [
32
+ offset(6),
33
+ flip(),
34
+ shift({
35
+ padding: 5,
36
+ }),
37
+ ],
38
+ }).then(({ x, y }: { x: number; y: number }): void => {
39
+ Object.assign($popperBody.value!.style, {
40
+ left: `${x}px`,
41
+ top: `${y}px`,
42
+ });
43
+ });
44
+ }
45
+
46
+ function showPopperContent(): void {
47
+ popperBodyVisible.value = true;
48
+
49
+ computePopperPosition();
50
+ }
51
+
52
+ function hidePopperContent(): void {
53
+ popperBodyVisible.value = false;
54
+ }
55
+
56
+ function handleHoverPopper(): void {
57
+ $popperTrigger.value!.addEventListener('mouseenter', showPopperContent);
58
+ $popperTrigger.value!.addEventListener('mouseleave', hidePopperContent);
59
+ }
60
+
61
+ function handleClickPopper(): void {
62
+ $popperTrigger.value!.addEventListener('click', (): void => {
63
+ popperBodyVisible.value
64
+ ? hidePopperContent()
65
+ : showPopperContent();
66
+ });
67
+ }
68
+
69
+ onMounted((): void => {
70
+ $popperTrigger.value = document.getElementById(popperTriggerId)!;
71
+ $popperBody.value = document.getElementById(popperBodyId)!;
72
+
73
+ onClickOutside($popperWrapper, (): void => {
74
+ hidePopperContent();
75
+ });
76
+
77
+ if (props.trigger === 'hover') {
78
+ handleHoverPopper();
79
+ }
80
+
81
+ if (props.trigger === 'click') {
82
+ handleClickPopper();
83
+ }
84
+ });
85
+ </script>
86
+
87
+ <template>
88
+ <span ref="$popperWrapper">
89
+ <slot />
90
+ </span>
91
+ </template>
@@ -0,0 +1,19 @@
1
+ <script lang="ts" setup>
2
+ import { inject } from 'vue';
3
+
4
+ const popperBodyId = inject<string>('popperBodyId');
5
+ const popperBodyVisible = inject<boolean>('popperBodyVisible');
6
+ </script>
7
+
8
+ <template>
9
+ <div
10
+ :id="popperBodyId"
11
+ class="absolute"
12
+ :class="{
13
+ 'hidden': !popperBodyVisible,
14
+ 'block': popperBodyVisible,
15
+ }"
16
+ >
17
+ <slot />
18
+ </div>
19
+ </template>
@@ -0,0 +1,14 @@
1
+ <script lang="ts" setup>
2
+ import { inject } from 'vue';
3
+
4
+ const popperTriggerId = inject<string>('popperTriggerId');
5
+ </script>
6
+
7
+ <template>
8
+ <span
9
+ :id="popperTriggerId"
10
+ class="inline-block"
11
+ >
12
+ <slot />
13
+ </span>
14
+ </template>
@@ -0,0 +1,42 @@
1
+ <script lang="ts" setup>
2
+ import {
3
+ Button,
4
+ PopperBody,
5
+ Popper,
6
+ PopperTrigger,
7
+ } from '../../src/components';
8
+ import api from '../component-meta/Popper.json';
9
+ </script>
10
+
11
+ # Popper (internal)
12
+
13
+ This component is used to create a popper component that can be triggered by a click or hover event. The popper component
14
+ is used for components like tooltips, dropdowns, and popovers.
15
+
16
+ <ComponentApi :api="api" />
17
+
18
+ ## Click
19
+
20
+ <ComponentWrapper>
21
+ <Popper trigger="click">
22
+ <PopperTrigger>
23
+ <Button>Popper trigger</Button>
24
+ </PopperTrigger>
25
+ <PopperBody>
26
+ Tooltip
27
+ </PopperBody>
28
+ </Popper>
29
+ </ComponentWrapper>
30
+
31
+ ## Hover
32
+
33
+ <ComponentWrapper>
34
+ <Popper trigger="hover">
35
+ <PopperTrigger>
36
+ <Button>Popper trigger</Button>
37
+ </PopperTrigger>
38
+ <PopperBody>
39
+ Tooltip
40
+ </PopperBody>
41
+ </Popper>
42
+ </ComponentWrapper>
@@ -0,0 +1,3 @@
1
+ export { default as PopperBody } from './PopperBody.vue';
2
+ export { default as Popper } from './Popper.vue';
3
+ export { default as PopperTrigger } from './PopperTrigger.vue';
@@ -1,17 +1,32 @@
1
1
  <script lang="ts" setup>
2
2
  import { VisuallyHidden } from '../VisuallyHidden';
3
+ import { TailwindColor, useTailwindColor } from '../../composables';
4
+ import { computed } from 'vue';
5
+
6
+ const props = withDefaults(defineProps<{
7
+ /** The color of the progress-bar. */
8
+ color?: TailwindColor;
3
9
 
4
- defineProps<{
5
10
  /** The value of the progress bar. */
6
11
  value: number;
7
12
 
8
13
  /** The position of the indicator relative to the progress bar. */
9
- indicatorPosition: 'above' | 'below';
10
- }>();
14
+ indicatorPosition?: 'above' | 'below' | null;
15
+ }>(), {
16
+ color: 'slate',
17
+ indicatorPosition: null,
18
+ });
19
+
20
+ const foregroundColor = computed((): string => {
21
+ return useTailwindColor(props.color, '500');
22
+ });
11
23
  </script>
12
24
 
13
25
  <template>
14
- <div class="space-y-2">
26
+ <div
27
+ class="space-y-2"
28
+ role="progressbar"
29
+ >
15
30
  <slot v-if="!!$slots.default && indicatorPosition === 'above'" />
16
31
 
17
32
  <VisuallyHidden>
@@ -23,8 +38,11 @@ defineProps<{
23
38
 
24
39
  <div class="bg-slate-300 rounded h-2 overflow-hidden">
25
40
  <div
26
- class="bg-slate-600 h-full rounded"
27
- :style="{ width: `${value}%` }"
41
+ class="h-full rounded"
42
+ :style="{
43
+ width: `${value}%`,
44
+ backgroundColor: foregroundColor,
45
+ }"
28
46
  />
29
47
  </div>
30
48
 
@@ -37,7 +37,7 @@ Use radio buttons to present each item in a list of options where users must mak
37
37
 
38
38
  ```js-vue
39
39
  <script lang="ts" setup>
40
- import { RadioButton } from 'focus-ui';
40
+ import { RadioButton } from '@returnless/focus-ui';
41
41
 
42
42
  const radioButtonModel = ref<string | null>(null);
43
43
  </script>
@@ -1,6 +1,6 @@
1
1
  <script lang="ts" setup>
2
2
  import { InputLabel } from '../InputLabel';
3
- import { useUniqueId } from '../../composables';
3
+ import { useTheme, useUniqueId } from '../../composables';
4
4
  import { TextStyle } from '../TextStyle';
5
5
 
6
6
  const props = withDefaults(defineProps<{
@@ -30,8 +30,9 @@ const elementId = props.id || useUniqueId('radioButton');
30
30
  <input
31
31
  :id="elementId"
32
32
  v-model="model"
33
+ :class="useTheme('focus')"
33
34
  :value="value"
34
- class="appearance-none border-slate-400 shadow-sm border bg-white h-4 w-4 rounded-full text-brand-500 focus:ring-indigo-600"
35
+ class="h-4 w-4 flex-shrink-0 appearance-none rounded-full border border-slate-400 bg-white shadow-sm text-brand-500"
35
36
  type="radio"
36
37
  >
37
38
  <div class="-mt-[2px] space-y-1">