mikuru 1.0.38 → 1.0.39

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.
Files changed (75) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/components/MikuruAlertDialog.mikuru +183 -0
  3. package/components/MikuruAvatar.mikuru +60 -0
  4. package/components/MikuruAvatarGroup.mikuru +66 -0
  5. package/components/MikuruBadge.mikuru +62 -0
  6. package/components/MikuruBreadcrumb.mikuru +86 -0
  7. package/components/MikuruCalendar.mikuru +142 -0
  8. package/components/MikuruChip.mikuru +64 -0
  9. package/components/MikuruCodeBlock.mikuru +20 -13
  10. package/components/MikuruCodeView.mikuru +21 -0
  11. package/components/MikuruColorPicker.mikuru +63 -0
  12. package/components/MikuruCommandPalette.mikuru +197 -0
  13. package/components/MikuruContextMenu.mikuru +137 -0
  14. package/components/MikuruDataList.mikuru +61 -0
  15. package/components/MikuruDatePicker.mikuru +293 -0
  16. package/components/MikuruDrawer.mikuru +115 -0
  17. package/components/MikuruEmptyState.mikuru +72 -0
  18. package/components/MikuruFileUpload.mikuru +161 -0
  19. package/components/MikuruKbd.mikuru +28 -0
  20. package/components/MikuruMarkdownEditor.mikuru +561 -0
  21. package/components/MikuruPagination.mikuru +109 -0
  22. package/components/MikuruPopover.mikuru +152 -0
  23. package/components/MikuruRadioGroup.mikuru +111 -0
  24. package/components/MikuruRangeSlider.mikuru +96 -0
  25. package/components/MikuruRating.mikuru +72 -0
  26. package/components/MikuruSearchInput.mikuru +97 -0
  27. package/components/MikuruSegmentedControl.mikuru +70 -0
  28. package/components/MikuruSkeleton.mikuru +74 -0
  29. package/components/MikuruSlider.mikuru +77 -0
  30. package/components/MikuruStatCard.mikuru +63 -0
  31. package/components/MikuruStepper.mikuru +123 -0
  32. package/components/MikuruSwitch.mikuru +104 -0
  33. package/components/MikuruTable.mikuru +242 -0
  34. package/components/MikuruTagInput.mikuru +127 -0
  35. package/components/MikuruTimePicker.mikuru +61 -0
  36. package/components/MikuruTimeline.mikuru +93 -0
  37. package/components/MikuruTreeView.mikuru +72 -0
  38. package/components/MikuruWysiwygEditor.mikuru +259 -0
  39. package/package.json +289 -1
  40. package/types/components/MikuruAlertDialog.d.ts +16 -0
  41. package/types/components/MikuruAvatar.d.ts +12 -0
  42. package/types/components/MikuruAvatarGroup.d.ts +19 -0
  43. package/types/components/MikuruBadge.d.ts +11 -0
  44. package/types/components/MikuruBreadcrumb.d.ts +16 -0
  45. package/types/components/MikuruCalendar.d.ts +11 -0
  46. package/types/components/MikuruChip.d.ts +12 -0
  47. package/types/components/MikuruCodeView.d.ts +11 -0
  48. package/types/components/MikuruColorPicker.d.ts +11 -0
  49. package/types/components/MikuruCommandPalette.d.ts +20 -0
  50. package/types/components/MikuruContextMenu.d.ts +18 -0
  51. package/types/components/MikuruDataList.d.ts +17 -0
  52. package/types/components/MikuruDatePicker.d.ts +12 -0
  53. package/types/components/MikuruDrawer.d.ts +14 -0
  54. package/types/components/MikuruEmptyState.d.ts +12 -0
  55. package/types/components/MikuruFileUpload.d.ts +14 -0
  56. package/types/components/MikuruKbd.d.ts +9 -0
  57. package/types/components/MikuruMarkdownEditor.d.ts +15 -0
  58. package/types/components/MikuruPagination.d.ts +12 -0
  59. package/types/components/MikuruPopover.d.ts +13 -0
  60. package/types/components/MikuruRadioGroup.d.ts +21 -0
  61. package/types/components/MikuruRangeSlider.d.ts +15 -0
  62. package/types/components/MikuruRating.d.ts +13 -0
  63. package/types/components/MikuruSearchInput.d.ts +12 -0
  64. package/types/components/MikuruSegmentedControl.d.ts +18 -0
  65. package/types/components/MikuruSkeleton.d.ts +13 -0
  66. package/types/components/MikuruSlider.d.ts +15 -0
  67. package/types/components/MikuruStatCard.d.ts +12 -0
  68. package/types/components/MikuruStepper.d.ts +19 -0
  69. package/types/components/MikuruSwitch.d.ts +12 -0
  70. package/types/components/MikuruTable.d.ts +27 -0
  71. package/types/components/MikuruTagInput.d.ts +13 -0
  72. package/types/components/MikuruTimePicker.d.ts +12 -0
  73. package/types/components/MikuruTimeline.d.ts +17 -0
  74. package/types/components/MikuruTreeView.d.ts +17 -0
  75. package/types/components/MikuruWysiwygEditor.d.ts +12 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.39 - 2026-05-18
