@mezzanine-ui/core 1.0.0-beta.0 → 1.0.0-beta.1

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/_styles.scss CHANGED
@@ -80,6 +80,7 @@
80
80
  @include _load-styles($options, date-range-picker);
81
81
  @include _load-styles($options, date-time-picker);
82
82
  @include _load-styles($options, slider);
83
+ @include _load-styles($options, dropdown);
83
84
 
84
85
  // Data Entry Form
85
86
  @include _load-styles($options, form, form-field);
@@ -0,0 +1,355 @@
1
+ @use 'sass:map';
2
+ @use '~@mezzanine-ui/system/spacing' as spacing;
3
+ @use '~@mezzanine-ui/system/palette' as palette;
4
+ @use '~@mezzanine-ui/system/typography' as typography;
5
+ @use '~@mezzanine-ui/system/radius' as radius;
6
+ @use '~@mezzanine-ui/system/effect' as effect;
7
+ @use '~@mezzanine-ui/system/transition' as transition;
8
+ @use './dropdown' as *;
9
+
10
+ $card-state-configs: (
11
+ enable: (
12
+ background: palette.semantic-variable(background, base),
13
+ title-color: palette.semantic-variable(text, neutral-strong),
14
+ description-color: palette.semantic-variable(text, neutral),
15
+ focus: none,
16
+ ),
17
+ hover: (
18
+ background: palette.semantic-variable(background, neutral-faint),
19
+ ),
20
+ active: (
21
+ background: palette.semantic-variable(background, neutral-subtle),
22
+ ),
23
+ focus: (
24
+ background: palette.semantic-variable(background, base),
25
+ focus: effect.variable(focus, primary),
26
+ ),
27
+ disabled: (
28
+ background: palette.semantic-variable(background, base),
29
+ title-color: palette.semantic-variable(text, neutral-light),
30
+ description-color: palette.semantic-variable(text, neutral-light),
31
+ focus: none,
32
+ ),
33
+ );
34
+
35
+ $card-level-padding: (
36
+ 0: spacing.semantic-variable(padding, horizontal, base),
37
+ 1: spacing.semantic-variable(padding, horizontal, relaxed),
38
+ 2: spacing.semantic-variable(padding, horizontal, ultra),
39
+ );
40
+
41
+ $section-configs: (
42
+ list: (
43
+ radius: radius.variable(roomy),
44
+ background: palette.semantic-variable(background, base),
45
+ shadow: effect.variable(shadow, inner-top-and-bottom),
46
+ padding-inline: spacing.semantic-variable(padding, horizontal, tight),
47
+ padding-block: spacing.semantic-variable(padding, vertical, tight),
48
+ ),
49
+ list-header: (
50
+ background: palette.semantic-variable(background, base),
51
+ padding-block: spacing.semantic-variable(padding, vertical, tight),
52
+ padding-inline: spacing.semantic-variable(padding, horizontal, tight),
53
+ ),
54
+ action: (
55
+ background: palette.semantic-variable(background, base),
56
+ ),
57
+ action-top-bar: (
58
+ background: palette.semantic-variable(separator, neutral-faint),
59
+ height: 1px,
60
+ margin-block: spacing.semantic-variable(padding, vertical, tiny),
61
+ ),
62
+ status: (
63
+ background: palette.semantic-variable(background, base),
64
+ gap: spacing.semantic-variable(gap, tight-fixed),
65
+ padding-inline: spacing.semantic-variable(padding, horizontal, base),
66
+ padding-block: spacing.semantic-variable(padding, vertical, base),
67
+ ),
68
+ );
69
+
70
+ @function _card-state($state, $property) {
71
+ $state-map: map.get($card-state-configs, $state);
72
+
73
+ @if $state-map {
74
+ @return map.get($state-map, $property);
75
+ }
76
+
77
+ @return null;
78
+ }
79
+
80
+ @mixin _apply-card-state($state) {
81
+ $background: _card-state($state, background);
82
+ $title-color: _card-state($state, title-color);
83
+ $description-color: _card-state($state, description-color);
84
+ $focus: _card-state($state, focus);
85
+
86
+ @if $background {
87
+ background-color: $background;
88
+ }
89
+
90
+ @if $title-color {
91
+ --#{$prefix}-item-card-title-color: #{$title-color};
92
+ }
93
+
94
+ @if $description-color {
95
+ --#{$prefix}-item-card-description-color: #{$description-color};
96
+ }
97
+
98
+ @if $focus {
99
+ box-shadow: $focus;
100
+ }
101
+ }
102
+
103
+ @mixin _apply-card-states() {
104
+ @include _apply-card-state(enable);
105
+
106
+ &:hover:not(.#{$prefix}-item-card--disabled) {
107
+ @include _apply-card-state(hover);
108
+ }
109
+
110
+ &:active:not(.#{$prefix}-item-card--disabled) {
111
+ @include _apply-card-state(active);
112
+ }
113
+
114
+ &:focus,
115
+ &:focus-visible,
116
+ &:focus-within {
117
+ @include _apply-card-state(focus);
118
+ outline: none;
119
+ }
120
+
121
+ &.#{$prefix}-item-card--active:not(.#{$prefix}-item-card--disabled) {
122
+ @include _apply-card-state(active);
123
+ }
124
+
125
+ &.#{$prefix}-item-card--disabled {
126
+ @include _apply-card-state(disabled);
127
+ box-shadow: none;
128
+ }
129
+ }
130
+
131
+ @function _section($section, $property) {
132
+ $section-map: map.get($section-configs, $section);
133
+
134
+ @if $section-map {
135
+ @return map.get($section-map, $property);
136
+ }
137
+
138
+ @return null;
139
+ }
140
+
141
+ @mixin _apply-section($section) {
142
+ $background: _section($section, background);
143
+ $radius: _section($section, radius);
144
+ $shadow: _section($section, shadow);
145
+ $padding-inline: _section($section, padding-inline);
146
+ $padding-block: _section($section, padding-block);
147
+ $gap: _section($section, gap);
148
+ $border-color: _section($section, border-color);
149
+ $height: _section($section, height);
150
+ $margin-block: _section($section, margin-block);
151
+
152
+ @if $background {
153
+ background-color: $background;
154
+ }
155
+
156
+ @if $radius {
157
+ border-radius: $radius;
158
+ }
159
+
160
+ @if $shadow {
161
+ box-shadow: $shadow;
162
+ }
163
+
164
+ @if $padding-inline {
165
+ padding-inline: $padding-inline;
166
+ }
167
+
168
+ @if $padding-block {
169
+ padding-block: $padding-block;
170
+ }
171
+
172
+ @if $gap {
173
+ gap: $gap;
174
+ }
175
+
176
+ @if $border-color {
177
+ border-color: $border-color;
178
+ }
179
+
180
+ @if $height {
181
+ height: $height;
182
+ }
183
+
184
+ @if $margin-block {
185
+ margin-block: $margin-block;
186
+ }
187
+ }
188
+
189
+ .#{$prefix} {
190
+ position: relative;
191
+
192
+ // dropdown items
193
+ &-list {
194
+ @include _apply-section(list);
195
+ width: 100%;
196
+ min-width: max-content;
197
+ max-width: 100%;
198
+ margin: 0;
199
+ list-style: none;
200
+ overflow: hidden;
201
+ display: flex;
202
+ flex-direction: column;
203
+ box-sizing: border-box;
204
+ }
205
+
206
+ &-list-header {
207
+ @include _apply-section(list-header);
208
+ position: sticky;
209
+ inset-block-start: 0;
210
+ z-index: 1;
211
+ }
212
+
213
+ &-list-header-inner {
214
+ display: block;
215
+ width: 100%;
216
+ }
217
+
218
+ &-group-label {
219
+ @include typography.semantic-variable(body);
220
+ color: palette.semantic-variable(text, neutral-light);
221
+ font-feature-settings: 'liga' off, 'clig' off;
222
+ padding-block: spacing.semantic-variable(padding, vertical, tiny);
223
+ padding-inline: spacing.semantic-variable(padding, horizontal, tiny);
224
+ }
225
+
226
+ &-list-wrapper {
227
+ overflow-y: auto;
228
+ padding-inline: spacing.semantic-variable(padding, horizontal, micro);
229
+ }
230
+
231
+ &-item-card {
232
+ @include _apply-card-states();
233
+ border-radius: radius.variable(base);
234
+ padding-inline: spacing.semantic-variable(padding, horizontal, base);
235
+ padding-block: spacing.semantic-variable(padding, vertical, base);
236
+ box-sizing: border-box;
237
+ cursor: pointer;
238
+ margin-bottom: spacing.semantic-variable(gap, tiny);
239
+ position: relative;
240
+ list-style: none;
241
+ width: 100%;
242
+ transition:
243
+ transition.standard(background-color, fast),
244
+ transition.standard(color, fast),
245
+ transition.standard(border, fast),
246
+ transition.standard(box-shadow, fast);
247
+ --#{$prefix}-item-card-title-color: palette.semantic-variable(text, neutral-strong);
248
+ --#{$prefix}-item-card-description-color: palette.semantic-variable(text, neutral);
249
+
250
+ &--disabled {
251
+ cursor: not-allowed;
252
+ }
253
+ }
254
+
255
+ // dropdown item card
256
+ @each $level, $padding-inline-start in $card-level-padding {
257
+ &-item-card--level-#{$level} {
258
+ padding-inline-start: $padding-inline-start;
259
+ }
260
+ }
261
+
262
+ &-item-card-underline {
263
+ width: 100%;
264
+ height: 1px;
265
+ border-bottom: 1px solid palette.semantic-variable(separator, neutral-faint);
266
+ margin-block: spacing.semantic-variable(padding, vertical, tiny);
267
+ }
268
+
269
+ &-item-card-container {
270
+ display: flex;
271
+ gap: spacing.semantic-variable(gap, base);
272
+ align-items: center;
273
+ width: 100%;
274
+ }
275
+
276
+ &-item-card-title {
277
+ @include typography.semantic-variable(label-primary);
278
+ overflow: hidden;
279
+ font-feature-settings: 'liga' off, 'clig' off;
280
+ text-overflow: ellipsis;
281
+ transition: transition.standard(color, fast);
282
+ color: var(--#{$prefix}-item-card-title-color, currentColor);
283
+ }
284
+ &-item-card-description {
285
+ @include typography.semantic-variable(caption);
286
+ overflow: hidden;
287
+ font-feature-settings: 'liga' off, 'clig' off;
288
+ text-overflow: ellipsis;
289
+ transition: transition.standard(color, fast);
290
+ color: var(--#{$prefix}-item-card-description-color, currentColor);
291
+ }
292
+ &-item-card-prepend-content {
293
+ display: flex;
294
+ align-items: center;
295
+ justify-content: center;
296
+ gap: spacing.semantic-variable(gap, base);
297
+ }
298
+ &-item-card-highlighted-text {
299
+ color: palette.semantic-variable(text, brand);
300
+ transition: transition.standard(color, fast);
301
+ }
302
+ &-item-card-body {
303
+ display: flex;
304
+ flex-direction: column;
305
+ flex: 1 0 0;
306
+ gap: spacing.semantic-variable(gap, tight);
307
+ }
308
+ &-item-card-append-content {
309
+ display: flex;
310
+ align-items: center;
311
+ justify-content: center;
312
+ gap: spacing.semantic-variable(gap, base);
313
+ }
314
+
315
+ // dropdown action
316
+ &-action {
317
+ display: flex;
318
+ @include _apply-section(action);
319
+ position: sticky;
320
+ inset-block-end: 0;
321
+ flex-direction: column;
322
+ width: 100%;
323
+ z-index: 1;
324
+ }
325
+
326
+ &-action--top-bar {
327
+ @include _apply-section(action-top-bar);
328
+ display: block;
329
+ width: 100%;
330
+ inset-block-start: 0;
331
+ }
332
+
333
+ &-action-tools {
334
+ display: flex;
335
+ align-items: center;
336
+ justify-content: space-between;
337
+ width: 100%;
338
+ }
339
+
340
+ // dropdown status
341
+ &-status {
342
+ display: flex;
343
+ @include _apply-section(status);
344
+ position: relative;
345
+ align-items: center;
346
+ width: 100%;
347
+ }
348
+
349
+ &-status-text {
350
+ @include typography.semantic-variable(input);
351
+ color: palette.semantic-variable(text, neutral);
352
+ text-align: center;
353
+ font-feature-settings: 'liga' off, 'clig' off;
354
+ }
355
+ }
@@ -0,0 +1 @@
1
+ $prefix: mzn-dropdown;
@@ -0,0 +1,2 @@
1
+ @forward './dropdown';
2
+
@@ -0,0 +1,143 @@
1
+ import type { IconDefinition } from '@mezzanine-ui/icons';
2
+ export declare const dropdownPrefix = "mzn-dropdown";
3
+ export type dropdownPlacement = 'top' | 'bottom' | 'left' | 'right';
4
+ export type dropdownStatus = 'loading' | 'empty';
5
+ export type dropdownMode = 'single' | 'multiple';
6
+ export type dropdownType = 'default' | 'tree' | 'grouped';
7
+ export type dropdownItemLevel = 0 | 1 | 2;
8
+ export type dropdownItemValidate = 'default' | 'danger';
9
+ export type dropdownCheckPosition = 'prepend' | 'append' | 'none';
10
+ export type dropdownInputPosition = 'inside' | 'outside';
11
+ /**
12
+ * Base dropdown option interface
13
+ */
14
+ export interface DropdownOption {
15
+ /**
16
+ * The name of the dropdown option.
17
+ */
18
+ name: string;
19
+ /**
20
+ * The id of the dropdown option.
21
+ */
22
+ id: string;
23
+ /**
24
+ * Whether to show the checkbox.
25
+ * @default false
26
+ */
27
+ showCheckbox?: boolean;
28
+ /**
29
+ * Whether to show the underline.
30
+ * @default false
31
+ */
32
+ showUnderline?: boolean;
33
+ /**
34
+ * The icon of the dropdown option.
35
+ */
36
+ icon?: IconDefinition;
37
+ /**
38
+ * The validation type of the dropdown option.
39
+ */
40
+ validate?: dropdownItemValidate;
41
+ /**
42
+ * The position of the checkbox.
43
+ */
44
+ checkSite?: dropdownCheckPosition;
45
+ /**
46
+ * The children options for tree/grouped structure.
47
+ * If provided, this option will be rendered as a group with expand/collapse functionality.
48
+ * Maximum depth: 3 levels (enforced at runtime by truncateArrayDepth)
49
+ */
50
+ children?: DropdownOption[];
51
+ /**
52
+ * The shortcut keys of the dropdown option.
53
+ */
54
+ shortcutKeys?: Array<string | number>;
55
+ /**
56
+ * The shortcut text of the dropdown option.
57
+ */
58
+ shortcutText?: string;
59
+ }
60
+ /**
61
+ * Base option without children
62
+ */
63
+ type DropdownOptionBase = Omit<DropdownOption, 'children'>;
64
+ /**
65
+ * Flat dropdown option (no children) - for 'default' type
66
+ */
67
+ export type DropdownOptionFlat = DropdownOptionBase;
68
+ /**
69
+ * Grouped dropdown option (one level of children) - for 'grouped' type
70
+ * Children cannot have nested children.
71
+ */
72
+ export interface DropdownOptionGrouped extends DropdownOptionBase {
73
+ /**
74
+ * Children options for grouped structure.
75
+ * Children cannot have nested children.
76
+ */
77
+ children: DropdownOptionFlat[];
78
+ }
79
+ /**
80
+ * Recursive type helper to limit tree depth to exactly N levels
81
+ * Level 1: no children
82
+ * Level 2: children with no nested children
83
+ * Level 3: children with children that have no nested children
84
+ */
85
+ type DropdownOptionTreeLevel1 = DropdownOptionBase;
86
+ type DropdownOptionTreeLevel2 = DropdownOptionBase & {
87
+ children?: DropdownOptionTreeLevel1[];
88
+ };
89
+ type DropdownOptionTreeLevel3 = DropdownOptionBase & {
90
+ children?: DropdownOptionTreeLevel2[];
91
+ };
92
+ /**
93
+ * Tree dropdown option (nested children up to 3 levels) - for 'tree' type
94
+ * Maximum depth is enforced at compile time: 3 levels
95
+ * - Level 1: root options (no children)
96
+ * - Level 2: options with children (children have no nested children)
97
+ * - Level 3: options with children that have children (grandchildren have no nested children)
98
+ */
99
+ export type DropdownOptionTree = DropdownOptionTreeLevel3;
100
+ /**
101
+ * Type helper to get the appropriate options array type based on dropdown type.
102
+ * This enforces structure constraints at compile time:
103
+ * - 'default': flat array (no children allowed)
104
+ * - 'grouped': array with one level of children (children cannot have children)
105
+ * - 'tree': array with nested children up to 3 levels
106
+ */
107
+ export type DropdownOptionsByType<T extends dropdownType | undefined> = T extends 'default' ? DropdownOptionFlat[] : T extends 'grouped' ? DropdownOptionGrouped[] : T extends 'tree' ? DropdownOptionTree[] : DropdownOption[];
108
+ export interface DropdownItemSharedProps {
109
+ disabled?: boolean;
110
+ mode?: dropdownMode;
111
+ onSelect?: (option: DropdownOption) => void;
112
+ type?: dropdownType;
113
+ value?: string | string[];
114
+ }
115
+ export declare const dropdownClasses: {
116
+ root: string;
117
+ inputPosition: (inputPosition: dropdownInputPosition) => string;
118
+ list: string;
119
+ listWrapper: string;
120
+ listHeader: string;
121
+ listHeaderInner: string;
122
+ option: string;
123
+ optionActive: string;
124
+ groupLabel: string;
125
+ status: string;
126
+ statusText: string;
127
+ action: string;
128
+ actionTopBar: string;
129
+ actionTools: string;
130
+ card: string;
131
+ cardContainer: string;
132
+ cardActive: string;
133
+ cardDisabled: string;
134
+ cardUnderline: string;
135
+ cardLevel: (level: dropdownItemLevel) => string;
136
+ cardBody: string;
137
+ cardTitle: string;
138
+ cardDescription: string;
139
+ cardHighlightedText: string;
140
+ cardPrependContent: string;
141
+ cardAppendContent: string;
142
+ };
143
+ export {};
@@ -0,0 +1,35 @@
1
+ const dropdownPrefix = 'mzn-dropdown';
2
+ const dropdownClasses = {
3
+ root: `${dropdownPrefix}`,
4
+ inputPosition: (inputPosition) => `${dropdownPrefix}--${inputPosition}`,
5
+ // dropdown list
6
+ list: `${dropdownPrefix}-list`,
7
+ listWrapper: `${dropdownPrefix}-list-wrapper`,
8
+ listHeader: `${dropdownPrefix}-list-header`,
9
+ listHeaderInner: `${dropdownPrefix}-list-header-inner`,
10
+ option: `${dropdownPrefix}-option`,
11
+ optionActive: `${dropdownPrefix}-option--active`,
12
+ groupLabel: `${dropdownPrefix}-group-label`,
13
+ // dropdown status
14
+ status: `${dropdownPrefix}-status`,
15
+ statusText: `${dropdownPrefix}-status-text`,
16
+ // dropdown action
17
+ action: `${dropdownPrefix}-action`,
18
+ actionTopBar: `${dropdownPrefix}-action--top-bar`,
19
+ actionTools: `${dropdownPrefix}-action-tools`,
20
+ // dropdown item card
21
+ card: `${dropdownPrefix}-item-card`,
22
+ cardContainer: `${dropdownPrefix}-item-card-container`,
23
+ cardActive: `${dropdownPrefix}-item-card--active`,
24
+ cardDisabled: `${dropdownPrefix}-item-card--disabled`,
25
+ cardUnderline: `${dropdownPrefix}-item-card-underline`,
26
+ cardLevel: (level) => `${dropdownPrefix}-item-card--level-${level}`,
27
+ cardBody: `${dropdownPrefix}-item-card-body`,
28
+ cardTitle: `${dropdownPrefix}-item-card-title`,
29
+ cardDescription: `${dropdownPrefix}-item-card-description`,
30
+ cardHighlightedText: `${dropdownPrefix}-item-card-highlighted-text`,
31
+ cardPrependContent: `${dropdownPrefix}-item-card-prepend-content`,
32
+ cardAppendContent: `${dropdownPrefix}-item-card-append-content`,
33
+ };
34
+
35
+ export { dropdownClasses, dropdownPrefix };
@@ -0,0 +1 @@
1
+ export * from './dropdown';
@@ -0,0 +1 @@
1
+ export { dropdownClasses, dropdownPrefix } from './dropdown.js';
@@ -1,218 +1,264 @@
1
- @use '~@mezzanine-ui/system/spacing';
2
- @use '~@mezzanine-ui/system/palette';
1
+ @use '~@mezzanine-ui/system/effect' as effect;
2
+ @use '~@mezzanine-ui/system/palette' as palette;
3
+ @use '~@mezzanine-ui/system/radius' as radius;
4
+ @use '~@mezzanine-ui/system/spacing' as spacing;
5
+ @use '~@mezzanine-ui/system/transition' as transition;
3
6
  @use '~@mezzanine-ui/system/typography';
4
- @use './navigation' as *;
7
+ @use '../button/utils' as btn-utils;
5
8
  @use '../icon';
9
+ @use './navigation' as *;
6
10
  @use './utils';
7
11
 
8
- $horizontal-max-height: 64px !default;
9
- $horizontal-item-height: 64px !default;
10
- $horizontal-group-item-height: 40px !default;
11
- $horizontal-toggle-icon-gap: 4px !default;
12
- $horizontal-icon-gap: 4px !default;
13
- $horizontal-item-padding-x: 8px !default;
12
+ // spacing.semantic-variable(padding, vertical, tight) * 2 + 16px(icon size, text height)
13
+ $vertical-item-height: 28px !default;
14
14
 
15
- $vertical-max-width: 256px !default;
16
- $vertical-item-height: 32px !default;
17
- $vertical-toggle-icon-gap: 8px !default;
18
- $vertical-icon-gap: 8px !default;
19
- $vertical-group-indent: 8px !default;
20
- $vertical-group-icon-indent: 40px !default;
21
-
22
- $icon-size: 24px !default;
15
+ $background: background;
23
16
 
24
17
  .#{$prefix} {
25
- @include utils.reset();
26
18
  @include typography.variant(button2);
27
19
 
28
20
  overflow: hidden;
29
- background-color: palette.color(surface);
21
+ background-color: palette.semantic-variable($background, base);
30
22
  color: palette.color(action-inactive);
31
- display: grid;
32
-
33
- &--horizontal {
34
- max-height: $horizontal-max-height;
35
- grid-auto-flow: column;
36
- grid-auto-columns: max-content;
37
-
38
- &__toggle-icon {
39
- margin-left: $horizontal-toggle-icon-gap;
40
- }
41
-
42
- .#{$item-prefix} {
43
- padding: 0 spacing.level(4);
44
- height: $horizontal-item-height;
45
- grid-auto-flow: column;
46
- align-items: center;
47
- border-bottom: 2px solid transparent;
23
+ display: flex;
24
+ flex-direction: column;
25
+ box-sizing: border-box;
48
26
 
49
- &--active {
50
- color: palette.color(primary);
51
- border-bottom: 2px solid palette.color(primary);
52
- }
27
+ &__content {
28
+ padding: spacing.semantic-variable(padding, vertical, base)
29
+ spacing.semantic-variable(padding, horizontal, comfort-fixed);
30
+ display: flex;
31
+ flex-direction: column;
32
+ flex-grow: 1;
33
+ gap: spacing.semantic-variable(gap, tight-fixed);
53
34
 
54
- &__icon {
55
- margin-right: $horizontal-icon-gap;
56
- }
35
+ > ul {
36
+ @include utils.reset();
57
37
 
58
- &:hover {
59
- color: palette.color(primary);
60
- }
61
- }
62
-
63
- .#{$sub-menu-prefix} {
64
- border-bottom: 2px solid transparent;
65
- height: $horizontal-item-height;
66
-
67
- &__icon {
68
- margin-right: $horizontal-icon-gap;
69
- }
70
-
71
- &__group {
72
- overflow: hidden;
73
- background-color: palette.color(surface);
74
- border-color: palette.color(border);
75
- border-width: 0 1px 1px;
76
- border-style: solid;
77
- .#{$item-prefix} {
78
- @include typography.variant(input1);
79
-
80
- height: $horizontal-group-item-height;
81
- color: palette.color(text-primary);
82
- border-bottom: none;
83
-
84
- &--active,
85
- &:hover {
86
- background-color: palette.color(primary-hover-bg);
87
- }
88
- }
89
- }
90
-
91
- &--open,
92
- &--active {
93
- color: palette.color(primary);
94
- border-bottom: 2px solid palette.color(primary);
95
- }
38
+ display: grid;
39
+ gap: spacing.semantic-variable(gap, tight);
96
40
  }
97
41
  }
