@imaginario27/air-ui-ds 1.0.16 → 1.0.17

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.
@@ -0,0 +1,104 @@
1
+ <template>
2
+ <footer
3
+ :class="[
4
+ 'w-full',
5
+ 'bg-background-surface',
6
+ 'py-section-xs',
7
+ hasSidePadding && 'px-content-side-padding-mobile md:px-content-side-padding',
8
+ ]"
9
+ >
10
+ <MaxWidthContainer
11
+ :class="[!hasContentMaxWidth && '!max-w-full']"
12
+ >
13
+ <template v-if="!$slots['default']">
14
+ <div
15
+ :class="[
16
+ 'w-full',
17
+ 'flex',
18
+ 'flex-col',
19
+ isMobileCentered &&'items-center text-center',
20
+ 'gap-10',
21
+ 'lg:flex-row',
22
+ 'lg:items-start',
23
+ 'lg:text-left',
24
+ 'lg:justify-between',
25
+ ]"
26
+ >
27
+ <span class="text-sm text-text-neutral-subtle">
28
+ {{ credits }}
29
+ </span>
30
+
31
+ <nav v-if="menuItems?.length">
32
+ <ul class="flex flex-col lg:flex-row gap-5">
33
+ <li
34
+ v-for="(item, index) in menuItems"
35
+ :key="index"
36
+ >
37
+ <NuxtLink
38
+ :to="item.to"
39
+ :class="[
40
+ 'text-sm',
41
+ 'hover:text-text-primary-brand-hover',
42
+ 'transition-colors',
43
+ ]"
44
+ >
45
+ {{ item.text }}
46
+ </NuxtLink>
47
+ </li>
48
+ </ul>
49
+ </nav>
50
+
51
+ <div v-if="socialNetworks?.length" class="flex gap-5">
52
+ <a
53
+ v-for="(network, index) in socialNetworks"
54
+ :key="index"
55
+ :href="network.link"
56
+ target="_blank"
57
+ rel="noopener noreferrer"
58
+ :class="[
59
+ 'text-text-neutral-subtle',
60
+ 'hover:text-text-primary-brand-hover',
61
+ 'transition-colors',
62
+ ]"
63
+ :aria-label="network.name"
64
+ >
65
+ <img
66
+ :src="network.icon"
67
+ :alt="`${network.name} icon`"
68
+ width="20"
69
+ height="20"
70
+ class="min-w-[20px] min-h-[20px]"
71
+ />
72
+ </a>
73
+ </div>
74
+ </div>
75
+ </template>
76
+ <template v-else>
77
+ <slot />
78
+ </template>
79
+ </MaxWidthContainer>
80
+ </footer>
81
+ </template>
82
+ <script setup lang="ts">
83
+ // Props
84
+ defineProps({
85
+ credits: {
86
+ type: String as PropType<string>,
87
+ default: '© <year> <your-company>. All rights reserved.',
88
+ },
89
+ menuItems: Array as PropType<MenuItem[]>,
90
+ socialNetworks: Array as PropType<SocialNetwork[]>,
91
+ hasContentMaxWidth: {
92
+ type: Boolean as PropType<boolean>,
93
+ default: false,
94
+ },
95
+ hasSidePadding: {
96
+ type: Boolean as PropType<boolean>,
97
+ default: true,
98
+ },
99
+ isMobileCentered: {
100
+ type: Boolean as PropType<boolean>,
101
+ default: false,
102
+ },
103
+ })
104
+ </script>
@@ -3,26 +3,32 @@
3
3
  :class="[
4
4
  'w-full flex flex-col',
5
5
  alignmentClasses,
6
- titleClass,
7
6
  ]"
8
7
  >
9
8
  <!-- Overtitle -->
10
- <p
9
+ <span
11
10
  v-if="overtitle"
12
11
  :class="[
13
12
  'font-semibold',
14
13
  overtitleSizeClass,
15
14
  'text-text-secondary-brand-default',
16
15
  spaceOvertitleClass,
16
+ isOverTitleUppercase && 'uppercase',
17
+ overtitleClass,
17
18
  ]"
18
19
  >
19
20
  {{ overtitle }}
20
- </p>
21
+ </span>
21
22
 
22
23
  <!-- Dynamic title -->
23
24
  <component
24
25
  :is="headingTag"
25
- :class="[titleSizeClass, 'font-semibold', 'text-text-default']"
26
+ :class="[
27
+ titleSizeClass,
28
+ 'font-semibold',
29
+ 'text-text-default',
30
+ titleClass,
31
+ ]"
26
32
  >
27
33
  {{ title }}
28
34
  </component>
@@ -30,7 +36,12 @@
30
36
  <!-- Description -->
31
37
  <p
32
38
  v-if="description"
