Skip to content

Commit

Permalink
feat: ButtonGroup useDisabledStyle“
Browse files Browse the repository at this point in the history
  • Loading branch information
EricWXY committed Apr 12, 2024
1 parent 2023913 commit 7ab1882
Show file tree
Hide file tree
Showing 33 changed files with 588 additions and 161 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,11 @@
"@eric-ui/hooks": "workspace:*",
"@eric-ui/theme": "workspace:*",
"@eric-ui/utils": "workspace:*",
"eric-ui": "workspace:*",
"@fortawesome/fontawesome-svg-core": "^6.5.1",
"@fortawesome/free-solid-svg-icons": "^6.5.1",
"@fortawesome/vue-fontawesome": "^3.0.6",
"eric-ui": "workspace:*",
"@popperjs/core": "^2.11.8",
"lodash-es": "^4.17.21"
},
"devDependencies": {
Expand Down
2 changes: 1 addition & 1 deletion packages/components/Alert/types.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export type AlertType = "success" | "info" | "warning" | "danger";

export interface AlertProps {
title: string;
title?: string;
type: AlertType;
description?: string;
effect?: "light" | "dark";
Expand Down
16 changes: 12 additions & 4 deletions packages/components/Button/Button.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script setup lang="ts">
import { ref, computed } from "vue";
import { ref, computed, inject } from "vue";
import type { ButtonProps, ButtonEmits } from "./types";
import { BUTTON_GROUP_CTX_KEY } from "./constants";
import { throttle } from "lodash-es";
import ErIcon from "../Icon/Icon.vue";
defineOptions({
Expand All @@ -14,22 +15,29 @@ const props = withDefaults(defineProps<ButtonProps>(), {
});
const emits = defineEmits<ButtonEmits>();
const slots = defineSlots();
const buttonGroupCtx = inject(BUTTON_GROUP_CTX_KEY, void 0);
const _ref = ref<HTMLButtonElement>();
const size = computed(() => buttonGroupCtx?.size ?? props.size ?? "");
const type = computed(() => buttonGroupCtx?.type ?? props.type ?? "");
const disabled = computed(
() => props.disabled || buttonGroupCtx?.disabled || false
);
const iconStyle = computed(() => ({
marginRight: slots.default ? "6px" : "0px",
}));
const handleBtnClick = (e: MouseEvent) => {
if (disabled.value) return;
emits("click", e);
};
const handlBtneCLickThrottle = throttle(handleBtnClick, props.throttleDuration);
defineExpose({
ref: _ref,
size: computed(() => props.size ?? ""),
type: computed(() => props.type ?? ""),
disabled: computed(() => !!props.disabled),
disabled,
size,
type,
});
</script>

Expand Down
29 changes: 29 additions & 0 deletions packages/components/Button/ButtonGroup.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
<script setup lang="ts">
import type { ButtonGroupProps } from "./types";
import { provide, reactive, toRef } from "vue";
import { BUTTON_GROUP_CTX_KEY } from "./constants";
defineOptions({
name: "ErButtonGroup",
});
const props = defineProps<ButtonGroupProps>();
provide(
BUTTON_GROUP_CTX_KEY,
reactive({
size: toRef(props, "size"),
type: toRef(props, "type"),
disabled: toRef(props, "disabled"),
})
);
</script>

<template>
<div class="er-button-group">
<slot></slot>
</div>
</template>

<style scoped>
@import "./style.css";
</style>
5 changes: 5 additions & 0 deletions packages/components/Button/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { InjectionKey } from "vue";
import type { ButtonGroupContext } from "./types";

export const BUTTON_GROUP_CTX_KEY: InjectionKey<ButtonGroupContext> =
Symbol("buttonGroupContext");
2 changes: 2 additions & 0 deletions packages/components/Button/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import Button from "./Button.vue";
import ButtonGroup from "./ButtonGroup.vue";
import { withInstall } from "@eric-ui/utils";

export const ErButton = withInstall(Button);
export const ErButtonGroup = withInstall(ButtonGroup);

export * from "./types";
50 changes: 50 additions & 0 deletions packages/components/Button/style.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
.er-button-group {
--er-button-group-border-color: var(--er-border-color-lighter);
}
.er-button {
--er-button-font-weight: var(--er-font-weight-primary);
--er-button-border-color: var(--er-border-color);
Expand Down Expand Up @@ -147,3 +150,50 @@
height: 12px;
}
}

.er-button-group {
display: inline-block;
vertical-align: middle;

&::after {
clear: both;
}
& > :deep(.er-button){
float: left;
position: relative;
margin-left: 0;
&:first-child{
border-top-right-radius: 0;
border-bottom-right-radius: 0;
border-right-color: var(--er-button-group-border-color);
}
&:last-child{
border-top-left-radius: 0;
border-bottom-left-radius: 0;
border-left-color: var(--er-button-group-border-color);
}
&:not(:first-child):not(:last-child) {
border-radius: 0;

border-left-color: var(--er-button-group-border-color);
border-right-color: var(--er-button-group-border-color);
}
&:not(:last-child) {
margin-right: -1px;
}
&:first-child:last-child {
border-top-right-radius: var(--er-border-radius-base);
border-bottom-right-radius: var(--er-border-radius-base);
border-top-left-radius: var(--er-border-radius-base);
border-bottom-left-radius: var(--er-border-radius-base);

&.is-round {
border-radius: var(--er-border-radius-round);
}

&.is-circle {
border-radius: 50%;
}
}
}
}
12 changes: 12 additions & 0 deletions packages/components/Button/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@ export interface ButtonProps {
throttleDuration?: number;
}

export interface ButtonGroupProps {
size?: ButtonSize;
type?: ButtonType;
disabled?: boolean
}

export interface ButtonGroupContext {
size?: ButtonSize;
type?: ButtonType;
disabled?: boolean;
}

export interface ButtonEmits {
(e: "click", value: MouseEvent): void;
}
Expand Down
63 changes: 33 additions & 30 deletions packages/components/Dropdown/Dropdown.vue
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
<script setup lang="ts">
import { ref, computed, provide, useSlots, watchEffect, type VNode } from "vue";
import { omit, each, isNil, assign, isFunction } from "lodash-es";
import { ref, computed, provide, useSlots } from "vue";
import { omit, isNil, assign, map } from "lodash-es";
import type {
DropdownProps,
DropdownEmits,
DropdownInstance,
MenuOption,
DropdownItemProps,
DropdownContext,
} from "./types";
import { useId, useDisabledStyle } from "@eric-ui/hooks";
import { DROPDOWN_CTX_KEY } from "./constants";
import type { TooltipInstance } from "../Tooltip/types";
import { useId } from "@eric-ui/hooks";
import type { ButtonInstance } from "../Button/types";
import ErButton from "../Button/Button.vue";
import ErButtonGroup from "../Button/ButtonGroup.vue";
import ErIcon from "../Icon/Icon.vue";
import DropdownItem from "./DropdownItem.vue";
import Tooltip from "../Tooltip/Tooltip.vue";
Expand All @@ -21,39 +25,30 @@ defineOptions({
});
const props = withDefaults(defineProps<DropdownProps>(), {
hideOnClick: true,
menuOptions: () => [] as MenuOption[],
items: () => [] as DropdownItemProps[],
});
const emits = defineEmits<DropdownEmits>();
const slots = useSlots();
const tooltipRef = ref<TooltipInstance | null>(null);
const tooltipRef = ref<TooltipInstance>();
const triggerRef = ref<ButtonInstance>();
const tooltipProps = computed(() =>
omit(props, ["menuOptions", "hideAfterClick"])
);
const _items = computed(() =>
map(props.items, (item) =>
assign(item, { command: item.command ?? useId().value })
)
);
function handleItemClick(e: MenuOption) {
if ((e as MenuOption).disabled) return;
function handleItemClick(e: DropdownItemProps) {
if (e.disabled) return;
props.hideOnClick && tooltipRef.value?.hide();
!isNil(e.command) && emits("command", e.command);
}
const _dfs = (nodes: VNode[], cb: (node: VNode) => void) =>
each(nodes, (node) => {
isFunction(cb) && cb(node);
node.children && _dfs(node.children as VNode[]);
});
watchEffect(() => {
props.disabled &&
_dfs(slots?.default?.() ?? [], (node) => {
node.props = assign(node.props, {
style: {
cursor: "not-allowed",
color: "var(--er-text-color-placeholder)",
},
});
});
});
useDisabledStyle(slots, props.disabled);
defineExpose<DropdownInstance>({
open: () => tooltipRef.value?.show(),
Expand All @@ -70,16 +65,24 @@ provide<DropdownContext>(DROPDOWN_CTX_KEY, {
<tooltip
ref="tooltipRef"
v-bind="tooltipProps"
:virtual-ref="triggerRef"
:virtual-triggering="splitButton"
@visible-change="$emit('visible-change', $event)"
>
<slot></slot>
<er-button-group :disabled="disabled" v-if="splitButton">
<er-button>
<slot name="default"></slot>
</er-button>
<er-button ref="triggerRef">
<er-icon icon="arrow-down" />
</er-button>
</er-button-group>
<slot v-else name="default"></slot>

<template #content>
<ul class="er-dropdown__menu">
<slot name="dropdown">
<template
v-for="item in items"
:key="item.command ?? useId().value"
>
<template v-for="item in _items" :key="item.command">
<dropdown-item v-bind="item" />
</template>
</slot>
Expand Down
6 changes: 5 additions & 1 deletion packages/components/Dropdown/DropdownItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,11 @@ import { inject } from "vue";
defineOptions({
name: "ErDropdownItem",
});
const props = defineProps<DropdownItemProps>();
const props = withDefaults(defineProps<DropdownItemProps>(), {
divided: false,
disabled: false,
command: useId().value,
});
const ctx = inject(DROPDOWN_CTX_KEY);
Expand Down
8 changes: 6 additions & 2 deletions packages/components/Dropdown/types.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
import type { VNode } from "vue";
import type { TooltipProps } from "../Tooltip/types";

export type DropdownCommand = string | number;

export interface DropdownItemProps {
command?: string | number;
command?: DropdownCommand;
label?: string | VNode;
disabled?: boolean;
divided?: boolean;
Expand All @@ -11,11 +13,13 @@ export interface DropdownItemProps {
export interface DropdownProps extends TooltipProps {
items?: DropdownItemProps[];
hideOnClick?: boolean;
splitButton?: boolean;
}

export interface DropdownEmits {
(e: "visible-change", value: boolean): void;
(e: "command", value: DropdownItemProps["command"]): void;
(e: "command", value: DropdownCommand): void;
(e: "click", value: MouseEvent): void;
}

export interface DropdownInstance {
Expand Down
6 changes: 3 additions & 3 deletions packages/components/Select/Select.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import type {
import type { TooltipInstance } from "../Tooltip/types";
import type { InputInstance } from "../Input/types";
import { RenderVnode, debugWarn } from "@eric-ui/utils";
import { useFocusController, useClickOutside, useId } from "@eric-ui/hooks";
import { useFocusController, useClickOutside } from "@eric-ui/hooks";
import { SELECT_CTX_KEY, POPPER_OPTIONS } from "./constants";
import { useFormItem, useFormDisabled, useFormItemInputId } from "../Form";
Expand Down Expand Up @@ -426,8 +426,8 @@ defineExpose<SelectInstance>({
</template>
<template v-else>
<template
v-for="[vNode, props] in filteredChilds"
:key="props.value ?? useId().value"
v-for="[vNode, _props] in filteredChilds"
:key="_props.value"
>
<render-vnode :vNode="vNode" />
</template>
Expand Down
Loading

0 comments on commit 7ab1882

Please sign in to comment.