98
42
 
99
43
  &--vertical {
100
- width: $vertical-max-width;
101
- grid-auto-flow: row;
102
- grid-auto-rows: max-content;
103
- padding: spacing.level(5);
44
+ width: spacing.semantic-variable(size, container, slim);
104
45
  height: 100%;
105
- gap: spacing.level(2);
106
46
 
107
- .#{$item-prefix} {
47
+ .#{$option-prefix} {
48
+ display: grid;
49
+ box-sizing: border-box;
108
50
  align-items: center;
109
- height: $vertical-item-height;
110
- grid-auto-flow: column;
111
- padding: 0 $horizontal-item-padding-x;
112
- overflow: hidden;
113
- max-width: 100%;
51
+ gap: spacing.semantic-variable(gap, tight);
52
+ height: unset;
114
53
 
115
- &__icon {
116
- margin-right: $vertical-icon-gap;
117
- }
54
+ &__content {
55
+ align-items: center;
56
+ border-radius: radius.variable(base);
57
+ box-sizing: border-box;
58
+ cursor: pointer;
59
+ display: flex;
60
+ gap: spacing.semantic-variable(gap, tight);
61
+ padding: spacing.semantic-variable(padding, vertical, tight)
62
+ spacing.semantic-variable(padding, horizontal, tight-fixed);
63
+ transition: transition.standard(background-color, fast);
118
64
 
119
- &--active,
120
- &:hover {
121
- background-color: palette.color(primary-hover-bg);
122
- color: palette.color(primary);
123
- }
124
- }
65
+ &:hover {
66
+ .#{$option-prefix}__icon {
67
+ color: palette.semantic-variable(text, neutral-solid);
68
+ }
125
69
 
126
- .#{$sub-menu-prefix} {
127
- flex-direction: column;
128
- height: unset;
129
- padding: 0;
130
- min-height: $vertical-item-height;
70
+ background-color: palette.semantic-variable($background, neutral-faint);
71
+ }
72
+ }
131
73
 