33
- :class="[descriptionSizeClass, 'text-text-neutral-subtle', spaceDescriptionClass]"
39
+ :class="[
40
+ descriptionSizeClass,
41
+ 'text-text-neutral-subtle',
42
+ spaceDescriptionClass,
43
+ descriptionClass,
44
+ ]"
34
45
  >
35
46
  {{ description }}
36
47
  </p>
@@ -41,6 +52,10 @@
41
52
  // Props
42
53
  const props = defineProps({
43
54
  overtitle: String as PropType<string>,
55
+ isOverTitleUppercase: {
56
+ type: Boolean as PropType<boolean>,
57
+ default: false,
58
+ },
44
59
  title: {
45
60
  type: String as PropType<string>,
46
61
  default: 'Heading title'
@@ -64,15 +79,17 @@ const props = defineProps({
64
79
  Object.values(HeadingSpacing).includes(value as HeadingSpacing),
65
80
  },
66
81
  headingTag: {
67
- type: [String, Number] as PropType<'h1' | 'h2' | 'h3'>,
82
+ type: [String, Number] as PropType<'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'>,
68
83
  default: 'h1',
69
- validator: (value: string | number) => ['h1', 'h2', 'h3'].includes(value as string)
84
+ validator: (value: string | number) => ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'].includes(value as string)
70
85
  },
71
86
  isMobileCentered: {
72
87
  type: Boolean as PropType<boolean>,
73
88
  default: false,
74
89
  },
90
+ overtitleClass: String as PropType<string>,
75
91
  titleClass: String as PropType<string>,
92
+ descriptionClass: String as PropType<string>,
76
93
  })
77
94
 
78
95
  // Computed classes
@@ -100,6 +117,8 @@ const alignmentClasses = computed(() => {
100
117
 
101
118
  const titleSizeClass = computed(() => {
102
119
  const map = {
120
+ [HeadingSize.XXS]: 'text-lg',
121
+ [HeadingSize.XS]: 'text-xl',
103
122
  [HeadingSize.SM]: 'text-2xl',
104
123
  [HeadingSize.MD]: 'text-3xl md:text-4xl',
105
124
  [HeadingSize.LG]: 'text-4xl md:text-5xl',
@@ -110,6 +129,8 @@ const titleSizeClass = computed(() => {
110
129
 
111
130
  const overtitleSizeClass = computed(() => {
112
131
  const map = {
132
+ [HeadingSize.XXS]: 'text-xs',
133
+ [HeadingSize.XS]: 'text-sm',
113
134
  [HeadingSize.SM]: 'text-sm',
114
135
  [HeadingSize.MD]: 'text-base',
115
136
  [HeadingSize.LG]: 'text-base',
@@ -120,6 +141,8 @@ const overtitleSizeClass = computed(() => {
120
141
 
121
142
  const descriptionSizeClass = computed(() => {
122
143
  const map = {
144
+ [HeadingSize.XXS]: 'text-sm',
145
+ [HeadingSize.XS]: 'text-sm',
123
146
  [HeadingSize.SM]: 'text-sm',
124
147
  [HeadingSize.MD]: 'text-lg',
125
148
  [HeadingSize.LG]: 'text-lg',
@@ -130,6 +153,8 @@ const descriptionSizeClass = computed(() => {
130
153
 
131
154
  const spaceOvertitleClass = computed(() => {
132
155
  const map = {
156
+ [HeadingSize.XXS]: 'mb-1',
157
+ [HeadingSize.XS]: 'mb-1',
133
158
  [HeadingSize.SM]: 'mb-1',
134
159
  [HeadingSize.MD]: 'mb-3',
135
160
  [HeadingSize.LG]: 'mb-3',
@@ -140,12 +165,16 @@ const spaceOvertitleClass = computed(() => {
140
165
 
141
166
  const spaceDescriptionClass = computed(() => {
142
167
  const normal = {
168
+ [HeadingSize.XXS]: 'mt-3',
169
+ [HeadingSize.XS]: 'mt-3',
143
170
  [HeadingSize.SM]: 'mt-3',
144
171
  [HeadingSize.MD]: 'mt-4',
145
172
  [HeadingSize.LG]: 'mt-6',
146
173
  [HeadingSize.XL]: 'mt-4',
147
174
  }
148
175
  const spaced = {
176
+ [HeadingSize.XXS]: 'mt-4',
177
+ [HeadingSize.XS]: 'mt-4',
149
178
  [HeadingSize.SM]: 'mt-4',
150
179
  [HeadingSize.MD]: 'mt-5',
151
180
  [HeadingSize.LG]: 'mt-9',
@@ -1,7 +1,7 @@
1
1
  <template>
2
2
  <span
3
3
  :class="[
4
- 'text-text-primary-brand-default',
4
+ colorClass,
5
5
  'text-sm',
6
6
  'font-medium',
7
7
  isUppercase && 'uppercase',
@@ -12,7 +12,7 @@
12
12
  </template>
13
13
  <script setup lang="ts">
14
14
  // Props
15
- defineProps({
15
+ const props = defineProps({
16
16
  title: {
17
17
  type: String as PropType<string>,
18
18
  default: 'Overtitle'
@@ -20,6 +20,32 @@ defineProps({
20
20
  isUppercase: {
21
21
  type: Boolean as PropType<boolean>,
22
22
  default: true,
23
+ },
24
+ color: {
25
+ type: String as PropType<
26
+ ColorAccent.PRIMARY_BRAND
27
+ | ColorAccent.SECONDARY_BRAND
28
+ | ColorAccent.NEUTRAL
29
+ >,
30
+ default: ColorAccent.SECONDARY_BRAND,
31
+ validator: (value: unknown): value is ColorAccent => {
32
+ return typeof value === 'string' &&
33
+ [
34
+ ColorAccent.PRIMARY_BRAND,
35
+ ColorAccent.SECONDARY_BRAND,
36
+ ColorAccent.NEUTRAL,
37
+ ].includes(value as ColorAccent)
38
+ },
39
+ },
40
+ })
41
+
42
+ const colorClass = computed(() => {
43
+ const variant: Partial<Record<ColorAccent, string>> = {
44
+ [ColorAccent.NEUTRAL]: 'text-text-default',
45
+ [ColorAccent.PRIMARY_BRAND]: 'text-text-primary-brand-default',
46
+ [ColorAccent.SECONDARY_BRAND]: 'text-text-secondary-brand-default',
23
47
  }
48
+
49
+ return variant[props.color as ColorAccent] || 'text-text-secondary-brand-default'
24
50
  })
25
51
  </script>
@@ -67,7 +67,6 @@ defineProps({
67
67
  default: true,
68
68
  },
69
69
  description: String as PropType<string>,
70
-
71
70
  hasGoBackLink: {
72
71
  type: Boolean as PropType<boolean>,
73
72
  default: false,
@@ -1,4 +1,6 @@
1
1
  export enum HeadingSize {
2
+ XXS = 'xxs',
3
+ XS = 'xs',
2
4
  SM = 'sm',
3
5
  MD = 'md',
4
6
  LG = 'lg',
@@ -3,9 +3,10 @@ export interface MenuItem {
3
3
  to: string
4
4
  }
5
5
 
6
- export interface FooterMenuItem {
7
- text: string
8
- to: string
6
+ export interface SocialNetwork {
7
+ name: string
8
+ link: string
9
+ icon: any
9
10
  }
10
11
 
11
12
  export interface SidebarMenuItem {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imaginario27/air-ui-ds",
3
- "version": "1.0.16",
3
+ "version": "1.0.17",
4
4
  "author": "imaginario27",
5
5
  "type": "module",
6
6
  "homepage": "https://air-ui.netlify.app/",
@@ -1,13 +0,0 @@
1
- <template>
2
- <div
3
- :class="[
4
- 'flex',
5
- 'flex-col',
6
- 'gap-6',
7
- 'bg-white',
8
- 'py-4 md:py-8'
9
- ]"
10
- >
11
- <slot></slot>
12
- </div>
13
- </template>
@@ -1,54 +0,0 @@
1
- <template>
2
- <header
3
- :class="[
4
- 'flex',
5
- 'items-center',
6
- 'justify-between',
7
- 'pt-12',
8
- 'pb-8',
9
- 'gap-3',
10
- 'px-content-side-padding-mobile md:px-content-side-padding',
11
- ]"
12
- >
13
- <div class="flex gap-4">
14
- <ActionIconButton
15
- :icon="isMobileSidebarOpen ? 'mdiMenuOpen' : 'mdiMenuClose'"
16
- class="lg:hidden shadow-sm"
17
- @click="toggleMobileSidebar"
18
- />
19
- <PageTitle class="hidden lg:flex" :type="pageTitleType"/>
20
- </div>
21
- <div class="flex gap-3 items-center xs:w-auto">
22
- <slot name="header-actions" />
23
- </div>
24
- </header>
25
-
26
- </template>
27
-
28
- <script setup lang="ts">
29
- // Imports
30
- import { useRoute } from 'vue-router'
31
-
32
- // Props
33
- defineProps({
34
- pageTitleType: {
35
- type: String as PropType<PageTitleType>,
36
- default: PageTitleType.SIMPLE
37
- }
38
- })
39
-
40
- // Page title
41
- const route = useRoute()
42
- const currentPageTitle = computed<string>(() =>
43
- (route.meta.title as string) || 'Page title'
44
- )
45
-
46
- // Dynamically set the page title
47
- useHead(() => ({
48
- title: pageTitle(currentPageTitle.value, App.NAME),
49
- }))
50
-
51
- // Composables
52
- const { isMobileSidebarOpen, toggleMobileSidebar } = useMobileSidebar()
53
-
54
- </script>