@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.
Files changed (194) hide show
  1. package/LICENSE.md +21 -0
  2. package/README.md +23 -0
  3. package/dist/focus-ui.es.js +33 -0
  4. package/dist/types/components/Accordion/Accordion.vue.d.ts +32 -0
  5. package/dist/types/components/Accordion/AccordionItem.vue.d.ts +2 -0
  6. package/dist/types/components/Accordion/index.d.ts +2 -0
  7. package/dist/types/components/index.d.ts +1 -0
  8. package/dist/types/index.d.ts +7 -0
  9. package/package.json +53 -0
  10. package/src/build-utils/generate-component-meta.ts +76 -0
  11. package/src/build-utils/update-component-list.js +31 -0
  12. package/src/build-utils/update-component-list.ts +32 -0
  13. package/src/components/Accordion/Accordion.vue +20 -0
  14. package/src/components/Accordion/AccordionContent.vue +14 -0
  15. package/src/components/Accordion/AccordionItem.vue +18 -0
  16. package/src/components/Accordion/AccordionTrigger.vue +35 -0
  17. package/src/components/Accordion/README.md +56 -0
  18. package/src/components/Accordion/index.ts +4 -0
  19. package/src/components/Alert/Alert.vue +55 -0
  20. package/src/components/Alert/AlertDescription.vue +8 -0
  21. package/src/components/Alert/AlertTitle.vue +11 -0
  22. package/src/components/Alert/DismissableAlertButton.vue +34 -0
  23. package/src/components/Alert/README.md +121 -0
  24. package/src/components/Alert/index.ts +3 -0
  25. package/src/components/AlertDialog/AlertDialog.vue +45 -0
  26. package/src/components/AlertDialog/AlertDialogActionButton.vue +9 -0
  27. package/src/components/AlertDialog/AlertDialogCancelButton.vue +15 -0
  28. package/src/components/AlertDialog/AlertDialogContent.vue +8 -0
  29. package/src/components/AlertDialog/AlertDialogDescription.vue +11 -0
  30. package/src/components/AlertDialog/AlertDialogFooter.vue +11 -0
  31. package/src/components/AlertDialog/AlertDialogHeader.vue +8 -0
  32. package/src/components/AlertDialog/AlertDialogTitle.vue +7 -0
  33. package/src/components/AlertDialog/README.md +85 -0
  34. package/src/components/AlertDialog/index.ts +8 -0
  35. package/src/components/Avatar/Avatar.vue +78 -0
  36. package/src/components/Avatar/README.md +122 -0
  37. package/src/components/Avatar/index.ts +1 -0
  38. package/src/components/Badge/Badge.vue +51 -0
  39. package/src/components/Badge/BadgeContent.vue +9 -0
  40. package/src/components/Badge/BadgeIcon.vue +7 -0
  41. package/src/components/Badge/README.md +131 -0
  42. package/src/components/Badge/index.ts +3 -0
  43. package/src/components/Button/Button.vue +63 -0
  44. package/src/components/Button/ButtonContent.vue +7 -0
  45. package/src/components/Button/ButtonIcon.vue +7 -0
  46. package/src/components/Button/README.md +228 -0
  47. package/src/components/Button/index.ts +3 -0
  48. package/src/components/ButtonGroup/ButtonGroup.vue +7 -0
  49. package/src/components/ButtonGroup/README.md +42 -0
  50. package/src/components/ButtonGroup/index.ts +1 -0
  51. package/src/components/Card/Card.vue +7 -0
  52. package/src/components/Card/CardDescription.vue +11 -0
  53. package/src/components/Card/CardFooter.vue +7 -0
  54. package/src/components/Card/CardHeader.vue +7 -0
  55. package/src/components/Card/CardSection.vue +7 -0
  56. package/src/components/Card/CardTitle.vue +8 -0
  57. package/src/components/Card/README.md +69 -0
  58. package/src/components/Card/index.ts +6 -0
  59. package/src/components/CategoryBar/CategoryBar.vue +25 -0
  60. package/src/components/CategoryBar/CategoryBarItem.vue +34 -0
  61. package/src/components/CategoryBar/README.md +17 -0
  62. package/src/components/CategoryBar/index.ts +2 -0
  63. package/src/components/Checkbox/Checkbox.vue +49 -0
  64. package/src/components/Checkbox/README.md +82 -0
  65. package/src/components/Checkbox/index.ts +1 -0
  66. package/src/components/Collapsible/README.md +25 -0
  67. package/src/components/DataTable/README.md +56 -0
  68. package/src/components/DatePicker/DatePicker.vue +140 -0
  69. package/src/components/DatePicker/DatePickerCard.vue +9 -0
  70. package/src/components/DatePicker/README.md +59 -0
  71. package/src/components/DatePicker/index.ts +2 -0
  72. package/src/components/DescriptionList/DescriptionList.vue +18 -0
  73. package/src/components/DescriptionList/DescriptionListDescription.vue +8 -0
  74. package/src/components/DescriptionList/DescriptionListItem.vue +21 -0
  75. package/src/components/DescriptionList/DescriptionListTerm.vue +11 -0
  76. package/src/components/DescriptionList/README.md +159 -0
  77. package/src/components/DescriptionList/index.ts +4 -0
  78. package/src/components/EmptyState/EmptyState.vue +13 -0
  79. package/src/components/EmptyState/EmptyStateActions.vue +11 -0
  80. package/src/components/EmptyState/EmptyStateContent.vue +7 -0
  81. package/src/components/EmptyState/EmptyStateDescription.vue +11 -0
  82. package/src/components/EmptyState/EmptyStateTitle.vue +7 -0
  83. package/src/components/EmptyState/README.md +102 -0
  84. package/src/components/EmptyState/index.ts +5 -0
  85. package/src/components/Feed/Feed.vue +7 -0
  86. package/src/components/Feed/FeedItem.vue +16 -0
  87. package/src/components/Feed/FeedItemBlock.vue +8 -0
  88. package/src/components/Feed/FeedItemDateIndicator.vue +11 -0
  89. package/src/components/Feed/FeedItemIcon.vue +26 -0
  90. package/src/components/Feed/FeedItemSimple.vue +8 -0
  91. package/src/components/Feed/README.md +115 -0
  92. package/src/components/Feed/index.ts +6 -0
  93. package/src/components/Form/Form.vue +30 -0
  94. package/src/components/Form/README.md +52 -0
  95. package/src/components/Form/index.ts +1 -0
  96. package/src/components/FormLayout/FormLayout.vue +7 -0
  97. package/src/components/FormLayout/README.md +59 -0
  98. package/src/components/FormLayout/index.ts +1 -0
  99. package/src/components/InputLabel/InputLabel.vue +32 -0
  100. package/src/components/InputLabel/index.ts +1 -0
  101. package/src/components/Link/Link.vue +38 -0
  102. package/src/components/Link/README.md +119 -0
  103. package/src/components/Link/index.ts +1 -0
  104. package/src/components/MetricCard/MetricCard.vue +11 -0
  105. package/src/components/MetricCard/MetricCardHeader.vue +7 -0
  106. package/src/components/MetricCard/MetricCardLabel.vue +9 -0
  107. package/src/components/MetricCard/MetricCardSection.vue +11 -0
  108. package/src/components/MetricCard/MetricCardValue.vue +8 -0
  109. package/src/components/MetricCard/README.md +53 -0
  110. package/src/components/MetricCard/index.ts +5 -0
  111. package/src/components/Navigation/Navigation.vue +8 -0
  112. package/src/components/Navigation/NavigationItem.vue +43 -0
  113. package/src/components/Navigation/NavigationSection.vue +27 -0
  114. package/src/components/Navigation/README.md +88 -0
  115. package/src/components/Navigation/index.ts +3 -0
  116. package/src/components/Page/Page.vue +38 -0
  117. package/src/components/Page/PageDescription.vue +11 -0
  118. package/src/components/Page/PageHeader.vue +34 -0
  119. package/src/components/Page/PageTitle.vue +9 -0
  120. package/src/components/Page/README.md +220 -0
  121. package/src/components/Page/index.ts +4 -0
  122. package/src/components/Pagination/Pagination.vue +8 -0
  123. package/src/components/Pagination/PaginationNextButton.vue +10 -0
  124. package/src/components/Pagination/PaginationPreviousButton.vue +10 -0
  125. package/src/components/Pagination/README.md +45 -0
  126. package/src/components/Pagination/index.ts +3 -0
  127. package/src/components/PinInput/PinInput.vue +169 -0
  128. package/src/components/PinInput/README.md +35 -0
  129. package/src/components/PinInput/index.ts +1 -0
  130. package/src/components/Popover/README.md +51 -0
  131. package/src/components/ProgressBar/ProgressBar.vue +33 -0
  132. package/src/components/ProgressBar/ProgressBarIndicator.vue +7 -0
  133. package/src/components/ProgressBar/README.md +98 -0
  134. package/src/components/ProgressBar/index.ts +2 -0
  135. package/src/components/RadioButton/README.md +111 -0
  136. package/src/components/RadioButton/RadioButton.vue +48 -0
  137. package/src/components/RadioButton/index.ts +1 -0
  138. package/src/components/Select/README.md +74 -0
  139. package/src/components/Select/Select.vue +91 -0
  140. package/src/components/Select/SelectGroup.vue +12 -0
  141. package/src/components/Select/SelectOption.vue +12 -0
  142. package/src/components/Select/index.ts +3 -0
  143. package/src/components/Separator/README.md +35 -0
  144. package/src/components/Separator/Separator.vue +7 -0
  145. package/src/components/Separator/index.ts +1 -0
  146. package/src/components/Spinner/README.md +53 -0
  147. package/src/components/Spinner/Spinner.vue +58 -0
  148. package/src/components/Spinner/index.ts +1 -0
  149. package/src/components/StatusIndicator/README.md +51 -0
  150. package/src/components/StatusIndicator/StatusIndicator.vue +38 -0
  151. package/src/components/StatusIndicator/index.ts +1 -0
  152. package/src/components/Tabs/README.md +53 -0
  153. package/src/components/Tabs/TabTrigger.vue +43 -0
  154. package/src/components/Tabs/Tabs.vue +13 -0
  155. package/src/components/Tabs/index.ts +2 -0
  156. package/src/components/Tag/README.md +27 -0
  157. package/src/components/TextField/README.md +317 -0
  158. package/src/components/TextField/TextField.vue +115 -0
  159. package/src/components/TextField/TextFieldPasswordIcon.vue +28 -0
  160. package/src/components/TextField/TextFieldSearchIcon.vue +11 -0
  161. package/src/components/TextField/index.ts +1 -0
  162. package/src/components/TextStyle/README.md +39 -0
  163. package/src/components/TextStyle/TextStyle.vue +24 -0
  164. package/src/components/TextStyle/index.ts +1 -0
  165. package/src/components/Toast/DismissToastAction.vue +34 -0
  166. package/src/components/Toast/README.md +167 -0
  167. package/src/components/Toast/Toast.vue +39 -0
  168. package/src/components/Toast/ToastGroup.vue +9 -0
  169. package/src/components/Toast/index.ts +2 -0
  170. package/src/components/Toggle/README.md +66 -0
  171. package/src/components/Toggle/Toggle.vue +86 -0
  172. package/src/components/Toggle/index.ts +1 -0
  173. package/src/components/Tooltip/README.md +51 -0
  174. package/src/components/Tooltip/Tooltip.vue +50 -0
  175. package/src/components/Tooltip/index.ts +1 -0
  176. package/src/components/TopBar/README.md +43 -0
  177. package/src/components/TopBar/TopBar.vue +7 -0
  178. package/src/components/TopBar/TopBarLogo.vue +8 -0
  179. package/src/components/TopBar/TopBarNavigation.vue +7 -0
  180. package/src/components/TopBar/TopBarNavigationItem.vue +13 -0
  181. package/src/components/TopBar/TopBarSearch.vue +15 -0
  182. package/src/components/TopBar/TopBarUserMenu.vue +20 -0
  183. package/src/components/TopBar/index.ts +6 -0
  184. package/src/components/VisuallyHidden/README.md +19 -0
  185. package/src/components/VisuallyHidden/VisuallyHidden.vue +25 -0
  186. package/src/components/VisuallyHidden/index.ts +1 -0
  187. package/src/components/index.ts +141 -0
  188. package/src/composables/index.ts +7 -0
  189. package/src/composables/useTailwindColor.ts +17 -0
  190. package/src/composables/useTheme.ts +29 -0
  191. package/src/composables/useToastNotifications.ts +55 -0
  192. package/src/composables/useUniqueId.ts +5 -0
  193. package/src/index.css +20 -0
  194. 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,11 @@