132
74
  &__icon {
133
- margin-right: $vertical-icon-gap;
75
+ width: spacing.semantic-variable(size, element, base);
76
+ height: spacing.semantic-variable(size, element, base);
77
+ color: palette.semantic-variable(icon, neutral);
134
78
  }
135
79
 
136
80
  &__title {
137
- padding: 0 $horizontal-item-padding-x;
138
- width: 100%;
81
+ color: palette.semantic-variable(text, neutral-solid);
82
+ }
139
83
 
140
- &:hover {
141
- background-color: palette.color(primary-hover-bg);
142
- color: palette.color(primary);
84
+ &--active {
85
+ .#{$option-prefix}__content {
86
+ background-color: palette.semantic-variable($background, brand-ghost);
143
87
  }
144
88
  }
145
89
 
146
- &__group {
147
- display: grid;
148
- padding-left: $vertical-group-indent;
149
- gap: spacing.level(2);
150
- margin-top: spacing.level(2);
151
-
152
- .#{$item-prefix} {
153
- height: $vertical-item-height;
90
+ &--basic.#{$option-prefix}--active {
91
+ .#{$option-prefix}__title {
92
+ color: palette.semantic-variable(text, brand-solid);
93
+ }
154
94
 
155
- &--active,
156
- &:hover {
157
- background-color: palette.color(primary-hover-bg);
158
- color: palette.color(primary);
159
- }
95
+ .#{$option-prefix}__content {
96
+ background-color: palette.semantic-variable($background, brand-faint);
160
97
  }
