@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,59 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { FormLayout, TextField } from '../../src/components';
|
|
3
|
+
import api from '../component-meta/Form.json';
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
# Form layout
|
|
7
|
+
|
|
8
|
+
Use form layout to arrange fields with a form using standard spacing. By default, it stacks fields vertically but also
|
|
9
|
+
support horizontal groups of fields.
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
<ComponentWrapper>
|
|
14
|
+
<FormLayout>
|
|
15
|
+
<TextField label="Name" />
|
|
16
|
+
<TextField label="Email" />
|
|
17
|
+
</FormLayout>
|
|
18
|
+
</ComponentWrapper>
|
|
19
|
+
|
|
20
|
+
```js-vue
|
|
21
|
+
<script lang="ts" setup>
|
|
22
|
+
import { FormLayout, TextField } from 'focus-ui';
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<template>
|
|
26
|
+
<FormLayout>
|
|
27
|
+
<TextField label="Name" />
|
|
28
|
+
<TextField label="Email" type="email" />
|
|
29
|
+
</FormLayout>
|
|
30
|
+
</template>
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Best practices
|
|
34
|
+
|
|
35
|
+
Forms should:
|
|
36
|
+
|
|
37
|
+
- Be considerate of users’ time and privacy by only asking for information that’s required
|
|
38
|
+
- Group related tasks under section titles to provide more context and make the interface easier to scan
|
|
39
|
+
- Follow a logical, predictable order—for example, always ask for first-name first, and last-name second on forms
|
|
40
|
+
|
|
41
|
+
## Content guidelines
|
|
42
|
+
|
|
43
|
+
### Form section title
|
|
44
|
+
|
|
45
|
+
Form section titles should follow the content guidelines for headings and subheadings.
|
|
46
|
+
|
|
47
|
+
### Field label
|
|
48
|
+
|
|
49
|
+
A label is a short description of a field. Labels are not help text, and they shouldn’t be used to provide instruction,
|
|
50
|
+
but they should be meaningful and clearly indicate what is expected. Labels should be:
|
|
51
|
+
|
|
52
|
+
- Placed above or beside the form field
|
|
53
|
+
- Short and succinct (1–3 words)
|
|
54
|
+
- Written in sentence case (the first word capitalized, the rest lowercase)
|
|
55
|
+
|
|
56
|
+
### Help text
|
|
57
|
+
|
|
58
|
+
Help text provides extra guidance to people filling out a form field. This text is easy for people to ignore, so users
|
|
59
|
+
should not need to depend on it to fill out a form. As with all forms, help text should be succinct and easy to read.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as FormLayout } from './FormLayout.vue';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { computed } from 'vue';
|
|
3
|
+
import { VisuallyHidden } from '../VisuallyHidden';
|
|
4
|
+
import { TextStyle } from '../TextStyle';
|
|
5
|
+
|
|
6
|
+
const props = withDefaults(defineProps<{
|
|
7
|
+
/** The label text. */
|
|
8
|
+
label: string;
|
|
9
|
+
|
|
10
|
+
/** The ID of the input the label is associated with. */
|
|
11
|
+
labelFor: string;
|
|
12
|
+
|
|
13
|
+
/** Whether the label should be hidden. */
|
|
14
|
+
labelHidden?: boolean;
|
|
15
|
+
}>(), {
|
|
16
|
+
labelHidden: false,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const componentType = computed(() => props.labelHidden ? VisuallyHidden : 'label');
|
|
20
|
+
</script>
|
|
21
|
+
|
|
22
|
+
<template>
|
|
23
|
+
<component
|
|
24
|
+
:is="componentType"
|
|
25
|
+
:for="labelFor"
|
|
26
|
+
class="block w-fit cursor-pointer truncate text-sm leading-0 align-baseline"
|
|
27
|
+
>
|
|
28
|
+
<TextStyle variant="strong">
|
|
29
|
+
{{ label }}
|
|
30
|
+
</TextStyle>
|
|
31
|
+
</component>
|
|
32
|
+
</template>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as InputLabel } from './InputLabel.vue';
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { computed } from 'vue';
|
|
3
|
+
import { Link } from '@inertiajs/vue3';
|
|
4
|
+
|
|
5
|
+
const props = withDefaults(defineProps<{
|
|
6
|
+
/** The aria-label attribute to be applied to the link */
|
|
7
|
+
accessibilityLabel?: string | null;
|
|
8
|
+
|
|
9
|
+
/** The href attribute to be applied to the link */
|
|
10
|
+
href: string;
|
|
11
|
+
|
|
12
|
+
/** Whether the link should be rendered as a native anchor element */
|
|
13
|
+
native?: boolean;
|
|
14
|
+
}>(), {
|
|
15
|
+
accessibilityLabel: null,
|
|
16
|
+
native: false,
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
const componentType = computed(() => {
|
|
20
|
+
return props.native ? 'a' : Link;
|
|
21
|
+
});
|
|
22
|
+
</script>
|
|
23
|
+
|
|
24
|
+
<template>
|
|
25
|
+
<component
|
|
26
|
+
:is="componentType"
|
|
27
|
+
:aria-label="accessibilityLabel"
|
|
28
|
+
:href="href"
|
|
29
|
+
v-bind="$attrs"
|
|
30
|
+
:class="[
|
|
31
|
+
'text-brand-500',
|
|
32
|
+
'cursor-pointer',
|
|
33
|
+
'hover:underline'
|
|
34
|
+
]"
|
|
35
|
+
>
|
|
36
|
+
<slot />
|
|
37
|
+
</component>
|
|
38
|
+
</template>
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { Link } from '../../src/components';
|
|
3
|
+
import api from '../component-meta/Link.json';
|
|
4
|
+
</script>
|
|
5
|
+
|
|
6
|
+
# Link
|
|
7
|
+
|
|
8
|
+
Links take users to another place, and usually appear within or directly following a sentence.
|
|
9
|
+
|
|
10
|
+
<ComponentApi :api="api" />
|
|
11
|
+
|
|
12
|
+
## Usage
|
|
13
|
+
|
|
14
|
+
Use for text links inside a paragraph or for standalone text. Default links open in the same browser tab.
|
|
15
|
+
|
|
16
|
+
<ComponentWrapper>
|
|
17
|
+
<Link href="my-page">A link</Link>
|
|
18
|
+
</ComponentWrapper>
|
|
19
|
+
|
|
20
|
+
```js-vue
|
|
21
|
+
<script lang="ts" setup>
|
|
22
|
+
import { Link } from 'focus-ui';
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<template>
|
|
26
|
+
<Link href="my-page">A link</Link>
|
|
27
|
+
</template>
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Best practices
|
|
31
|
+
|
|
32
|
+
### Buttons versus links
|
|
33
|
+
|
|
34
|
+
Links are used primarily for navigation, and usually appear within or directly following a sentence.
|
|
35
|
+
|
|
36
|
+
Buttons are used primarily for actions, such as "Add", "Close", "Cancel", or "Save". The HTML that renders for
|
|
37
|
+
the `Button` and `Link` components carriers meaning. Using these components intentionally and consistently results in:
|
|
38
|
+
|
|
39
|
+
- A more inclusive experience for assistive technology users.
|
|
40
|
+
- A more cohesive visual experience for sighted users.
|
|
41
|
+
- Products that are easier to maintain at scale.
|
|
42
|
+
|
|
43
|
+
### Open a new tap only when necessary
|
|
44
|
+
|
|
45
|
+
Use default links whenever possible to avoid disorienting users and causing accessibility problems by opening a new tab.
|
|
46
|
+
|
|
47
|
+
External links should be used when users are:
|
|
48
|
+
|
|
49
|
+
- Performing a task or workflow, link creating a product.
|
|
50
|
+
- Navigating to a page outside the application.
|
|
51
|
+
|
|
52
|
+
### No icon
|
|
53
|
+
|
|
54
|
+
Avoid using the `external icon`, as it can add unnecessary visual load inside a sentence or when accompanied by
|
|
55
|
+
other content. Instead, add clarity to external links through clear link text and predictable placement of the link
|
|
56
|
+
in a user's workflow.
|
|
57
|
+
|
|
58
|
+
Edge cases: External icons should not be used to indicate a new tab or window is being opened. However, they may be
|
|
59
|
+
used sparingly in features where symbols help users scan and pick from a list of several kinds of navigation options.
|
|
60
|
+
|
|
61
|
+
## Content guidelines
|
|
62
|
+
|
|
63
|
+
Links need to be clear and predictable. Users should be able to anticipate what will happen when they select a link.
|
|
64
|
+
Never mislead someone by mislabeling a link.
|
|
65
|
+
|
|
66
|
+
Links should never use "click here" or "here" as link text.
|
|
67
|
+
|
|
68
|
+
### Links in sentences
|
|
69
|
+
|
|
70
|
+
Links in full sentences shouldn't link the entire sentence, only the text that describes where users go when they
|
|
71
|
+
select a link.
|
|
72
|
+
|
|
73
|
+
It's better for internationalization to have only single terms or small parts of phrases linked. Linking a full
|
|
74
|
+
phrase is problematic because the word order might change, which would break the link into two parts.
|
|
75
|
+
|
|
76
|
+
### Links outside of sentences
|
|
77
|
+
|
|
78
|
+
Links that aren't in full sentences should use the {verb + noun} pattern and not be punctuated, except question marks.
|
|
79
|
+
|
|
80
|
+
### "Learn more" links
|
|
81
|
+
|
|
82
|
+
When linking out to documentation from help text in the admin, link the relevant keywords. In general, don't add
|
|
83
|
+
another sentence starting with "Learn more...", because it's repetitive and takes up unnecessary space.
|
|
84
|
+
|
|
85
|
+
Only add a "Learn more..." sentence if the help text addresses more than one concept, each of which could be linked
|
|
86
|
+
to their own help doc. In that situation, pick the most appropriate link and contextualize it with "Learn more...".
|
|
87
|
+
|
|
88
|
+
## Accessibility
|
|
89
|
+
|
|
90
|
+
Use the `href` prop to give the link component a valid `href` value. This allows the element to be identified as a
|
|
91
|
+
link to assistive technologies and gives it default keyboard support.
|
|
92
|
+
|
|
93
|
+
The Link component is underlined to give interactive elements a shape. This allows links to not rely on color from
|
|
94
|
+
being the only way users can tell if an element is interactive.
|
|
95
|
+
|
|
96
|
+
### Submitting data
|
|
97
|
+
|
|
98
|
+
Users generally expect links to navigate, and not to submit data or take action. If you need a component that
|
|
99
|
+
doesn't have a URL associated with it, then use the `button component` instead.
|
|
100
|
+
|
|
101
|
+
### Labeling
|
|
102
|
+
|
|
103
|
+
Give text links text that clearly describes their purpose.
|
|
104
|
+
|
|
105
|
+
The `accessibilityLabel` prop adds an `aria-label` attribute to the link, which can be accessed by assistive
|
|
106
|
+
technologies like screen readers. Typically, this label text replaces the visual text on the link for users who use
|
|
107
|
+
assistive technology.
|
|
108
|
+
|
|
109
|
+
To provide consistence and clarity:
|
|
110
|
+
|
|
111
|
+
- Use the same text for links that navigate to the same content.
|
|
112
|
+
- Use different text for links that navigate to different content.
|
|
113
|
+
|
|
114
|
+
### Keyboard support
|
|
115
|
+
|
|
116
|
+
Links use browser defaults for keyboard interaction.
|
|
117
|
+
|
|
118
|
+
- Give links keyboard focus with the tab key (or shift + tab when tabbing backwards).
|
|
119
|
+
- Activate links with the enter/return key.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Link } from './Link.vue';
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import {
|
|
3
|
+
Badge,
|
|
4
|
+
BadgeContent,
|
|
5
|
+
BadgeIcon,
|
|
6
|
+
MetricCard,
|
|
7
|
+
MetricCardHeader,
|
|
8
|
+
MetricCardLabel,
|
|
9
|
+
MetricCardSection,
|
|
10
|
+
MetricCardValue,
|
|
11
|
+
} from '../../src/components';
|
|
12
|
+
import { ArrowTrendingUpIcon, ArrowTrendingDownIcon } from '@heroicons/vue/16/solid';
|
|
13
|
+
import api from '../component-meta/MetricCard.json';
|
|
14
|
+
</script>
|
|
15
|
+
|
|
16
|
+
# Metric Card
|
|
17
|
+
|
|
18
|
+
The Metric Card component is used to display a metric value with a label and an optional icon.
|
|
19
|
+
|
|
20
|
+
<ComponentApi :api="api" />
|
|
21
|
+
|
|
22
|
+
## Usage
|
|
23
|
+
|
|
24
|
+
<ComponentWrapper>
|
|
25
|
+
<div style="max-width: 350px;">
|
|
26
|
+
<MetricCard>
|
|
27
|
+
<MetricCardSection>
|
|
28
|
+
<MetricCardHeader>
|
|
29
|
+
<MetricCardLabel>Missed Revenue</MetricCardLabel>
|
|
30
|
+
<MetricCardValue>€ 325,44</MetricCardValue>
|
|
31
|
+
</MetricCardHeader>
|
|
32
|
+
<Badge color="green">
|
|
33
|
+
<BadgetContent>+ 25%</BadgetContent>
|
|
34
|
+
<BadgeIcon>
|
|
35
|
+
<ArrowTrendingUpIcon />
|
|
36
|
+
</BadgeIcon>
|
|
37
|
+
</Badge>
|
|
38
|
+
</MetricCardSection>
|
|
39
|
+
<MetricCardSection>
|
|
40
|
+
<MetricCardHeader>
|
|
41
|
+
<MetricCardLabel>Product Costs</MetricCardLabel>
|
|
42
|
+
<MetricCardValue>€ 204,00</MetricCardValue>
|
|
43
|
+
</MetricCardHeader>
|
|
44
|
+
</MetricCardSection>
|
|
45
|
+
<MetricCardSection>
|
|
46
|
+
<MetricCardHeader>
|
|
47
|
+
<MetricCardLabel>Estimated Lost Margin</MetricCardLabel>
|
|
48
|
+
<MetricCardValue>€ 121,44</MetricCardValue>
|
|
49
|
+
</MetricCardHeader>
|
|
50
|
+
</MetricCardSection>
|
|
51
|
+
</MetricCard>
|
|
52
|
+
</div>
|
|
53
|
+
</ComponentWrapper>
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { default as MetricCard } from './MetricCard.vue';
|
|
2
|
+
export { default as MetricCardHeader } from './MetricCardHeader.vue';
|
|
3
|
+
export { default as MetricCardLabel } from './MetricCardLabel.vue';
|
|
4
|
+
export { default as MetricCardSection } from './MetricCardSection.vue';
|
|
5
|
+
export { default as MetricCardValue } from './MetricCardValue.vue';
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { computed } from 'vue';
|
|
3
|
+
import { Link } from '@inertiajs/vue3';
|
|
4
|
+
|
|
5
|
+
const props = withDefaults(defineProps<{
|
|
6
|
+
/** The URL to navigate to. */
|
|
7
|
+
href: string;
|
|
8
|
+
|
|
9
|
+
/** Whether the navigation item is active. */
|
|
10
|
+
active?: boolean;
|
|
11
|
+
}>(), {
|
|
12
|
+
active: false,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const classList = computed(() => {
|
|
16
|
+
return [
|
|
17
|
+
{ 'relative bg-white shadow-sm text-brand-500': props.active },
|
|
18
|
+
{ 'text-slate-500 hover:bg-slate-100': !props.active },
|
|
19
|
+
];
|
|
20
|
+
});
|
|
21
|
+
</script>
|
|
22
|
+
|
|
23
|
+
<template>
|
|
24
|
+
<div class="block">
|
|
25
|
+
<Link :href="href">
|
|
26
|
+
<div
|
|
27
|
+
class="flex items-center rounded px-3 py-2 space-x-3"
|
|
28
|
+
:class="classList"
|
|
29
|
+
>
|
|
30
|
+
<span
|
|
31
|
+
v-if="!!$slots.icon"
|
|
32
|
+
class="h-4 w-4 opacity-75"
|
|
33
|
+
>
|
|
34
|
+
<slot name="icon" />
|
|
35
|
+
</span>
|
|
36
|
+
|
|
37
|
+
<span class="font-medium">
|
|
38
|
+
<slot />
|
|
39
|
+
</span>
|
|
40
|
+
</div>
|
|
41
|
+
</Link>
|
|
42
|
+
</div>
|
|
43
|
+
</template>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { TextStyle } from '../TextStyle';
|
|
3
|
+
|
|
4
|
+
withDefaults(defineProps<{
|
|
5
|
+
/** The label for the navigation section. */
|
|
6
|
+
label: string | null;
|
|
7
|
+
}>(), {
|
|
8
|
+
label: null,
|
|
9
|
+
});
|
|
10
|
+
</script>
|
|
11
|
+
|
|
12
|
+
<template>
|
|
13
|
+
<div class="pb-8">
|
|
14
|
+
<TextStyle
|
|
15
|
+
v-if="label"
|
|
16
|
+
variant="strong"
|
|
17
|
+
>
|
|
18
|
+
<p class="px-3 py-2">
|
|
19
|
+
{{ label }}
|
|
20
|
+
</p>
|
|
21
|
+
</TextStyle>
|
|
22
|
+
|
|
23
|
+
<div class="space-y-0.5">
|
|
24
|
+
<slot />
|
|
25
|
+
</div>
|
|
26
|
+
</div>
|
|
27
|
+
</template>
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { Navigation, NavigationItem, NavigationSection } from '../../src/components';
|
|
3
|
+
import api from '../component-meta/Navigation.json';
|
|
4
|
+
import { UserIcon, HandThumbDownIcon, QuestionMarkCircleIcon, BoltIcon } from '@heroicons/vue/16/solid';
|
|
5
|
+
</script>
|
|
6
|
+
|
|
7
|
+
# Navigation
|
|
8
|
+
|
|
9
|
+
The navigation component is used to display the primary navigation in the sidebar of the interface of an application.
|
|
10
|
+
Navigation includes a list of links that users use to move between sections of the application.
|
|
11
|
+
|
|
12
|
+
<ComponentApi :api="api" />
|
|
13
|
+
|
|
14
|
+
## Usage
|
|
15
|
+
|
|
16
|
+
<ComponentWrapper>
|
|
17
|
+
<Navigation>
|
|
18
|
+
<NavigationSection>
|
|
19
|
+
<NavigationItem>General</NavigationItem>
|
|
20
|
+
</NavigationSection>
|
|
21
|
+
<NavigationSection label="Workflow management">
|
|
22
|
+
<NavigationItem>
|
|
23
|
+
<template #icon>
|
|
24
|
+
<HandThumbDownIcon />
|
|
25
|
+
</template>
|
|
26
|
+
Return reasons
|
|
27
|
+
</NavigationItem>
|
|
28
|
+
<NavigationItem active>
|
|
29
|
+
<template #icon>
|
|
30
|
+
<QuestionMarkCircleIcon />
|
|
31
|
+
</template>
|
|
32
|
+
Return questions
|
|
33
|
+
</NavigationItem>
|
|
34
|
+
<NavigationItem>
|
|
35
|
+
<template #icon>
|
|
36
|
+
<BoltIcon />
|
|
37
|
+
</template>
|
|
38
|
+
Automations
|
|
39
|
+
</NavigationItem>
|
|
40
|
+
</NavigationSection>
|
|
41
|
+
</Navigation>
|
|
42
|
+
</ComponentWrapper>
|
|
43
|
+
|
|
44
|
+
```js-vue
|
|
45
|
+
<script lang="ts" setup>
|
|
46
|
+
import { Navigation, NavigationItem, NavigationSection } from 'focus-ui';
|
|
47
|
+
import { UserIcon, HandThumbDownIcon, QuestionMarkCircleIcon, BoltIcon } from '@heroicons/vue/16/solid';
|
|
48
|
+
</script>
|
|
49
|
+
|
|
50
|
+
<template>
|
|
51
|
+
<Navigation>
|
|
52
|
+
<NavigationSection>
|
|
53
|
+
<NavigationItem>General</NavigationItem>
|
|
54
|
+
</NavigationSection>
|
|
55
|
+
<NavigationSection label="Workflow management">
|
|
56
|
+
<NavigationItem>
|
|
57
|
+
<template #icon>
|
|
58
|
+
<HandThumbDownIcon />
|
|
59
|
+
</template>
|
|
60
|
+
Return reasons
|
|
61
|
+
</NavigationItem>
|
|
62
|
+
<NavigationItem active>
|
|
63
|
+
<template #icon>
|
|
64
|
+
<QuestionMarkCircleIcon />
|
|
65
|
+
</template>
|
|
66
|
+
Return questions
|
|
67
|
+
</NavigationItem>
|
|
68
|
+
<NavigationItem>
|
|
69
|
+
<template #icon>
|
|
70
|
+
<BoltIcon />
|
|
71
|
+
</template>
|
|
72
|
+
Automations
|
|
73
|
+
</NavigationItem>
|
|
74
|
+
</NavigationSection>
|
|
75
|
+
</Navigation>
|
|
76
|
+
</template>
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Best practices
|
|
80
|
+
|
|
81
|
+
The navigation component should:
|
|
82
|
+
|
|
83
|
+
- Contain primary navigation items that perform an action when clicked. Each action should navigate to a URL or
|
|
84
|
+
trigger another action like a modal overlay.
|
|
85
|
+
- Only use secondary actions for supplementary actions to the primary actions.
|
|
86
|
+
- Provide a non-primary link or action as a secondary action to the section or an item.
|
|
87
|
+
- Group navigation items into sections based on related categories.
|
|
88
|
+
- Use a section title to clarify the category of a section.
|
|
@@ -0,0 +1,38 @@
|
|
|
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>
|
|
21
|
+
|
|
22
|
+
<template>
|
|
23
|
+
<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>
|
|
37
|
+
</div>
|
|
38
|
+
</template>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
import { ArrowLeftIcon } from '@heroicons/vue/16/solid';
|
|
3
|
+
|
|
4
|
+
type BackAction = {
|
|
5
|
+
content: string;
|
|
6
|
+
href: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
withDefaults(defineProps<{
|
|
10
|
+
/** The back action to display in the header. */
|
|
11
|
+
backAction?: BackAction | null;
|
|
12
|
+
}>(), {
|
|
13
|
+
backAction: null,
|
|
14
|
+
});
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<template>
|
|
18
|
+
<div class="mb-12 flex">
|
|
19
|
+
<div
|
|
20
|
+
v-if="backAction"
|
|
21
|
+
class="mr-4 mt-0.5"
|
|
22
|
+
>
|
|
23
|
+
<button class="rounded bg-slate-200 p-1 hover:bg-slate-300">
|
|
24
|
+
<ArrowLeftIcon class="h-4 w-4" />
|
|
25
|
+
</button>
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
<div class="flex flex-grow flex-col space-y-1.5">
|
|
29
|
+
<slot />
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
<slot name="page-header-actions" />
|
|
33
|
+
</div>
|
|
34
|
+
</template>
|