@returnless/focus-ui 0.0.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.
- package/LICENSE.md +21 -0
- package/README.md +23 -0
- package/dist/focus-ui.es.js +33 -0
- package/dist/types/components/Accordion/Accordion.vue.d.ts +32 -0
- package/dist/types/components/Accordion/AccordionItem.vue.d.ts +2 -0
- package/dist/types/components/Accordion/index.d.ts +2 -0
- package/dist/types/components/index.d.ts +1 -0
- package/dist/types/index.d.ts +7 -0
- package/package.json +53 -0
- package/src/build-utils/generate-component-meta.ts +76 -0
- package/src/build-utils/update-component-list.js +31 -0
- package/src/build-utils/update-component-list.ts +32 -0
- package/src/components/Accordion/Accordion.vue +20 -0
- package/src/components/Accordion/AccordionContent.vue +14 -0
- package/src/components/Accordion/AccordionItem.vue +18 -0
- package/src/components/Accordion/AccordionTrigger.vue +35 -0
- package/src/components/Accordion/README.md +56 -0
- package/src/components/Accordion/index.ts +4 -0
- package/src/components/Alert/Alert.vue +55 -0
- package/src/components/Alert/AlertDescription.vue +8 -0
- package/src/components/Alert/AlertTitle.vue +11 -0
- package/src/components/Alert/DismissableAlertButton.vue +34 -0
- package/src/components/Alert/README.md +121 -0
- package/src/components/Alert/index.ts +3 -0
- package/src/components/AlertDialog/AlertDialog.vue +45 -0
- package/src/components/AlertDialog/AlertDialogActionButton.vue +9 -0
- package/src/components/AlertDialog/AlertDialogCancelButton.vue +15 -0
- package/src/components/AlertDialog/AlertDialogContent.vue +8 -0
- package/src/components/AlertDialog/AlertDialogDescription.vue +11 -0
- package/src/components/AlertDialog/AlertDialogFooter.vue +11 -0
- package/src/components/AlertDialog/AlertDialogHeader.vue +8 -0
- package/src/components/AlertDialog/AlertDialogTitle.vue +7 -0
- package/src/components/AlertDialog/README.md +85 -0
- package/src/components/AlertDialog/index.ts +8 -0
- package/src/components/Avatar/Avatar.vue +78 -0
- package/src/components/Avatar/README.md +122 -0
- package/src/components/Avatar/index.ts +1 -0
- package/src/components/Badge/Badge.vue +51 -0
- package/src/components/Badge/BadgeContent.vue +9 -0
- package/src/components/Badge/BadgeIcon.vue +7 -0
- package/src/components/Badge/README.md +131 -0
- package/src/components/Badge/index.ts +3 -0
- package/src/components/Button/Button.vue +63 -0
- package/src/components/Button/ButtonContent.vue +7 -0
- package/src/components/Button/ButtonIcon.vue +7 -0
- package/src/components/Button/README.md +228 -0
- package/src/components/Button/index.ts +3 -0
- package/src/components/ButtonGroup/ButtonGroup.vue +7 -0
- package/src/components/ButtonGroup/README.md +42 -0
- package/src/components/ButtonGroup/index.ts +1 -0
- package/src/components/Card/Card.vue +7 -0
- package/src/components/Card/CardDescription.vue +11 -0
- package/src/components/Card/CardFooter.vue +7 -0
- package/src/components/Card/CardHeader.vue +7 -0
- package/src/components/Card/CardSection.vue +7 -0
- package/src/components/Card/CardTitle.vue +8 -0
- package/src/components/Card/README.md +69 -0
- package/src/components/Card/index.ts +6 -0
- package/src/components/CategoryBar/CategoryBar.vue +25 -0
- package/src/components/CategoryBar/CategoryBarItem.vue +34 -0
- package/src/components/CategoryBar/README.md +17 -0
- package/src/components/CategoryBar/index.ts +2 -0
- package/src/components/Checkbox/Checkbox.vue +49 -0
- package/src/components/Checkbox/README.md +82 -0
- package/src/components/Checkbox/index.ts +1 -0
- package/src/components/Collapsible/README.md +25 -0
- package/src/components/DataTable/README.md +56 -0
- package/src/components/DatePicker/DatePicker.vue +140 -0
- package/src/components/DatePicker/DatePickerCard.vue +9 -0
- package/src/components/DatePicker/README.md +59 -0
- package/src/components/DatePicker/index.ts +2 -0
- package/src/components/DescriptionList/DescriptionList.vue +18 -0
- package/src/components/DescriptionList/DescriptionListDescription.vue +8 -0
- package/src/components/DescriptionList/DescriptionListItem.vue +21 -0
- package/src/components/DescriptionList/DescriptionListTerm.vue +11 -0
- package/src/components/DescriptionList/README.md +159 -0
- package/src/components/DescriptionList/index.ts +4 -0
- package/src/components/EmptyState/EmptyState.vue +13 -0
- package/src/components/EmptyState/EmptyStateActions.vue +11 -0
- package/src/components/EmptyState/EmptyStateContent.vue +7 -0
- package/src/components/EmptyState/EmptyStateDescription.vue +11 -0
- package/src/components/EmptyState/EmptyStateTitle.vue +7 -0
- package/src/components/EmptyState/README.md +102 -0
- package/src/components/EmptyState/index.ts +5 -0
- package/src/components/Feed/Feed.vue +7 -0
- package/src/components/Feed/FeedItem.vue +16 -0
- package/src/components/Feed/FeedItemBlock.vue +8 -0
- package/src/components/Feed/FeedItemDateIndicator.vue +11 -0
- package/src/components/Feed/FeedItemIcon.vue +26 -0
- package/src/components/Feed/FeedItemSimple.vue +8 -0
- package/src/components/Feed/README.md +115 -0
- package/src/components/Feed/index.ts +6 -0
- package/src/components/Form/Form.vue +30 -0
- package/src/components/Form/README.md +52 -0
- package/src/components/Form/index.ts +1 -0
- package/src/components/FormLayout/FormLayout.vue +7 -0
- package/src/components/FormLayout/README.md +59 -0
- package/src/components/FormLayout/index.ts +1 -0
- package/src/components/InputLabel/InputLabel.vue +32 -0
- package/src/components/InputLabel/index.ts +1 -0
- package/src/components/Link/Link.vue +38 -0
- package/src/components/Link/README.md +119 -0
- package/src/components/Link/index.ts +1 -0
- package/src/components/MetricCard/MetricCard.vue +11 -0
- package/src/components/MetricCard/MetricCardHeader.vue +7 -0
- package/src/components/MetricCard/MetricCardLabel.vue +9 -0
- package/src/components/MetricCard/MetricCardSection.vue +11 -0
- package/src/components/MetricCard/MetricCardValue.vue +8 -0
- package/src/components/MetricCard/README.md +53 -0
- package/src/components/MetricCard/index.ts +5 -0
- package/src/components/Navigation/Navigation.vue +8 -0
- package/src/components/Navigation/NavigationItem.vue +43 -0
- package/src/components/Navigation/NavigationSection.vue +27 -0
- package/src/components/Navigation/README.md +88 -0
- package/src/components/Navigation/index.ts +3 -0
- package/src/components/Page/Page.vue +38 -0
- package/src/components/Page/PageDescription.vue +11 -0
- package/src/components/Page/PageHeader.vue +34 -0
- package/src/components/Page/PageTitle.vue +9 -0
- package/src/components/Page/README.md +220 -0
- package/src/components/Page/index.ts +4 -0
- package/src/components/Pagination/Pagination.vue +8 -0
- package/src/components/Pagination/PaginationNextButton.vue +10 -0
- package/src/components/Pagination/PaginationPreviousButton.vue +10 -0
- package/src/components/Pagination/README.md +45 -0
- package/src/components/Pagination/index.ts +3 -0
- package/src/components/PinInput/PinInput.vue +169 -0
- package/src/components/PinInput/README.md +35 -0
- package/src/components/PinInput/index.ts +1 -0
- package/src/components/Popover/README.md +51 -0
- package/src/components/ProgressBar/ProgressBar.vue +33 -0
- package/src/components/ProgressBar/ProgressBarIndicator.vue +7 -0
- package/src/components/ProgressBar/README.md +98 -0
- package/src/components/ProgressBar/index.ts +2 -0
- package/src/components/RadioButton/README.md +111 -0
- package/src/components/RadioButton/RadioButton.vue +48 -0
- package/src/components/RadioButton/index.ts +1 -0
- package/src/components/Select/README.md +74 -0
- package/src/components/Select/Select.vue +91 -0
- package/src/components/Select/SelectGroup.vue +12 -0
- package/src/components/Select/SelectOption.vue +12 -0
- package/src/components/Select/index.ts +3 -0
- package/src/components/Separator/README.md +35 -0
- package/src/components/Separator/Separator.vue +7 -0
- package/src/components/Separator/index.ts +1 -0
- package/src/components/Spinner/README.md +53 -0
- package/src/components/Spinner/Spinner.vue +58 -0
- package/src/components/Spinner/index.ts +1 -0
- package/src/components/StatusIndicator/README.md +51 -0
- package/src/components/StatusIndicator/StatusIndicator.vue +38 -0
- package/src/components/StatusIndicator/index.ts +1 -0
- package/src/components/Tabs/README.md +53 -0
- package/src/components/Tabs/TabTrigger.vue +43 -0
- package/src/components/Tabs/Tabs.vue +13 -0
- package/src/components/Tabs/index.ts +2 -0
- package/src/components/Tag/README.md +27 -0
- package/src/components/TextField/README.md +317 -0
- package/src/components/TextField/TextField.vue +115 -0
- package/src/components/TextField/TextFieldPasswordIcon.vue +28 -0
- package/src/components/TextField/TextFieldSearchIcon.vue +11 -0
- package/src/components/TextField/index.ts +1 -0
- package/src/components/TextStyle/README.md +39 -0
- package/src/components/TextStyle/TextStyle.vue +24 -0
- package/src/components/TextStyle/index.ts +1 -0
- package/src/components/Toast/DismissToastAction.vue +34 -0
- package/src/components/Toast/README.md +167 -0
- package/src/components/Toast/Toast.vue +39 -0
- package/src/components/Toast/ToastGroup.vue +9 -0
- package/src/components/Toast/index.ts +2 -0
- package/src/components/Toggle/README.md +66 -0
- package/src/components/Toggle/Toggle.vue +86 -0
- package/src/components/Toggle/index.ts +1 -0
- package/src/components/Tooltip/README.md +51 -0
- package/src/components/Tooltip/Tooltip.vue +50 -0
- package/src/components/Tooltip/index.ts +1 -0
- package/src/components/TopBar/README.md +43 -0
- package/src/components/TopBar/TopBar.vue +7 -0
- package/src/components/TopBar/TopBarLogo.vue +8 -0
- package/src/components/TopBar/TopBarNavigation.vue +7 -0
- package/src/components/TopBar/TopBarNavigationItem.vue +13 -0
- package/src/components/TopBar/TopBarSearch.vue +15 -0
- package/src/components/TopBar/TopBarUserMenu.vue +20 -0
- package/src/components/TopBar/index.ts +6 -0
- package/src/components/VisuallyHidden/README.md +19 -0
- package/src/components/VisuallyHidden/VisuallyHidden.vue +25 -0
- package/src/components/VisuallyHidden/index.ts +1 -0
- package/src/components/index.ts +141 -0
- package/src/composables/index.ts +7 -0
- package/src/composables/useTailwindColor.ts +17 -0
- package/src/composables/useTheme.ts +29 -0
- package/src/composables/useToastNotifications.ts +55 -0
- package/src/composables/useUniqueId.ts +5 -0
- package/src/index.css +20 -0
- package/src/index.ts +12 -0
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { Alert, AlertTitle, AlertDescription } from '../../src/components';
|
|
3
|
+
import api from '../component-meta/Alert.json';
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
# Alert
|
|
7
|
+
|
|
8
|
+
Informs users about important changes or persistent conditions. Use this component if you need to communicate to
|
|
9
|
+
users in a prominent way. Alerts are placed at the top of the page or section they apply to, and below the page or
|
|
10
|
+
section header.
|
|
11
|
+
|
|
12
|
+
<ComponentApi :api="api" />
|
|
13
|
+
|
|
14
|
+
## Variants
|
|
15
|
+
|
|
16
|
+
### Default
|
|
17
|
+
|
|
18
|
+
Use to convey general information or actions that aren't critical. For example, you might show an alert that asks
|
|
19
|
+
for users feedback. Default alerts contain lower priority information and should always be dismissable.
|
|
20
|
+
|
|
21
|
+
<ComponentWrapper>
|
|
22
|
+
<Alert>
|
|
23
|
+
<AlertTitle>Heads up!</AlertTitle>
|
|
24
|
+
<AlertDescription>
|
|
25
|
+
You can add components to your app using the cli.
|
|
26
|
+
</AlertDescription>
|
|
27
|
+
</Alert>
|
|
28
|
+
</ComponentWrapper>
|
|
29
|
+
|
|
30
|
+
```js-vue
|
|
31
|
+
<script lang="ts" setup>
|
|
32
|
+
import { Alert, AlertDescription, AlertTitle } from 'focus-ui';
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<template>
|
|
36
|
+
<Alert>
|
|
37
|
+
<AlertTitle>Heads up!</AlertTitle>
|
|
38
|
+
<AlertDescription>
|
|
39
|
+
You can add components to your app using the cli.
|
|
40
|
+
</AlertDescription>
|
|
41
|
+
</Alert>
|
|
42
|
+
</template>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Destructive
|
|
46
|
+
|
|
47
|
+
Use to communicate critical information or actions that require immediate attention. For example, you might show an
|
|
48
|
+
alert that warns users about a critical system failure. Destructive alerts contain higher priority information.
|
|
49
|
+
|
|
50
|
+
<ComponentWrapper>
|
|
51
|
+
<Alert variant="destructive">
|
|
52
|
+
<AlertTitle>Error</AlertTitle>
|
|
53
|
+
<AlertDescription>
|
|
54
|
+
Your session has expired. Please log in again.
|
|
55
|
+
</AlertDescription>
|
|
56
|
+
</Alert>
|
|
57
|
+
</ComponentWrapper>
|
|
58
|
+
|
|
59
|
+
```js-vue
|
|
60
|
+
<script lang="ts" setup>
|
|
61
|
+
import { Alert, AlertDescription, AlertTitle } from 'focus-ui';
|
|
62
|
+
</script>
|
|
63
|
+
|
|
64
|
+
<template>
|
|
65
|
+
<Alert variant="destructive">
|
|
66
|
+
<AlertTitle>Error</AlertTitle>
|
|
67
|
+
<AlertDescription>
|
|
68
|
+
Your session has expired. Please log in again.
|
|
69
|
+
</AlertDescription>
|
|
70
|
+
</Alert>
|
|
71
|
+
</template>
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Best practices
|
|
75
|
+
|
|
76
|
+
Alerts should:
|
|
77
|
+
|
|
78
|
+
- Be used thoughtfully and sparingly for only the most important information.
|
|
79
|
+
- Not be used to call attention to what a user needs to do in the UI instead of making the action clear in the UI
|
|
80
|
+
itself.
|
|
81
|
+
- Not be the primary entry point of information or actions users need on a regular basis.
|
|
82
|
+
- Be dismissible unless they contain critical information or an important step users need to take.
|
|
83
|
+
|
|
84
|
+
### Placement
|
|
85
|
+
|
|
86
|
+
Alerts should be placed in the appropriate context:
|
|
87
|
+
|
|
88
|
+
- Alerts relevant to an entire page should be placed at the top of that page, below the page header. They should
|
|
89
|
+
occupy the full width of the content area.
|
|
90
|
+
- Alerts related to a section of a page (like a card, popover, or modal) should be placed inside that section, below
|
|
91
|
+
any section heading.
|
|
92
|
+
- Alerts related to an element more specific that a section should be placed immediately above or below that element.
|
|
93
|
+
|
|
94
|
+
## Content guidelines
|
|
95
|
+
|
|
96
|
+
Alerts should:
|
|
97
|
+
|
|
98
|
+
- Focus on a single theme, piece of information, or required action to avoid overwhelming users.
|
|
99
|
+
- Be concise and scannable - users shouldn't need to spend a lot of time figuring out what the alert is trying to
|
|
100
|
+
communicate.
|
|
101
|
+
- Be limited to a few important calls to action with no more than one primary action.
|
|
102
|
+
|
|
103
|
+
### Body content
|
|
104
|
+
|
|
105
|
+
Body content should:
|
|
106
|
+
|
|
107
|
+
- Be concise: keep the content to 1 or 2 sentences where possible.
|
|
108
|
+
- Clarify the benefit of the main task.
|
|
109
|
+
- Be written in sentence case and use appropriate punctuation.
|
|
110
|
+
- Avoid repeating the heading.
|
|
111
|
+
- Explain how to resolve the issue, particularly for destructive alerts.
|
|
112
|
+
|
|
113
|
+
## Accessibility
|
|
114
|
+
|
|
115
|
+
Alerts provide context and assist workflows for users with disabilities.
|
|
116
|
+
|
|
117
|
+
- Destructive alerts have a `role="alert"` attribute and are announced by assistive technologies when they appear.
|
|
118
|
+
- All other alerts have a `role="status"` attribute and are read after any critical announcements.
|
|
119
|
+
- Alert containers have a `tabindex="0"` attribute and display a visible keyboard focus indicator. Because of this,
|
|
120
|
+
merchants can discover banners while tabbing through forms or other interactions, and developers can programmatically
|
|
121
|
+
move focus to banners.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { onMounted, onUnmounted, provide } from 'vue';
|
|
3
|
+
|
|
4
|
+
withDefaults(defineProps<{
|
|
5
|
+
/** Whether the alert dialog is open. */
|
|
6
|
+
open?: boolean;
|
|
7
|
+
}>(), {
|
|
8
|
+
open: false,
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const emits = defineEmits<{
|
|
12
|
+
cancel: [];
|
|
13
|
+
}>();
|
|
14
|
+
|
|
15
|
+
function cancelAlertDialog(): void {
|
|
16
|
+
emits('cancel');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function onKeyDown(e: KeyboardEvent): void {
|
|
20
|
+
if (e.key === 'Escape') {
|
|
21
|
+
cancelAlertDialog();
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
onMounted((): void => {
|
|
26
|
+
document.addEventListener('keydown', onKeyDown);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
onUnmounted((): void => {
|
|
30
|
+
document.removeEventListener('keydown', onKeyDown);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
provide('cancelAlertDialog', cancelAlertDialog);
|
|
34
|
+
</script>
|
|
35
|
+
|
|
36
|
+
<template>
|
|
37
|
+
<div
|
|
38
|
+
v-if="open"
|
|
39
|
+
class="fixed top-0 left-0 z-10 h-screen w-screen bg-slate-500/50 text-sm"
|
|
40
|
+
>
|
|
41
|
+
<div class="flex min-h-full items-center justify-center">
|
|
42
|
+
<slot />
|
|
43
|
+
</div>
|
|
44
|
+
</div>
|
|
45
|
+
</template>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { Button } from '../Button';
|
|
3
|
+
import { inject } from 'vue';
|
|
4
|
+
|
|
5
|
+
const cancelAlertDialog = inject('cancelAlertDialog');
|
|
6
|
+
</script>
|
|
7
|
+
|
|
8
|
+
<template>
|
|
9
|
+
<Button
|
|
10
|
+
variant="secondary"
|
|
11
|
+
@click="cancelAlertDialog"
|
|
12
|
+
>
|
|
13
|
+
<slot />
|
|
14
|
+
</Button>
|
|
15
|
+
</template>
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { ref } from "vue";
|
|
3
|
+
import {
|
|
4
|
+
AlertDialog,
|
|
5
|
+
AlertDialogActionButton,
|
|
6
|
+
AlertDialogCancelButton,
|
|
7
|
+
AlertDialogContent,
|
|
8
|
+
AlertDialogDescription,
|
|
9
|
+
AlertDialogFooter,
|
|
10
|
+
AlertDialogHeader,
|
|
11
|
+
AlertDialogTitle,
|
|
12
|
+
Button,
|
|
13
|
+
} from '../../src/components';
|
|
14
|
+
import api from '../component-meta/AlertDialog.json';
|
|
15
|
+
|
|
16
|
+
const alertDialogOpen = ref(false);
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
# Alert Dialog
|
|
20
|
+
|
|
21
|
+
A modal dialog that interrupts the user with important content and expects a response.
|
|
22
|
+
|
|
23
|
+
<ComponentApi :api="api" />
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
<ComponentWrapper>
|
|
28
|
+
<Button @click="alertDialogOpen = true">
|
|
29
|
+
Open Dialog
|
|
30
|
+
</Button>
|
|
31
|
+
|
|
32
|
+
<AlertDialog :open="alertDialogOpen" @cancel="alertDialogOpen = false">
|
|
33
|
+
<AlertDialogContent>
|
|
34
|
+
<AlertDialogHeader>
|
|
35
|
+
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
|
|
36
|
+
<AlertDialogDescription>
|
|
37
|
+
This action cannot be undone. This will permanently delete your account and remove your data from our servers.
|
|
38
|
+
</AlertDialogDescription>
|
|
39
|
+
</AlertDialogHeader>
|
|
40
|
+
<AlertDialogFooter>
|
|
41
|
+
<AlertDialogCancelButton>Cancel</AlertDialogCancelButton>
|
|
42
|
+
<AlertDialogActionButton>Continue</AlertDialogActionButton>
|
|
43
|
+
</AlertDialogFooter>
|
|
44
|
+
</AlertDialogContent>
|
|
45
|
+
</AlertDialog>
|
|
46
|
+
</ComponentWrapper>
|
|
47
|
+
|
|
48
|
+
```js-vue
|
|
49
|
+
<script lang="ts" setup>
|
|
50
|
+
import {
|
|
51
|
+
AlertDialog,
|
|
52
|
+
AlertDialogActionButton,
|
|
53
|
+
AlertDialogCancelButton,
|
|
54
|
+
AlertDialogContent,
|
|
55
|
+
AlertDialogDescription,
|
|
56
|
+
AlertDialogFooter,
|
|
57
|
+
AlertDialogHeader,
|
|
58
|
+
AlertDialogTitle,
|
|
59
|
+
Button,
|
|
60
|
+
} from 'focus-ui';
|
|
61
|
+
|
|
62
|
+
const alertDialogOpen = ref(false);
|
|
63
|
+
</script>
|
|
64
|
+
|
|
65
|
+
<template>
|
|
66
|
+
<Button v-on:click="alertDialogOpen = true">
|
|
67
|
+
Open Dialog
|
|
68
|
+
</Button>
|
|
69
|
+
|
|
70
|
+
<AlertDialog :open="alertDialogOpen" v-on:cancel="alertDialogOpen = false">
|
|
71
|
+
<AlertDialogContent>
|
|
72
|
+
<AlertDialogHeader>
|
|
73
|
+
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
|
|
74
|
+
<AlertDialogDescription>
|
|
75
|
+
This action cannot be undone. This will permanently delete your account and remove your data from our servers.
|
|
76
|
+
</AlertDialogDescription>
|
|
77
|
+
</AlertDialogHeader>
|
|
78
|
+
<AlertDialogFooter>
|
|
79
|
+
<AlertDialogCancelButton>Cancel</AlertDialogCancelButton>
|
|
80
|
+
<AlertDialogActionButton>Continue</AlertDialogActionButton>
|
|
81
|
+
</AlertDialogFooter>
|
|
82
|
+
</AlertDialogContent>
|
|
83
|
+
</AlertDialog>
|
|
84
|
+
</template>
|
|
85
|
+
```
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { default as AlertDialog } from './AlertDialog.vue';
|
|
2
|
+
export { default as AlertDialogActionButton } from './AlertDialogActionButton.vue';
|
|
3
|
+
export { default as AlertDialogCancelButton } from './AlertDialogCancelButton.vue';
|
|
4
|
+
export { default as AlertDialogContent } from './AlertDialogContent.vue';
|
|
5
|
+
export { default as AlertDialogDescription } from './AlertDialogDescription.vue';
|
|
6
|
+
export { default as AlertDialogFooter } from './AlertDialogFooter.vue';
|
|
7
|
+
export { default as AlertDialogHeader } from './AlertDialogHeader.vue';
|
|
8
|
+
export { default as AlertDialogTitle } from './AlertDialogTitle.vue';
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { UserIcon } from '@heroicons/vue/16/solid';
|
|
3
|
+
import { computed } from 'vue';
|
|
4
|
+
|
|
5
|
+
const props = withDefaults(defineProps<{
|
|
6
|
+
/** The size of the avatar */
|
|
7
|
+
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
8
|
+
|
|
9
|
+
/** The name of the person, company or entity */
|
|
10
|
+
name?: string | null;
|
|
11
|
+
|
|
12
|
+
/** Initials of person to display. */
|
|
13
|
+
initials?: string | null;
|
|
14
|
+
|
|
15
|
+
/** URL of the avatar image which falls back to initials if the image fails to load. */
|
|
16
|
+
source?: string | null;
|
|
17
|
+
|
|
18
|
+
/** Accessible label for the avatar image. */
|
|
19
|
+
accessibilityLabel?: string | null;
|
|
20
|
+
}>(), {
|
|
21
|
+
size: 'md',
|
|
22
|
+
name: null,
|
|
23
|
+
initials: null,
|
|
24
|
+
source: null,
|
|
25
|
+
accessibilityLabel: null,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const classList = computed(() => {
|
|
29
|
+
return [
|
|
30
|
+
{ 'w-4 h-4': props.size === 'xs' },
|
|
31
|
+
{ 'w-6 h-6': props.size === 'sm' },
|
|
32
|
+
{ 'w-8 h-8': props.size === 'md' },
|
|
33
|
+
{ 'w-10 h-10': props.size === 'lg' },
|
|
34
|
+
{ 'w-12 h-12': props.size === 'xl' },
|
|
35
|
+
];
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
const iconSize = computed(() => {
|
|
39
|
+
return [
|
|
40
|
+
{ 'w-3 h-3': props.size === 'xs' },
|
|
41
|
+
];
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const textSize = computed(() => {
|
|
45
|
+
return [
|
|
46
|
+
{ 'text-xs': props.size === 'xs' },
|
|
47
|
+
{ 'text-xs': props.size === 'sm' },
|
|
48
|
+
{ 'text-md': props.size === 'md' },
|
|
49
|
+
{ 'text-lg': props.size === 'lg' },
|
|
50
|
+
{ 'text-lg': props.size === 'xl' },
|
|
51
|
+
];
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
function renderInitials(initials: string): string {
|
|
55
|
+
return props.size === 'xs'
|
|
56
|
+
? initials?.slice(0, 1)
|
|
57
|
+
: initials;
|
|
58
|
+
}
|
|
59
|
+
</script>
|
|
60
|
+
|
|
61
|
+
<template>
|
|
62
|
+
<div
|
|
63
|
+
class="relative flex items-center justify-center rounded bg-slate-200"
|
|
64
|
+
:class="classList"
|
|
65
|
+
>
|
|
66
|
+
<UserIcon
|
|
67
|
+
v-if="!initials"
|
|
68
|
+
role="img"
|
|
69
|
+
:class="iconSize"
|
|
70
|
+
/>
|
|
71
|
+
<span
|
|
72
|
+
class="font-semibold"
|
|
73
|
+
:class="textSize"
|
|
74
|
+
>
|
|
75
|
+
{{ renderInitials(initials) }}
|
|
76
|
+
</span>
|
|
77
|
+
</div>
|
|
78
|
+
</template>
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { Avatar } from '../../src/components';
|
|
3
|
+
import api from '../component-meta/Avatar.json';
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
# Avatar
|
|
7
|
+
|
|
8
|
+
Avatars are used to show a thumbnail representation of an individual or business in the interface.
|
|
9
|
+
|
|
10
|
+
<ComponentApi :api="api" />
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
<ComponentWrapper>
|
|
15
|
+
<Avatar name="John Doe" />
|
|
16
|
+
</ComponentWrapper>
|
|
17
|
+
|
|
18
|
+
```js-vue
|
|
19
|
+
<script lang="ts" setup>
|
|
20
|
+
import { Avatar } from 'focus-ui';
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<template>
|
|
24
|
+
<Avatar name="John Doe" />
|
|
25
|
+
</template>
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Variants
|
|
29
|
+
|
|
30
|
+
### With initials
|
|
31
|
+
|
|
32
|
+
<ComponentWrapper>
|
|
33
|
+
<Avatar name="John Doe" initials="JD" />
|
|
34
|
+
</ComponentWrapper>
|
|
35
|
+
|
|
36
|
+
```js-vue
|
|
37
|
+
<script lang="ts" setup>
|
|
38
|
+
import { Avatar } from 'focus-ui';
|
|
39
|
+
</script>
|
|
40
|
+
|
|
41
|
+
<template>
|
|
42
|
+
<Avatar name="John Doe" initials="JD" />
|
|
43
|
+
</template>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Sizes
|
|
47
|
+
|
|
48
|
+
<ComponentWrapper>
|
|
49
|
+
<ComponentGrid>
|
|
50
|
+
<ComponentGrid>
|
|
51
|
+
<Avatar name="John Doe" size="xs" />
|
|
52
|
+
<Avatar name="John Doe" size="sm" />
|
|
53
|
+
<Avatar name="John Doe" size="md" />
|
|
54
|
+
<Avatar name="John Doe" size="lg" />
|
|
55
|
+
<Avatar name="John Doe" size="xl" />
|
|
56
|
+
</ComponentGrid>
|
|
57
|
+
<ComponentGrid>
|
|
58
|
+
<Avatar name="John Doe" size="xs" initials="JD" />
|
|
59
|
+
<Avatar name="John Doe" size="sm" initials="JD" />
|
|
60
|
+
<Avatar name="John Doe" size="md" initials="JD" />
|
|
61
|
+
<Avatar name="John Doe" size="lg" initials="JD" />
|
|
62
|
+
<Avatar name="John Doe" size="xl" initials="JD" />
|
|
63
|
+
</ComponentGrid>
|
|
64
|
+
</ComponentGrid>
|
|
65
|
+
</ComponentWrapper>
|
|
66
|
+
|
|
67
|
+
```js-vue
|
|
68
|
+
<script lang="ts" setup>
|
|
69
|
+
import { Avatar } from 'focus-ui';
|
|
70
|
+
</script>
|
|
71
|
+
|
|
72
|
+
<template>
|
|
73
|
+
<Avatar name="John Doe" size="xs" />
|
|
74
|
+
<Avatar name="John Doe" size="sm" />
|
|
75
|
+
<Avatar name="John Doe" size="md" />
|
|
76
|
+
<Avatar name="John Doe" size="lg" />
|
|
77
|
+
<Avatar name="John Doe" size="xl" />
|
|
78
|
+
|
|
79
|
+
// Or with initials...
|
|
80
|
+
<Avatar name="John Doe" size="xs" initials="JD" />
|
|
81
|
+
<Avatar name="John Doe" size="sm" initials="JD" />
|
|
82
|
+
<Avatar name="John Doe" size="md" initials="JD" />
|
|
83
|
+
<Avatar name="John Doe" size="lg" initials="JD" />
|
|
84
|
+
<Avatar name="John Doe" size="xl" initials="JD" />
|
|
85
|
+
</template>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Best practices
|
|
89
|
+
|
|
90
|
+
Avatars should be one of 5 sizes:
|
|
91
|
+
|
|
92
|
+
- Extra-small (20 x 20 px): use in tightly condensed layouts
|
|
93
|
+
- Small (24 × 24 px): use when the medium size is too big for the layout, or when the avatar has less importance
|
|
94
|
+
- Medium (28 × 28 px): use as the default size
|
|
95
|
+
- Large (32 × 32 px): use when an avatar is a focal point, such as on a single customer card
|
|
96
|
+
- Extra large (40 × 40 px): use when an avatar is a focal point, such as on a single customer card
|
|
97
|
+
|
|
98
|
+
## Content guidelines
|
|
99
|
+
|
|
100
|
+
Any time you use an image to communicate a concept in the interface, it's important to use descriptive alt text.
|
|
101
|
+
Doing this is important for accessibility because it allows screen readers to describe what's in the image to people
|
|
102
|
+
who may not be able to see it.
|
|
103
|
+
|
|
104
|
+
For avatars, we recommend using a format that describes what will show in the image:
|
|
105
|
+
|
|
106
|
+
- `alt=Person's name"` if the avatar represents a person
|
|
107
|
+
- `alt=Company name"` if the avatar represents a business
|
|
108
|
+
- `alt=""` if the name of the person/business appears next to the avatar as text
|
|
109
|
+
|
|
110
|
+
## Accessibility
|
|
111
|
+
|
|
112
|
+
### Structure
|
|
113
|
+
|
|
114
|
+
The avatar component uses a generated scalable vector graphics (SVG) file, which can cause challenges for users that
|
|
115
|
+
use assistive technologies. To create a standard experience, the `<img>` is hidden from assistive technologies by
|
|
116
|
+
using an empty `alt` attribute, and replaced with a `<span>` that has `role="img"`.
|
|
117
|
+
|
|
118
|
+
### Labeling
|
|
119
|
+
|
|
120
|
+
The avatar component represents content, and should have a text equivalent for users using assistive technologies.
|
|
121
|
+
By default, the value of the `name` prop is used for the alternative text. If different text would be more accurate,
|
|
122
|
+
use the `accessibilityLabel` prop to replace the value provided by `name`.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Avatar } from './Avatar.vue';
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { computed, CSSProperties } from 'vue';
|
|
3
|
+
import { VisuallyHidden } from '../VisuallyHidden';
|
|
4
|
+
import { TextStyle } from '../TextStyle';
|
|
5
|
+
import { TailwindColor, useTailwindColor } from '../../composables';
|
|
6
|
+
|
|
7
|
+
const props = withDefaults(defineProps<{
|
|
8
|
+
/** Accessible label for the avatar image. */
|
|
9
|
+
accessibilityLabel?: string | null;
|
|
10
|
+
|
|
11
|
+
/** The color of the badge. */
|
|
12
|
+
color: TailwindColor;
|
|
13
|
+
|
|
14
|
+
/** The size of the badge */
|
|
15
|
+
size?: 'sm' | 'md' | 'lg' | 'xl';
|
|
16
|
+
}>(), {
|
|
17
|
+
accessibilityLabel: null,
|
|
18
|
+
size: 'sm',
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
const colorValues = computed((): CSSProperties => {
|
|
22
|
+
return {
|
|
23
|
+
backgroundColor: useTailwindColor(props.color, '200'),
|
|
24
|
+
color: useTailwindColor(props.color, '900'),
|
|
25
|
+
};
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const classList = computed(() => {
|
|
29
|
+
return [
|
|
30
|
+
{ 'text-xs px-2 py-1': props.size === 'sm' },
|
|
31
|
+
{ 'text-sm px-3 py-1.5': props.size === 'md' },
|
|
32
|
+
{ 'text-md px-4 py-2': props.size === 'lg' },
|
|
33
|
+
];
|
|
34
|
+
});
|
|
35
|
+
</script>
|
|
36
|
+
|
|
37
|
+
<template>
|
|
38
|
+
<span
|
|
39
|
+
class="inline-flex rounded bg-slate-200"
|
|
40
|
+
:class="classList"
|
|
41
|
+
:style="colorValues"
|
|
42
|
+
>
|
|
43
|
+
<TextStyle variant="strong">
|
|
44
|
+
<div class="flex items-center space-x-2">
|
|
45
|
+
<slot />
|
|
46
|
+
</div>
|
|
47
|
+
</TextStyle>
|
|
48
|
+
|
|
49
|
+
<VisuallyHidden v-if="accessibilityLabel">{{ accessibilityLabel }}</VisuallyHidden>
|
|
50
|
+
</span>
|
|
51
|
+
</template>
|