161
98
  }
162
99
 
163
- &__toggle-icon {
164
- margin-left: auto;
100
+ &__group {
101
+ @include utils.reset();
102
+
103
+ display: grid;
165
104
  }
166
105
 
167
- &--indent {
168
- .#{$sub-menu-prefix}__group {
169
- padding-left: $vertical-group-icon-indent;
170
- }
106
+ &__toggle-icon {
107
+ margin-left: auto;
171
108
  }
172
109
 
173
- &--active {
174
- .#{$sub-menu-prefix}__title {
175
- background-color: palette.color(primary-hover-bg);
176
- color: palette.color(primary);
177
- }
110
+ &--level-1 {
111
+ margin-left: 0;
178
112
  }
179
113
 
180
- &--open {
181
- .#{$sub-menu-prefix}__title {
182
- color: palette.color(primary);
183
- }
114
+ &--level-2 {
115
+ margin-left: spacing.semantic-variable(padding, horizontal, relaxed);
184
116
  }
185
117
 
186
- &:hover {
187
- color: unset;
188
- background-color: unset;
118
+ &--level-3 {
119
+ margin-left: spacing.semantic-variable(padding, horizontal, breath);
189
120
  }
190
121
  }
191
122
  }
192
123
  }
193
124
 
194
- .#{$item-prefix} {
125
+ .#{$header-prefix} {
126
+ @include typography.semantic-variable(h3);
127
+
128
+ align-items: center;
129
+ border-bottom: 1px solid palette.semantic-variable(separator, neutral-faint);
195
130
  box-sizing: border-box;
