Skip to content

Commit 734a35a

Browse files
committed
feat: improved how attributes are passed to wrappers
BREAKING CHANGE: anything that previously used *Attrs properties to pass attributes needs to be changed to *-property-name, so :wrapperAttrs="{class:``}" becomes wrapper-class. BREAKING CHANGE: Font awesome wrapper no longer has fixed-width attribute by default.
1 parent 9acbd9e commit 734a35a

File tree

9 files changed

+300
-205
lines changed

9 files changed

+300
-205
lines changed

README.md

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ Everything can just be done from the config. Nuxt will automatically import the
3333
In `main.ts` or where vue is mounted:
3434

3535
```ts
36-
// a global style import is required to get the component styles working if not using tailwind
37-
// import "@alanscodelog/vue-components/style.css" // currently broken, vite is not properly resolving css imports
38-
import "../node_modules/@alanscodelog/vue-components/dist/style.css"
36+
// if NOT using tailwind a global style import is required to get the component styles working
37+
// import "../node_modules/@alanscodelog/vue-components/dist/style.css"
38+
// proper import is currently broken, vite is not properly resolving css imports
3939

4040
// import plugin
4141
import { MyLibPlugin } from "@alanscodelog/vue-components"
@@ -73,18 +73,25 @@ You should also be able to use tailwind directly instead of importing the styles
7373
You can use the exported config and merge it with your own if needed.
7474

7575
```ts
76-
import componentsConfig from "@alanscodelog/vue-components/tailwind/config.js"
77-
import { theme } from "./lib/general/theme.js"
7876

