@xy-planning-network/trees 0.9.9 → 0.10.0

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 (33) hide show
  1. package/README.md +5 -13
  2. package/config/tailwind.config.js +8 -4
  3. package/config/theme/colors.ts +10 -1
  4. package/config/theme/index.ts +4 -1
  5. package/config/theme/layout.ts +11 -0
  6. package/config/theme/typography.ts +25 -0
  7. package/dist/trees.es.js +2338 -2164
  8. package/dist/trees.umd.js +8 -8
  9. package/package.json +5 -3
  10. package/src/index.css +106 -11
  11. package/src/lib-components/forms/FieldsetLegend.vue +1 -1
  12. package/src/lib-components/forms/InputHelp.vue +1 -1
  13. package/src/lib-components/forms/MultiCheckboxes.vue +11 -6
  14. package/src/lib-components/forms/Radio.vue +11 -6
  15. package/src/lib-components/forms/RadioCards.vue +6 -6
  16. package/src/lib-components/forms/YesOrNoRadio.vue +9 -4
  17. package/src/lib-components/indicators/InlineAlert.vue +3 -3
  18. package/src/lib-components/indicators/ProgressCircles.vue +87 -0
  19. package/src/lib-components/indicators/ProgressCirclesLabeled.vue +104 -0
  20. package/src/lib-components/layout/SidebarLayout.vue +61 -53
  21. package/src/lib-components/layout/StackedLayout.vue +1 -1
  22. package/src/lib-components/lists/Cards.vue +1 -1
  23. package/src/lib-components/navigation/Steps.vue +1 -1
  24. package/src/lib-components/overlays/ContentModal.vue +1 -1
  25. package/src/lib-components/overlays/Modal.vue +5 -5
  26. package/src/lib-components/overlays/Popover/PopoverContent.vue +1 -1
  27. package/src/lib-components/overlays/Tooltip.vue +2 -2
  28. package/types/components.d.ts +1 -1
  29. package/types/lib-components/index.d.ts +5 -1
  30. package/types/lib-components/indicators/ProgressCircles.vue.d.ts +31 -0
  31. package/types/lib-components/indicators/ProgressCirclesLabeled.vue.d.ts +31 -0
  32. package/types/lib-components/layout/SidebarLayout.vue.d.ts +2 -0
  33. package/config/theme/fontFamily.ts +0 -5
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xy-planning-network/trees",
3
- "version": "0.9.9",
3
+ "version": "0.10.0",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "repository": "github:xy-planning-network/trees",
@@ -21,7 +21,7 @@
21
21
  "*.vue"
22
22
  ],
23
23
  "scripts": {
24
- "dev": "vite",
24
+ "dev": "vite --config vite.docs.config.ts",
25
25
  "build": "npm run lint && vue-tsc -p src --emitDeclarationOnly && vite build && npm run copy:types && tsc-alias -p src/tsconfig.json",
26
26
  "build:docs": "vue-tsc -p dev --noEmit && vite build --config vite.docs.config.ts",
27
27
  "copy:types": "copyfiles -f ./src/*.d.ts ./types",
@@ -34,7 +34,6 @@
34
34
  "typecheck:docs": "vue-tsc -p dev --noEmit"
35
35
  },
36
36
  "devDependencies": {
37
- "@point-hub/vue-highlight": "^0.1.4",
38
37
  "@rushstack/eslint-patch": "^1.2.0",
39
38
  "@tailwindcss/forms": "^0.5.3",
40
39
  "@tailwindcss/typography": "^0.5.7",
@@ -46,11 +45,14 @@
46
45
  "copyfiles": "^2.4.1",
47
46
  "eslint": "^8.42.0",
48
47
  "eslint-plugin-vue": "^9.14.1",
48
+ "markdown-it-prism": "^2.3.0",
49
49
  "postcss": "^8.4.21",
50
50
  "prettier": "^3.0.3",
51
51
  "tailwindcss": "^3.3.3",
52
52
  "tsc-alias": "^1.8.5",
53
53
  "typescript": "~5.4.5",
54
+ "unplugin-vue-components": "^0.27.4",
55
+ "unplugin-vue-markdown": "^0.25.2",
54
56
  "vite": "^4.3.9",
55
57
  "vue-tsc": "^2.0.29"
56
58
  },
