@jx3box/jx3box-ui 2.0.37 → 2.0.38

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jx3box/jx3box-ui",
3
- "version": "2.0.37",
3
+ "version": "2.0.38",
4
4
  "description": "JX3BOX Vue3 UI",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -1,11 +1,19 @@
1
1
  <template>
2
- <div class="relative h-full group c-header-client">
2
+ <div class="relative h-full c-header-client" ref="dropdown">
3
3
  <!-- 当前选择展示 (触发器) -->
4
- <button type="button" class="u-trigger h-full px-4 flex items-center gap-2 transition-colors duration-200">
4
+ <button
5
+ type="button"
6
+ class="u-trigger h-full px-4 flex items-center gap-2 transition-colors duration-200"
7
+ :class="{ 'is-active': isMenuOpen }"
8
+ @click="toggleMenu"
9
+ :aria-expanded="isMenuOpen"
10
+ aria-haspopup="true"
11
+ >
5
12
  <div class="u-client--current">
6
13
  <span class="text-sm font-medium text-gray-200">{{ currentGameLabel }}</span>
7
14
  <svg
8
- class="w-3 h-3 text-gray-400 transition-transform duration-300 group-hover:rotate-180 group-focus-within:rotate-180"
15
+ class="w-3 h-3 text-gray-400 transition-transform duration-300"
16
+ :class="{ 'rotate-180': isMenuOpen }"
9
17
  viewBox="0 0 20 20"
10
18
  fill="currentColor"
11
19
  aria-hidden="true"
@@ -21,7 +29,11 @@
21
29
 
22
30
  <!-- 下拉菜单内容 -->
23
31
  <div
24
- class="absolute top-full left-0 w-56 bg-[#242424] border border-gray-700 rounded-b-lg shadow-2xl py-2 overflow-hidden z-50 transition duration-200 ease-out origin-top opacity-0 -translate-y-2 invisible pointer-events-none group-hover:opacity-100 group-hover:translate-y-0 group-hover:visible group-hover:pointer-events-auto group-focus-within:opacity-100 group-focus-within:translate-y-0 group-focus-within:visible group-focus-within:pointer-events-auto"
32
+ class="absolute top-full left-0 w-56 bg-[#242424] border border-gray-700 rounded-b-lg shadow-2xl py-2 overflow-hidden z-50 transition duration-200 ease-out origin-top"
33
+ :class="{
34
+ 'opacity-100 translate-y-0 visible pointer-events-auto': isMenuOpen,
35
+ 'opacity-0 -translate-y-2 invisible pointer-events-none': !isMenuOpen
36
+ }"
25
37
  role="menu"
26
38
  >
27
39
  <div class="px-3 py-2 text-[10px] text-gray-500 uppercase tracking-widest border-b border-gray-800 mb-1">
@@ -31,23 +43,18 @@
31
43
  <!-- 剑网3 -->
32
44
  <a
33
45
  href="javascript:void(0)"
34
- class="flex items-center justify-between px-4 py-3 hover:bg-indigo-600 transition-colors group/item"
46
+ class="flex items-center justify-between px-4 py-3 hover:bg-indigo-600 active:bg-indigo-700 transition-colors group/item"
35
47
  role="menuitem"
36
48
  @click.prevent="switchGame('std')"
37
49
  >
38
50
  <div class="flex items-center">
39
51
  <span class="mr-3 text-indigo-400 group-hover/item:text-white">
40
- <!-- <svg class="w-4 h-4" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
41
- <path d="M4 5a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V5Z" />
42
- <path d="M4 13a2 2 0 0 1 2-2h8a2 2 0 0 1 2 2v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2v-2Z" />
43
- </svg> -->
44
52
  <img
45
53
  class="w-4 h-4"
46
54
  svg-inline
47
55
  src="../../assets/img/common/jx3-www.svg"
48
56
  :alt="$jx3boxT('jx3boxUi.commonHeader.jx3Full', '剑网3 / 无界')"
49
57
  />
50
- <!-- <Jx3Icon class="w-4 h-4" /> -->
51
58
  </span>
52
59
  <div>
53
60
  <div class="text-sm font-bold text-gray-200 group-hover/item:text-white">
@@ -62,26 +69,18 @@
62
69
  <!-- 缘起 -->
63
70
  <a
64
71
  href="javascript:void(0)"
65
- class="flex items-center justify-between px-4 py-3 hover:bg-indigo-600 transition-colors group/item"
72
+ class="flex items-center justify-between px-4 py-3 hover:bg-indigo-600 active:bg-indigo-700 transition-colors group/item"
66
73
  role="menuitem"
67
74
  @click.prevent="switchGame('origin')"
68
75
  >
69
76
  <div class="flex items-center">
70
77
  <span class="mr-3 text-amber-400 group-hover/item:text-white">
