Context menu
Меню, которое открывается щелчком правой кнопки мыши.
- Браузеры
- Chrome 151+Почему указана эта версия?, Firefox 151+
CSS anchor positioning places this surface beside its trigger using
position-anchor, andanchor(). Older Chrome versions may place the surface away from its trigger.Почему указана эта версия?, Safari 27+CSS anchor positioning places this surface beside its trigger using
position-anchor, andanchor(). Older Firefox versions may place the surface away from its trigger.Почему указана эта версия?CSS anchor positioning places this surface beside its trigger using
position-anchor, andanchor(). Older Safari versions may place the surface away from its trigger. - Уровень
- 2
- Сжатый размер
- 4.90 kB
- Лимит принудительной компоновки
- 0 ms
- Лимит axe
- 0
- Совместим с SSR
- Да
- Публичный контракт
- Тестовый стенд
Песочница
Context Menu
Закрыт
Область щелчка правой кнопкой мыши
Копировать
Вставить
Открыт
Область щелчка правой кнопкой мыши
Копировать
Вставить
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
import { ContextMenu } from "@gunkin/uiify";
export default function Example() {
return (
<ContextMenu.Root>
<ContextMenu.Trigger className="">Right-click here</ContextMenu.Trigger>
<ContextMenu.Content className="">
<ContextMenu.Item className="">Copy</ContextMenu.Item>
<ContextMenu.Separator className="" />
<ContextMenu.Item className="">Paste</ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Root>
);
}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
- 182
- 183
- 184
- 185
- 186
- 187
- 188
- 189
- 190
- 191
- 192
- 193
- 194
- 195
- 196
- 197
- 198
- 199
- 200
- 201
- 202
- 203
- 204
- 205
- 206
- 207
- 208
- 209
- 210
- 211
- 212
- 213
- 214
- 215
- 216
- 217
- 218
- 219
- 220
- 221
- 222
- 223
- 224
- 225
- 226
- 227
- 228
- 229
- 230
- 231
- 232
- 233
- 234
- 235
- 236
- 237
- 238
- 239
- 240
- 241
- 242
- 243
- 244
- 245
- 246
- 247
- 248
- 249
- 250
- 251
- 252
- 253
- 254
- 255
- 256
- 257
- 258
- 259
- 260
- 261
- 262
- 263
- 264
- 265
- 266
- 267
- 268
- 269
- 270
- 271
- 272
- 273
- 274
- 275
- 276
- 277
- 278
- 279
- 280
- 281
- 282
- 283
- 284
- 285
- 286
- 287
- 288
- 289
- 290
- 291
- 292
- 293
- 294
- 295
- 296
- 297
- 298
- 299
- 300
- 301
- 302
- 303
- 304
- 305
- 306
- 307
- 308
- 309
- 310
- 311
- 312
- 313
- 314
- 315
- 316
- 317
- 318
- 319
- 320
- 321
- 322
- 323
- 324
- 325
- 326
- 327
- 328
- 329
- 330
- 331
- 332
- 333
- 334
- 335
- 336
/* Generic skin for custom core surfaces used by the demo and consumers. */
@layer components {
[data-uiify-surface] {
display: grid;
gap: var(--space-md);
inline-size: max-content;
max-inline-size: min(28rem, calc(100vw - 2 * var(--space-lg)));
padding: var(--space-lg);
border: var(--border-width) solid var(--border);
border-radius: var(--radius-xl);
corner-shape: squircle;
background-color: var(--card);
color: var(--card-foreground);
box-shadow: var(--shadow-popover);
}
[data-uiify-surface][popover]:not(:popover-open) {
display: none;
}
@media (prefers-reduced-motion: no-preference) {
[data-uiify-surface][popover] {
transition: var(--transition-presence);
}
[data-uiify-surface][popover]:not(:popover-open) {
opacity: 0;
scale: var(--presence-scale);
}
@starting-style {
[data-uiify-surface][popover]:popover-open {
opacity: 0;
scale: var(--presence-scale);
}
}
}
}
/* Dropdown menu — a compact command surface with explicit anatomy hooks. */
@layer components {
[data-uiify-menu-bar] {
display: inline-flex;
align-items: center;
gap: var(--space-xs);
padding: var(--space-xs);
border: var(--border-width) solid var(--border);
border-radius: var(--radius-lg);
corner-shape: squircle;
background-color: var(--background);
}
:where(
[data-uiify-menu] :is([data-part="content"], [data-part="sub-content"]),
[data-uiify-menu]:is([data-part="content"], [data-part="sub-content"])
):where(:not([popover]), :popover-open) {
display: flex;
}
:where(
[data-uiify-menu] :is([data-part="content"], [data-part="sub-content"]),
[data-uiify-menu]:is([data-part="content"], [data-part="sub-content"])
) {
flex-direction: column;
min-inline-size: 12rem;
max-block-size: min(24rem, calc(100dvb - 2rem));
overflow-block: auto;
overscroll-behavior: contain;
padding: var(--space-xs);
border: var(--border-width) solid var(--border);
border-radius: var(--radius-lg);
corner-shape: squircle;
background-color: var(--popover);
color: var(--popover-foreground);
box-shadow: var(--shadow-popover);
transform-origin: var(--transform-origin, top);
}
:where(
[data-uiify-menu] :is([data-part="content"], [data-part="sub-content"]),
[data-uiify-menu]:is([data-part="content"], [data-part="sub-content"])
)[data-state="closed"] {
display: none;
}
[data-uiify-menu]
:is(
[data-part="item"],
[data-part="checkbox-item"],
[data-part="radio-item"],
[data-part="sub-trigger"]
) {
display: flex;
align-items: center;
column-gap: var(--space-md);
padding-block: var(--space-sm);
padding-inline: var(--space-md);
border-radius: calc(var(--radius-lg) - var(--space-xs));
corner-shape: squircle;
cursor: pointer;
user-select: none;
inline-size: 100%;
border: 0;
background: transparent;
color: inherit;
font: inherit;
font-size: var(--text-sm) !important;
line-height: var(--leading-normal);
text-align: start;
appearance: none;
}
[data-uiify-menu]
:is(
[data-part="item"],
[data-part="checkbox-item"],
[data-part="radio-item"],
[data-part="sub-trigger"]
):is(:hover, :focus-visible, [data-highlighted]) {
background-color: var(--accent);
color: var(--accent-foreground);
outline: none;
}
[data-uiify-menu]
[data-part="radio-item"]:hover[role="menuitemradio"][data-state="checked"]
[data-part="item-indicator"],
[data-uiify-menu]
[data-part="radio-item"]:focus-visible[role="menuitemradio"][data-state="checked"]
[data-part="item-indicator"],
[data-uiify-menu]
[data-part="radio-item"][data-highlighted][role="menuitemradio"][data-state="checked"]
[data-part="item-indicator"] {
border-color: var(--accent-foreground);
}
[data-uiify-menu]
:is(
[data-part="item"],
[data-part="checkbox-item"],
[data-part="radio-item"],
[data-part="sub-trigger"]
):is([aria-disabled="true"], [data-disabled]) {
opacity: 0.5;
pointer-events: none;
}
[data-uiify-menu]
:is(
[data-part="item"],
[data-part="checkbox-item"],
[data-part="radio-item"],
[data-part="sub-trigger"]
)[data-danger] {
color: var(--destructive, var(--foreground));
}
[data-uiify-menu]
:is(
[data-part="item"],
[data-part="checkbox-item"],
[data-part="radio-item"],
[data-part="sub-trigger"]
)[data-danger]:is(:hover, :focus-visible, [data-highlighted]) {
background-color: var(--destructive);
color: var(--destructive-foreground);
}
[data-uiify-menu] [data-part="item-icon"],
[data-uiify-menu] [data-part="item-indicator"] {
display: inline-grid;
place-items: center;
inline-size: 1.25rem;
block-size: 1.25rem;
flex: 0 0 1.25rem;
}
[data-uiify-menu] [data-part="item-indicator"] {
border: var(--border-width) solid var(--input);
border-radius: var(--radius-xs);
corner-shape: squircle;
color: transparent;
}
[role="menuitemcheckbox"][data-state="checked"] [data-part="item-indicator"],
[role="menuitemcheckbox"][data-state="indeterminate"] [data-part="item-indicator"] {
border-color: var(--primary);
background: var(--primary);
color: var(--primary-foreground);
}
[role="menuitemcheckbox"][data-state="checked"] [data-part="item-indicator"]::before {
inline-size: 0.65rem;
block-size: 0.65rem;
background-color: currentcolor;
clip-path: polygon(14% 44%, 0 65%, 38% 100%, 100% 22%, 84% 6%, 38% 68%);
content: "";
}
[role="menuitemcheckbox"][data-state="indeterminate"] [data-part="item-indicator"]::before {
inline-size: 0.65rem;
block-size: 0.12rem;
background: currentcolor;
content: "";
}
[role="menuitemradio"] [data-part="item-indicator"] {
border-radius: 50%;
}
[role="menuitemradio"][data-state="checked"] [data-part="item-indicator"] {
border-width: 5px;
border-color: var(--primary);
background: var(--card);
}
[role="menuitemradio"][data-state="checked"] [data-part="item-indicator"]::before {
content: none;
}
[data-uiify-menu] [data-part="item-icon"] > svg,
[data-uiify-menu] [data-part="item-indicator"] > svg {
display: block;
inline-size: 100%;
block-size: 100%;
}
[data-uiify-menu] [data-part="item-text"] {
display: grid;
flex: 1 1 auto;
min-inline-size: 0;
}
[data-uiify-menu] [data-part="item-description"] {
color: var(--muted-foreground);
font-size: var(--text-xs);
line-height: var(--leading-normal);
}
[data-uiify-menu]
:is(
[data-part="item"],
[data-part="checkbox-item"],
[data-part="radio-item"],
[data-part="sub-trigger"]
):is(:hover, :focus-visible, [data-highlighted])
[data-part="item-description"] {
color: inherit;
opacity: 0.8;
}
[data-uiify-menu] [data-part="shortcut"] {
margin-inline-start: auto;
color: var(--muted-foreground);
font-size: var(--text-xs);
font-family: inherit;
font-weight: inherit;
line-height: 1;
white-space: nowrap;
}
[data-uiify-menu]
:is(
[data-part="item"],
[data-part="checkbox-item"],
[data-part="radio-item"],
[data-part="sub-trigger"]
):is(:hover, :focus-visible, [data-highlighted])
[data-part="shortcut"] {
color: inherit;
opacity: 0.85;
}
[data-uiify-menu] [data-part="label"] {
padding-block: var(--space-xs);
padding-inline: var(--space-md);
color: var(--muted-foreground);
font-size: var(--text-xs);
font-weight: var(--weight-semibold);
}
[data-uiify-menu] [data-part="separator"] {
block-size: var(--border-width);
margin-block: var(--space-xs);
margin-inline: calc(-1 * var(--space-xs));
background-color: var(--border);
}
[data-uiify-menu] [data-part="sub-content"] {
min-inline-size: 11rem;
}
[data-uiify-menu] [data-part="sub-content"][data-side="right"] {
--uiify-anchor-offset: 0;
inset-block-start: calc(anchor(start) - var(--space-xs));
}
@media (prefers-reduced-motion: no-preference) {
:where(
[data-uiify-menu] :is([data-part="content"], [data-part="sub-content"]),
[data-uiify-menu]:is([data-part="content"], [data-part="sub-content"])
) {
transition: var(--transition-presence);
}
:where(
[data-uiify-menu] :is([data-part="content"], [data-part="sub-content"]),
[data-uiify-menu]:is([data-part="content"], [data-part="sub-content"])
)[popover]:not(:popover-open) {
opacity: 0;
scale: var(--presence-scale);
}
@starting-style {
:where(
[data-uiify-menu] :is([data-part="content"], [data-part="sub-content"]),
[data-uiify-menu]:is([data-part="content"], [data-part="sub-content"])
):popover-open {
opacity: 0;
scale: var(--presence-scale);
}
}
}
}
@layer components {
:is([data-uiify-dropdown-menu], [data-uiify-context-menu])
[role="menuitemradio"]
[data-part="item-indicator"] {
border-radius: 50%;
corner-shape: round;
}
}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
import { ContextMenu } from "@gunkin/uiify";
export default function Example() {
return (
<ContextMenu.Root>
<ContextMenu.Trigger
className="
grid gap-md w-max max-w-[min(28rem,calc(100vw_-_2_*_var(--space-lg)))] p-6 border border-border rounded-xl
[corner-shape:squircle] bg-card text-card-foreground shadow-popover [&[popover]:not(:popover-open)]:hidden
motion-safe:[&[popover]]:[transition:var(--transition-presence)]
motion-safe:[&[popover]:not(:popover-open)]:opacity-0
motion-safe:[&[popover]:not(:popover-open)]:[scale:var(--presence-scale)]
motion-safe:starting:[&[popover]:popover-open]:opacity-0
motion-safe:starting:[&[popover]:popover-open]:[scale:var(--presence-scale)]
"
>
Right-click here
</ContextMenu.Trigger>
<ContextMenu.Content
className="
[&[data-positioning=native]]:[--uiify-anchor-offset:var(--space-sm)]
[&_[data-positioning=native]]:[--uiify-anchor-offset:var(--space-sm)]
[&[popover]:popover-open:not([data-positioning=native])]:[margin:revert]
[&_[popover]:popover-open:not([data-positioning=native])]:[margin:revert] flex-col [min-inline-size:12rem]
[max-block-size:min(24rem,calc(100dvb_-_2rem))] overflow-y-auto overscroll-contain p-xs
border-[length:var(--border-width)] border-solid border-border rounded-lg [corner-shape:squircle] bg-popover
text-popover-foreground shadow-popover [transform-origin:var(--transform-origin,top)]
data-[state=closed]:hidden [&:where(:not([popover]),:popover-open)]:flex
[&[data-part=sub-content]]:[min-inline-size:11rem]
[&[data-part=sub-content][data-side=right]]:[--uiify-anchor-offset:0]
[&[data-part=sub-content][data-side=right]]:[inset-block-start:calc(anchor(start)_-_var(--space-xs))]
motion-safe:[transition:var(--transition-presence)] motion-safe:[&:not(:popover-open)]:opacity-0
motion-safe:[&:not(:popover-open)]:[scale:var(--presence-scale)]
motion-safe:starting:[&:popover-open]:opacity-0
motion-safe:starting:[&:popover-open]:[scale:var(--presence-scale)]
"
>
<ContextMenu.Item
className={
"flex items-center gap-md w-full py-sm px-md border-0 rounded-[calc(var(--radius-lg)_-_var(--space-xs))]" +
" [corner-shape:squircle] bg-transparent text-inherit [font-family:inherit] [font-weight:inherit] text-s" +
"m [line-height:var(--leading-normal)] text-start cursor-pointer select-none appearance-none hover:bg-ac" +
"cent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground focus-vi" +
"sible:outline-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground aria-[disable" +
"d=true]:opacity-50 aria-[disabled=true]:pointer-events-none data-[disabled]:opacity-50 data-[disabled]:" +
"pointer-events-none data-[danger]:text-destructive data-[danger]:hover:bg-destructive data-[danger]:hov" +
"er:text-destructive-foreground data-[danger]:focus-visible:bg-destructive data-[danger]:focus-visible:t" +
"ext-destructive-foreground data-[danger]:data-[highlighted]:bg-destructive data-[danger]:data-[highligh" +
"ted]:text-destructive-foreground [&_[data-part=item-icon]]:inline-grid [&_[data-part=item-icon]]:place-" +
"items-center [&_[data-part=item-icon]]:size-5 [&_[data-part=item-icon]]:flex-[0_0_1.25rem] [&_[data-par" +
"t=item-indicator]]:inline-grid [&_[data-part=item-indicator]]:place-items-center [&_[data-part=item-ind" +
"icator]]:size-5 [&_[data-part=item-indicator]]:flex-[0_0_1.25rem] [&_[data-part=item-indicator]>svg]:bl" +
"ock [&_[data-part=item-indicator]>svg]:size-full [&[role=menuitemcheckbox]_[data-part=item-indicator]]:" +
"border-[length:var(--border-width)] [&[role=menuitemcheckbox]_[data-part=item-indicator]]:border-input " +
"[&[role=menuitemcheckbox]_[data-part=item-indicator]]:rounded-xs [&[role=menuitemcheckbox][data-state=c" +
"hecked]_[data-part=item-indicator]]:border-primary [&[role=menuitemcheckbox][data-state=checked]_[data-" +
"part=item-indicator]]:bg-primary [&[role=menuitemcheckbox][data-state=checked]_[data-part=item-indicato" +
"r]]:text-primary-foreground [&[role=menuitemcheckbox][data-state=checked]_[data-part=item-indicator]::b" +
"efore]:content-[''] [&[role=menuitemcheckbox][data-state=checked]_[data-part=item-indicator]::before]:s" +
"ize-[0.65rem] [&[role=menuitemcheckbox][data-state=checked]_[data-part=item-indicator]::before]:bg-curr" +
"ent [&[role=menuitemcheckbox][data-state=checked]_[data-part=item-indicator]::before]:[clip-path:polygo" +
"n(14%_44%,0_65%,38%_100%,100%_22%,84%_6%,38%_68%)] [&[role=menuitemcheckbox][data-state=indeterminate]_" +
"[data-part=item-indicator]]:border-primary [&[role=menuitemcheckbox][data-state=indeterminate]_[data-pa" +
"rt=item-indicator]]:bg-primary [&[role=menuitemcheckbox][data-state=indeterminate]_[data-part=item-indi" +
"cator]]:text-primary-foreground [&[role=menuitemcheckbox][data-state=indeterminate]_[data-part=item-ind" +
"icator]::before]:content-[''] [&[role=menuitemcheckbox][data-state=indeterminate]_[data-part=item-indic" +
"ator]::before]:w-[0.65rem] [&[role=menuitemcheckbox][data-state=indeterminate]_[data-part=item-indicato" +
"r]::before]:h-[0.12rem] [&[role=menuitemcheckbox][data-state=indeterminate]_[data-part=item-indicator]:" +
":before]:bg-current [&[role=menuitemradio]_[data-part=item-indicator]]:rounded-full [&[role=menuitemrad" +
"io][data-state=checked]_[data-part=item-indicator]]:border-[5px] [&[role=menuitemradio][data-state=chec" +
"ked]_[data-part=item-indicator]]:border-primary [&[role=menuitemradio][data-state=checked]_[data-part=i" +
"tem-indicator]]:bg-card [&_[data-part=item-text]]:grid [&_[data-part=item-text]]:flex-auto [&_[data-par" +
"t=item-text]]:[min-inline-size:0] [&_[data-part=item-description]]:text-muted-foreground [&_[data-part=" +
"item-description]]:text-xs [&_[data-part=item-description]]:[line-height:var(--leading-normal)] [&_[dat" +
"a-part=shortcut]]:ms-auto [&_[data-part=shortcut]]:text-muted-foreground [&_[data-part=shortcut]]:text-" +
"xs [&_[data-part=shortcut]]:leading-none [&_[data-part=shortcut]]:whitespace-nowrap"
}
>
Copy
</ContextMenu.Item>
<ContextMenu.Separator
className="
[block-size:var(--border-width)] [margin-block:var(--space-xs)] [margin-inline:calc(-1_*var(--space-xs))]
bg-border
"
/>
<ContextMenu.Item
className={
"flex items-center gap-md w-full py-sm px-md border-0 rounded-[calc(var(--radius-lg)_-_var(--space-xs))]" +
" [corner-shape:squircle] bg-transparent text-inherit [font-family:inherit] [font-weight:inherit] text-s" +
"m [line-height:var(--leading-normal)] text-start cursor-pointer select-none appearance-none hover:bg-ac" +
"cent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground focus-vi" +
"sible:outline-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground aria-[disable" +
"d=true]:opacity-50 aria-[disabled=true]:pointer-events-none data-[disabled]:opacity-50 data-[disabled]:" +
"pointer-events-none data-[danger]:text-destructive data-[danger]:hover:bg-destructive data-[danger]:hov" +
"er:text-destructive-foreground data-[danger]:focus-visible:bg-destructive data-[danger]:focus-visible:t" +
"ext-destructive-foreground data-[danger]:data-[highlighted]:bg-destructive data-[danger]:data-[highligh" +
"ted]:text-destructive-foreground [&_[data-part=item-icon]]:inline-grid [&_[data-part=item-icon]]:place-" +
"items-center [&_[data-part=item-icon]]:size-5 [&_[data-part=item-icon]]:flex-[0_0_1.25rem] [&_[data-par" +
"t=item-indicator]]:inline-grid [&_[data-part=item-indicator]]:place-items-center [&_[data-part=item-ind" +
"icator]]:size-5 [&_[data-part=item-indicator]]:flex-[0_0_1.25rem] [&_[data-part=item-indicator]>svg]:bl" +
"ock [&_[data-part=item-indicator]>svg]:size-full [&[role=menuitemcheckbox]_[data-part=item-indicator]]:" +
"border-[length:var(--border-width)] [&[role=menuitemcheckbox]_[data-part=item-indicator]]:border-input " +
"[&[role=menuitemcheckbox]_[data-part=item-indicator]]:rounded-xs [&[role=menuitemcheckbox][data-state=c" +
"hecked]_[data-part=item-indicator]]:border-primary [&[role=menuitemcheckbox][data-state=checked]_[data-" +
"part=item-indicator]]:bg-primary [&[role=menuitemcheckbox][data-state=checked]_[data-part=item-indicato" +
"r]]:text-primary-foreground [&[role=menuitemcheckbox][data-state=checked]_[data-part=item-indicator]::b" +
"efore]:content-[''] [&[role=menuitemcheckbox][data-state=checked]_[data-part=item-indicator]::before]:s" +
"ize-[0.65rem] [&[role=menuitemcheckbox][data-state=checked]_[data-part=item-indicator]::before]:bg-curr" +
"ent [&[role=menuitemcheckbox][data-state=checked]_[data-part=item-indicator]::before]:[clip-path:polygo" +
"n(14%_44%,0_65%,38%_100%,100%_22%,84%_6%,38%_68%)] [&[role=menuitemcheckbox][data-state=indeterminate]_" +
"[data-part=item-indicator]]:border-primary [&[role=menuitemcheckbox][data-state=indeterminate]_[data-pa" +
"rt=item-indicator]]:bg-primary [&[role=menuitemcheckbox][data-state=indeterminate]_[data-part=item-indi" +
"cator]]:text-primary-foreground [&[role=menuitemcheckbox][data-state=indeterminate]_[data-part=item-ind" +
"icator]::before]:content-[''] [&[role=menuitemcheckbox][data-state=indeterminate]_[data-part=item-indic" +
"ator]::before]:w-[0.65rem] [&[role=menuitemcheckbox][data-state=indeterminate]_[data-part=item-indicato" +
"r]::before]:h-[0.12rem] [&[role=menuitemcheckbox][data-state=indeterminate]_[data-part=item-indicator]:" +
":before]:bg-current [&[role=menuitemradio]_[data-part=item-indicator]]:rounded-full [&[role=menuitemrad" +
"io][data-state=checked]_[data-part=item-indicator]]:border-[5px] [&[role=menuitemradio][data-state=chec" +
"ked]_[data-part=item-indicator]]:border-primary [&[role=menuitemradio][data-state=checked]_[data-part=i" +
"tem-indicator]]:bg-card [&_[data-part=item-text]]:grid [&_[data-part=item-text]]:flex-auto [&_[data-par" +
"t=item-text]]:[min-inline-size:0] [&_[data-part=item-description]]:text-muted-foreground [&_[data-part=" +
"item-description]]:text-xs [&_[data-part=item-description]]:[line-height:var(--leading-normal)] [&_[dat" +
"a-part=shortcut]]:ms-auto [&_[data-part=shortcut]]:text-muted-foreground [&_[data-part=shortcut]]:text-" +
"xs [&_[data-part=shortcut]]:leading-none [&_[data-part=shortcut]]:whitespace-nowrap"
}
>
Paste
</ContextMenu.Item>
</ContextMenu.Content>
</ContextMenu.Root>
);
}- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
- 152
- 153
- 154
- 155
- 156
- 157
- 158
- 159
- 160
- 161
- 162
- 163
- 164
- 165
- 166
- 167
- 168
- 169
- 170
- 171
- 172
- 173
- 174
- 175
- 176
- 177
- 178
- 179
- 180
- 181
/* app.css */
@layer reset, ui, app, tokens, base, demo, components, utilities, theme;
@import "@gunkin/uiify/styles/reset";
@import "@gunkin/uiify/components/behavior.css";
@import "@gunkin/uiify/styles/tokens";
@import "@gunkin/uiify/styles/tailwind";
@import "tailwindcss/utilities.css";
@theme { --spacing: 0.25rem; --font-weight-normal: 400; --font-weight-medium: 500; --font-weight-semibold: 600; --font-weight-bold: 700; }
@source inline('grid gap-md w-max max-w-[min(28rem,calc(100vw_-_2_*_var(--space-lg)))] p-6 border border-border rounded-xl [corner-shape:squircle] bg-card text-card-foreground shadow-popover [&[popover]:not(:popover-open)]:hidden motion-safe:[&[popover]]:[transition:var(--transition-presence)] motion-safe:[&[popover]:not(:popover-open)]:opacity-0 motion-safe:[&[popover]:not(:popover-open)]:[scale:var(--presence-scale)] motion-safe:starting:[&[popover]:popover-open]:opacity-0 motion-safe:starting:[&[popover]:popover-open]:[scale:var(--presence-scale)] [&[data-positioning=native]]:[--uiify-anchor-offset:var(--space-sm)] [&_[data-positioning=native]]:[--uiify-anchor-offset:var(--space-sm)] [&[popover]:popover-open:not([data-positioning=native])]:[margin:revert] [&_[popover]:popover-open:not([data-positioning=native])]:[margin:revert] flex-col [min-inline-size:12rem] [max-block-size:min(24rem,calc(100dvb_-_2rem))] overflow-y-auto overscroll-contain p-xs border-[length:var(--border-width)] border-solid rounded-lg bg-popover text-popover-foreground [transform-origin:var(--transform-origin,top)] data-[state=closed]:hidden [&:where(:not([popover]),:popover-open)]:flex [&[data-part=sub-content]]:[min-inline-size:11rem] [&[data-part=sub-content][data-side=right]]:[--uiify-anchor-offset:0] [&[data-part=sub-content][data-side=right]]:[inset-block-start:calc(anchor(start)_-_var(--space-xs))] motion-safe:[transition:var(--transition-presence)] motion-safe:[&:not(:popover-open)]:opacity-0 motion-safe:[&:not(:popover-open)]:[scale:var(--presence-scale)] motion-safe:starting:[&:popover-open]:opacity-0 motion-safe:starting:[&:popover-open]:[scale:var(--presence-scale)] flex items-center w-full py-sm px-md border-0 rounded-[calc(var(--radius-lg)_-_var(--space-xs))] bg-transparent text-inherit [font-family:inherit] [font-weight:inherit] text-sm [line-height:var(--leading-normal)] text-start cursor-pointer select-none appearance-none hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground focus-visible:outline-none data-[highlighted]:bg-accent data-[highlighted]:text-accent-foreground aria-[disabled=true]:opacity-50 aria-[disabled=true]:pointer-events-none data-[disabled]:opacity-50 data-[disabled]:pointer-events-none data-[danger]:text-destructive data-[danger]:hover:bg-destructive data-[danger]:hover:text-destructive-foreground data-[danger]:focus-visible:bg-destructive data-[danger]:focus-visible:text-destructive-foreground data-[danger]:data-[highlighted]:bg-destructive data-[danger]:data-[highlighted]:text-destructive-foreground [&_[data-part=item-icon]]:inline-grid [&_[data-part=item-icon]]:place-items-center [&_[data-part=item-icon]]:size-5 [&_[data-part=item-icon]]:flex-[0_0_1.25rem] [&_[data-part=item-indicator]]:inline-grid [&_[data-part=item-indicator]]:place-items-center [&_[data-part=item-indicator]]:size-5 [&_[data-part=item-indicator]]:flex-[0_0_1.25rem] [&_[data-part=item-indicator]>svg]:block [&_[data-part=item-indicator]>svg]:size-full [&[role=menuitemcheckbox]_[data-part=item-indicator]]:border-[length:var(--border-width)] [&[role=menuitemcheckbox]_[data-part=item-indicator]]:border-input [&[role=menuitemcheckbox]_[data-part=item-indicator]]:rounded-xs [&[role=menuitemcheckbox][data-state=checked]_[data-part=item-indicator]]:border-primary [&[role=menuitemcheckbox][data-state=checked]_[data-part=item-indicator]]:bg-primary [&[role=menuitemcheckbox][data-state=checked]_[data-part=item-indicator]]:text-primary-foreground [&[role=menuitemcheckbox][data-state=checked]_[data-part=item-indicator]::before]:size-[0.65rem] [&[role=menuitemcheckbox][data-state=checked]_[data-part=item-indicator]::before]:bg-current [&[role=menuitemcheckbox][data-state=checked]_[data-part=item-indicator]::before]:[clip-path:polygon(14%_44%,0_65%,38%_100%,100%_22%,84%_6%,38%_68%)] [&[role=menuitemcheckbox][data-state=indeterminate]_[data-part=item-indicator]]:border-primary [&[role=menuitemcheckbox][data-state=indeterminate]_[data-part=item-indicator]]:bg-primary [&[role=menuitemcheckbox][data-state=indeterminate]_[data-part=item-indicator]]:text-primary-foreground [&[role=menuitemcheckbox][data-state=indeterminate]_[data-part=item-indicator]::before]:w-[0.65rem] [&[role=menuitemcheckbox][data-state=indeterminate]_[data-part=item-indicator]::before]:h-[0.12rem] [&[role=menuitemcheckbox][data-state=indeterminate]_[data-part=item-indicator]::before]:bg-current [&[role=menuitemradio]_[data-part=item-indicator]]:rounded-full [&[role=menuitemradio][data-state=checked]_[data-part=item-indicator]]:border-[5px] [&[role=menuitemradio][data-state=checked]_[data-part=item-indicator]]:border-primary [&[role=menuitemradio][data-state=checked]_[data-part=item-indicator]]:bg-card [&_[data-part=item-text]]:grid [&_[data-part=item-text]]:flex-auto [&_[data-part=item-text]]:[min-inline-size:0] [&_[data-part=item-description]]:text-muted-foreground [&_[data-part=item-description]]:text-xs [&_[data-part=item-description]]:[line-height:var(--leading-normal)] [&_[data-part=shortcut]]:ms-auto [&_[data-part=shortcut]]:text-muted-foreground [&_[data-part=shortcut]]:text-xs [&_[data-part=shortcut]]:leading-none [&_[data-part=shortcut]]:whitespace-nowrap [block-size:var(--border-width)] [margin-block:var(--space-xs)] [margin-inline:calc(-1_*var(--space-xs))] bg-border');
@source inline("[&[role=menuitemcheckbox][data-state=checked]_[data-part=item-indicator]::before]:content-[''] [&[role=menuitemcheckbox][data-state=indeterminate]_[data-part=item-indicator]::before]:content-['']");
@layer base { :root { --uiify-control-text: var(--text-sm); } @media (pointer: coarse) { :root { --uiify-control-text: var(--text-base); } } }
/* Authored animation and registered properties used by the Tailwind skin.
* Visual rules belong in utility recipes; only at-rule definitions live here. */
@layer components {
@keyframes uiify-presence-in {
from {
opacity: 0;
scale: var(--presence-scale);
}
}
}
@layer components {
@keyframes uiify-presence-out {
to {
opacity: 0;
scale: var(--presence-scale);
}
}
}
@property --uiify-spinner-tail {
syntax: "<angle>";
inherits: false;
initial-value: 0deg;
}
@property --uiify-spinner-length {
syntax: "<angle>";
inherits: false;
initial-value: 36deg;
}
@layer components {
@keyframes uiify-spinner-rotate {
to {
transform: rotate(360deg);
}
}
}
@layer components {
@keyframes uiify-spinner-orbit {
0% {
--uiify-spinner-tail: 0deg;
--uiify-spinner-length: 36deg;
}
50% {
--uiify-spinner-tail: 90deg;
--uiify-spinner-length: 324deg;
}
100% {
--uiify-spinner-tail: 360deg;
--uiify-spinner-length: 36deg;
}
}
}
@layer components {
@keyframes uiify-skeleton-pulse {
50% {
opacity: 0.45;
}
}
}
@layer components {
@keyframes uiify-skeleton-shimmer {
to {
background-position: -200% 0;
}
}
}
@layer components {
@keyframes uiify-skeleton-reveal {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
}
@property --candle-body-height {
syntax: "<percentage>";
inherits: true;
initial-value: 0%;
}
@property --candle-body-top {
syntax: "<percentage>";
inherits: true;
initial-value: 50%;
}
@property --candle-slot {
syntax: "<percentage>";
inherits: true;
initial-value: 100%;
}
@property --candle-wick-height {
syntax: "<percentage>";
inherits: true;
initial-value: 0%;
}
@property --candle-wick-top {
syntax: "<percentage>";
inherits: true;
initial-value: 50%;
}
@property --candle-x {
syntax: "<percentage>";
inherits: true;
initial-value: 0%;
}
@property --candle-scale {
syntax: "<number>";
inherits: true;
initial-value: 1;
}
@property --line-y {
syntax: "<percentage>";
inherits: true;
initial-value: 50%;
}
@property --line-prev-y {
syntax: "<percentage>";
inherits: true;
initial-value: 50%;
}
@property --line-count {
syntax: "<integer>";
inherits: false;
initial-value: 1;
}
@property --line-scale {
syntax: "<number>";
inherits: true;
initial-value: 1;
}
@layer components {
@keyframes uiify-otp-input-caret-blink {
50% {
opacity: 0;
}
}
}API
ContextMenu.Root
| Свойство | Тип | По умолчанию | Описание |
|---|---|---|---|
children | ReactNode | — | Область триггера и содержимое меню. |
defaultOpen | boolean | — | Начальное состояние открытия неуправляемого меню. |
id | string | — | Идентификатор всплывающего элемента, содержащего меню. |
onOpenChange | PopoverChangeHandler | — | Вызывается при открытии или закрытии меню с причиной и исходным событием. |
open | boolean | — | Состояние открытия меню, делающее его управляемым. |
ContextMenu.Trigger
| Свойство | Тип | По умолчанию | Описание |
|---|---|---|---|
children | ReactNode | — | Область, открывающая меню щелчком правой кнопки мыши. |
className | string | — | Класс отображаемого элемента. |
render | ReactElement | ((props, state) => ReactElement) | — | Заменяет отображаемый элемент, сохраняя поведение и связи доступности. |
ContextMenu.Content
| Свойство | Тип | По умолчанию | Описание |
|---|---|---|---|
children | ReactNode | — | Пункты, подписи и разделители меню. |
className | string | — | Класс отображаемого элемента. |
render | ReactElement | ((props, state) => ReactElement) | — | Заменяет отображаемый элемент, сохраняя поведение и связи доступности. |
ContextMenu.Item
| Свойство | Тип | По умолчанию | Описание |
|---|---|---|---|
children | ReactNode | — | Содержимое пункта. |
className | string | — | Класс отображаемого элемента. |
disabled | boolean | false | Отключает пункт и пропускает его при навигации с клавиатуры. |
onSelect | (event: MenuSelectEvent) => void | — | Вызывается при выборе пункта; вызов preventDefault у события оставляет меню открытым. |
textValue | string | — | Текст для поиска вводом символов, если содержимое пункта не является обычным текстом. |
render | ReactElement | ((props, state) => ReactElement) | — | Заменяет отображаемый элемент, сохраняя поведение и связи доступности. |
ContextMenu.CheckboxItem
| Свойство | Тип | По умолчанию | Описание |
|---|---|---|---|
checked | boolean | "indeterminate" | false | Состояние отметки пункта. |
children | ReactNode | — | Содержимое пункта. |
className | string | — | Класс отображаемого элемента. |
disabled | boolean | false | Отключает пункт и пропускает его при навигации с клавиатуры. |
onCheckedChange | (checked: boolean) => void | — | Вызывается с новым состоянием отметки при выборе пункта. |
textValue | string | — | Текст для поиска вводом символов, если содержимое пункта не является обычным текстом. |
ContextMenu.RadioItem
| Свойство | Тип | По умолчанию | Описание |
|---|---|---|---|
value* | string | — | Значение, выбираемое этим пунктом в меню. |
children | ReactNode | — | Содержимое пункта. |
className | string | — | Класс отображаемого элемента. |
disabled | boolean | false | Отключает пункт и пропускает его при навигации с клавиатуры. |
textValue | string | — | Текст для поиска вводом символов, если содержимое пункта не является обычным текстом. |
ContextMenu.Label
| Свойство | Тип | По умолчанию | Описание |
|---|---|---|---|
children | ReactNode | — | Текст заголовка группы. |
className | string | — | Класс отображаемого элемента. |
ContextMenu.Separator
| Свойство | Тип | По умолчанию | Описание |
|---|---|---|---|
className | string | — | Класс отображаемого элемента. |
ContextMenu.Sub
| Свойство | Тип | По умолчанию | Описание |
|---|---|---|---|
children | ReactNode | — | Триггер подменю и его содержимое. |
ContextMenu.Sub.Trigger
| Свойство | Тип | По умолчанию | Описание |
|---|---|---|---|
children | ReactNode | — | Подпись триггера подменю. |
className | string | — | Класс отображаемого элемента. |
disabled | boolean | false | Отключает триггер и пропускает его при навигации с клавиатуры. |
textValue | string | — | Текст для поиска вводом символов, если содержимое пункта не является обычным текстом. |
ContextMenu.Sub.Content
| Свойство | Тип | По умолчанию | Описание |
|---|---|---|---|
children | ReactNode | — | Пункты подменю. |
className | string | — | Класс отображаемого элемента. |
Клавиатура
| Клавиша | Действие |
|---|---|
| Shift+F10 / Menu key | Открыть у элемента в фокусе |
| ↑ / ↓ | Перемещаться между пунктами |
| Escape | Закрыть и вернуть фокус |
Доступность
Меню открывается в позиции указателя или в позиции, заданной вызовом с клавиатуры.
Привязка стилей
data-statedata-highlighted