@allxsmith/bestax-bulma 5.60.0 → 5.62.0
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/dist/bestax.css +1 -1
- package/dist/bestax.css.map +1 -1
- package/dist/esm/components/Carousel.js +3 -43
- package/dist/esm/components/Carousel.js.map +1 -1
- package/dist/esm/components/Command.js +3 -3
- package/dist/esm/components/Navbar.js +3 -1
- package/dist/esm/components/Navbar.js.map +1 -1
- package/dist/esm/components/Popover.js +7 -27
- package/dist/esm/components/Popover.js.map +1 -1
- package/dist/esm/components/Sidebar.js +17 -58
- package/dist/esm/components/Sidebar.js.map +1 -1
- package/dist/esm/components/TreeView.js +14 -10
- package/dist/esm/components/TreeView.js.map +1 -1
- package/dist/esm/form/ColorPicker.js +4 -4
- package/dist/esm/form/ColorPicker.js.map +1 -1
- package/dist/esm/form/Combobox.js +11 -16
- package/dist/esm/form/Combobox.js.map +1 -1
- package/dist/esm/form/Field.js.map +1 -1
- package/dist/esm/form/TreeSelect.js +395 -0
- package/dist/esm/form/TreeSelect.js.map +1 -0
- package/dist/esm/form/_pickerInternals/PickerPopover.js +5 -1
- package/dist/esm/form/_pickerInternals/PickerPopover.js.map +1 -1
- package/dist/esm/form/_selectInternals/DialogSelect.js +208 -0
- package/dist/esm/form/_selectInternals/DialogSelect.js.map +1 -0
- package/dist/esm/form/_selectInternals/ValueTags.js +28 -0
- package/dist/esm/form/_selectInternals/ValueTags.js.map +1 -0
- package/dist/esm/helpers/overlayStack.js +33 -1
- package/dist/esm/helpers/overlayStack.js.map +1 -1
- package/dist/esm/helpers/treeData.js +97 -0
- package/dist/esm/helpers/treeData.js.map +1 -0
- package/dist/esm/helpers/useBulmaViewport.js +82 -0
- package/dist/esm/helpers/useBulmaViewport.js.map +1 -0
- package/dist/esm/helpers/useComboboxEngine.js +2 -2
- package/dist/esm/helpers/useComboboxEngine.js.map +1 -1
- package/dist/esm/helpers/useControlled.js +30 -0
- package/dist/esm/helpers/useControlled.js.map +1 -0
- package/dist/esm/helpers/useInertSiblings.js +7 -3
- package/dist/esm/helpers/useInertSiblings.js.map +1 -1
- package/dist/esm/helpers/useOutsidePress.js +53 -0
- package/dist/esm/helpers/useOutsidePress.js.map +1 -0
- package/dist/esm/helpers/useOverlayFocus.js +74 -0
- package/dist/esm/helpers/useOverlayFocus.js.map +1 -0
- package/dist/esm/helpers/useTreeView.js +15 -13
- package/dist/esm/helpers/useTreeView.js.map +1 -1
- package/dist/esm/layout/AppFrame.js +438 -0
- package/dist/esm/layout/AppFrame.js.map +1 -0
- package/dist/extras.css +1 -1
- package/dist/extras.css.map +1 -1
- package/dist/index.cjs +1767 -518
- package/dist/index.cjs.map +1 -1
- package/dist/index.esm.js +2 -0
- package/dist/index.esm.js.map +1 -1
- package/dist/types/components/Navbar.d.ts +4 -3
- package/dist/types/form/Field.d.ts +1 -1
- package/dist/types/form/TreeSelect.d.ts +308 -0
- package/dist/types/form/_pickerInternals/PickerPopover.d.ts +8 -0
- package/dist/types/form/_selectInternals/DialogSelect.d.ts +86 -0
- package/dist/types/form/_selectInternals/ValueTags.d.ts +40 -0
- package/dist/types/helpers/overlayStack.d.ts +17 -0
- package/dist/types/helpers/treeData.d.ts +48 -0
- package/dist/types/helpers/useBulmaViewport.d.ts +34 -0
- package/dist/types/helpers/useControlled.d.ts +14 -0
- package/dist/types/helpers/useInertSiblings.d.ts +4 -1
- package/dist/types/helpers/useOutsidePress.d.ts +24 -0
- package/dist/types/helpers/useOverlayFocus.d.ts +44 -0
- package/dist/types/helpers/useTreeView.d.ts +30 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/layout/AppFrame.d.ts +306 -0
- package/dist/types-cjs/components/Navbar.d.ts +4 -3
- package/dist/types-cjs/form/Field.d.ts +1 -1
- package/dist/types-cjs/form/TreeSelect.d.ts +308 -0
- package/dist/types-cjs/form/_pickerInternals/PickerPopover.d.ts +8 -0
- package/dist/types-cjs/form/_selectInternals/DialogSelect.d.ts +86 -0
- package/dist/types-cjs/form/_selectInternals/ValueTags.d.ts +40 -0
- package/dist/types-cjs/helpers/overlayStack.d.ts +17 -0
- package/dist/types-cjs/helpers/treeData.d.ts +48 -0
- package/dist/types-cjs/helpers/useBulmaViewport.d.ts +34 -0
- package/dist/types-cjs/helpers/useControlled.d.ts +14 -0
- package/dist/types-cjs/helpers/useInertSiblings.d.ts +4 -1
- package/dist/types-cjs/helpers/useOutsidePress.d.ts +24 -0
- package/dist/types-cjs/helpers/useOverlayFocus.d.ts +44 -0
- package/dist/types-cjs/helpers/useTreeView.d.ts +30 -0
- package/dist/types-cjs/index.d.ts +2 -0
- package/dist/types-cjs/layout/AppFrame.d.ts +306 -0
- package/dist/versions/bestax-no-dark-mode.css +1 -1
- package/dist/versions/bestax-no-dark-mode.css.map +1 -1
- package/dist/versions/bestax-no-helpers-prefixed.css +1 -1
- package/dist/versions/bestax-no-helpers-prefixed.css.map +1 -1
- package/dist/versions/bestax-no-helpers.css +1 -1
- package/dist/versions/bestax-no-helpers.css.map +1 -1
- package/dist/versions/bestax-prefixed.css +1 -1
- package/dist/versions/bestax-prefixed.css.map +1 -1
- package/package.json +1 -1
- package/src/scss/form/_index.scss +1 -0
- package/src/scss/form/_picker-popover.scss +6 -0
- package/src/scss/form/_treeselect.scss +146 -0
- package/src/scss/layout/_appframe.scss +306 -0
- package/src/scss/layout/_index.scss +1 -0
|
@@ -62,6 +62,12 @@ $picker-trigger-hover-color: cv.getVar('text-strong') !default;
|
|
|
62
62
|
right: 0;
|
|
63
63
|
margin-bottom: cv.getVar('picker-popover-offset');
|
|
64
64
|
}
|
|
65
|
+
// At least as wide as the anchor it's placed against, as a list under a
|
|
66
|
+
// field is. Portaled, the anchor's width comes inline instead, since 100%
|
|
67
|
+
// there would be the viewport's.
|
|
68
|
+
&.#{iv.$class-prefix}has-anchor-width:not(.#{iv.$class-prefix}is-portal) {
|
|
69
|
+
min-width: 100%;
|
|
70
|
+
}
|
|
65
71
|
// Portaled: fixed to the viewport at the top and left the positioning hook
|
|
66
72
|
// sets inline, so the corner's own right and bottom must not apply. Left
|
|
67
73
|
// in, `right: 0` stretches the panel to the viewport's right edge and the
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// Bestax Extras - TreeSelect Styles
|
|
2
|
+
// A form field whose options are a tree. The field is Bulma's input, the
|
|
3
|
+
// panel the pickers' popover (`--bulma-picker-popover-*`) and the tree
|
|
4
|
+
// TreeView's (`--bulma-tree-view-*`), so this draws what sits between them:
|
|
5
|
+
// the chevron and the clear button on the field, the panel's height, the
|
|
6
|
+
// search box over the tree and the message when a search finds nothing. The
|
|
7
|
+
// panel is at least as wide as the field through the picker popover's own
|
|
8
|
+
// `has-anchor-width` rule.
|
|
9
|
+
|
|
10
|
+
@use 'bulma/sass/utilities/initial-variables' as iv;
|
|
11
|
+
@use 'bulma/sass/utilities/css-variables' as cv;
|
|
12
|
+
|
|
13
|
+
// The tree scrolls past this, as Combobox's list does.
|
|
14
|
+
$tree-select-panel-max-height: 15rem !default;
|
|
15
|
+
$tree-select-search-gap: 0.5rem !default;
|
|
16
|
+
// The chevron's box at the field's inline end, drawn as a Control's icon is.
|
|
17
|
+
// Bulma registers its input variables on the field and its Control, which the
|
|
18
|
+
// root is outside, so these start from the tokens those start from.
|
|
19
|
+
$tree-select-chevron-width: cv.getVar('control-height') !default;
|
|
20
|
+
$tree-select-chevron-color: cv.getVar('text-light') !default;
|
|
21
|
+
$tree-select-chevron-hover-color: cv.getVar('text-weak') !default;
|
|
22
|
+
$tree-select-chevron-focus-color: cv.getVar('link') !default;
|
|
23
|
+
// Over the field, as Bulma stacks a Control's icon, and the clear button
|
|
24
|
+
// over the chevron.
|
|
25
|
+
$tree-select-chevron-z-index: 4 !default;
|
|
26
|
+
$tree-select-clear-z-index: 5 !default;
|
|
27
|
+
$tree-select-empty-color: cv.getVar('text-weak') !default;
|
|
28
|
+
$tree-select-empty-padding: 0.5em 0.75em !default;
|
|
29
|
+
// Room around the tree for the focus ring of a row at its edge, which the
|
|
30
|
+
// scrolling would cut off: the ring's width and its offset.
|
|
31
|
+
$tree-select-tree-inset: 4px !default;
|
|
32
|
+
|
|
33
|
+
// Registered on the root, which a panel in place sits inside and inherits
|
|
34
|
+
// from, so a value set on the root or through `className` reaches it, and on
|
|
35
|
+
// a portaled panel, which a portal puts outside the root, so it carries its
|
|
36
|
+
// own copy, as Combobox's menu does.
|
|
37
|
+
.#{iv.$class-prefix}tree-select,
|
|
38
|
+
.#{iv.$class-prefix}tree-select-panel.#{iv.$class-prefix}is-portal {
|
|
39
|
+
@include cv.register-vars(
|
|
40
|
+
(
|
|
41
|
+
'tree-select-panel-max-height': #{$tree-select-panel-max-height},
|
|
42
|
+
'tree-select-search-gap': #{$tree-select-search-gap},
|
|
43
|
+
'tree-select-chevron-width': #{$tree-select-chevron-width},
|
|
44
|
+
'tree-select-chevron-color': #{$tree-select-chevron-color},
|
|
45
|
+
'tree-select-chevron-hover-color': #{$tree-select-chevron-hover-color},
|
|
46
|
+
'tree-select-chevron-focus-color': #{$tree-select-chevron-focus-color},
|
|
47
|
+
'tree-select-chevron-z-index': #{$tree-select-chevron-z-index},
|
|
48
|
+
'tree-select-clear-z-index': #{$tree-select-clear-z-index},
|
|
49
|
+
'tree-select-empty-color': #{$tree-select-empty-color},
|
|
50
|
+
'tree-select-empty-padding': #{$tree-select-empty-padding},
|
|
51
|
+
'tree-select-tree-inset': #{$tree-select-tree-inset},
|
|
52
|
+
)
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// What the panel in place, the chevron and the clear button are placed
|
|
57
|
+
// against, when a Control around it holds no other field.
|
|
58
|
+
.#{iv.$class-prefix}tree-select {
|
|
59
|
+
position: relative;
|
|
60
|
+
|
|
61
|
+
.#{iv.$class-prefix}input {
|
|
62
|
+
cursor: pointer;
|
|
63
|
+
padding-inline-end: cv.getVar('tree-select-chevron-width');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
&.#{iv.$class-prefix}has-clear .#{iv.$class-prefix}input {
|
|
67
|
+
padding-inline-end: calc(2 * #{cv.getVar('tree-select-chevron-width')});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
.#{iv.$class-prefix}input[disabled] {
|
|
71
|
+
cursor: not-allowed;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Bulma's Control icon, at the inline end, where a press goes to the field.
|
|
76
|
+
.#{iv.$class-prefix}tree-select-chevron {
|
|
77
|
+
align-items: center;
|
|
78
|
+
color: cv.getVar('tree-select-chevron-color');
|
|
79
|
+
display: flex;
|
|
80
|
+
height: 100%;
|
|
81
|
+
inset-block-start: 0;
|
|
82
|
+
inset-inline-end: 0;
|
|
83
|
+
justify-content: center;
|
|
84
|
+
pointer-events: none;
|
|
85
|
+
position: absolute;
|
|
86
|
+
width: cv.getVar('tree-select-chevron-width');
|
|
87
|
+
z-index: cv.getVar('tree-select-chevron-z-index');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
.#{iv.$class-prefix}tree-select .#{iv.$class-prefix}input {
|
|
91
|
+
&:hover ~ .#{iv.$class-prefix}tree-select-chevron {
|
|
92
|
+
color: cv.getVar('tree-select-chevron-hover-color');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
&:focus ~ .#{iv.$class-prefix}tree-select-chevron,
|
|
96
|
+
&.#{iv.$class-prefix}is-focused ~ .#{iv.$class-prefix}tree-select-chevron,
|
|
97
|
+
&[aria-expanded='true'] ~ .#{iv.$class-prefix}tree-select-chevron {
|
|
98
|
+
color: cv.getVar('tree-select-chevron-focus-color');
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
&[disabled] ~ .#{iv.$class-prefix}tree-select-chevron {
|
|
102
|
+
color: cv.getVar('input-disabled-color');
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// The chevron's box is in em, so it follows the field's size.
|
|
106
|
+
&.#{iv.$class-prefix}is-small ~ * {
|
|
107
|
+
font-size: cv.getVar('size-small');
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
&.#{iv.$class-prefix}is-medium ~ * {
|
|
111
|
+
font-size: cv.getVar('size-medium');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
&.#{iv.$class-prefix}is-large ~ * {
|
|
115
|
+
font-size: cv.getVar('size-large');
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Beside the chevron, centred on the field's height.
|
|
120
|
+
.#{iv.$class-prefix}tree-select-clear {
|
|
121
|
+
inset-block-start: 50%;
|
|
122
|
+
inset-inline-end: cv.getVar('tree-select-chevron-width');
|
|
123
|
+
position: absolute;
|
|
124
|
+
transform: translateY(-50%);
|
|
125
|
+
z-index: cv.getVar('tree-select-clear-z-index');
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.#{iv.$class-prefix}tree-select-panel {
|
|
129
|
+
display: flex;
|
|
130
|
+
flex-direction: column;
|
|
131
|
+
gap: cv.getVar('tree-select-search-gap');
|
|
132
|
+
|
|
133
|
+
// The tree scrolls, with room for the focus ring of the row at its edge,
|
|
134
|
+
// and still lines up with the search box over it.
|
|
135
|
+
> .#{iv.$class-prefix}tree-view {
|
|
136
|
+
margin-inline: calc(-1 * #{cv.getVar('tree-select-tree-inset')});
|
|
137
|
+
max-height: cv.getVar('tree-select-panel-max-height');
|
|
138
|
+
overflow-y: auto;
|
|
139
|
+
padding: cv.getVar('tree-select-tree-inset');
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
.#{iv.$class-prefix}tree-select-empty {
|
|
144
|
+
color: cv.getVar('tree-select-empty-color');
|
|
145
|
+
padding: cv.getVar('tree-select-empty-padding');
|
|
146
|
+
}
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
// Bestax Extras - AppFrame Styles
|
|
2
|
+
// The frame an app's pages sit in: a header across the top, a nav column down
|
|
3
|
+
// the side, the page, an aside and a footer, laid out by a grid. The header
|
|
4
|
+
// and the column stick while the document scrolls. Bulma has no frame.
|
|
5
|
+
//
|
|
6
|
+
// Below the root's breakpoint the nav is a drawer instead: fixed to the
|
|
7
|
+
// inline-start edge, slid out and `visibility: hidden` until it opens, so a
|
|
8
|
+
// closed one is out of the Tab order and the accessibility tree before any
|
|
9
|
+
// script runs. The layout is all in here, with a media query per breakpoint
|
|
10
|
+
// class, so the server's markup lays out as the browser's does.
|
|
11
|
+
|
|
12
|
+
@use 'bulma/sass/utilities/initial-variables' as iv;
|
|
13
|
+
@use 'bulma/sass/utilities/css-variables' as cv;
|
|
14
|
+
@use 'bulma/sass/utilities/mixins' as mx;
|
|
15
|
+
@use '../variables' as *;
|
|
16
|
+
@use '../mixins' as *;
|
|
17
|
+
|
|
18
|
+
// How far down the nav column starts sticking, and how far an in-page link
|
|
19
|
+
// or a Tab scrolls clear of the sticky header. A header taller than Bulma's
|
|
20
|
+
// navbar sets it on `:root`.
|
|
21
|
+
$app-frame-header-height: cv.getVar('navbar-height') !default;
|
|
22
|
+
$app-frame-header-background: cv.getVar('scheme-main') !default;
|
|
23
|
+
$app-frame-nav-width: 16rem !default;
|
|
24
|
+
$app-frame-nav-padding: 0.75rem !default;
|
|
25
|
+
$app-frame-nav-background: cv.getVar('scheme-main') !default;
|
|
26
|
+
$app-frame-aside-width: 20rem !default;
|
|
27
|
+
$app-frame-border-color: cv.getVar('border') !default;
|
|
28
|
+
$app-frame-border-width: 1px !default;
|
|
29
|
+
// The modal background's color: the inverted scheme at 0.86 alpha.
|
|
30
|
+
$app-frame-backdrop-background: hsla(
|
|
31
|
+
#{cv.getVar('scheme-h')},
|
|
32
|
+
#{cv.getVar('scheme-s')},
|
|
33
|
+
#{cv.getVar('scheme-invert-l')},
|
|
34
|
+
0.86
|
|
35
|
+
) !default;
|
|
36
|
+
$app-frame-drawer-shadow: cv.getVar('shadow') !default;
|
|
37
|
+
$app-frame-transition-duration: cv.getVar('duration') !default;
|
|
38
|
+
$app-frame-skip-link-background: cv.getVar('scheme-main') !default;
|
|
39
|
+
$app-frame-skip-link-color: cv.getVar('link') !default;
|
|
40
|
+
|
|
41
|
+
// The drawer leaves this much of the window showing beside it, so there's
|
|
42
|
+
// backdrop to press.
|
|
43
|
+
$-drawer-gap: 3rem;
|
|
44
|
+
|
|
45
|
+
// On Bulma's variables host, as `--bulma-navbar-height` is, so the document
|
|
46
|
+
// can read it for `scroll-padding-top`.
|
|
47
|
+
#{iv.$variables-host} {
|
|
48
|
+
@include cv.register-vars(
|
|
49
|
+
(
|
|
50
|
+
'app-frame-header-height': #{$app-frame-header-height},
|
|
51
|
+
)
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.#{iv.$class-prefix}app-frame {
|
|
56
|
+
@include cv.register-vars(
|
|
57
|
+
(
|
|
58
|
+
'app-frame-header-background': #{$app-frame-header-background},
|
|
59
|
+
'app-frame-nav-width': #{$app-frame-nav-width},
|
|
60
|
+
'app-frame-nav-padding': #{$app-frame-nav-padding},
|
|
61
|
+
'app-frame-nav-background': #{$app-frame-nav-background},
|
|
62
|
+
'app-frame-aside-width': #{$app-frame-aside-width},
|
|
63
|
+
'app-frame-border-color': #{$app-frame-border-color},
|
|
64
|
+
'app-frame-border-width': #{$app-frame-border-width},
|
|
65
|
+
'app-frame-backdrop-background': #{$app-frame-backdrop-background},
|
|
66
|
+
'app-frame-drawer-shadow': #{$app-frame-drawer-shadow},
|
|
67
|
+
'app-frame-transition-duration': #{$app-frame-transition-duration},
|
|
68
|
+
'app-frame-skip-link-background': #{$app-frame-skip-link-background},
|
|
69
|
+
'app-frame-skip-link-color': #{$app-frame-skip-link-color},
|
|
70
|
+
)
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// An in-page link or a Tab lands below the sticky header (WCAG technique C43).
|
|
75
|
+
html:has(.#{iv.$class-prefix}app-frame) {
|
|
76
|
+
scroll-padding-top: cv.getVar('app-frame-header-height');
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// ---- The grid, below the breakpoint ----------------------------------------------
|
|
80
|
+
|
|
81
|
+
// One column: the header, the page, the aside under it, and the footer. A
|
|
82
|
+
// part that isn't there leaves an empty `auto` row, which takes no room.
|
|
83
|
+
.#{iv.$class-prefix}app-frame {
|
|
84
|
+
display: grid;
|
|
85
|
+
grid-template-columns: minmax(0, 1fr);
|
|
86
|
+
grid-template-rows: auto 1fr auto auto;
|
|
87
|
+
grid-template-areas: 'header' 'main' 'aside' 'footer';
|
|
88
|
+
min-height: 100vh;
|
|
89
|
+
min-height: 100dvh;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.#{iv.$class-prefix}app-frame-header {
|
|
93
|
+
grid-area: header;
|
|
94
|
+
position: sticky;
|
|
95
|
+
inset-block-start: 0;
|
|
96
|
+
z-index: $extras-z-index-sticky;
|
|
97
|
+
background-color: cv.getVar('app-frame-header-background');
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.#{iv.$class-prefix}app-frame-main {
|
|
101
|
+
grid-area: main;
|
|
102
|
+
min-width: 0;
|
|
103
|
+
|
|
104
|
+
// Focus lands here from the skip link, to start the Tab order there. It's
|
|
105
|
+
// not a control, so it draws no ring.
|
|
106
|
+
&:focus {
|
|
107
|
+
outline: none;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
.#{iv.$class-prefix}app-frame-aside {
|
|
112
|
+
grid-area: aside;
|
|
113
|
+
min-width: 0;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
.#{iv.$class-prefix}app-frame-footer {
|
|
117
|
+
grid-area: footer;
|
|
118
|
+
min-width: 0;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// The drawer: over everything, header included, from the inline-start edge.
|
|
122
|
+
// It slides out and hides once the slide is over, and shows at once as it
|
|
123
|
+
// opens, so focus can move in straight away.
|
|
124
|
+
.#{iv.$class-prefix}app-frame-nav {
|
|
125
|
+
position: fixed;
|
|
126
|
+
inset-block: 0;
|
|
127
|
+
inset-inline-start: 0;
|
|
128
|
+
z-index: $extras-z-index-fixed;
|
|
129
|
+
inline-size: min(
|
|
130
|
+
#{cv.getVar('app-frame-nav-width')},
|
|
131
|
+
calc(100vw - #{$-drawer-gap})
|
|
132
|
+
);
|
|
133
|
+
overflow-y: auto;
|
|
134
|
+
overscroll-behavior: contain;
|
|
135
|
+
padding: cv.getVar('app-frame-nav-padding');
|
|
136
|
+
background-color: cv.getVar('app-frame-nav-background');
|
|
137
|
+
box-shadow: cv.getVar('app-frame-drawer-shadow');
|
|
138
|
+
transform: translateX(-100%);
|
|
139
|
+
visibility: hidden;
|
|
140
|
+
transition-property: transform, visibility;
|
|
141
|
+
transition-duration: cv.getVar('app-frame-transition-duration'), 0s;
|
|
142
|
+
transition-delay: 0s, cv.getVar('app-frame-transition-duration');
|
|
143
|
+
transition-timing-function: $extras-easing;
|
|
144
|
+
|
|
145
|
+
&:dir(rtl) {
|
|
146
|
+
transform: translateX(100%);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// The open drawer is Bulma's active state, on the nav as on a navbar's menu.
|
|
151
|
+
.#{iv.$class-prefix}app-frame
|
|
152
|
+
> .#{iv.$class-prefix}app-frame-nav.#{iv.$class-prefix}is-active {
|
|
153
|
+
transform: none;
|
|
154
|
+
visibility: visible;
|
|
155
|
+
transition-delay: 0s;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// The close button, at the top of the drawer on its far side. Bulma's
|
|
159
|
+
// `.delete` is inline, which an auto margin can't push, whichever loads last.
|
|
160
|
+
.#{iv.$class-prefix}app-frame-nav > .#{iv.$class-prefix}app-frame-close {
|
|
161
|
+
display: flex;
|
|
162
|
+
margin-inline-start: auto;
|
|
163
|
+
margin-block-end: 0.5rem;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
.#{iv.$class-prefix}app-frame-backdrop {
|
|
167
|
+
position: fixed;
|
|
168
|
+
inset: 0;
|
|
169
|
+
z-index: $extras-z-index-fixed - 1;
|
|
170
|
+
background-color: cv.getVar('app-frame-backdrop-background');
|
|
171
|
+
opacity: 0;
|
|
172
|
+
visibility: hidden;
|
|
173
|
+
transition-property: opacity, visibility;
|
|
174
|
+
transition-duration: cv.getVar('app-frame-transition-duration'), 0s;
|
|
175
|
+
transition-delay: 0s, cv.getVar('app-frame-transition-duration');
|
|
176
|
+
transition-timing-function: $extras-easing;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.#{iv.$class-prefix}app-frame
|
|
180
|
+
> .#{iv.$class-prefix}app-frame-backdrop.#{iv.$class-prefix}is-active {
|
|
181
|
+
opacity: 1;
|
|
182
|
+
visibility: visible;
|
|
183
|
+
transition-delay: 0s;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Bulma hides a navbar's burger from desktop up. The frame's shows at every
|
|
187
|
+
// width, since from the breakpoint up it collapses the column.
|
|
188
|
+
.#{iv.$class-prefix}navbar-burger.#{iv.$class-prefix}app-frame-burger {
|
|
189
|
+
display: inline-flex;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// Hidden until it has focus, then over the header's start. It shows at once,
|
|
193
|
+
// rather than fading its background in with Bulma's link transition, which
|
|
194
|
+
// leaves its text over the header's while it fades.
|
|
195
|
+
.#{iv.$class-prefix}app-frame-skip-link {
|
|
196
|
+
@include extras-sr-only;
|
|
197
|
+
transition: none;
|
|
198
|
+
|
|
199
|
+
&:focus {
|
|
200
|
+
position: fixed;
|
|
201
|
+
inset-block-start: 0.5rem;
|
|
202
|
+
inset-inline-start: 0.5rem;
|
|
203
|
+
z-index: $extras-z-index-fixed;
|
|
204
|
+
width: auto;
|
|
205
|
+
height: auto;
|
|
206
|
+
margin: 0;
|
|
207
|
+
padding: 0.5em 1em;
|
|
208
|
+
overflow: visible;
|
|
209
|
+
clip: auto;
|
|
210
|
+
white-space: normal;
|
|
211
|
+
border-radius: cv.getVar('radius');
|
|
212
|
+
background-color: cv.getVar('app-frame-skip-link-background');
|
|
213
|
+
color: cv.getVar('app-frame-skip-link-color');
|
|
214
|
+
box-shadow: cv.getVar('shadow');
|
|
215
|
+
@include extras-focus-outline;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// ---- From the breakpoint up ------------------------------------------------------
|
|
220
|
+
|
|
221
|
+
// Three columns, the nav's, the page's and the aside's, each as wide as what's
|
|
222
|
+
// in it, under the header. The footer sits under the page. The nav is a
|
|
223
|
+
// column that sticks under the header as tall as the window less the header,
|
|
224
|
+
// and collapsed it slides out past the inline-start edge as its column
|
|
225
|
+
// closes, then hides.
|
|
226
|
+
@mixin -wide {
|
|
227
|
+
grid-template-columns: auto minmax(0, 1fr) auto;
|
|
228
|
+
grid-template-rows: auto 1fr auto;
|
|
229
|
+
grid-template-areas:
|
|
230
|
+
'header header header'
|
|
231
|
+
'nav main aside'
|
|
232
|
+
'nav footer aside';
|
|
233
|
+
|
|
234
|
+
> .#{iv.$class-prefix}app-frame-nav {
|
|
235
|
+
grid-area: nav;
|
|
236
|
+
position: sticky;
|
|
237
|
+
inset: auto;
|
|
238
|
+
inset-block-start: cv.getVar('app-frame-header-height');
|
|
239
|
+
z-index: auto;
|
|
240
|
+
align-self: start;
|
|
241
|
+
inline-size: cv.getVar('app-frame-nav-width');
|
|
242
|
+
block-size: calc(100vh - #{cv.getVar('app-frame-header-height')});
|
|
243
|
+
block-size: calc(100dvh - #{cv.getVar('app-frame-header-height')});
|
|
244
|
+
border-inline-end: cv.getVar('app-frame-border-width') solid
|
|
245
|
+
cv.getVar('app-frame-border-color');
|
|
246
|
+
box-shadow: none;
|
|
247
|
+
transform: none;
|
|
248
|
+
visibility: visible;
|
|
249
|
+
transition-property: margin-inline-start, visibility;
|
|
250
|
+
transition-delay: 0s;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
&.#{iv.$class-prefix}is-nav-collapsed > .#{iv.$class-prefix}app-frame-nav {
|
|
254
|
+
margin-inline-start: calc(-1 * #{cv.getVar('app-frame-nav-width')});
|
|
255
|
+
visibility: hidden;
|
|
256
|
+
transition-delay: 0s, cv.getVar('app-frame-transition-duration');
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
> .#{iv.$class-prefix}app-frame-nav > .#{iv.$class-prefix}app-frame-close,
|
|
260
|
+
> .#{iv.$class-prefix}app-frame-backdrop {
|
|
261
|
+
display: none;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
> .#{iv.$class-prefix}app-frame-aside {
|
|
265
|
+
inline-size: cv.getVar('app-frame-aside-width');
|
|
266
|
+
border-inline-start: cv.getVar('app-frame-border-width') solid
|
|
267
|
+
cv.getVar('app-frame-border-color');
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
@include mx.tablet {
|
|
272
|
+
.#{iv.$class-prefix}app-frame.#{iv.$class-prefix}is-tablet {
|
|
273
|
+
@include -wide;
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
@include mx.desktop {
|
|
278
|
+
.#{iv.$class-prefix}app-frame.#{iv.$class-prefix}is-desktop {
|
|
279
|
+
@include -wide;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
@include mx.widescreen {
|
|
284
|
+
.#{iv.$class-prefix}app-frame.#{iv.$class-prefix}is-widescreen {
|
|
285
|
+
@include -wide;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
// ---- Media ---------------------------------------------------------------------
|
|
290
|
+
|
|
291
|
+
// The drawer's shadow is dropped in forced colors, so its open edge gets a
|
|
292
|
+
// border, as the column has.
|
|
293
|
+
@media (forced-colors: active) {
|
|
294
|
+
.#{iv.$class-prefix}app-frame-nav {
|
|
295
|
+
border-inline-end: cv.getVar('app-frame-border-width') solid
|
|
296
|
+
cv.getVar('app-frame-border-color');
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// No slide, collapse or fade: each state shows at once.
|
|
301
|
+
@media (prefers-reduced-motion: reduce) {
|
|
302
|
+
.#{iv.$class-prefix}app-frame-nav,
|
|
303
|
+
.#{iv.$class-prefix}app-frame-backdrop {
|
|
304
|
+
transition: none !important;
|
|
305
|
+
}
|
|
306
|
+
}
|