71
- <!-- <svg class="w-4 h-4" viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
72
- <path
73
- fill-rule="evenodd"
74
- d="M10 18a8 8 0 1 0 0-16 8 8 0 0 0 0 16Zm.75-12.25a.75.75 0 0 0-1.5 0V10c0 .2.08.39.22.53l2.5 2.5a.75.75 0 1 0 1.06-1.06l-2.28-2.28V5.75Z"
75
- clip-rule="evenodd"
76
- />
77
- </svg> -->
78
78
  <img
79
79
  class="w-4 h-4"
80
80
  svg-inline
81
81
  src="../../assets/img/common/jx3-origin.svg"
82
82
  :alt="$jx3boxT('jx3boxUi.commonHeader.originFull', '剑网3·缘起')"
83
83
  />
84
- <!-- <OriginIcon class="w-4 h-4" /> -->
85
84
  </span>
86
85
  <div>
87
86
  <div class="text-sm font-bold text-gray-200 group-hover/item:text-white">
@@ -97,16 +96,10 @@
97
96
  </template>
98
97
 
99
98
  <script>
100
- // import Jx3Icon from "@/assets/img/components/common/header/jx3-www.svg";
101
- // import OriginIcon from "@/assets/img/components/common/header/jx3-origin.svg";
102
99
  import i18nMixin from "../../i18n/mixin";
103
100
  export default {
104
101
  name: "clientSwitch",
105
102
  mixins: [i18nMixin],
106
- components: {
107
- // Jx3Icon,
108
- // OriginIcon,
109
- },
110
103
  props: {
111
104
  defaultValue: {
112
105
  type: String,
@@ -116,6 +109,7 @@ export default {
116
109
  data: function () {
117
110
  return {
118
111
  activeKey: this.defaultValue || (location.host.includes("origin") ? "origin" : "std"),
112
+ isMenuOpen: false,
119
113
  };
120
114
  },
121
115
  computed: {
@@ -131,6 +125,17 @@ export default {
131
125
  },
132
126
  },
133
127
  methods: {
128
+ toggleMenu: function() {
129
+ this.isMenuOpen = !this.isMenuOpen;
130
+ },
131
+ closeMenu: function() {
132
+ this.isMenuOpen = false;
133
+ },
134
+ handleClickOutside: function(event) {
135
+ if (this.$refs.dropdown && !this.$refs.dropdown.contains(event.target)) {
136
+ this.closeMenu();
137
+ }
138
+ },
134
139
  switchGame: function (target) {
135
140
  if (!target || (target !== "std" && target !== "origin")) return;
136
141
 
@@ -143,10 +148,21 @@ export default {
143
148
  const finalUrl = protocol + "//" + targetHost + currentPath + currentSearch + currentHash;
144
149
 
145
150
  this.activeKey = target;
151
+ this.closeMenu();
146
152
  window.location.href = finalUrl;
147
153
  },
148
154
  },
149
- mounted: function () {},
155
+ mounted: function () {
156
+ // 监听点击外部区域关闭菜单
157
+ document.addEventListener('click', this.handleClickOutside);
158
+ // 支持触摸设备
159
+ document.addEventListener('touchstart', this.handleClickOutside);
160
+ },
161
+ beforeUnmount: function() {
162
+ // 清理事件监听器
163
+ document.removeEventListener('click', this.handleClickOutside);
164
+ document.removeEventListener('touchstart', this.handleClickOutside);
165
+ },
150
166
  };
151
167
  </script>
152
168
 
@@ -155,9 +171,10 @@ export default {
155
171
  .c-header-client {
156
172
  .u-trigger {
157
173
  .pr;
158
- }
159
- &:hover {
160
- .u-trigger::after {
174
+ // 为iOS添加触摸反馈
175
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0.1);
176
+
177
+ &::after {
161
178
  content: "";
162
179
  .db;
163
180
  .pa;
@@ -165,6 +182,20 @@ export default {
165
182
  .w(90px);
166
183
  .h(2px);
167
184
  background-color: #e19f3a;
185
+ opacity: 0;
186
+ transition: opacity 0.2s ease;
187
+ }
188
+
189
+ // 菜单打开时显示激活条
190
+ &.is-active::after {
191
+ opacity: 1;
192
+ }
193
+ }
194
+
195
+ // 桌面端保留hover效果
196
+ @media (hover: hover) and (pointer: fine) {
197
+ &:hover .u-trigger::after {
198
+ opacity: 1;
168
199
  }
169
200
  }
170
201
  height: @header-height;
@@ -185,5 +216,10 @@ export default {
185
216
  fill: #fff !important;
186
217
  }
187
218
  }
219
+
220
+ // 为iOS添加active状态样式
221
+ a[role="menuitem"]:active {
222
+ background-color: rgb(79, 70, 229) !important;
223
+ }
188
224
  }
189
225
  </style>