196
131
  display: flex;
132
+ gap: spacing.semantic-variable(gap, comfort);
133
+ justify-content: space-between;
134
+ padding: spacing.semantic-variable(padding, horizontal, comfort)
135
+ spacing.semantic-variable(padding, horizontal, comfort-fixed)
136
+ spacing.semantic-variable(padding, vertical, base);
197
137
  width: 100%;
198
- cursor: pointer;
199
138
 
200
- .#{icon.$prefix} {
201
- width: $icon-size;
202
- height: $icon-size;
139
+ &__content {
140
+ align-items: center;
141
+ color: palette.semantic-variable(text, neutral-solid);
142
+ display: flex;
143
+ flex-grow: 1;
144
+ gap: spacing.semantic-variable(gap, base);
145
+ height: 100%;
146
+ }
147
+ }
148
+
149
+ .#{$footer-prefix} {
150
+ box-sizing: border-box;
151
+ width: 100%;
152
+ border-top: 1px solid palette.color(divider);
153
+ display: flex;
154
+ align-items: center;
155
+ justify-content: space-between;
156
+ padding: spacing.semantic-variable(padding, vertical, base)
157
+ spacing.semantic-variable(padding, horizontal, comfort-fixed)
158
+ spacing.semantic-variable(padding, vertical, comfort);
159
+ gap: spacing.semantic-variable(gap, tight-fixed);
160
+
161
+ &__icons {
162
+ display: flex;
163
+ align-items: center;
164
+ gap: spacing.semantic-variable(gap, tiny);
203
165
  }
