Skip to content

Commit e78924f

Browse files
authored
Merge pull request #373 from devforth/AdminForth/855
Admin forth/855
2 parents bded928 + e3214bb commit e78924f

File tree

13 files changed

+262
-11
lines changed

13 files changed

+262
-11
lines changed

adminforth/documentation/docs/tutorial/03-Customization/15-afcl.md

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,68 @@ import { Button } from '@/afcl'
4141

4242
loader prop would show loader when it's true.
4343

44+
## Button Group
45+
### With active button
46+
<div class="split-screen" >
47+
48+
```ts
49+
import { IconGridSolid, IconUserCircleSolid, IconLockSolid, IconShieldOutline } from '@iconify-prerendered/vue-flowbite';
50+
import { ButtonGroup } from '@/afcl'
51+
52+
const activeButton = ref('')
53+
54+
...
55+
56+
<ButtonGroup v-model="activeButton">
57+
<template #button:Profile>
58+
<div class="flex px-4 py-2">
59+
<IconUserCircleSolid class="w-5 h-5 me-2"/>
60+
Profile
61+
</div>
62+
</template>
63+
<template #button:Dashboard>
64+
<div class="flex px-4 py-2">
65+
<IconGridSolid class="w-5 h-5 me-2"/>
66+
Board
67+
</div>
68+
</template>
69+
</ButtonGroup>
70+
```
71+
72+
![AFCL Button-group](ButtonGroup1.png)
73+
74+
</div>
75+
76+
### With solid color
77+
78+
<div class="split-screen" >
79+
80+
```ts
81+
import { ButtonGroup } from '@/afcl'
82+
import { IconPlusOutline, IconCaretDownSolid } from '@iconify-prerendered/vue-flowbite';
83+
84+
...
85+
86+
<ButtonGroup :solidColor="true">
87+
<template #button:Profile>
88+
<div class="flex px-4 py-2" @click="console.log("Add passkey got clicked")">
89+
<IconPlusOutline class="w-5 h-5 me-2"/>
90+
<p>Add Local Passkey</p>
91+
</div>
92+
</template>
93+
<template #button:Dropdown>
94+
<div id="dropdown-button" class="flex px-2 py-2" @click="console.log("Dropdown got clicked")">
95+
<IconCaretDownSolid class="w-5 h-5"/>
96+
</div>
97+
</template>
98+
</ButtonGroup>
99+
100+
```
101+
102+
![AFCL Button-group](ButtonGroup2.png)
103+
104+
</div>
105+
44106

45107
## Link
46108

@@ -362,6 +424,54 @@ const enable = ref(false)
362424
</div>
363425
</div>
364426

427+
## Card
428+
429+
### Custom card
430+
If you need custom card, you can make it without
431+
<div class="split-screen">
432+
```ts
433+
<Card>
434+
<p class="font-semibold text-gray-600 text-xl dark:text-gray-300">Total Profit</p>
435+
<p class="text-green-500 font-bold mt-2">$100,000</p>
436+
</Card>
437+
```
438+
439+
440+
![AFCL Checkbox](Card3.png)
441+
442+
</div>
443+
444+
### Standart card
445+
<div class="split-screen">
446+
447+
```ts
448+
import { Card } from '@/afcl'
449+
450+
...
451+
452+
<Card
453+
title="This is a large card"
454+
description="Description text for large card. This is a large card. Very nice card. Big one. You can put here any content you want."
455+
>
456+
</Card>
457+
458+
<Card
459+
size="md"
460+
title="This is a medium card"
461+
description="Description text for medium card. This is a medium card. Very nice card. Big one. You can put here any content you want."
462+
>
463+
</Card>
464+
465+
<Card
466+
size="sm"
467+
title="This is a small card"
468+
description="Description text for small card. This is a small card. Very nice card. Big one. You can put here any content you want."
469+
>
470+
</Card>
471+
```
472+
![AFCL Checkbox](Card2.png)
473+
474+
</div>
365475

366476
## Toggle
367477

5.03 KB
Loading
3.54 KB
Loading
15.2 KB
Loading
48.9 KB
Loading
8.01 KB
Loading

