@baklavue/ui 1.0.0-preview.2 → 1.0.0-preview.3
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/CHANGELOG.md +8 -0
- package/README.md +69 -7
- package/package.json +1 -1
- package/src/index.ts +2 -0
- package/src/scroll-to-top/ScrollToTop.vue +130 -0
- package/src/scroll-to-top/index.ts +2 -0
- package/src/scroll-to-top/scroll-to-top.types.ts +42 -0
- package/src/skeleton/Skeleton.vue +115 -0
- package/src/skeleton/index.ts +2 -0
- package/src/skeleton/skeleton.types.ts +33 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
# [@baklavue/ui-v1.0.0-preview.3](https://github.com/erbilnas/baklavue/compare/@baklavue/ui-v1.0.0-preview.2...@baklavue/ui-v1.0.0-preview.3) (2026-02-11)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* add new components ([b3c535e](https://github.com/erbilnas/baklavue/commit/b3c535e010e1e43b9b04365df2205b69a0777695))
|
|
7
|
+
* add new composables ([49105ea](https://github.com/erbilnas/baklavue/commit/49105eaa106f1a5b888f9e3f9638ed9776b3d55b))
|
|
8
|
+
|
|
1
9
|
# [@baklavue/ui-v1.0.0-preview.2](https://github.com/erbilnas/baklavue/compare/@baklavue/ui-v1.0.0-preview.1...@baklavue/ui-v1.0.0-preview.2) (2026-02-11)
|
|
2
10
|
|
|
3
11
|
|
package/README.md
CHANGED
|
@@ -1,15 +1,77 @@
|
|
|
1
|
-
# ui
|
|
1
|
+
# @baklavue/ui
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Vue 3 UI kit for [Trendyol Baklava](https://github.com/Trendyol/baklava) design system. Vue-friendly wrappers with full `v-model` support, slots, and TypeScript.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
4
6
|
|
|
5
7
|
```bash
|
|
6
|
-
bun
|
|
8
|
+
# bun
|
|
9
|
+
bun add @baklavue/ui
|
|
10
|
+
|
|
11
|
+
# npm
|
|
12
|
+
npm install @baklavue/ui
|
|
13
|
+
|
|
14
|
+
# pnpm
|
|
15
|
+
pnpm add @baklavue/ui
|
|
16
|
+
|
|
17
|
+
# yarn
|
|
18
|
+
yarn add @baklavue/ui
|
|
7
19
|
```
|
|
8
20
|
|
|
9
|
-
|
|
21
|
+
Requires Vue 3 and TypeScript 5.9+ (peer dependencies).
|
|
10
22
|
|
|
11
|
-
|
|
12
|
-
|
|
23
|
+
## Setup
|
|
24
|
+
|
|
25
|
+
Components load Baklava styles and scripts automatically when mounted. For explicit loading (e.g. before any component mounts), call `loadBaklavaResources()` in `main.ts`:
|
|
26
|
+
|
|
27
|
+
```ts
|
|
28
|
+
import { loadBaklavaResources } from "@baklavue/ui";
|
|
29
|
+
|
|
30
|
+
loadBaklavaResources(); // optional
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Usage
|
|
34
|
+
|
|
35
|
+
```vue
|
|
36
|
+
<template>
|
|
37
|
+
<BvButton variant="primary" @click="handleClick">Click me</BvButton>
|
|
38
|
+
<BvInput v-model="email" label="Email" placeholder="Enter your email" />
|
|
39
|
+
</template>
|
|
40
|
+
|
|
41
|
+
<script setup>
|
|
42
|
+
import { ref } from "vue";
|
|
43
|
+
import { BvButton, BvInput } from "@baklavue/ui";
|
|
44
|
+
|
|
45
|
+
const email = ref("");
|
|
46
|
+
|
|
47
|
+
const handleClick = () => {
|
|
48
|
+
console.log("Email:", email.value);
|
|
49
|
+
};
|
|
50
|
+
</script>
|
|
13
51
|
```
|
|
14
52
|
|
|
15
|
-
|
|
53
|
+
## Components
|
|
54
|
+
|
|
55
|
+
All components use the `Bv-` prefix and support TypeScript, `v-model`, Vue events, reactive props, and slots.
|
|
56
|
+
|
|
57
|
+
| Category | Components |
|
|
58
|
+
| ---------- | -------------------------------------------------------------------------- |
|
|
59
|
+
| **Form** | BvButton, BvInput, BvCheckbox, BvRadio, BvSwitch, BvSelect, BvTextarea, BvDatepicker |
|
|
60
|
+
| **Feedback** | BvAlert, BvBadge, BvTag, BvNotification, BvSpinner |
|
|
61
|
+
| **Layout** | BvDialog, BvDrawer, BvDropdown, BvTooltip, BvAccordion, BvTab, BvStepper |
|
|
62
|
+
| **Navigation** | BvLink, BvPagination, BvSplitButton |
|
|
63
|
+
| **Data** | BvTable, BvIcon |
|
|
64
|
+
|
|
65
|
+
## Requirements
|
|
66
|
+
|
|
67
|
+
- **Vue 3.0+** — Composition API
|
|
68
|
+
- **TypeScript 5.9.2+** (peer dependency)
|
|
69
|
+
|
|
70
|
+
## Documentation
|
|
71
|
+
|
|
72
|
+
- [Full docs](https://erbilnas.github.io/baklavue/) — Guide and examples
|
|
73
|
+
- [Components](https://erbilnas.github.io/baklavue/components/) — Component reference
|
|
74
|
+
|
|
75
|
+
## License
|
|
76
|
+
|
|
77
|
+
[MIT](LICENSE)
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -23,7 +23,9 @@ export * from "./link";
|
|
|
23
23
|
export * from "./notification";
|
|
24
24
|
export * from "./pagination";
|
|
25
25
|
export * from "./radio";
|
|
26
|
+
export * from "./scroll-to-top";
|
|
26
27
|
export * from "./select";
|
|
28
|
+
export * from "./skeleton";
|
|
27
29
|
export * from "./spinner";
|
|
28
30
|
export * from "./split-button";
|
|
29
31
|
export * from "./stepper";
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* ScrollToTop Component
|
|
4
|
+
*
|
|
5
|
+
* A floating button that appears when the user scrolls past a threshold.
|
|
6
|
+
* Clicking it scrolls smoothly to the top of the page.
|
|
7
|
+
*
|
|
8
|
+
* @component
|
|
9
|
+
* @example
|
|
10
|
+
* ```vue
|
|
11
|
+
* <template>
|
|
12
|
+
* <BvScrollToTop />
|
|
13
|
+
* </template>
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
import { onMounted, onUnmounted, ref } from "vue";
|
|
17
|
+
import BvButton from "../button/Button.vue";
|
|
18
|
+
import { loadBaklavaResources } from "../utils/loadBaklavaResources";
|
|
19
|
+
import type { ScrollToTopProps } from "./scroll-to-top.types";
|
|
20
|
+
|
|
21
|
+
const props = withDefaults(defineProps<ScrollToTopProps>(), {
|
|
22
|
+
threshold: 300,
|
|
23
|
+
position: "bottom-right",
|
|
24
|
+
label: "Scroll to top",
|
|
25
|
+
size: "medium",
|
|
26
|
+
variant: "primary",
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const emit = defineEmits<{
|
|
30
|
+
click: [];
|
|
31
|
+
}>();
|
|
32
|
+
|
|
33
|
+
const isVisible = ref(false);
|
|
34
|
+
let rafId: number | null = null;
|
|
35
|
+
|
|
36
|
+
const checkVisibility = () => {
|
|
37
|
+
isVisible.value = window.scrollY > props.threshold;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const handleScroll = () => {
|
|
41
|
+
if (rafId !== null) return;
|
|
42
|
+
rafId = requestAnimationFrame(() => {
|
|
43
|
+
checkVisibility();
|
|
44
|
+
rafId = null;
|
|
45
|
+
});
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
const scrollToTop = () => {
|
|
49
|
+
window.scrollTo({ top: 0, behavior: "smooth" });
|
|
50
|
+
emit("click");
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const positionClasses: Record<
|
|
54
|
+
NonNullable<ScrollToTopProps["position"]>,
|
|
55
|
+
string
|
|
56
|
+
> = {
|
|
57
|
+
"bottom-right": "scroll-to-top--bottom-right",
|
|
58
|
+
"bottom-left": "scroll-to-top--bottom-left",
|
|
59
|
+
"top-right": "scroll-to-top--top-right",
|
|
60
|
+
"top-left": "scroll-to-top--top-left",
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
onMounted(() => {
|
|
64
|
+
loadBaklavaResources();
|
|
65
|
+
checkVisibility();
|
|
66
|
+
window.addEventListener("scroll", handleScroll, { passive: true });
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
onUnmounted(() => {
|
|
70
|
+
window.removeEventListener("scroll", handleScroll);
|
|
71
|
+
if (rafId !== null) cancelAnimationFrame(rafId);
|
|
72
|
+
});
|
|
73
|
+
</script>
|
|
74
|
+
|
|
75
|
+
<template>
|
|
76
|
+
<Transition name="scroll-to-top-fade">
|
|
77
|
+
<div
|
|
78
|
+
v-show="isVisible"
|
|
79
|
+
:class="['scroll-to-top', positionClasses[position]]"
|
|
80
|
+
role="complementary"
|
|
81
|
+
aria-label="Scroll to top"
|
|
82
|
+
>
|
|
83
|
+
<BvButton
|
|
84
|
+
:variant="variant"
|
|
85
|
+
:size="size"
|
|
86
|
+
:label="label"
|
|
87
|
+
icon="arrow_up"
|
|
88
|
+
@click="scrollToTop"
|
|
89
|
+
>
|
|
90
|
+
<template #default></template>
|
|
91
|
+
</BvButton>
|
|
92
|
+
</div>
|
|
93
|
+
</Transition>
|
|
94
|
+
</template>
|
|
95
|
+
|
|
96
|
+
<style scoped>
|
|
97
|
+
.scroll-to-top {
|
|
98
|
+
position: fixed;
|
|
99
|
+
z-index: 1000;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
.scroll-to-top--bottom-right {
|
|
103
|
+
bottom: 1.5rem;
|
|
104
|
+
right: 1.5rem;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.scroll-to-top--bottom-left {
|
|
108
|
+
bottom: 1.5rem;
|
|
109
|
+
left: 1.5rem;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.scroll-to-top--top-right {
|
|
113
|
+
top: 1.5rem;
|
|
114
|
+
right: 1.5rem;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
.scroll-to-top--top-left {
|
|
118
|
+
top: 1.5rem;
|
|
119
|
+
left: 1.5rem;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.scroll-to-top-fade-enter-active,
|
|
123
|
+
.scroll-to-top-fade-leave-active {
|
|
124
|
+
transition: opacity 0.2s ease;
|
|
125
|
+
}
|
|
126
|
+
.scroll-to-top-fade-enter-from,
|
|
127
|
+
.scroll-to-top-fade-leave-to {
|
|
128
|
+
opacity: 0;
|
|
129
|
+
}
|
|
130
|
+
</style>
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { ButtonSize, ButtonVariant } from "@trendyol/baklava/dist/components/button/bl-button";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Position of the scroll-to-top button.
|
|
5
|
+
*/
|
|
6
|
+
export type ScrollToTopPosition =
|
|
7
|
+
| "bottom-right"
|
|
8
|
+
| "bottom-left"
|
|
9
|
+
| "top-right"
|
|
10
|
+
| "top-left";
|
|
11
|
+
|
|
12
|
+
export interface ScrollToTopProps {
|
|
13
|
+
/**
|
|
14
|
+
* Scroll threshold in pixels. Button becomes visible when user scrolls past this.
|
|
15
|
+
* @default 300
|
|
16
|
+
*/
|
|
17
|
+
threshold?: number;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Fixed position of the button.
|
|
21
|
+
* @default "bottom-right"
|
|
22
|
+
*/
|
|
23
|
+
position?: ScrollToTopPosition;
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Accessible label for screen readers.
|
|
27
|
+
* @default "Scroll to top"
|
|
28
|
+
*/
|
|
29
|
+
label?: string;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Button size.
|
|
33
|
+
* @default "medium"
|
|
34
|
+
*/
|
|
35
|
+
size?: ButtonSize;
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Button variant.
|
|
39
|
+
* @default "primary"
|
|
40
|
+
*/
|
|
41
|
+
variant?: ButtonVariant;
|
|
42
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
/**
|
|
3
|
+
* Skeleton Component
|
|
4
|
+
*
|
|
5
|
+
* Animated placeholder for content loading states.
|
|
6
|
+
* Displays a shimmer effect with configurable variants.
|
|
7
|
+
*
|
|
8
|
+
* @component
|
|
9
|
+
* @example
|
|
10
|
+
* ```vue
|
|
11
|
+
* <template>
|
|
12
|
+
* <BvSkeleton />
|
|
13
|
+
* </template>
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```vue
|
|
18
|
+
* <template>
|
|
19
|
+
* <BvSkeleton variant="text" :count="3" />
|
|
20
|
+
* </template>
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
import { computed, onMounted } from "vue";
|
|
24
|
+
import { loadBaklavaResources } from "../utils/loadBaklavaResources";
|
|
25
|
+
import type { SkeletonProps } from "./skeleton.types";
|
|
26
|
+
|
|
27
|
+
const props = withDefaults(defineProps<SkeletonProps>(), {
|
|
28
|
+
variant: "rectangle",
|
|
29
|
+
width: undefined,
|
|
30
|
+
height: undefined,
|
|
31
|
+
count: 1,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const effectiveWidth = computed(() => {
|
|
35
|
+
if (props.width) return props.width;
|
|
36
|
+
if (props.variant === "circle") return "40px";
|
|
37
|
+
return "100%";
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
const effectiveHeight = computed(() => {
|
|
41
|
+
if (props.height) return props.height;
|
|
42
|
+
if (props.variant === "circle") return "40px";
|
|
43
|
+
return "1rem";
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
onMounted(() => {
|
|
48
|
+
loadBaklavaResources();
|
|
49
|
+
});
|
|
50
|
+
</script>
|
|
51
|
+
|
|
52
|
+
<template>
|
|
53
|
+
<div
|
|
54
|
+
class="skeleton-wrapper"
|
|
55
|
+
:class="`skeleton-wrapper--${props.variant}`"
|
|
56
|
+
role="status"
|
|
57
|
+
aria-label="Loading"
|
|
58
|
+
>
|
|
59
|
+
<div
|
|
60
|
+
v-for="n in count"
|
|
61
|
+
:key="n"
|
|
62
|
+
class="skeleton"
|
|
63
|
+
:class="['skeleton--' + props.variant]"
|
|
64
|
+
:style="{
|
|
65
|
+
width: effectiveWidth,
|
|
66
|
+
height: effectiveHeight,
|
|
67
|
+
}"
|
|
68
|
+
/>
|
|
69
|
+
</div>
|
|
70
|
+
</template>
|
|
71
|
+
|
|
72
|
+
<style scoped>
|
|
73
|
+
.skeleton-wrapper {
|
|
74
|
+
display: flex;
|
|
75
|
+
flex-direction: column;
|
|
76
|
+
gap: 0.5rem;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.skeleton {
|
|
80
|
+
background: var(--bl-color-neutral-light, #e5e7eb);
|
|
81
|
+
border-radius: var(--bl-border-radius-s, 0.25rem);
|
|
82
|
+
position: relative;
|
|
83
|
+
overflow: hidden;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.skeleton::after {
|
|
87
|
+
content: "";
|
|
88
|
+
position: absolute;
|
|
89
|
+
inset: 0;
|
|
90
|
+
background: linear-gradient(
|
|
91
|
+
90deg,
|
|
92
|
+
transparent 0%,
|
|
93
|
+
rgba(255, 255, 255, 0.4) 50%,
|
|
94
|
+
transparent 100%
|
|
95
|
+
);
|
|
96
|
+
animation: skeleton-shimmer 1.5s ease-in-out infinite;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.skeleton--circle {
|
|
100
|
+
border-radius: var(--bl-border-radius-circle, 50%);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.skeleton--text {
|
|
104
|
+
height: 1rem;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
@keyframes skeleton-shimmer {
|
|
108
|
+
0% {
|
|
109
|
+
transform: translateX(-100%);
|
|
110
|
+
}
|
|
111
|
+
100% {
|
|
112
|
+
transform: translateX(100%);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
</style>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skeleton shape variant.
|
|
3
|
+
*/
|
|
4
|
+
export type SkeletonVariant = "text" | "rectangle" | "circle";
|
|
5
|
+
|
|
6
|
+
export interface SkeletonProps {
|
|
7
|
+
/**
|
|
8
|
+
* Shape variant of the skeleton.
|
|
9
|
+
* - text: Line shape for text placeholders
|
|
10
|
+
* - rectangle: Default block shape
|
|
11
|
+
* - circle: Circular shape for avatars
|
|
12
|
+
* @default "rectangle"
|
|
13
|
+
*/
|
|
14
|
+
variant?: SkeletonVariant;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Width as CSS value (e.g. "100%", "200px", "5rem").
|
|
18
|
+
* @default "100%" for text/rectangle, "40px" for circle
|
|
19
|
+
*/
|
|
20
|
+
width?: string;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Height as CSS value (e.g. "1rem", "20px").
|
|
24
|
+
* @default "1rem" for text, "1rem" for rectangle, "40px" for circle
|
|
25
|
+
*/
|
|
26
|
+
height?: string;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Number of skeleton elements to render (for text lines).
|
|
30
|
+
* @default 1
|
|
31
|
+
*/
|
|
32
|
+
count?: number;
|
|
33
|
+
}
|