1
+ <script lang="ts" setup>
2
+ import { Card } from '../Card';
3
+ </script>
4
+
5
+ <template>
6
+ <Card>
7
+ <div class="divide-y">
8
+ <slot />
9
+ </div>
10
+ </Card>
11
+ </template>
@@ -0,0 +1,7 @@
1
+ <script lang="ts" setup></script>
2
+
3
+ <template>
4
+ <div class="relative space-y-2">
5
+ <slot />
6
+ </div>
7
+ </template>
@@ -0,0 +1,9 @@
1
+ <script lang="ts" setup>
2
+ import { TextStyle } from '../TextStyle';
3
+ </script>
4
+
5
+ <template>
6
+ <TextStyle variant="subdued">
7
+ <slot />
8
+ </TextStyle>
9
+ </template>
@@ -0,0 +1,11 @@
1
+ <script lang="ts" setup>
2
+ import { CardSection } from '../Card';
3
+ </script>
4
+
5
+ <template>
6
+ <CardSection>
7
+ <div class="space-y-8">
8
+ <slot />
9
+ </div>
10
+ </CardSection>
11
+ </template>
@@ -0,0 +1,8 @@
1
+ <script lang="ts" setup>
2
+ </script>
3
+
4
+ <template>
5
+ <div class="text-xl font-bold leading-none">
6
+ <slot />
7
+ </div>
8
+ </template>
@@ -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>&euro; 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>&euro; 204,00</MetricCardValue>
43
+ </MetricCardHeader>
44
+ </MetricCardSection>
45
+ <MetricCardSection>
46
+ <MetricCardHeader>
47
+ <MetricCardLabel>Estimated Lost Margin</MetricCardLabel>
48
+ <MetricCardValue>&euro; 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,8 @@
1
+ <script lang="ts" setup>
2
+ </script>
3
+
4
+ <template>
5
+ <div>
6
+ <slot />
7
+ </div>
8
+ </template>
@@ -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,3 @@
1
+ export { default as Navigation } from './Navigation.vue';
2
+ export { default as NavigationItem } from './NavigationItem.vue';
3
+ export { default as NavigationSection } from './NavigationSection.vue';
@@ -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,11 @@
1
+ <script lang="ts" setup>
2
+ import { TextStyle } from '../TextStyle';
3
+ </script>
4
+
5
+ <template>
6
+ <p>
7
+ <TextStyle variant="subdued">
8
+ <slot />
9
+ </TextStyle>
10
+ </p>
11
+ </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>
@@ -0,0 +1,9 @@
1
+ <script lang="ts" setup>
2
+
3
+ </script>
4
+
5
+ <template>
6
+ <h1 class="text-2xl font-semibold leading-none">
7
+ <slot />
8
+ </h1>
9
+ </template>