79-
export default {
80-
...componentsConfig,
81-
// ... your config
77+
import { config } from "@alanscodelog/vue-components/tailwind/config.js"
78+
79+
export default {
80+
...config,
81+
content: [
82+
...config.content,
83+
"./index.html",
84+
"./src/**/*.{vue,js,ts,jsx,tsx}",
85+
// be sure to add this or tailwind will not include the classes in the component library
86+
"./node_modules/@alanscodelog/vue-components/**/*.{vue,js,ts,jsx,tsx}",
87+
],
8288
plugins: [
83-
// ...your plugins
84-
...componentsConfig.plugins
89+
...config.plugins
8590
]
8691
}
8792

93+
94+
8895
```
8996

9097
If you need to setup the config completely from scratch the package provides a plugin `@alanscodelog/vue-components/tailwind/plugin.js` that sets up a few utility classes\*. It also requires setting up the theming library. The options it uses are exported for easy re-use.
@@ -102,6 +109,7 @@ import {
102109

103110
const config = {
104111
darkMode: "class",
112+
content: [/* ... */],
105113
plugins: [
106114
// integration with my theme library
107115
createTailwindPlugin(theme, themePluginOpts),

src/components/LibButton/LibButton.stories.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,20 +24,27 @@ export const Primary: Story = {
2424
template: `
2525
<div class="flex gap-4 justify-center">
2626
<template v-for="type of [false, 'ok', 'warning', 'danger', 'primary', 'secondary' ]">
27-
<lib-button v-bind="{...args, color: type, label: args.label + ' ' + capitalize(type || 'false')}">
27+
<lib-button v-bind="{...args, color: type, label: !args.label ? undefined : args.label + ' ' + capitalize(type || 'false')}" icon-fixed-width>
2828
</lib-button>
2929
</template>
3030
</div>
3131
<div class="flex flex-col gap-4 pt-10">
3232
<template v-for="type of [false, 'ok', 'warning', 'danger', 'primary', 'secondary']">
33-
<lib-button v-bind="{...args, color: type , label: args.label + ' ' + capitalize(type || 'false') }">
33+
<lib-button v-bind="{...args, color: type , label: !args.label ? undefined : args.label + ' ' + capitalize(type || 'false') }" icon-fixed-width>
3434
</lib-button>
3535
</template>
3636
</div>
3737
`,
3838
}),
3939
}
4040

41+
export const OnlyIcon: Story = {
42+
...Primary,
43+
args: {
44+
...Primary.args,
45+
label: undefined,
46+
},
47+
}
4148
export const Disabled: Story = {
4249
...Primary,
4350
args: {

src/components/LibButton/LibButton.vue

Lines changed: 133 additions & 116 deletions
Original file line numberDiff line numberDiff line change
@@ -23,135 +23,135 @@
2323
`,
2424
!color && `active:text-neutral-800` /* todo for colors */,
2525
border && `
26-
transition-all
27-
bg-neutral-100
28-
shadow-[0_1px_1px_0]
29-
shadow-neutral-950/20
30-
hover:shadow-[0_1px_3px_0]
31-
hover:shadow-neutral-950/30
32-
hover:border-neutral-300
33-
34-
relative
35-
after:absolute
36-
after:rounded
37-
after:inset-0
38-
after:content
39-
after:shadow-[0_1px_0_0_inset]
40-
after:shadow-bg/20
41-
hover:after:shadow-bg/60
42-
dark:after:shadow-bg/10
43-
dark:hover:after:shadow-bg/50
44-
after:pointer-events-none
45-
after:mix-blend-overlay
46-
47-
active:shadow-inner
48-
active:shadow-fg/20
49-
active:border-transparent
50-
border
51-
border-neutral-400
52-
disabled:border-neutral-200
53-
disabled:bg-neutral-50
54-
55-
dark:hover:shadow-accent-950/30
56-
dark:active:shadow-fg/40
57-
dark:active:border-neutral-900
58-
dark:bg-neutral-800
59-
dark:border-neutral-900
60-
dark:disabled:border-neutral-800
61-
dark:disabled:bg-neutral-900
62-
`,
26+
transition-all
27+
bg-neutral-100
28+
shadow-[0_1px_1px_0]
29+
shadow-neutral-950/20
30+
hover:shadow-[0_1px_3px_0]
31+
hover:shadow-neutral-950/30
32+
hover:border-neutral-300
33+
34+
relative
35+
after:absolute
36+
after:rounded
37+
after:inset-0
38+
after:content
39+
after:shadow-[0_1px_0_0_inset]
40+
after:shadow-bg/20
41+
hover:after:shadow-bg/60
42+
dark:after:shadow-bg/10
43+
dark:hover:after:shadow-bg/50
44+
after:pointer-events-none
45+
after:mix-blend-overlay
46+
47+
active:shadow-inner
48+
active:shadow-fg/20
49+
active:border-transparent
50+
border
51+
border-neutral-400
52+
disabled:border-neutral-200
53+
disabled:bg-neutral-50
54+
55+
dark:hover:shadow-accent-950/30
56+
dark:active:shadow-fg/40
57+
dark:active:border-neutral-900
58+
dark:bg-neutral-800
59+
dark:border-neutral-900
60+
dark:disabled:border-neutral-800
61+
dark:disabled:bg-neutral-900
62+
`,
6363
border && ( !color || color === `secondary` ) && `
6464
after:shadow-bg/90
6565
hover:after:shadow-bg
6666
dark:after:shadow-bg/20
6767
dark:hover:after:shadow-bg/90
6868
`,
6969
!border && color === `primary` && `
70-
font-bold
71-
hover:text-accent-50
72-
`,
70+
font-bold
71+
hover:text-accent-50
72+
`,
7373
!border && color === `ok` && `
74-
text-ok-600 hover:text-ok-500
75-
dark:text-ok-600 dark:hover:text-ok-500
76-
`,
74+
text-ok-600 hover:text-ok-500
75+
dark:text-ok-600 dark:hover:text-ok-500
76+
`,
7777
!border && color === `warning` && `
7878
text-warning-500 hover:text-warning-300
7979
dark:text-warning-600 dark:hover:text-warning-400
8080
`,
8181
!border && color === `danger` && `
82-
text-danger-500 hover:text-danger-300
83-
dark:text-danger-600 dark:hover:text-danger-400
84-
`,
82+
text-danger-500 hover:text-danger-300
83+
dark:text-danger-600 dark:hover:text-danger-400
84+
`,
8585
!border && color === `secondary` && `
86-
text-accent-700 hover:text-accent-500
87-
dark:text-accent-600 dark:hover:text-accent-400
88-
`,
86+
text-accent-700 hover:text-accent-500
87+
dark:text-accent-600 dark:hover:text-accent-400
88+
`,
8989
!border && color === `primary` && `
90-
text-accent-700 hover:text-accent-500
91-
dark:text-accent-600 dark:hover:text-accent-400
92-
`,
90+
text-accent-700 hover:text-accent-500
91+
dark:text-accent-600 dark:hover:text-accent-400
92+
`,
9393
border && color === `ok` && `
94-
text-ok-950
95-
hover:text-ok-800
96-
bg-ok-400
97-
border-ok-500
98-
hover:border-ok-600
99-
hover:shadow-ok-900/50
100-
101-
dark:text-ok-100
102-
dark:hover:text-ok-200
103-
dark:bg-ok-700
104-
dark:border-ok-800
105-
dark:hover:border-ok-900
106-
dark:hover:shadow-ok-900/30
107-
`,
94+
text-ok-950
95+
hover:text-ok-800
96+
bg-ok-400
97+
border-ok-500
98+
hover:border-ok-600
99+
hover:shadow-ok-900/50
100+
101+
dark:text-ok-100
102+
dark:hover:text-ok-200
103+
dark:bg-ok-700
104+
dark:border-ok-800
105+
dark:hover:border-ok-900
106+
dark:hover:shadow-ok-900/30
107+
`,
108108
border && color === `warning` && `
109-
text-warning-950
110-
hover:text-warning-900
111-
bg-warning-300
112-
border-warning-400
113-
hover:border-warning-400
114-
hover:shadow-warning-900/50
115-
116-
dark:text-warning-100
117-
dark:hover:text-warning-200
118-
dark:bg-warning-700
119-
dark:border-warning-700
120-
dark:hover:shadow-warning-900/25
121-
`,
109+
text-warning-950
110+
hover:text-warning-900
111+
bg-warning-300
112+
border-warning-400
113+
hover:border-warning-400
114+
hover:shadow-warning-900/50
115+
116+
dark:text-warning-100
117+
dark:hover:text-warning-200
118+
dark:bg-warning-700
119+
dark:border-warning-700
120+
dark:hover:shadow-warning-900/25
121+
`,
122122
border && color === `danger` && `
123-
text-danger-950
124-
hover:text-danger-900
125-
bg-danger-400
126-
border-danger-500
127-
hover:border-danger-500
128-
hover:shadow-red-900/50
129-
130-
dark:text-danger-100
131-
dark:hover:text-danger-200
132-
dark:bg-danger-900
133-
dark:border-danger-950
134-
dark:hover:shadow-red-500/10
135-
`,
123+
text-danger-950
124+
hover:text-danger-900
125+
bg-danger-400
126+
border-danger-500
127+
hover:border-danger-500
128+
hover:shadow-red-900/50
129+
130+
dark:text-danger-100
131+
dark:hover:text-danger-200
132+
dark:bg-danger-900
133+
dark:border-danger-950
134+
dark:hover:shadow-red-500/10
135+
`,
136136
border && color === `secondary` && `
137-
text-accent-800
138-
dark:text-accent-400
139-
`,
137+
text-accent-800
138+
dark:text-accent-400
139+
`,
140140
border && color === `primary` && `
141-
text-bg
142-
hover:text-bg
143-
bg-accent-600
144-
border-accent-700
145-
hover:border-accent-800
146-
hover:shadow-accent-950/30
147-
148-
dark:text-bg
149-
dark:bg-accent-600
150-
dark:hover:text-accent-200
151-
dark:border-accent-800
152-
dark:hover:border-accent-700
153-
dark:hover:shadow-accent-900/50
154-
`,
141+
text-bg
142+
hover:text-bg
143+
bg-accent-600
144+
border-accent-700
145+
hover:border-accent-800
146+
hover:shadow-accent-950/30
147+
148+
dark:text-bg
149+
dark:bg-accent-600
150+
dark:hover:text-accent-200
151+
dark:border-accent-800
152+
dark:hover:border-accent-700
153+
dark:hover:shadow-accent-900/50
154+
`,
155155
$attrs.class as any
156156
)"
157157
:type="$attrs.type ?? 'submit'"
@@ -160,18 +160,24 @@
160160
:data-border="border"
161161
:data-color="color"
162162
:aria-disabled="disabled"
163-
:aria-labelledby="label ? `label-${id}` : undefined"
164-
v-bind="{ ...$attrs, class: undefined, ...listeners }"
163+
v-bind="{
164+
...autoTitle,
165+
...$attrs,
166+
class: undefined,
167+
...listeners,
168+
...ariaLabel,
169+
}"
165170
>
166-
<label :id="`label-${id}`" class="label pointer-events-none flex flex-1 items-center justify-center">
171+
<label :id="`label-${id}`" class="label pointer-events-none flex flex-1 items-center justify-center gap-1">
167172
<slot>
168-
<slot name="icon">
173+
<slot name="icon" v-bind="{icon, ...iconAttrs}">
169174
<fa v-if="icon"
170175
:icon="icon"
171-
class="slot before:content-vertical-holder peer flex items-center justify-center"
176+
v-bind="{...iconAttrs}"
177+
class="slot before:content-vertical-holder flex items-center justify-center"
172178
/>
173179
</slot>
174-
<span v-if="!isBlank(label)" class="peer-[.icon]:pl-2">
180+
<span v-if="!isBlank(label)">
175181
{{ label }}
176182
</span>
177183
</slot>
@@ -182,17 +188,20 @@
182188
import { isBlank, keys, pick } from "@alanscodelog/utils"
183189
import { computed, type PropType, useAttrs } from "vue"
184190
191+
import { useAriaLabel } from "../../composables/useAriaLabel.js"
192+
import { useDivideAttrs } from "../../composables/useDivideAttrs.js"
185193
import { twMerge } from "../../helpers/twMerge.js"
186194
import fa from "../fa/Fa.vue"
187195
import { baseInteractiveProps, fallthroughEventProps, labelProp, linkableByIdProps } from "../shared/props.js"
188196
189197
190-
const $attrs = useAttrs()
198+
const { $attrs, iconAttrs } = useDivideAttrs(useAttrs(), ["icon"])
191199
192200
defineOptions({
193201
name: "lib-button",
194202
})
195203
204+
/** Attributes can be passed to the icon by prefixing with icon- */
196205
const props = defineProps({
197206
...linkableByIdProps(),
198207
...labelProp,
@@ -202,9 +211,17 @@ const props = defineProps({
202211
icon: { type: String, required: false, default: undefined },
203212
color: { type: [String, Boolean] as PropType<"warning" | "ok" | "danger" | "primary" | "secondary" | false>, required: false, default: false },
204213
unstyle: { type: Boolean, required: false, default: false },
214+
autoTitleFromAria: Boolean,
215+
test: Boolean,
205216
})
206217
207218
const listeners = computed(() => pick(props, keys(fallthroughEventProps) as any) as any)
208219
220+
const ariaLabel = useAriaLabel(props)
221+
222+
const autoTitle = computed(() => ({
223+
title: props.autoTitleFromAria && ($attrs["aria-label"] ?? props.label),
224+
}))
225+
209226
</script>
210227

0 commit comments

Comments
 (0)