4
+
5
+ - Added package-exported `MikuruPopover`, `MikuruAlertDialog`, `MikuruTable`, `MikuruPagination`, `MikuruDatePicker`, `MikuruMarkdownEditor`, and `MikuruWysiwygEditor` components with typed exports and dogfood coverage.
6
+ - Added package-exported `MikuruCodeView` and render `MikuruMarkdownEditor` fenced code blocks through it.
7
+ - Added package-exported `MikuruDrawer`, `MikuruBreadcrumb`, `MikuruSwitch`, `MikuruRadioGroup`, `MikuruFileUpload`, `MikuruEmptyState`, `MikuruSkeleton`, `MikuruBadge`, and `MikuruCommandPalette` components with typed exports and dogfood coverage.
8
+ - Added package-exported `MikuruAvatar`, `MikuruAvatarGroup`, `MikuruContextMenu`, `MikuruStepper`, `MikuruSlider`, `MikuruRating`, `MikuruTimeline`, `MikuruStatCard`, and `MikuruKbd` components with typed exports and dogfood coverage.
9
+ - Added package-exported `MikuruSearchInput`, `MikuruSegmentedControl`, `MikuruChip`, `MikuruTagInput`, `MikuruRangeSlider`, `MikuruColorPicker`, `MikuruTimePicker`, `MikuruCalendar`, `MikuruDataList`, and `MikuruTreeView` components with typed exports and dogfood coverage.
10
+
3
11
  ## 1.0.38 - 2026-05-17
4
12
 
5
13
  - Fixed `MikuruVideoPlayer` speed and skip settings so option active states follow the selected value without reactive menu churn, preventing settings menu crashes in consuming apps while keeping speed highlights and skip actions in sync.
