Skip to content

Commit

Permalink
feat: optimized action buttons
Browse files Browse the repository at this point in the history
  • Loading branch information
tikazyq committed Oct 31, 2024
1 parent 38e58be commit b80d284
Show file tree
Hide file tree
Showing 35 changed files with 422 additions and 319 deletions.
1 change: 1 addition & 0 deletions scripts/gen-index.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ function processFile(filePath, moduleName) {
readFileAndModify(filePath, compName);
return { importLine, exportLine };
} else if (
!filePath.endsWith('.d.ts') &&
(filePath.endsWith('.ts') || filePath.endsWith('.tsx')) &&
fileName !== INDEX_COMP_NAME
) {
Expand Down
2 changes: 2 additions & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import AtomMaterialIcon from './ui/icon/AtomMaterialIcon.vue';
import BlockOptionsDropdownList from './ui/lexical/components/BlockOptionsDropdownList.vue';
import Box from './ui/box/Box.vue';
import Button from './ui/button/Button.vue';
import ButtonGroup from './ui/button/ButtonGroup.vue';
import Chart from './ui/chart/Chart.vue';
import CheckTag from './ui/tag/CheckTag.vue';
import CheckTagGroup from './ui/tag/CheckTagGroup.vue';
Expand Down Expand Up @@ -239,6 +240,7 @@ export {
BlockOptionsDropdownList as ClBlockOptionsDropdownList,
Box as ClBox,
Button as ClButton,
ButtonGroup as ClButtonGroup,
Chart as ClChart,
CheckTag as ClCheckTag,
CheckTagGroup as ClCheckTagGroup,
Expand Down
74 changes: 26 additions & 48 deletions src/components/ui/button/Button.vue
Original file line number Diff line number Diff line change
@@ -1,30 +1,13 @@
<script setup lang="ts">
import { computed } from 'vue';
interface ButtonProps {
tooltip?: string;
type?: BasicType;
size?: BasicSize;
round?: boolean;
circle?: boolean;
plain?: boolean;
disabled?: boolean;
isIcon?: boolean;
loading?: boolean;
onClick?: () => void;
className?: string;
id?: string;
noMargin?: boolean;
}
import { ButtonProps, ButtonEmits } from './types';
const props = withDefaults(defineProps<ButtonProps>(), {
type: 'primary',
size: 'default',
});
const emit = defineEmits<{
(e: 'click', event: Event): void;
}>();
const emit = defineEmits<ButtonEmits>();
const cls = computed<string>(() => {
const { noMargin, className, isIcon } = props;
Expand All @@ -34,46 +17,41 @@ const cls = computed<string>(() => {
if (className) classes.push(className);
return classes.join(' ');
});
defineOptions({ name: 'ClButton' });
</script>

<template>
<el-tooltip :content="tooltip" :disabled="!tooltip">
<span :id="id" :class="['button-wrapper', cls].join(' ')">
<el-button
:circle="circle"
:disabled="disabled"
:plain="plain"
:round="round"
:size="size"
:title="tooltip"
:type="type"
:loading="loading"
@click="(event: Event) => emit('click', event)"
>
<slot></slot>
</el-button>
</span>
<el-button
:id="id"
:class="cls"
:circle="circle"
:disabled="disabled"
:plain="plain"
:round="round"
:size="size"
:title="tooltip"
:type="type"
:loading="loading"
@click="(event: Event) => emit('click', event)"
@mouseenter="(event: Event) => emit('mouseenter', event)"
@mouseleave="(event: Event) => emit('mouseleave', event)"
>
<slot></slot>
</el-button>
</el-tooltip>
</template>

<style lang="scss" scoped>
.button-wrapper {
<style scoped>
.el-button {
position: relative;
margin-right: 10px;
vertical-align: inherit;
&.no-margin {
margin-right: 0;
}
.el-button {
vertical-align: inherit;
&:deep(.icon-button) {
padding: 7px;
}
}
</style>

<style scoped>
.button-wrapper:deep(.icon-button) {
padding: 7px;
}
</style>
<style scoped></style>
88 changes: 88 additions & 0 deletions src/components/ui/button/ButtonGroup.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<script setup lang="ts">
import { computed, ref } from 'vue';
import { ButtonGroupProps } from './types';
const props = withDefaults(defineProps<ButtonGroupProps>(), {
size: 'small',
type: 'primary',
dropdownTrigger: 'click',
});
// Compute display buttons with proper component mapping
const displayButtons = computed(() => {
return props.buttons?.map(btn => ({
...btn,
// Set component type based on buttonType
component:
btn.buttonType === 'fa-icon'
? 'cl-fa-icon-button'
: btn.buttonType === 'icon'
? 'cl-icon-button'
: btn.buttonType === 'label'
? 'cl-label-button'
: 'cl-button',
}));
});
const visible = ref(false);
const onDropdownClick = (event: Event) => {
event.stopPropagation();
if (props.dropdownTrigger === 'click') {
visible.value = !visible.value;
}
};
defineOptions({ name: 'ClButtonGroup' });
</script>

<template>
<el-button-group :type="type" :size="size">
<component
v-for="(btn, $index) in displayButtons"
:key="$index"
:is="btn.component"
v-bind="btn"
:size="size"
:type="btn.type || type"
/>
<cl-context-menu
v-if="dropdownItems?.length"
:visible="visible"
:trigger="dropdownTrigger"
placement="bottom-start"
>
<template #reference>
<div class="el-button show-more">
<cl-fa-icon-button
:icon="['fa', 'ellipsis-v']"
:size="size"
@click="onDropdownClick"
/>
</div>
</template>
<cl-context-menu-list
:items="dropdownItems"
@hide="() => (visible = false)"
/>
</cl-context-menu>
</el-button-group>
</template>
<style scoped>
.el-button-group {
&:deep(.show-more) {
float: none;
margin: 0;
padding: 0;
border: none;
height: inherit;
vertical-align: unset;
}
&:deep(.show-more > .el-button) {
border-bottom-left-radius: 0;
border-top-left-radius: 0;
}
}
</style>
34 changes: 7 additions & 27 deletions src/components/ui/button/FaIconButton.vue
Original file line number Diff line number Diff line change
@@ -1,40 +1,18 @@
<script setup lang="ts">
import { computed } from 'vue';
import { ButtonEmits, FaIconButtonProps } from './types';
interface ButtonProps {
tooltip?: string;
type?: BasicType;
size?: BasicSize;
round?: boolean;
circle?: boolean;
plain?: boolean;
disabled?: boolean;
isIcon?: boolean;
loading?: boolean;
onClick?: () => void;
className?: string;
id?: string;
noMargin?: boolean;
}
const props = defineProps<
ButtonProps & {
icon: Icon;
badgeIcon?: Icon;
spin?: boolean;
}
>();
const props = defineProps<FaIconButtonProps>();
const emit = defineEmits<{
(e: 'click', event: Event): void;
}>();
const emit = defineEmits<ButtonEmits>();
const cls = computed<string>(() => {
const { className } = props;
const classes = ['fa-icon-button'];
if (className) classes.push(className);
return classes.join(' ');
});
defineOptions({ name: 'ClFaIconButton' });
</script>

Expand All @@ -51,6 +29,8 @@ defineOptions({ name: 'ClFaIconButton' });
:id="id"
:class-name="cls"
@click="(event: Event) => emit('click', event)"
@mouseenter="(event: Event) => emit('mouseenter', event)"
@mouseleave="(event: Event) => emit('mouseleave', event)"
>
<cl-icon :icon="icon" :spinning="spin" />
<div v-if="badgeIcon" class="badge-icon">
Expand All @@ -59,7 +39,7 @@ defineOptions({ name: 'ClFaIconButton' });
</cl-button>
</template>

<style lang="scss" scoped>
<style scoped>
.badge-icon {
position: absolute;
top: -2px;
Expand Down
29 changes: 7 additions & 22 deletions src/components/ui/button/IconButton.vue
Original file line number Diff line number Diff line change
@@ -1,26 +1,10 @@
<script setup lang="ts">
import { ButtonEmits, IconButtonProps } from './types';
interface ButtonProps {
tooltip?: string;
type?: BasicType;
size?: BasicSize;
round?: boolean;
circle?: boolean;
plain?: boolean;
disabled?: boolean;
isIcon?: boolean;
loading?: boolean;
onClick?: () => void;
className?: string;
id?: string;
noMargin?: boolean;
}
defineProps<IconButtonProps>();
const emit = defineEmits<ButtonEmits>();
defineProps<
ButtonProps & {
icon: string;
}
>();
defineOptions({ name: 'ClIconButton' });
</script>

Expand All @@ -36,13 +20,14 @@ defineOptions({ name: 'ClIconButton' });
:size="size"
:title="tooltip"
:type="type"
@click="() => $emit('click')"
@click="(event: Event) => emit('click', event)"
@mouseenter="(event: Event) => emit('mouseenter', event)"
@mouseleave="(event: Event) => emit('mouseleave', event)"
/>
</div>
</el-tooltip>
</template>


<style scoped>
.icon-button {
padding: 7px;
Expand Down
32 changes: 6 additions & 26 deletions src/components/ui/button/LabelButton.vue
Original file line number Diff line number Diff line change
@@ -1,31 +1,10 @@
<script setup lang="ts">
import { ButtonEmits, LabelButtonProps } from './types';
interface ButtonProps {
tooltip?: string;
type?: BasicType;
size?: BasicSize;
round?: boolean;
circle?: boolean;
plain?: boolean;
disabled?: boolean;
isIcon?: boolean;
loading?: boolean;
onClick?: () => void;
className?: string;
id?: string;
noMargin?: boolean;
}
defineProps<LabelButtonProps>();
defineProps<
ButtonProps & {
label?: string;
icon?: Icon;
}
>();
const emit = defineEmits<ButtonEmits>();
const emit = defineEmits<{
(e: 'click'): void;
}>();
defineOptions({ name: 'ClLabelButton' });
</script>

Expand All @@ -43,15 +22,16 @@ defineOptions({ name: 'ClLabelButton' });
:id="id"
:class-name="['label-button', className].join(' ')"
:loading="loading"
@click="() => emit('click')"
@click="(event: Event) => emit('click', event)"
@mouseenter="(event: Event) => emit('mouseenter', event)"
@mouseleave="(event: Event) => emit('mouseleave', event)"
>
<font-awesome-icon v-if="icon && !loading" :icon="icon" class="icon" />
{{ label }}
</cl-button>
</div>
</template>


<style scoped>
.label-button:deep(.icon) {
width: 20px;
Expand Down
Loading

0 comments on commit b80d284

Please sign in to comment.