package/src/index.css CHANGED
@@ -3,9 +3,14 @@
3
3
  @tailwind utilities;
4
4
 
5
5
  @layer base {
6
+ html {
7
+ @apply antialiased;
8
+ font-optical-sizing: auto;
9
+ }
10
+
6
11
  /* general body copy */
7
12
  body {
8
- @apply text-base leading-normal text-gray-900;
13
+ @apply text-base leading-normal text-gray-800; /* NOTE(spk): expecting this to eventually hold the xy-black value */
9
14
  }
10
15
 
11
16
  /* Headers */
@@ -37,32 +42,122 @@
37
42
  @layer components {
38
43
  /* Badge classes - TODO: handle anchor tag class cases and generic wrapper cases */
39
44
  .xy-badge {
40
- @apply inline-flex justify-center items-center px-2 py-0.5 rounded text-xs font-semibold bg-gray-100 text-gray-800;
45
+ @apply inline-flex justify-center items-center px-2 py-0.5 rounded-full text-xs font-semibold bg-gray-100 text-gray-800;
41
46
  }
42
47
 
43
48
  .xy-badge-blue {
44
- @apply inline-flex justify-center items-center px-2 py-0.5 rounded text-xs font-semibold bg-blue-100 text-blue-800;
49
+ @apply inline-flex justify-center items-center px-2 py-0.5 rounded-full text-xs font-semibold bg-blue-100 text-blue-800;
50
+ }
51
+
52
+ .xy-badge-green {
53
+ /* NOTE(spk): currently does not meet contrast ratio requirements */
54
+ @apply inline-flex justify-center items-center px-2 py-0.5 rounded-full text-xs font-semibold bg-xy-green-50/40 text-xy-green-900;
45
55
  }
46
56
 
47
57
  .xy-badge-yellow {
48
- @apply inline-flex justify-center items-center px-2 py-0.5 rounded text-xs font-semibold bg-yellow-100 text-yellow-800;
58
+ @apply inline-flex justify-center items-center px-2 py-0.5 rounded-full text-xs font-semibold bg-yellow-100 text-yellow-800;
59
+ }
60
+
61
+ /*
62
+ Button classes
63
+
64
+ NOTE(spk): prefer rounded-3xl to rounded-full to support line wrapping in buttons.
65
+ NOTE(spk): prefer a consistent focus ring color for tracking - best practice.
66
+ NOTE(spk): using opacity in disabled states fails contrast accessibility standards (revisit).
67
+ */
68
+ .xy-btn-sm {
69
+ @apply inline-flex justify-center items-center px-2.5 py-1.5 border border-transparent text-xs font-display font-semibold rounded-3xl shadow-sm text-white bg-xy-blue-600 hover:bg-xy-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-xy-blue-500 disabled:bg-xy-blue-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors ease-linear duration-300;
49
70
  }
50
71
 
51
- /* Button classes */
52
72
  .xy-btn {
53
- @apply inline-flex justify-center items-center px-4 py-2 border border-transparent text-sm font-semibold rounded-md shadow-md text-white bg-xy-blue-600 hover:bg-xy-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-xy-blue-500 disabled:opacity-50 disabled:cursor-not-allowed;
73
+ @apply inline-flex justify-center items-center px-4 py-2 border border-transparent text-sm font-display font-semibold rounded-3xl shadow-sm text-white bg-xy-blue-600 hover:bg-xy-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-xy-blue-500 disabled:bg-xy-blue-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors ease-linear duration-300;
54
74
  }
55
75
 
56
- .xy-btn-secondary {
57
- @apply inline-flex justify-center items-center px-4 py-2 border border-transparent text-sm font-semibold rounded-md shadow-md text-blue-700 bg-blue-100 hover:bg-blue-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50 disabled:cursor-not-allowed;
76
+ .xy-btn-lg {
77
+ @apply inline-flex justify-center items-center px-5 py-2.5 border border-transparent text-base font-display font-semibold rounded-3xl shadow-sm text-white bg-xy-blue-600 hover:bg-xy-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-xy-blue-500 disabled:bg-xy-blue-600 disabled:opacity-50 disabled:cursor-not-allowed transition-colors ease-linear duration-300;
58
78
  }
59
79
 
80
+ /* NOTE(spk): including .xy-btn-red alias for backwards compatibility */
81
+ .xy-btn-danger-sm,
82
+ .xy-btn-red-sm {
83
+ @apply inline-flex justify-center items-center px-2.5 py-1.5 border border-transparent text-xs font-display font-semibold rounded-3xl shadow-sm text-white bg-red-700 hover:bg-red-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-xy-blue-500 disabled:opacity-50 disabled:cursor-not-allowed transition-colors ease-linear duration-500;
84
+ }
85
+
86
+ .xy-btn-danger,
60
87
  .xy-btn-red {
61
- @apply inline-flex justify-center items-center px-4 py-2 border border-transparent text-xs md:text-sm font-semibold rounded-md shadow-md text-red-700 bg-red-100 hover:bg-red-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-300 disabled:opacity-50 disabled:cursor-not-allowed;
88
+ @apply inline-flex justify-center items-center px-4 py-2 border border-transparent text-sm font-display font-semibold rounded-3xl shadow-sm text-white bg-red-700 hover:bg-red-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-xy-blue-500 disabled:opacity-50 disabled:cursor-not-allowed transition-colors ease-linear duration-500;
89
+ }
90
+
91
+ .xy-btn-danger-lg,
92
+ .xy-btn-red-lg {
93
+ @apply inline-flex justify-center items-center px-5 py-2.5 border border-transparent text-base font-display font-semibold rounded-3xl shadow-sm text-white bg-red-700 hover:bg-red-800 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-xy-blue-500 disabled:opacity-50 disabled:cursor-not-allowed transition-colors ease-linear duration-500;
94
+ }
95
+
96
+ .xy-btn-neutral-sm {
97
+ @apply inline-flex justify-center items-center px-2.5 py-1.5 border border-transparent text-xs font-display font-semibold rounded-3xl shadow-none text-neutral-800 bg-neutral-100 hover:bg-neutral-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-xy-blue-500 disabled:bg-neutral-50 disabled:text-neutral-500 disabled:cursor-not-allowed transition-colors ease-linear duration-300;
98
+ }
99
+
100
+ .xy-btn-neutral {
101
+ @apply inline-flex justify-center items-center px-4 py-2 border border-transparent text-sm font-display font-semibold rounded-3xl shadow-none text-neutral-800 bg-neutral-100 hover:bg-neutral-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-xy-blue-500 disabled:bg-neutral-50 disabled:text-neutral-500 disabled:cursor-not-allowed transition-colors ease-linear duration-300;
102
+ }
103
+
104
+ .xy-btn-neutral-lg {
105
+ @apply inline-flex justify-center items-center px-5 py-2.5 border border-transparent text-base font-display font-semibold rounded-3xl shadow-none text-neutral-800 bg-neutral-100 hover:bg-neutral-200 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-xy-blue-500 disabled:bg-neutral-50 disabled:text-neutral-500 disabled:cursor-not-allowed transition-colors ease-linear duration-300;
106
+ }
107
+
108
+ /* NOTE(spk): always consider the relative box-sizing between buttons with solid backgrounds and full borders vs secondary styles as they will commonly be laid out next to each other */
109
+ /* NOTE(spk): there's no way to round a ring or outline in a focus state without rounding the entire button. Avoid this as it causes odd shapes on the bottom border and using content hacks aren't worth the trouble */
110
+ .xy-btn-secondary-sm {
111
+ @apply inline-flex justify-center items-center py-1.5 border-b-2 border-b-xy-blue-600 text-xs font-display font-semibold shadow-none text-neutral-800 hover:text-xy-blue-600 hover:border-b-transparent focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-xy-blue-500 disabled:text-neutral-800 disabled:border-b-xy-blue-600 disabled:opacity-70 disabled:cursor-not-allowed transition-colors ease-linear duration-150;
112
+ }
113
+
114
+ .xy-btn-secondary {
115
+ @apply inline-flex justify-center items-center py-2 border-b-2 border-b-xy-blue-600 text-sm font-display font-semibold shadow-none text-neutral-800 hover:text-xy-blue-600 hover:border-b-transparent focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-xy-blue-500 disabled:text-neutral-800 disabled:border-b-xy-blue-600 disabled:opacity-70 disabled:cursor-not-allowed transition-colors ease-linear duration-150;
116
+ }
117
+
118
+ .xy-btn-secondary-lg {
119
+ @apply inline-flex justify-center items-center py-2.5 border-b-2 border-b-xy-blue-600 text-base font-display font-semibold shadow-none text-neutral-800 hover:text-xy-blue-600 hover:border-b-transparent focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-xy-blue-500 disabled:text-neutral-800 disabled:border-b-xy-blue-600 disabled:opacity-70 disabled:cursor-not-allowed transition-colors ease-linear duration-150;
120
+ }
121
+
122
+ .xy-btn-accent-sm {
123
+ @apply inline-flex justify-center items-center py-1.5 border-b-2 border-b-xy-green text-xs font-display font-semibold shadow-none text-neutral-800 hover:text-xy-green-900 hover:border-b-transparent focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-xy-blue-500 disabled:text-neutral-800 disabled:border-b-xy-green disabled:opacity-70 disabled:cursor-not-allowed transition-colors ease-linear duration-150;
124
+ }
125
+
126
+ .xy-btn-accent {
127
+ @apply inline-flex justify-center items-center py-2 border-b-2 border-b-xy-green text-sm font-display font-semibold shadow-none text-neutral-800 hover:text-xy-green-900 hover:border-b-transparent focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-xy-blue-500 disabled:text-neutral-800 disabled:border-b-xy-green disabled:opacity-70 disabled:cursor-not-allowed transition-colors ease-linear duration-150;
128
+ }
129
+
130
+ .xy-btn-accent-lg {
131
+ @apply inline-flex justify-center items-center py-2.5 border-b-2 border-b-xy-green text-base font-display font-semibold shadow-none text-neutral-800 hover:text-xy-green-900 hover:border-b-transparent focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-xy-blue-500 disabled:text-neutral-800 disabled:border-b-xy-green disabled:opacity-70 disabled:cursor-not-allowed transition-colors ease-linear duration-150;
132
+ }
133
+
134
+ .xy-btn-accent-inverse-sm {
135
+ @apply inline-flex justify-center items-center py-1.5 border-b-2 border-b-xy-green text-xs font-display font-semibold shadow-none text-white hover:text-xy-green hover:border-b-transparent focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-xy-blue-500 disabled:text-white disabled:border-b-xy-green disabled:opacity-75 disabled:cursor-not-allowed transition-colors ease-linear duration-150;
136
+ }
137
+
138
+ .xy-btn-accent-inverse {
139
+ @apply inline-flex justify-center items-center py-2 border-b-2 border-b-xy-green text-sm font-display font-semibold shadow-none text-white hover:text-xy-green hover:border-b-transparent focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-xy-blue-500 disabled:text-white disabled:border-b-xy-green disabled:opacity-75 disabled:cursor-not-allowed transition-colors ease-linear duration-150;
140
+ }
141
+
142
+ .xy-btn-accent-inverse-lg {
143
+ @apply inline-flex justify-center items-center py-2.5 border-b-2 border-b-xy-green text-base font-display font-semibold shadow-none text-white hover:text-xy-green hover:border-b-transparent focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-xy-blue-500 disabled:text-white disabled:border-b-xy-green disabled:opacity-75 disabled:cursor-not-allowed transition-colors ease-linear duration-150;
144
+ }
145
+
146
+ .xy-btn-secondary-danger-sm {
147
+ @apply inline-flex justify-center items-center py-1.5 border-b-2 border-b-red-700 text-xs font-display font-semibold shadow-none text-neutral-800 hover:text-red-700 hover:border-b-transparent focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-xy-blue-500 disabled:text-neutral-800 disabled:border-b-red-700 disabled:opacity-70 disabled:cursor-not-allowed transition-colors ease-linear duration-150;
148
+ }
149
+
150
+ .xy-btn-secondary-danger {
151
+ @apply inline-flex justify-center items-center py-2 border-b-2 border-b-red-700 text-sm font-display font-semibold shadow-none text-neutral-800 hover:text-red-700 hover:border-b-transparent focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-xy-blue-500 disabled:text-neutral-800 disabled:border-b-red-700 disabled:opacity-70 disabled:cursor-not-allowed transition-colors ease-linear duration-150;
152
+ }
153
+
154
+ .xy-btn-secondary-danger-lg {
155
+ @apply inline-flex justify-center items-center py-2.5 border-b-2 border-b-red-700 text-base font-display font-semibold shadow-none text-neutral-800 hover:text-red-700 hover:border-b-transparent focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-xy-blue-500 disabled:text-neutral-800 disabled:border-b-red-700 disabled:opacity-70 disabled:cursor-not-allowed transition-colors ease-linear duration-150;
62
156
  }
63
157
 
158
+ /* Deprecated */
64
159
  .xy-btn-white {
65
- @apply inline-flex justify-center items-center px-4 py-2 border border-xy-blue shadow-md text-sm font-semibold rounded-md text-xy-blue bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-xy-blue-500 disabled:opacity-50 disabled:cursor-not-allowed;
160
+ @apply inline-flex justify-center items-center px-4 py-2 border border-xy-blue shadow-sm text-sm font-semibold rounded-3xl text-xy-blue bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-xy-blue-500 disabled:opacity-50 disabled:cursor-not-allowed;
66
161
  }
67
162
 
68
163
  /* Header classes */
@@ -108,7 +203,7 @@
108
203
 
109
204
  /* Link classes */
110
205
  .xy-link {
111
- @apply font-semibold underline text-xy-blue-600 hover:text-xy-blue-500;
206
+ @apply font-medium border-b-2 border-b-xy-blue hover:border-b-transparent hover:text-xy-blue;
112
207
  }
113
208
  }
114
209
 
@@ -34,7 +34,7 @@ const labelDisplay = computed((): string => {
34
34
  <component
35
35
  :is="tag"
36
36
  v-if="label"
37
- class="block text-base leading-snug font-medium text-gray-800"
37
+ class="block text-sm leading-6 font-semibold text-gray-800"
38
38
  v-bind="$attrs"
39
39
  >
40
40
  {{ labelDisplay }}
@@ -14,7 +14,7 @@ withDefaults(
14
14
  <component
15
15
  :is="tag"
16
16
  v-if="text"
17
- class="text-sm leading-snug font-normal text-gray-600"
17
+ class="text-sm leading-6 font-normal text-gray-600"
18
18
  v-bind="$attrs"
19
19
  >
20
20
  {{ text }}
@@ -85,7 +85,7 @@ const setValidationError = () => {
85
85
 
86
86
  <template>
87
87
  <fieldset
88
- class="relative space-y-4"
88
+ class="relative space-y-6"
89
89
  :aria-labelledby="aria.labelledby"
90
90
  :aria-describedby="aria.describedby"
91
91
  :aria-errormessage="aria.errormessage"
@@ -96,11 +96,16 @@ const setValidationError = () => {
96
96
  :label="label"
97
97
  :required="minCount > 0"
98
98
  />
99
- <InputHelp v-if="help" :id="aria.describedby" tag="p" :text="help" />
99
+ <InputHelp
100
+ v-if="help"
101
+ :id="aria.describedby"
102
+ class="mt-1"
103
+ tag="p"
104
+ :text="help"
105
+ />
106
+ <InputError :id="aria.errormessage" class="mt-1" :text="errorState" />
100
107
  </div>
101
108
 
102
- <InputError :id="aria.errormessage" :text="errorState" />
103
-
104
109
  <!--Hidden input for custom validation-->
105
110
  <input
106
111
  v-if="countError"
@@ -114,9 +119,9 @@ const setValidationError = () => {
114
119
 
115
120
  <div class="flex">
116
121
  <div
117
- class="grid gap-y-6"
122
+ class="grid gap-y-5"
118
123
  :class="{
119
- 'sm:grid sm:gap-x-5 sm:space-y-0': columns !== undefined,
124
+ 'sm:grid sm:gap-x-10': columns !== undefined,
120
125
  'sm:grid-cols-2': columns === 2,
121
126
  'sm:grid-cols-3': columns === 3,
122
127
  }"
@@ -36,7 +36,7 @@ const onChange = (e: Event, val: string | number) => {
36
36
 
37
37
  <template>
38
38
  <fieldset
39
- class="space-y-4"
39
+ class="space-y-6"
40
40
  :aria-labelledby="aria.labelledby"
41
41
  :aria-describedby="aria.describedby"
42
42
  :aria-errormessage="aria.errormessage"
@@ -47,16 +47,21 @@ const onChange = (e: Event, val: string | number) => {
47
47
  :label="label"
48
48
  :required="isRequired"
49
49
  />
50
- <InputHelp v-if="help" :id="aria.describedby" tag="p" :text="help" />
50
+ <InputHelp
51
+ v-if="help"
52
+ :id="aria.describedby"
53
+ class="mt-1"
54
+ tag="p"
55
+ :text="help"
56
+ />
57
+ <InputError :id="aria.errormessage" class="mt-1" :text="errorState" />
51
58
  </div>
52
59
 
53
- <InputError :id="aria.errormessage" :text="errorState" />
54
-
55
60
  <div class="flex">
56
61
  <div
57
- class="grid gap-y-6"
62
+ class="grid gap-y-5"
58
63
  :class="{
59
- 'sm:grid sm:gap-x-5 sm:space-y-0': columns !== undefined,
64
+ 'sm:grid sm:gap-x-10': columns !== undefined,
60
65
  'sm:grid-cols-2': columns === 2,
61
66
  'sm:grid-cols-3': columns === 3,
62
67
  }"
@@ -66,14 +66,14 @@ const onUpdate = (val: unknown) => {
66
66
  <FieldsetLegend tag="div" :label="label" :required="isRequired" />
67
67
  </RadioGroupLabel>
68
68
 
69
- <RadioGroupDescription v-if="help">
69
+ <RadioGroupDescription v-if="help" class="mt-1">
70
70
  <InputHelp :text="help" />
71
71
  </RadioGroupDescription>
72
72
 
73
- <InputError :id="aria.errormessage" :text="errorState" />
73
+ <InputError :id="aria.errormessage" class="mt-1" :text="errorState" />
74
74
 
75
75
  <div
76
- class="mt-4 grid grid-cols-1 gap-y-5 gap-x-4 relative"
76
+ class="mt-6 grid grid-cols-1 gap-y-5 gap-x-4 relative"
77
77
  :class="{
78
78
  'sm:grid-cols-2': columns === 2,
79
79
  'sm:grid-cols-3': columns === 3,
@@ -87,9 +87,9 @@ const onUpdate = (val: unknown) => {
87
87
  checked,
88
88
  disabled,
89
89
  }: {
90
- active: boolean,
91
- checked: boolean,
92
- disabled: boolean,
90
+ active: boolean
91
+ checked: boolean
92
+ disabled: boolean
93
93
  }"
94
94
  as="template"
95
95
  :disabled="isDisabled || option.disabled"
@@ -32,7 +32,7 @@ const onChange = (e: Event, val: boolean) => {
32
32
 
33
33
  <template>
34
34
  <fieldset
35
- class="space-y-4"
35
+ class="space-y-6"
36
36
  :aria-labelledby="aria.labelledby"
37
37
  :aria-describedby="aria.describedby"
38
38
  :aria-errormessage="aria.errormessage"
@@ -45,11 +45,16 @@ const onChange = (e: Event, val: boolean) => {
45
45
  :required="isRequired"
46
46
  tag="legend"
47
47
  />
48
- <InputHelp v-if="help" :id="aria.describedby" tag="p" :text="help" />
48
+ <InputHelp
49
+ v-if="help"
50
+ :id="aria.describedby"
51
+ class="mt-1"
52
+ tag="p"
53
+ :text="help"
54
+ />
55
+ <InputError :id="aria.errormessage" class="mt-1" :text="errorState" />
49
56
  </div>
50
57
 
51
- <InputError :id="aria.errormessage" :text="errorState" />
52
-
53
58
  <div>
54
59
  <label
55
60
  class="inline-flex items-center group"
@@ -116,7 +116,7 @@ const icon = computed(() => {
116
116
  </script>
117
117
 
118
118
  <template>
119
- <div v-if="visible" class="rounded-lg p-4" :class="display.bgColor">
119
+ <div v-if="visible" class="rounded-xy p-4" :class="display.bgColor">
120
120
  <div class="flex">
121
121
  <div class="flex-shrink-0">
122
122
  <component
@@ -152,7 +152,7 @@ const icon = computed(() => {
152
152
  >
153
153
  <div v-if="btnText">
154
154
  <a
155
- class="inline-flex rounded-md px-2 py-1.5 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-offset-2"
155
+ class="inline-flex rounded-3xl px-2.5 py-1.5 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-offset-2"
156
156
  :class="display.btnAction"
157
157
  :href="btnLink"
158
158
  :role="btnLink ? 'link' : 'button'"
@@ -163,7 +163,7 @@ const icon = computed(() => {
163
163
  </div>
164
164
  <div v-if="secondaryBtnText">
165
165
  <a
166
- class="inline-flex rounded-md px-2 py-1.5 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-offset-2"
166
+ class="inline-flex rounded-3xl px-2.5 py-1.5 text-sm font-medium focus:outline-none focus:ring-2 focus:ring-offset-2"
167
167
  :class="display.btnAction"
168
168
  :href="secondaryBtnLink"
169
169
  :role="secondaryBtnLink ? 'link' : 'button'"
@@ -0,0 +1,87 @@
1
+ <script setup lang="ts">
2
+ import { CheckIcon } from "@heroicons/vue/solid"
3
+ import { computed } from "vue"
4
+
5
+ type StepStatus = "complete" | "current" | "incomplete"
6
+
7
+ interface Step {
8
+ name: string
9
+ description?: string
10
+ }
11
+
12
+ const props = defineProps<{
13
+ /**
14
+ * current sets the "current" step using an index of the steps prop
15
+ * to show all steps in an "incomplete" state set step to -1
16
+ * to show all steps in an "complete" state set step to a value >= steps.length
17
+ */
18
+ current: number
19
+ steps: Step[]
20
+ }>()
21
+
22
+ const layoutSteps = computed(() => {
23
+ return props.steps.map((step, stepIndex) => {
24
+ let status: StepStatus
25
+
26
+ if (props.current > stepIndex) {
27
+ status = "complete"
28
+ } else if (props.current === stepIndex) {
29
+ status = "current"
30
+ } else {
31
+ status = "incomplete"
32
+ }
33
+
34
+ return {
35
+ name: step.name,
36
+ description: step?.description || "",
37
+ status: status,
38
+ }
39
+ })
40
+ })
41
+ </script>
42
+
43
+ <template>
44
+ <nav aria-label="Progress">
45
+ <ol role="list" class="flex items-center">
46
+ <li
47
+ v-for="(step, index) in layoutSteps"
48
+ :key="step.name"
49
+ :class="[index !== layoutSteps.length - 1 ? 'pr-8' : '', 'relative']"
50
+ >
51
+ <!--NOTE: horizontal connecting bar-->
52
+ <div class="absolute inset-0 flex items-center" aria-hidden="true">
53
+ <div
54
+ :class="[
55
+ 'h-0.5 w-full',
56
+ step.status === 'complete' ? 'bg-xy-blue' : 'bg-gray-300',
57
+ ]"
58
+ />
59
+ </div>
60
+ <div
61
+ :class="{
62
+ 'relative flex h-5 w-5 items-center justify-center rounded-full': true,
63
+ 'bg-xy-blue': step.status === 'complete',
64
+ 'border-2 border-indigo-600 bg-white': step.status === 'current',
65
+ 'border-2 border-gray-300 bg-white': step.status === 'incomplete',
66
+ }"
67
+ :aria-current="step.status === 'current' ? true : undefined"
68
+ >
69
+ <CheckIcon
70
+ v-if="step.status === 'complete'"
71
+ class="h-3 w-3 text-white"
72
+ aria-hidden="true"
73
+ />
74
+ <span
75
+ v-else-if="step.status === 'current'"
76
+ class="h-3 w-3 rounded-full bg-xy-blue"
77
+ aria-hidden="true"
78
+ />
79
+ <span class="sr-only">{{ step.name }}</span>
80
+ <span v-if="step.description" class="sr-only">{{
81
+ step.description
82
+ }}</span>
83
+ </div>
84
+ </li>
85
+ </ol>
86
+ </nav>
87
+ </template>
@@ -0,0 +1,104 @@
1
+ <script setup lang="ts">
2
+ import { CheckIcon } from "@heroicons/vue/solid"
3
+ import { computed } from "vue"
4
+
5
+ type StepStatus = "complete" | "current" | "incomplete"
6
+
7
+ interface Step {
8
+ name: string
9
+ description?: string
10
+ }
11
+
12
+ const props = defineProps<{
13
+ /**
14
+ * current sets the "current" step using an index of the steps prop
15
+ * to show all steps in an "incomplete" state set step to -1
16
+ * to show all steps in an "complete" state set step to a value >= steps.length
17
+ */
18
+ current: number
19
+ steps: Step[]
20
+ }>()
21
+
22
+ const layoutSteps = computed(() => {
23
+ return props.steps.map((step, stepIndex) => {
24
+ let status: StepStatus
25
+
26
+ if (props.current > stepIndex) {
27
+ status = "complete"
28
+ } else if (props.current === stepIndex) {
29
+ status = "current"
30
+ } else {
31
+ status = "incomplete"
32
+ }
33
+
34
+ return {
35
+ name: step.name,
36
+ description: step?.description || "",
37
+ status: status,
38
+ }
39
+ })
40
+ })
41
+ </script>
42
+
43
+ <template>
44
+ <div aria-label="Progress">
45
+ <ol role="list" class="overflow-hidden">
46
+ <li
47
+ v-for="(step, index) in layoutSteps"
48
+ :key="index"
49
+ :class="[index !== layoutSteps.length - 1 ? 'pb-6' : '', 'relative']"
50
+ >
51
+ <!--NOTE: vertical connecting bar-->
52
+ <div
53
+ v-if="index !== layoutSteps.length - 1"
54
+ :class="[
55
+ 'absolute left-4 top-4 -ml-px mt-0.5 h-full w-0.5',
56
+ step.status === 'complete' ? 'bg-xy-blue' : 'bg-gray-300',
57
+ ]"
58
+ aria-hidden="true"
59
+ />
60
+ <div
61
+ class="group relative flex items-start"
62
+ :aria-current="step.status === 'current' ? true : undefined"
63
+ >
64
+ <span class="flex h-9 items-center">
65
+ <span
66
+ :class="{
67
+ 'relative z-10 flex h-8 w-8 items-center justify-center rounded-full': true,
68
+ 'bg-xy-blue ': step.status === 'complete',
69
+ 'border-2 border-xy-blue bg-white': step.status === 'current',
70
+ 'border-2 border-gray-300 bg-white':
71
+ step.status === 'incomplete',
72
+ }"
73
+ >
74
+ <CheckIcon
75
+ v-if="step.status === 'complete'"
76
+ class="h-5 w-5 text-white"
77
+ aria-hidden="true"
78
+ />
79
+ <span
80
+ v-else-if="step.status === 'current'"
81
+ class="h-2.5 w-2.5 rounded-full bg-xy-blue"
82
+ />
83
+ </span>
84
+ </span>
85
+ <span class="ml-4 flex min-w-0 flex-col">
86
+ <span
87
+ :class="{
88
+ 'text-sm font-bold': true,
89
+ 'text-gray-800': step.status === 'complete',
90
+ 'text-xy-blue': step.status === 'current',
91
+ 'text-gray-600': step.status === 'incomplete',
92
+ 'mt-2': !step.description,
93
+ }"
94
+ >{{ step.name }}</span
95
+ >
96
+ <span v-if="step.description" class="text-sm text-gray-600">{{
97
+ step.description
98
+ }}</span>
99
+ </span>
100
+ </div>
101
+ </li>
102
+ </ol>
103
+ </div>
104
+ </template>