@@ -0,0 +1,183 @@
1
+ <template>
2
+ <Teleport to="body">
3
+ <div
4
+ m-if="open"
5
+ class="alert-backdrop"
6
+ role="presentation"
7
+ @click="handleBackdrop"
8
+ >
9
+ <section
10
+ ref="dialogEl"
11
+ class="mikuru-alert-dialog"
12
+ role="alertdialog"
13
+ aria-modal="true"
14
+ :aria-label="title"
15
+ tabindex="-1"
16
+ @click="stopEvent"
17
+ >
18
+ <header>
19
+ <h2>{{ title }}</h2>
20
+ <p>{{ description }}</p>
21
+ </header>
22
+
23
+ <div m-if="body" class="alert-body">
24
+ {{ body }}
25
+ </div>
26
+ <div m-else class="alert-body">
27
+ <slot></slot>
28
+ </div>
29
+
30
+ <footer>
31
+ <button class="secondary" type="button" @click="cancel">{{ cancelLabel }}</button>
32
+ <button class="primary" type="button" @click="confirm">{{ confirmLabel }}</button>
33
+ </footer>
34
+ </section>
35
+ </div>
36
+ </Teleport>
37
+ </template>
38
+
39
+ <script>
40
+ import { onMounted, onUnmounted, ref, watch } from "mikuru";
41
+
42
+ const {
43
+ open = false,
44
+ title = "Confirm action",
45
+ description = "This action needs confirmation.",
46
+ body = "",
47
+ confirmLabel = "Confirm",
48
+ cancelLabel = "Cancel",
49
+ closeOnBackdrop = true,
50
+ closeOnEscape = true
51
+ } = defineProps({
52
+ open: Boolean,
53
+ title: String,
54
+ description: String,
55
+ body: String,
56
+ confirmLabel: String,
57
+ cancelLabel: String,
58
+ closeOnBackdrop: Boolean,
59
+ closeOnEscape: Boolean
60
+ });
61
+
62
+ const emit = defineEmits(["confirm", "cancel", "close"]);
63
+ const dialogEl = ref(null);
64
+
65
+ onMounted(() => {
66
+ document.addEventListener("keydown", handleDocumentKeydown);
67
+ focusDialog();
68
+ });
69
+
70
+ onUnmounted(() => {
71
+ document.removeEventListener("keydown", handleDocumentKeydown);
72
+ });
73
+
74
+ watch(open, focusDialog);
75
+
76
+ function focusDialog() {
77
+ requestAnimationFrame(() => {
78
+ if (open.value && dialogEl.value) {
79
+ dialogEl.value.focus();
80
+ }
81
+ });
82
+ }
83
+
84
+ function confirm() {
85
+ emit("confirm");
86
+ emit("close");
87
+ }
88
+
89
+ function cancel() {
90
+ emit("cancel");
91
+ emit("close");
92
+ }
93
+
94
+ function handleBackdrop() {
95
+ if (closeOnBackdrop.value) {
96
+ cancel();
97
+ }
98
+ }
99
+
100
+ function handleDocumentKeydown(event) {
101
+ if (!open.value || !closeOnEscape.value) return;
102
+ if (event.key === "Escape") {
103
+ cancel();
104
+ }
105
+ }
106
+
107
+ function stopEvent(event) {
108
+ event.stopPropagation();
109
+ }
110
+ </script>
111
+
112
+ <style scoped>
113
+ .alert-backdrop {
114
+ position: fixed;
115
+ inset: 0;
116
+ z-index: 60;
117
+ display: grid;
118
+ place-items: center;
119
+ padding: 20px;
120
+ background: rgb(15 23 42 / 72%);
121
+ }
122
+
123
+ .mikuru-alert-dialog {
124
+ display: grid;
125
+ gap: 14px;
126
+ width: min(440px, 100%);
127
+ border-radius: 8px;
128
+ padding: 18px;
129
+ color: #111827;
130
+ background: #ffffff;
131
+ box-shadow: 0 24px 80px rgb(15 23 42 / 34%);
132
+ outline: none;
133
+ }
134
+
135
+ header,
136
+ .alert-body {
137
+ display: grid;
138
+ gap: 6px;
139
+ }
140
+
141
+ h2,
142
+ p {
143
+ margin: 0;
144
+ }
145
+
146
+ h2 {
147
+ font-size: 1.08rem;
148
+ }
149
+
150
+ p,
151
+ .alert-body {
152
+ color: #475569;
153
+ }
154
+
155
+ footer {
156
+ display: flex;
157
+ justify-content: flex-end;
158
+ gap: 8px;
159
+ }
160
+
161
+ button {
162
+ border: 1px solid #cbd5e1;
163
+ border-radius: 8px;
164
+ padding: 9px 12px;
165
+ font: inherit;
166
+ cursor: pointer;
167
+ }
168
+
169
+ .secondary {
170
+ color: #111827;
171
+ background: #ffffff;
172
+ }
173
+
174
+ .primary {
175
+ border-color: #dc2626;
176
+ color: #ffffff;
177
+ background: #dc2626;
178
+ }
179
+
180
+ button:focus-visible {
181
+ outline: 3px solid rgb(37 99 235 / 18%);
182
+ }
183
+ </style>
@@ -0,0 +1,60 @@
1
+ <template>
2
+ <span class="mikuru-avatar" :data-size="size" :aria-label="alt || name">
3
+ <img m-if="src" :src="src" :alt="alt || name" />
4
+ <span m-else>{{ initials }}</span>
5
+ </span>
6
+ </template>
7
+
8
+ <script>
9
+ import { computed } from "mikuru";
10
+
11
+ const {
12
+ src = "",
13
+ name = "User",
14
+ alt = "",
15
+ size = "md"
16
+ } = defineProps({
17
+ src: String,
18
+ name: String,
19
+ alt: String,
20
+ size: String
21
+ });
22
+
23
+ const initials = computed(() => {
24
+ const words = String(name.value || "User").trim().split(/\s+/).slice(0, 2);
25
+ return words.map((word) => word[0]?.toUpperCase() || "").join("") || "U";
26
+ });
27
+ </script>
28
+
29
+ <style scoped>
30
+ .mikuru-avatar {
31
+ --avatar-size: 40px;
32
+ display: inline-grid;
33
+ place-items: center;
34
+ width: var(--avatar-size);
35
+ height: var(--avatar-size);
36
+ overflow: hidden;
37
+ border: 1px solid #cbd5e1;
38
+ border-radius: 999px;
39
+ color: #1e3a8a;
40
+ background: #dbeafe;
41
+ font-weight: 800;
42
+ line-height: 1;
43
+ }
44
+
45
+ .mikuru-avatar[data-size="sm"] {
46
+ --avatar-size: 28px;
47
+ font-size: 0.78rem;
48
+ }
49
+
50
+ .mikuru-avatar[data-size="lg"] {
51
+ --avatar-size: 56px;
52
+ font-size: 1.1rem;
53
+ }
54
+
55
+ img {
56
+ width: 100%;
57
+ height: 100%;
58
+ object-fit: cover;
59
+ }
60
+ </style>
@@ -0,0 +1,66 @@
1
+ <template>
2
+ <div class="mikuru-avatar-group" :aria-label="label">
3
+ <MikuruAvatar
4
+ m-for="avatar in visibleAvatars"
5
+ :key="avatarKey(avatar)"
6
+ :src="avatar.src"
7
+ :name="avatar.name"
8
+ :alt="avatar.alt"
9
+ :size="size"
10
+ />
11
+ <span m-if="overflowCount > 0" class="avatar-overflow">+{{ overflowCount }}</span>
12
+ </div>
13
+ </template>
14
+
15
+ <script>
16
+ import { computed } from "mikuru";
17
+ import MikuruAvatar from "./MikuruAvatar.mikuru";
18
+
19
+ const {
20
+ avatars = [],
21
+ max = 4,
22
+ size = "md",
23
+ label = "Avatar group"
24
+ } = defineProps({
25
+ avatars: Array,
26
+ max: Number,
27
+ size: String,
28
+ label: String
29
+ });
30
+
31
+ const visibleAvatars = computed(() => avatars.value.slice(0, Math.max(0, max.value)));
32
+ const overflowCount = computed(() => Math.max(0, avatars.value.length - max.value));
33
+
34
+ function avatarKey(avatar) {
35
+ return avatar.id || avatar.src || avatar.name;
36
+ }
37
+ </script>
38
+
39
+ <style scoped>
40
+ .mikuru-avatar-group {
41
+ display: inline-flex;
42
+ align-items: center;
43
+ }
44
+
45
+ :deep(.mikuru-avatar),
46
+ .avatar-overflow {
47
+ box-shadow: 0 0 0 2px #ffffff;
48
+ }
49
+
50
+ :deep(.mikuru-avatar:not(:first-child)),
51
+ .avatar-overflow {
52
+ margin-left: -8px;
53
+ }
54
+
55
+ .avatar-overflow {
56
+ display: inline-grid;
57
+ place-items: center;
58
+ min-width: 40px;
59
+ height: 40px;
60
+ border-radius: 999px;
61
+ color: #334155;
62
+ background: #f1f5f9;
63
+ font-size: 0.82rem;
64
+ font-weight: 800;
65
+ }
66
+ </style>
@@ -0,0 +1,62 @@
1
+ <template>
2
+ <span class="mikuru-badge" :data-tone="tone" :data-variant="variant">
3
+ <slot>{{ label }}</slot>
4
+ </span>
5
+ </template>
6
+
7
+ <script>
8
+ const {
9
+ label = "Badge",
10
+ tone = "neutral",
11
+ variant = "soft"
12
+ } = defineProps({
13
+ label: String,
14
+ tone: String,
15
+ variant: String
16
+ });
17
+ </script>
18
+
19
+ <style scoped>
20
+ .mikuru-badge {
21
+ display: inline-flex;
22
+ align-items: center;
23
+ width: fit-content;
24
+ min-height: 22px;
25
+ border: 1px solid transparent;
26
+ border-radius: 999px;
27
+ padding: 2px 8px;
28
+ font-size: 0.78rem;
29
+ font-weight: 700;
30
+ line-height: 1.2;
31
+ }
32
+
33
+ .mikuru-badge[data-tone="neutral"] {
34
+ color: #334155;
35
+ background: #f1f5f9;
36
+ }
37
+
38
+ .mikuru-badge[data-tone="success"] {
39
+ color: #166534;
40
+ background: #dcfce7;
41
+ }
42
+
43
+ .mikuru-badge[data-tone="warning"] {
44
+ color: #92400e;
45
+ background: #fef3c7;
46
+ }
47
+
48
+ .mikuru-badge[data-tone="danger"] {
49
+ color: #991b1b;
50
+ background: #fee2e2;
51
+ }
52
+
53
+ .mikuru-badge[data-tone="info"] {
54
+ color: #1e40af;
55
+ background: #dbeafe;
56
+ }
57
+
58
+ .mikuru-badge[data-variant="outline"] {
59
+ background: transparent;
60
+ border-color: currentColor;
61
+ }
62
+ </style>
@@ -0,0 +1,86 @@
1
+ <template>
2
+ <nav class="mikuru-breadcrumb" aria-label="Breadcrumb">
3
+ <ol>
4
+ <li m-for="item in items" :key="itemKey(item)">
5
+ <a
6
+ m-if="item.href && !item.current"
7
+ :href="item.href"
8
+ @click="selectItem(item, $event)"
9
+ >{{ item.label }}</a>
10
+ <button
11
+ m-else-if="!item.current"
12
+ type="button"
13
+ @click="selectItem(item, $event)"
14
+ >{{ item.label }}</button>
15
+ <span m-else aria-current="page">{{ item.label }}</span>
16
+ </li>
17
+ </ol>
18
+ </nav>
19
+ </template>
20
+
21
+ <script>
22
+ const {
23
+ items = []
24
+ } = defineProps({
25
+ items: Array
26
+ });
27
+
28
+ const emit = defineEmits(["select"]);
29
+
30
+ function itemKey(item) {
31
+ return item.value || item.href || item.label;
32
+ }
33
+
34
+ function selectItem(item, event) {
35
+ emit("select", item, event);
36
+ }
37
+ </script>
38
+
39
+ <style scoped>
40
+ .mikuru-breadcrumb {
41
+ color: #64748b;
42
+ font: inherit;
43
+ }
44
+
45
+ ol {
46
+ display: flex;
47
+ flex-wrap: wrap;
48
+ align-items: center;
49
+ gap: 6px;
50
+ margin: 0;
51
+ padding: 0;
52
+ list-style: none;
53
+ }
54
+
55
+ li {
56
+ display: inline-flex;
57
+ align-items: center;
58
+ gap: 6px;
59
+ }
60
+
61
+ li:not(:last-child)::after {
62
+ color: #94a3b8;
63
+ content: "/";
64
+ }
65
+
66
+ a,
67
+ button {
68
+ border: 0;
69
+ padding: 0;
70
+ color: #2563eb;
71
+ background: transparent;
72
+ font: inherit;
73
+ text-decoration: none;
74
+ cursor: pointer;
75
+ }
76
+
77
+ a:hover,
78
+ button:hover {
79
+ text-decoration: underline;
80
+ }
81
+
82
+ span {
83
+ color: #111827;
84
+ font-weight: 650;
85
+ }
86
+ </style>
@@ -0,0 +1,142 @@
1
+ <template>
2
+ <section class="mikuru-calendar" :aria-label="label">
3
+ <header>
4
+ <button type="button" @click="previousMonth">Prev</button>
5
+ <strong>{{ monthLabel }}</strong>
6
+ <button type="button" @click="nextMonth">Next</button>
7
+ </header>
8
+ <div class="weekday-grid">
9
+ <span m-for="day in weekdays" :key="day">{{ day }}</span>
10
+ </div>
11
+ <div class="day-grid">
12
+ <button
13
+ m-for="day in days"
14
+ :key="day.key"
15
+ type="button"
16
+ :data-muted="day.currentMonth ? 'false' : 'true'"
17
+ :data-selected="day.date === modelValue ? 'true' : 'false'"
18
+ @click="selectDay(day)"
19
+ >{{ day.day }}</button>
20
+ </div>
21
+ </section>
22
+ </template>
23
+
24
+ <script>
25
+ import { computed, ref, watch } from "mikuru";
26
+
27
+ const {
28
+ label = "Calendar",
29
+ modelValue = "",
30
+ locale = "en-US"
31
+ } = defineProps({
32
+ label: String,
33
+ modelValue: String,
34
+ locale: String
35
+ });
36
+
37
+ const emit = defineEmits(["update:modelValue", "change"]);
38
+ const viewDate = ref(new Date());
39
+ const weekdays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
40
+
41
+ watch(modelValue, () => {
42
+ if (!modelValue.value) return;
43
+ const parsed = new Date(`${modelValue.value}T00:00:00`);
44
+ if (!Number.isNaN(parsed.getTime())) viewDate.value = parsed;
45
+ }, { immediate: true });
46
+
47
+ const monthLabel = computed(() => {
48
+ return viewDate.value.toLocaleDateString(locale.value, { month: "long", year: "numeric" });
49
+ });
50
+
51
+ const days = computed(() => {
52
+ const year = viewDate.value.getFullYear();
53
+ const month = viewDate.value.getMonth();
54
+ const first = new Date(year, month, 1);
55
+ const start = new Date(year, month, 1 - first.getDay());
56
+ return Array.from({ length: 42 }, (_, index) => {
57
+ const date = new Date(start);
58
+ date.setDate(start.getDate() + index);
59
+ return {
60
+ key: date.toISOString(),
61
+ day: date.getDate(),
62
+ date: toDateValue(date),
63
+ currentMonth: date.getMonth() === month
64
+ };
65
+ });
66
+ });
67
+
68
+ function previousMonth() {
69
+ viewDate.value = new Date(viewDate.value.getFullYear(), viewDate.value.getMonth() - 1, 1);
70
+ }
71
+
72
+ function nextMonth() {
73
+ viewDate.value = new Date(viewDate.value.getFullYear(), viewDate.value.getMonth() + 1, 1);
74
+ }
75
+
76
+ function selectDay(day) {
77
+ emit("update:modelValue", day.date);
78
+ emit("change", day.date, day);
79
+ }
80
+
81
+ function toDateValue(date) {
82
+ const year = date.getFullYear();
83
+ const month = String(date.getMonth() + 1).padStart(2, "0");
84
+ const day = String(date.getDate()).padStart(2, "0");
85
+ return `${year}-${month}-${day}`;
86
+ }
87
+ </script>
88
+
89
+ <style scoped>
90
+ .mikuru-calendar {
91
+ display: grid;
92
+ gap: 8px;
93
+ width: min(320px, 100%);
94
+ color: #111827;
95
+ font: inherit;
96
+ }
97
+
98
+ header,
99
+ .weekday-grid,
100
+ .day-grid {
101
+ display: grid;
102
+ grid-template-columns: repeat(7, minmax(0, 1fr));
103
+ gap: 4px;
104
+ }
105
+
106
+ header {
107
+ grid-template-columns: auto 1fr auto;
108
+ align-items: center;
109
+ }
110
+
111
+ strong {
112
+ text-align: center;
113
+ }
114
+
115
+ button {
116
+ border: 1px solid #cbd5e1;
117
+ border-radius: 8px;
118
+ padding: 7px;
119
+ color: #111827;
120
+ background: #ffffff;
121
+ font: inherit;
122
+ cursor: pointer;
123
+ }
124
+
125
+ .weekday-grid span {
126
+ color: #64748b;
127
+ font-size: 0.78rem;
128
+ font-weight: 700;
129
+ text-align: center;
130
+ }
131
+
132
+ .day-grid button[data-muted="true"] {
133
+ color: #94a3b8;
134
+ background: #f8fafc;
135
+ }
136
+
137
+ .day-grid button[data-selected="true"] {
138
+ border-color: #2563eb;
139
+ color: #ffffff;
140
+ background: #2563eb;
141
+ }
142
+ </style>
@@ -0,0 +1,64 @@
1
+ <template>
2
+ <span class="mikuru-chip" :data-tone="tone">
3
+ <slot>{{ label }}</slot>
4
+ <button m-if="removable" type="button" :aria-label="removeLabel" @click="remove">Remove</button>
5
+ </span>
6
+ </template>
7
+
8
+ <script>
9
+ const {
10
+ label = "Chip",
11
+ tone = "neutral",
12
+ removable = false,
13
+ removeLabel = "Remove chip"
14
+ } = defineProps({
15
+ label: String,
16
+ tone: String,
17
+ removable: Boolean,
18
+ removeLabel: String
19
+ });
20
+
21
+ const emit = defineEmits(["remove"]);
22
+
23
+ function remove() {
24
+ emit("remove");
25
+ }
26
+ </script>
27
+
28
+ <style scoped>
29
+ .mikuru-chip {
30
+ display: inline-flex;
31
+ align-items: center;
32
+ gap: 6px;
33
+ width: fit-content;
34
+ min-height: 26px;
35
+ border: 1px solid #cbd5e1;
36
+ border-radius: 999px;
37
+ padding: 3px 9px;
38
+ color: #334155;
39
+ background: #f8fafc;
40
+ font-size: 0.86rem;
41
+ font-weight: 650;
42
+ }
43
+
44
+ .mikuru-chip[data-tone="info"] {
45
+ border-color: #bfdbfe;
46
+ color: #1e40af;
47
+ background: #eff6ff;
48
+ }
49
+
50
+ .mikuru-chip[data-tone="success"] {
51
+ border-color: #bbf7d0;
52
+ color: #166534;
53
+ background: #f0fdf4;
54
+ }
55
+
56
+ button {
57
+ border: 0;
58
+ padding: 0;
59
+ color: inherit;
60
+ background: transparent;
61
+ font: inherit;
62
+ cursor: pointer;
63
+ }
64
+ </style>