204
166
  }
205
167
 
206
- .#{$sub-menu-prefix} {
168
+ .#{$icon-button-prefix} {
169
+ @include btn-utils.reset();
170
+
171
+ align-items: center;
172
+ justify-content: center;
173
+ border-radius: radius.variable(base);
207
174
  box-sizing: border-box;
175
+ color: palette.semantic-variable(icon, neutral);
176
+ display: flex;
177
+ padding: spacing.semantic-variable(padding, vertical, tight-fixed)
178
+ spacing.semantic-variable(padding, horizontal, tight-fixed);
179
+ transition: transition.standard(background-color, fast);
180
+ width: spacing.semantic-variable(size, element, airy);
181
+ height: spacing.semantic-variable(size, element, airy);
182
+
183
+ &:hover {
184
+ background-color: palette.semantic-variable($background, neutral-faint);
185
+ }
208
186
 
209
- &__title {
187
+ &:focus-visible {
188
+ box-shadow: effect.variable(focus, primary);
189
+ }
190
+ }
191
+
192
+ .#{$user-menu-prefix} {
193
+ @include btn-utils.reset();
194
+
195
+ box-sizing: border-box;
196
+ display: flex;
197
+ align-items: center;
198
+ gap: spacing.semantic-variable(gap, tight-fixed);
199
+ width: fit-content;
200
+ border-radius: radius.variable(base);
201
+ padding: spacing.semantic-variable(padding, vertical, micro)
202
+ spacing.semantic-variable(padding, horizontal, tiny);
203
+
204
+ &__avatar {
210
205
  box-sizing: border-box;
206
+ width: spacing.semantic-variable(size, element, airy);
207
+ height: spacing.semantic-variable(size, element, airy);
208
+ border-radius: radius.variable(full);
209
+ background-color: palette.semantic-variable($background, neutral);
210
+ color: palette.semantic-variable(icon, fixed-light);
211
+ border: 1px solid palette.semantic-variable($background, neutral-subtle);
211
212
  display: flex;
212
213
  align-items: center;
214
+ justify-content: center;
213
215
  }
214
216
 
215
- &__group {
217
+ &__user-name {
218
+ @include typography.variant(caption);
219
+
220
+ color: palette.semantic-variable(text, neutral-solid);
221
+ }
222
+
223
+ &__icon {
224
+ color: palette.semantic-variable(icon, neutral-bold);
225
+ transition: transition.standard(transform, fast);
226
+ }
227
+
228
+ &--open {
229
+ background-color: palette.semantic-variable($background, neutral-subtle);
230
+
231
+ .#{$user-menu-prefix}__icon {
232
+ transform: rotate(180deg);
233
+ }
234
+ }
235
+
236
+ &:hover,
237
+ &:active {
238
+ background-color: palette.semantic-variable($background, neutral-subtle);
239
+ }
240
+
241
+ &:focus-visible {
242
+ box-shadow: effect.variable(focus, primary);
243
+ }
244
+ }
245
+
246
+ .#{$option-category-prefix} {
247
+ box-sizing: border-box;
248
+ width: 100%;
249
+
250
+ &__title {
251
+ @include typography.variant(annotation);
252
+
253
+ color: palette.semantic-variable(text, neutral-light);
254
+ padding: spacing.semantic-variable(padding, vertical, micro)
255
+ spacing.semantic-variable(padding, horizontal, tight-fixed);
256
+ }
257
+
258
+ > ul {
216
259
  @include utils.reset();
260
+
261
+ display: grid;
262
+ gap: spacing.semantic-variable(gap, tight);
217
263
  }
218
264
  }
@@ -1,4 +1,8 @@
1
1
  $prefix: mzn-navigation;