adminforth/modules/styles.ts

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
2-
31
export const styles = () => ({
42
colors: {
53
lightHtml: "#FFFFFF", // main background
@@ -146,6 +144,16 @@ export const styles = () => ({
146144
lightButtonsHover: "alias:lightPrimary lighten", // button hover
147145
lightButtonsBorderHover: "alias:lightPrimary", // button border hover
148146
lightButtonFocusRing: "alias:lightPrimary opacity:0.6", // button focus ring
147+
148+
lightButtonGroupBackground: "#FFFFFF", // button group background
149+
lightButtonGroupBorder: "#D1D5DB", // button group border
150+
lightButtonGroupText: "#111827", // button group text
151+
lightButtonGroupFocusRing: "#F3F4F6", // button group focus ring
152+
lightButtonGroupBackgroundHover: "#F3F4F6", // button group background hover
153+
lightButtonGroupTextHover: "alias:lightPrimary", // button group text hover
154+
lightButtonGroupActiveBackground: "alias:lightPrimary", // button group active background
155+
lightButtonGroupActiveText: "alias:lightPrimaryContrast", // button group active text
156+
lightButtonGroupActiveFocusRing: "alias:lightPrimary opacity:0.6", // button group active focus ring
149157

150158
lightDropdownButtonsBackground: "#f9fafb", // dropdown button/input background color
151159
lightDropownButtonsBorder: "#D1D5DB", //border color
@@ -332,11 +340,12 @@ export const styles = () => ({
332340
lightToastCloseIconFocusRing: "#D1D5DB",
333341
lightToastText: "#6B7280",
334342

343+
lightCardBackground: "#FFFFFF",
344+
lightCardBackgroundHover: "#F3F4F6",
345+
lightCardBorder: "#E5E7EB",
346+
lightCardTitle: "#374151",
347+
lightCardDescription: "#6B7280",
335348

336-
337-
338-
339-
340349
// colors for dark theme
341350
darkHtml: "#111827",
342351

@@ -479,11 +488,20 @@ export const styles = () => ({
479488
darkButtonsBorderHover: "alias:darkPrimary", // button border hover
480489
darkButtonFocusRing: "alias:darkPrimary opacity:0.6", // button focus ring
481490

491+
darkButtonGroupBackground: "#1F2937", // button group background
492+
darkButtonGroupBorder: "#4B5563", // button group border
493+
darkButtonGroupText: "#9CA3AF", // button group text
494+
darkButtonGroupFocusRing: "#374151", // button group focus ring
495+
darkButtonGroupBackgroundHover: "#374151", // button group background hover
496+
darkButtonGroupTextHover: "alias:darkButtonGroupText", // button group text hover
497+
darkButtonGroupActiveBackground: "alias:darkPrimary", // button group active background
498+
darkButtonGroupActiveText: "alias:darkPrimaryContrast", // button group active text
499+
darkButtonGroupActiveFocusRing: "alias:darkPrimary opacity:0.6", // button group active focus ring
500+
482501
darkDropdownButtonsBackground: "#374151",
483502
darkDropdownButtonsBorder: "#4b5563",
484503
darkDropdownButtonsText: "#FFFFFF",
485504
darkDropdownButtonsPlaceholderText: "#9CA3AF",
486-
487505
darkDropdownOptionsBackground: "#374151",
488506
darkDropdownOptionsHoverBackground: "#4b5563",
489507
darkDropdownPicked:"#212a40",
@@ -665,6 +683,11 @@ export const styles = () => ({
665683
darkToastCloseIconFocusRing: "#374151",
666684
darkToastText: "#9CA3AF",
667685

686+
darkCardBackground: "#1F2937", // card background
687+
darkCardBackgroundHover: "#374151", // card background hover
688+
darkCardBorder: "#4B5563", // card border
689+
darkCardTitle: "#FFFFFF", // card title
690+
darkCardDescription: "#9CA3AF", // card description
668691

669692
},
670693
boxShadow: {
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<template>
2+
<div v-if="isInitFinished" class="inline-flex rounded-md shadow-xs" role="group">
3+
<button v-for="button in buttons" :key="`${button}-button-controll`"
4+
:disabled="slotProps[button].disabled"
5+
class="inline-flex items-center text-sm font-medium border-t border-b border-r border-lightButtonGroupBorder focus:z-10 focus:ring-2 dark:border-darkButtonGroupBorder disabled:opacity-50 disabled:cursor-not-allowed"
6+
:class="[
7+
buttonsStyles[button] === 'rounded' ? 'border rounded-lg'
8+
: buttonsStyles[button] === 'rounded-left' ? 'border rounded-s-lg'
9+
: buttonsStyles[button] === 'rounded-right' ? 'border rounded-e-lg border-l-lightButtonGroupBackground focus:border-l-lightButtonGroupBorder dark:border-l-darkButtonGroupBackground dark:focus:border-l-darkButtonGroupBorder'
10+
: buttonsStyles[button] === 'no-rounded' ? 'border border-l-lightButtonGroupBackground focus:border-l-lightButtonGroupBorder dark:border-l-darkButtonGroupBackground dark:focus:border-l-darkButtonGroupBorder'
11+
: buttonsStyles[button] === 'rounded-left-with-right-border' ? 'border rounded-s-lg' : '',
12+
(button === activeButton || props.solidColor === true) ? 'bg-lightButtonGroupActiveBackground text-lightButtonGroupActiveText focus:ring-lightButtonGroupActiveFocusRing dark:bg-darkButtonGroupActiveBackground dark:text-darkButtonGroupActiveText dark:focus:ring-darkButtonGroupActiveFocusRing'
13+
:'text-lightButtonGroupText bg-lightButtonGroupBackground focus:ring-lightButtonGroupFocusRing hover:bg-lightButtonGroupBackgroundHover hover:text-lightButtonGroupTextHover dark:bg-darkButtonGroupBackground dark:text-darkButtonGroupText dark:hover:text-darkButtonGroupTextHover dark:hover:bg-darkButtonGroupBackgroundHover dark:focus:ring-darkButtonGroupFocusRing'
14+
]"
15+
@click="setActiveButton(button)"
16+
>
17+
<slot :name="`button:${button}`"></slot>
18+
</button>
19+
</div>
20+
</template>
21+
22+
<script lang="ts" setup>
23+
import { onMounted, useSlots, reactive, ref, type Ref } from 'vue';
24+
25+
const buttons : Ref<string[]> = ref([]);
26+
const buttonsStyles : Ref<Record<string, string>> = ref({});
27+
const activeButton = ref('');
28+
const slotProps = reactive<Record<string, any>>({});
29+
const isInitFinished = ref(false);
30+
31+
const emits = defineEmits(['update:modelValue']);
32+
33+
const props = defineProps<{
34+
solidColor?: boolean;
35+
modelValue?: string;
36+
}>();
37+
38+
onMounted(() => {
39+
const slots = useSlots();
40+
buttons.value = Object.keys(slots).reduce((tbs: string[], tb: string) => {
41+
if (tb.startsWith('button:')) {
42+
tbs.push(tb.replace('button:', ''));
43+
}
44+
return tbs;
45+
}, []);
46+
if (buttons.value.length > 0) {
47+
activeButton.value = buttons.value[0];
48+
}
49+
for (const button of buttons.value) {
50+
const temp = {
51+
[button]: getButtonsClasses(button)
52+
}
53+
buttonsStyles.value = { ...buttonsStyles.value, ...temp };
54+
const slot = slots[`button:${button}`];
55+
if (slot && slot()[0]?.props) {
56+
slotProps[button] = slot()[0].props;
57+
} else {
58+
slotProps[button] = {};
59+
}
60+
if (slotProps[button]?.disabled === undefined) {
61+
slotProps[button].disabled = false;
62+
}
63+
}
64+
isInitFinished.value = true;
65+
});
66+
67+
68+
function setActiveButton(button: string) {
69+
if (buttons.value.includes(button)) {
70+
activeButton.value = button;
71+
emits('update:modelValue', button);
72+
}
73+
}
74+
75+
function getButtonsClasses(button: string) {
76+
const index = buttons.value.indexOf(button);
77+
const lenght = buttons.value.length;
78+
if ( lenght === 1 ) {
79+
return 'rounded'
80+
} else if ( lenght === 2 && index === 0 ) {
81+
return 'rounded-left-with-right-border'
82+
} else if ( index === 0 ) {
83+
return 'rounded-left'
84+
} else if ( index === lenght - 1 ) {
85+
return 'rounded-right'
86+
} else {
87+
return 'no-rounded'
88+
}
89+
}
90+
91+
</script>

adminforth/spa/src/afcl/Card.vue

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
<template>
2+
<a href="#"
3+
class="block max-w-sm bg-lightCardBackground border border-lightCardBorder rounded-lg shadow-sm hover:bg-lightCardBackgroundHover dark:bg-darkCardBackground dark:border-darkCardBorder dark:hover:bg-darkCardBackgroundHover"
4+
:class="[
5+
props.size === 'sm' ? 'p-2' : props.size === 'md' ? 'p-4' : 'p-6',
6+
props.hideBorder ? 'border-0' : ''
7+
]"
8+
>
9+
10+
<h5 class="font-bold tracking-tight text-lightCardTitle dark:text-darkCardTitle" :class="[props.size === 'sm' ? 'text-base' : props.size === 'md' ? 'text-lg mb-1' : 'text-xl mb-2']">{{ props.title }}</h5>
11+
<p class="font-normal text-lightCardDescription dark:text-darkCardDescription" :class="[props.size === 'sm' ? 'text-sm' : props.size === 'md' ? 'text-base' : 'text-lg']">{{ props.description }}</p>
12+
<slot></slot>
13+
</a>
14+
</template>
15+
16+
17+
<script setup lang="ts">
18+
const props = defineProps<{
19+
title?: string;
20+
description?: string;
21+
size?: 'sm' | 'md' | 'lg';
22+
hideBorder?: boolean;
23+
}>();
24+
25+
</script>

adminforth/spa/src/afcl/Table.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<template>
2-
<div class="afcl-table-container relative overflow-x-auto shadow-md sm:rounded-lg">
2+
<div class="afcl-table-container relative overflow-x-auto shadow-md rounded-lg">
33
<div class="overflow-x-auto w-full">
44
<table class="afcl-table w-full text-sm text-left rtl:text-right text-lightTableText dark:text-darkTableText overflow-x-auto">
55
<thead class="afcl-table-thread text-xs text-lightTableHeadingText uppercase bg-lightTableHeadingBackground dark:bg-darkTableHeadingBackground dark:text-darkTableHeadingText">

0 commit comments

Comments
 (0)