@returnless/focus-ui 0.0.1 → 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.
- package/dist/focus-ui.js +10851 -0
- package/dist/focus-ui.umd.cjs +26 -0
- package/dist/style.css +1 -0
- package/package.json +13 -8
- package/src/build-utils/generate-component-meta.ts +5 -1
- package/src/build-utils/update-component-list.ts +1 -1
- package/src/components/Accordion/AccordionContent.vue +34 -5
- package/src/components/Accordion/AccordionItem.vue +5 -2
- package/src/components/Accordion/AccordionTrigger.vue +5 -2
- package/src/components/Accordion/README.md +1 -1
- package/src/components/ActionList/ActionList.vue +9 -0
- package/src/components/ActionList/ActionListBody.vue +11 -0
- package/src/components/ActionList/ActionListItem.vue +37 -0
- package/src/components/ActionList/ActionListSection.vue +7 -0
- package/src/components/ActionList/ActionListTrigger.vue +9 -0
- package/src/components/ActionList/README.md +113 -0
- package/src/components/ActionList/index.ts +5 -0
- package/src/components/Alert/Alert.vue +23 -10
- package/src/components/Alert/AlertDescription.vue +13 -1
- package/src/components/Alert/AlertTitle.vue +1 -1
- package/src/components/Alert/DismissableAlertButton.vue +6 -4
- package/src/components/Alert/README.md +31 -2
- package/src/components/Alert/index.ts +2 -0
- package/src/components/Alert/types.ts +1 -0
- package/src/components/AlertDialog/AlertDialog.vue +10 -1
- package/src/components/AlertDialog/AlertDialogActionButton.vue +9 -2
- package/src/components/AlertDialog/AlertDialogCancelButton.vue +1 -1
- package/src/components/AlertDialog/AlertDialogDescription.vue +7 -1
- package/src/components/AlertDialog/AlertDialogTitle.vue +11 -3
- package/src/components/AlertDialog/README.md +15 -16
- package/src/components/AspectRatio/AspectRatio.vue +19 -0
- package/src/components/AspectRatio/README.md +36 -0
- package/src/components/AspectRatio/index.ts +1 -0
- package/src/components/Avatar/Avatar.vue +57 -13
- package/src/components/Avatar/README.md +3 -9
- package/src/components/Badge/Badge.vue +1 -1
- package/src/components/Badge/README.md +9 -9
- package/src/components/BarChart/BarChart.vue +80 -0
- package/src/components/{MetricCard/MetricCardHeader.vue → BarChart/BarChartContainer.vue} +1 -1
- package/src/components/BarChart/BarChartStacked.vue +93 -0
- package/src/components/BarChart/README.md +83 -0
- package/src/components/BarChart/index.ts +3 -0
- package/src/components/Breadcrumbs/Breadcrumb.vue +7 -0
- package/src/components/Breadcrumbs/BreadcrumbEllipsis.vue +12 -0
- package/src/components/{MetricCard/MetricCardValue.vue → Breadcrumbs/BreadcrumbItem.vue} +2 -2
- package/src/components/Breadcrumbs/BreadcrumbLink.vue +13 -0
- package/src/components/Breadcrumbs/BreadcrumbList.vue +8 -0
- package/src/components/Breadcrumbs/BreadcrumbPage.vue +13 -0
- package/src/components/Breadcrumbs/BreadcrumbSeparator.vue +12 -0
- package/src/components/Breadcrumbs/README.md +91 -0
- package/src/components/Breadcrumbs/index.ts +7 -0
- package/src/components/Button/Button.vue +53 -41
- package/src/components/Button/ButtonContent.vue +1 -1
- package/src/components/Button/ButtonIcon.vue +28 -3
- package/src/components/Button/README.md +32 -29
- package/src/components/Button/index.ts +2 -0
- package/src/components/Button/types.ts +30 -0
- package/src/components/ButtonGroup/README.md +1 -1
- package/src/components/Card/CardHelp.vue +23 -0
- package/src/components/Card/CardSection.vue +17 -2
- package/src/components/Card/CardTitle.vue +6 -3
- package/src/components/Card/README.md +97 -10
- package/src/components/Card/index.ts +2 -1
- package/src/components/Checkbox/Checkbox.vue +29 -5
- package/src/components/Checkbox/README.md +34 -5
- package/src/components/DatePicker/DatePicker.vue +7 -27
- package/src/components/DatePicker/README.md +1 -1
- package/src/components/DescriptionList/DescriptionList.vue +1 -1
- package/src/components/DescriptionList/DescriptionListItem.vue +1 -1
- package/src/components/DescriptionList/README.md +2 -2
- package/src/components/Dialog/README.md +2 -0
- package/src/components/Dialog/index.ts +0 -0
- package/src/components/DropZone/DropZone.vue +105 -0
- package/src/components/DropZone/README.md +48 -0
- package/src/components/DropZone/index.ts +1 -0
- package/src/components/EmptyState/README.md +1 -1
- package/src/components/Feed/FeedItem.vue +4 -1
- package/src/components/Feed/FeedItemBlock.vue +4 -1
- package/src/components/Feed/README.md +1 -1
- package/src/components/FileUploadButton/FileUploadButton.vue +62 -0
- package/src/components/FileUploadButton/index.ts +1 -0
- package/src/components/Form/Form.vue +7 -2
- package/src/components/Form/README.md +1 -1
- package/src/components/FormLayout/FormLayout.vue +20 -2
- package/src/components/FormLayout/README.md +39 -1
- package/src/components/Heading/Heading.vue +32 -0
- package/src/components/Heading/index.ts +3 -0
- package/src/components/Heading/types.ts +3 -0
- package/src/components/Image/Image.vue +30 -0
- package/src/components/Image/index.ts +1 -0
- package/src/components/InertiaLink/InertiaLink.vue +11 -0
- package/src/components/InertiaLink/index.ts +1 -0
- package/src/components/InlineError/InlineError.vue +21 -0
- package/src/components/InlineError/README.md +63 -0
- package/src/components/InlineError/index.ts +1 -0
- package/src/components/KPICard/KPICard.vue +28 -0
- package/src/components/KPICard/KPICardSection.vue +30 -0
- package/src/components/KPICard/README.md +124 -0
- package/src/components/KPICard/index.ts +2 -0
- package/src/components/Legend/Legend.vue +7 -0
- package/src/components/Legend/LegendItem.vue +34 -0
- package/src/components/Legend/README.md +32 -0
- package/src/components/Legend/index.ts +2 -0
- package/src/components/Link/Link.vue +4 -4
- package/src/components/Link/README.md +1 -1
- package/src/components/Navigation/Navigation.vue +2 -2
- package/src/components/Navigation/NavigationItem.vue +14 -10
- package/src/components/Navigation/NavigationSecondarySection.vue +12 -0
- package/src/components/Navigation/NavigationSection.vue +1 -1
- package/src/components/Navigation/README.md +10 -15
- package/src/components/Navigation/index.ts +1 -0
- package/src/components/Page/Page.vue +2 -33
- package/src/components/Page/PageBody.vue +36 -0
- package/src/components/Page/PageTitle.vue +6 -3
- package/src/components/Page/README.md +45 -39
- package/src/components/Page/index.ts +1 -0
- package/src/components/Pagination/README.md +1 -1
- package/src/components/PinInput/README.md +1 -1
- package/src/components/Popover/Popover.vue +18 -0
- package/src/components/Popover/PopoverBody.vue +11 -0
- package/src/components/Popover/PopoverTrigger.vue +9 -0
- package/src/components/Popover/README.md +34 -6
- package/src/components/Popover/index.ts +3 -0
- package/src/components/Popper/Popper.vue +91 -0
- package/src/components/Popper/PopperBody.vue +19 -0
- package/src/components/Popper/PopperTrigger.vue +14 -0
- package/src/components/Popper/README.md +42 -0
- package/src/components/Popper/index.ts +3 -0
- package/src/components/ProgressBar/ProgressBar.vue +24 -6
- package/src/components/RadioButton/README.md +1 -1
- package/src/components/RadioButton/RadioButton.vue +3 -2
- package/src/components/ResourceList/README.md +160 -0
- package/src/components/ResourceList/ResourceList.vue +7 -0
- package/src/components/ResourceList/ResourceListItem.vue +7 -0
- package/src/components/ResourceList/ResourceListItemContent.vue +7 -0
- package/src/components/ResourceList/index.ts +3 -0
- package/src/components/Select/README.md +1 -1
- package/src/components/Select/Select.vue +1 -1
- package/src/components/Separator/README.md +5 -1
- package/src/components/Separator/Separator.vue +20 -3
- package/src/components/Spinner/README.md +1 -1
- package/src/components/Spinner/Spinner.vue +10 -4
- package/src/components/StatusIndicator/README.md +2 -2
- package/src/components/StatusIndicator/StatusIndicator.vue +11 -5
- package/src/components/Stepper/README.md +38 -0
- package/src/components/Stepper/Stepper.vue +104 -0
- package/src/components/Stepper/index.ts +1 -0
- package/src/components/Tabs/README.md +1 -1
- package/src/components/Tabs/TabTrigger.vue +5 -4
- package/src/components/Tabs/Tabs.vue +4 -1
- package/src/components/Tag/Tag.vue +45 -0
- package/src/components/Tag/index.ts +1 -0
- package/src/components/TextField/README.md +24 -6
- package/src/components/TextField/TextField.vue +25 -5
- package/src/components/TextField/TextFieldIcon.vue +19 -0
- package/src/components/TextStyle/README.md +1 -1
- package/src/components/TextStyle/TextStyle.vue +1 -1
- package/src/components/Toast/DismissToastAction.vue +1 -1
- package/src/components/Toast/README.md +1 -1
- package/src/components/Toggle/README.md +1 -1
- package/src/components/Toggle/Toggle.vue +8 -5
- package/src/components/Tooltip/README.md +1 -1
- package/src/components/Tooltip/Tooltip.vue +15 -41
- package/src/components/TopBar/TopBarSearch.vue +2 -2
- package/src/components/index.ts +68 -12
- package/src/components/types.ts +5 -0
- package/src/composables/useTheme.ts +13 -1
- package/src/composables/useToastNotifications.ts +1 -1
- package/src/composables/useUniqueId.ts +4 -3
- package/src/index.css +17 -13
- package/src/index.ts +0 -11
- package/dist/focus-ui.es.js +0 -33
- package/dist/types/components/Accordion/Accordion.vue.d.ts +0 -32
- package/dist/types/components/Accordion/AccordionItem.vue.d.ts +0 -2
- package/dist/types/components/Accordion/index.d.ts +0 -2
- package/dist/types/components/index.d.ts +0 -1
- package/dist/types/index.d.ts +0 -7
- package/src/components/CategoryBar/CategoryBar.vue +0 -25
- package/src/components/CategoryBar/CategoryBarItem.vue +0 -34
- package/src/components/CategoryBar/README.md +0 -17
- package/src/components/CategoryBar/index.ts +0 -2
- package/src/components/MetricCard/MetricCard.vue +0 -11
- package/src/components/MetricCard/MetricCardLabel.vue +0 -9
- package/src/components/MetricCard/MetricCardSection.vue +0 -11
- package/src/components/MetricCard/README.md +0 -53
- 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
|
-
<
|
|
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>
|
|
@@ -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
|
-
<
|
|
119
|
-
<
|
|
120
|
-
<
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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
|
-
<
|
|
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
|
-
<
|
|
174
|
-
<
|
|
175
|
-
<
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
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';
|
|
@@ -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>
|
|
@@ -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,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,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>
|
|
@@ -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
|
|
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
|
|
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="
|
|
27
|
-
:style="{
|
|
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
|
|
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">
|