2
2
 
3
- $item-prefix: #{$prefix}-item;
4
- $sub-menu-prefix: #{$prefix}-sub-menu;
3
+ $option-prefix: #{$prefix}-option;
4
+ $header-prefix: #{$prefix}-header;
5
+ $footer-prefix: #{$prefix}-footer;
6
+ $icon-button-prefix: #{$prefix}-icon-button;
7
+ $user-menu-prefix: #{$prefix}-user-menu;
8
+ $option-category-prefix: #{$prefix}-option-category;
@@ -1,3 +1,7 @@
1
1
  export * from './navigation';
2
- export * from './navigationItem';
3
- export * from './navigationSubMenu';
2
+ export * from './navigationFooter';
3
+ export * from './navigationHeader';
4
+ export * from './navigationIconButton';
5
+ export * from './navigationOption';
6
+ export * from './navigationUserMenu';
7
+ export * from './navigationOptionCategory';
@@ -1,3 +1,7 @@
1
1
  export { navigationClasses, navigationPrefix } from './navigation.js';
2
- export { navigationItemClasses, navigationItemPrefix } from './navigationItem.js';
3
- export { navigationSubMenuClasses, navigationSubMenuPrefix } from './navigationSubMenu.js';
2
+ export { navigationFooterClasses, navigationFooterPrefix } from './navigationFooter.js';
3
+ export { navigationHeaderClasses, navigationHeaderPrefix } from './navigationHeader.js';
4
+ export { navigationIconButtonClasses, navigationIconButtonPrefix } from './navigationIconButton.js';
5
+ export { navigationOptionClasses, navigationOptionPrefix } from './navigationOption.js';
6
+ export { navigationUserMenuClasses, navigationUserMenuPrefix } from './navigationUserMenu.js';
7
+ export { navigationOptionCategoryClasses, navigationOptionCategoryPrefix } from './navigationOptionCategory.js';
@@ -3,6 +3,6 @@ export declare const navigationPrefix = "mzn-navigation";
3
3
  export type NavigationOrientation = Orientation;
4
4
  export declare const navigationClasses: {
5
5
  readonly host: "mzn-navigation";
6
- readonly horizontal: "mzn-navigation--horizontal";
7
6
  readonly vertical: "mzn-navigation--vertical";
7
+ readonly content: "mzn-navigation__content";
8
8
  };
@@ -1,8 +1,8 @@
1
1
  const navigationPrefix = 'mzn-navigation';
2
2
  const navigationClasses = {
3
3
  host: navigationPrefix,
4
- horizontal: `${navigationPrefix}--horizontal`,
5
4
  vertical: `${navigationPrefix}--vertical`,
5
+ content: `${navigationPrefix}__content`,
6
6
  };
7
7
 
8
8
  export { navigationClasses, navigationPrefix };
@@ -0,0 +1,5 @@
1
+ export declare const navigationFooterPrefix: "mzn-navigation-footer";
2
+ export declare const navigationFooterClasses: {
3
+ readonly host: "mzn-navigation-footer";
4
+ readonly icons: "mzn-navigation-footer__icons";
5
+ };
@@ -0,0 +1,9 @@
1
+ import { navigationPrefix } from './navigation.js';
2
+
3
+ const navigationFooterPrefix = `${navigationPrefix}-footer`;
4
+ const navigationFooterClasses = {
5
+ host: navigationFooterPrefix,
6
+ icons: `${navigationFooterPrefix}__icons`,
7
+ };
8
+
9
+ export { navigationFooterClasses, navigationFooterPrefix };
@@ -0,0 +1,5 @@
1
+ export declare const navigationHeaderPrefix: "mzn-navigation-header";
2
+ export declare const navigationHeaderClasses: {
3
+ readonly host: "mzn-navigation-header";
4
+ readonly content: "mzn-navigation-header__content";
5
+ };
@@ -0,0 +1,9 @@
1
+ import { navigationPrefix } from './navigation.js';
2
+
3
+ const navigationHeaderPrefix = `${navigationPrefix}-header`;
4
+ const navigationHeaderClasses = {
5
+ host: navigationHeaderPrefix,
6
+ content: `${navigationHeaderPrefix}__content`,
7
+ };
8
+
9
+ export { navigationHeaderClasses, navigationHeaderPrefix };
@@ -0,0 +1,4 @@
1
+ export declare const navigationIconButtonPrefix: "mzn-navigation-icon-button";
2
+ export declare const navigationIconButtonClasses: {
3
+ readonly host: "mzn-navigation-icon-button";
4
+ };
@@ -0,0 +1,8 @@
1
+ import { navigationPrefix } from './navigation.js';
2
+
3
+ const navigationIconButtonPrefix = `${navigationPrefix}-icon-button`;
4
+ const navigationIconButtonClasses = {
5
+ host: navigationIconButtonPrefix,
6
+ };
7
+
8
+ export { navigationIconButtonClasses, navigationIconButtonPrefix };
@@ -0,0 +1,13 @@
1
+ export declare const navigationOptionPrefix: "mzn-navigation-option";
2
+ export declare const navigationOptionClasses: {
3
+ readonly host: "mzn-navigation-option";
4
+ readonly group: "mzn-navigation-option__group";
5
+ readonly basic: "mzn-navigation-option--basic";
6
+ readonly level: (level: number) => `mzn-navigation-option--level-${number}`;
7
+ readonly content: "mzn-navigation-option__content";
8
+ readonly title: "mzn-navigation-option__title";
9
+ readonly toggleIcon: "mzn-navigation-option__toggle-icon";
10
+ readonly icon: "mzn-navigation-option__icon";
11
+ readonly active: "mzn-navigation-option--active";
12
+ readonly open: "mzn-navigation-option--open";
13
+ };
@@ -0,0 +1,17 @@
1
+ import { navigationPrefix } from './navigation.js';
2
+
3
+ const navigationOptionPrefix = `${navigationPrefix}-option`;
4
+ const navigationOptionClasses = {
5
+ host: navigationOptionPrefix,
6
+ group: `${navigationOptionPrefix}__group`,
7
+ basic: `${navigationOptionPrefix}--basic`,
8
+ level: (level) => `${navigationOptionPrefix}--level-${level}`,
9
+ content: `${navigationOptionPrefix}__content`,
10
+ title: `${navigationOptionPrefix}__title`,
11
+ toggleIcon: `${navigationOptionPrefix}__toggle-icon`,
12
+ icon: `${navigationOptionPrefix}__icon`,
13
+ active: `${navigationOptionPrefix}--active`,
14
+ open: `${navigationOptionPrefix}--open`,
15
+ };
16
+
17
+ export { navigationOptionClasses, navigationOptionPrefix };
@@ -0,0 +1,5 @@
1
+ export declare const navigationOptionCategoryPrefix: "mzn-navigation-option-category";
2
+ export declare const navigationOptionCategoryClasses: {
3
+ readonly host: "mzn-navigation-option-category";
4
+ readonly title: "mzn-navigation-option-category__title";
5
+ };
@@ -0,0 +1,9 @@
1
+ import { navigationPrefix } from './navigation.js';
2
+
3
+ const navigationOptionCategoryPrefix = `${navigationPrefix}-option-category`;
4
+ const navigationOptionCategoryClasses = {
5
+ host: navigationOptionCategoryPrefix,
6
+ title: `${navigationOptionCategoryPrefix}__title`,
7
+ };
8
+
9
+ export { navigationOptionCategoryClasses, navigationOptionCategoryPrefix };
@@ -0,0 +1,8 @@
1
+ export declare const navigationUserMenuPrefix: "mzn-navigation-user-menu";
2
+ export declare const navigationUserMenuClasses: {
3
+ readonly host: "mzn-navigation-user-menu";
4
+ readonly open: "mzn-navigation-user-menu--open";
5
+ readonly avatar: "mzn-navigation-user-menu__avatar";
6
+ readonly userName: "mzn-navigation-user-menu__user-name";
7
+ readonly icon: "mzn-navigation-user-menu__icon";
8
+ };
@@ -0,0 +1,12 @@
1
+ import { navigationPrefix } from './navigation.js';
2
+
3
+ const navigationUserMenuPrefix = `${navigationPrefix}-user-menu`;
4
+ const navigationUserMenuClasses = {
5
+ host: navigationUserMenuPrefix,
6
+ open: `${navigationUserMenuPrefix}--open`,
7
+ avatar: `${navigationUserMenuPrefix}__avatar`,
8
+ userName: `${navigationUserMenuPrefix}__user-name`,
9
+ icon: `${navigationUserMenuPrefix}__icon`,
10
+ };
11
+
12
+ export { navigationUserMenuClasses, navigationUserMenuPrefix };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mezzanine-ui/core",
3
- "version": "1.0.0-beta.0",
3
+ "version": "1.0.0-beta.1",
4
4
  "description": "Core for mezzanine-ui",
5
5
  "author": "Mezzanine",
6
6
  "repository": {
@@ -40,8 +40,8 @@
40
40
  }
41
41
  },
42
42
  "dependencies": {
43
- "@mezzanine-ui/icons": "^1.0.0-beta.0",
44
- "@mezzanine-ui/system": "^1.0.0-beta.0",
43
+ "@mezzanine-ui/icons": "^1.0.0-beta.1",
44
+ "@mezzanine-ui/system": "^1.0.0-beta.1",
45
45
  "lodash": "^4.17.21",
46
46
  "tslib": "^2.8.1"
47
47
  },
@@ -1,6 +0,0 @@
1
- export declare const navigationItemPrefix: "mzn-navigation-item";
2
- export declare const navigationItemClasses: {
3
- readonly host: "mzn-navigation-item";
4
- readonly icon: "mzn-navigation-item__icon";
5
- readonly active: "mzn-navigation-item--active";
6
- };
@@ -1,10 +0,0 @@
1
- import { navigationPrefix } from './navigation.js';
2
-
3
- const navigationItemPrefix = `${navigationPrefix}-item`;
4
- const navigationItemClasses = {
5
- host: navigationItemPrefix,
6
- icon: `${navigationItemPrefix}__icon`,
7
- active: `${navigationItemPrefix}--active`,
8
- };
9
-
10
- export { navigationItemClasses, navigationItemPrefix };
@@ -1,11 +0,0 @@
1
- export declare const navigationSubMenuPrefix: "mzn-navigation-sub-menu";
2
- export declare const navigationSubMenuClasses: {
3
- readonly host: "mzn-navigation-sub-menu";
4
- readonly group: "mzn-navigation-sub-menu__group";
5
- readonly indent: "mzn-navigation-sub-menu--indent";
6
- readonly title: "mzn-navigation-sub-menu__title";
7
- readonly toggleIcon: "mzn-navigation-sub-menu__toggle-icon";
8
- readonly icon: "mzn-navigation-sub-menu__icon";
9
- readonly active: "mzn-navigation-sub-menu--active";
10
- readonly open: "mzn-navigation-sub-menu--open";
11
- };
@@ -1,15 +0,0 @@
1
- import { navigationPrefix } from './navigation.js';
2
-
3
- const navigationSubMenuPrefix = `${navigationPrefix}-sub-menu`;
4
- const navigationSubMenuClasses = {
5
- host: navigationSubMenuPrefix,
6
- group: `${navigationSubMenuPrefix}__group`,
7
- indent: `${navigationSubMenuPrefix}--indent`,
8
- title: `${navigationSubMenuPrefix}__title`,
9
- toggleIcon: `${navigationSubMenuPrefix}__toggle-icon`,
10
- icon: `${navigationSubMenuPrefix}__icon`,
11
- active: `${navigationSubMenuPrefix}--active`,
12
- open: `${navigationSubMenuPrefix}--open`,
13
- };
14
-
15
- export { navigationSubMenuClasses, navigationSubMenuPrefix };