@@ -16,6 +16,7 @@ import {ModalConfig, ModalSize} from './modal-config';
1616 [class.active]="transitionController?.isVisible"
1717 [class.fullscreen]="isFullScreen"
1818 [class.basic]="isBasic"
19+ [class.scrolling]="mustScroll"
1920 #modal>
2021
2122 <!-- Configurable close icon -->
@@ -25,7 +26,15 @@ import {ModalConfig, ModalSize} from './modal-config';
2526 <!-- @ViewChild reference so we can insert elements beside this div. -->
2627 <div #templateSibling></div>
2728</div>
28- `
29+ ` ,
30+ styles : [ `
31+ .scrolling {
32+ position: absolute !important;
33+ margin-top: 3.5rem !important;
34+ margin-bottom: 3.5rem !important;
35+ top: 0;
36+ }
37+ ` ]
2938} )
3039export class SuiModal < T , U > implements OnInit , AfterViewInit {
3140 @Input ( )
@@ -83,6 +92,23 @@ export class SuiModal<T, U> implements OnInit, AfterViewInit {
8392 @Input ( )
8493 public isBasic :boolean ;
8594
95+ // Whether the modal currently is displaying a scrollbar.
96+ private _mustScroll :boolean ;
97+ // Whether or not the modal should always display a scrollbar.
98+ private _mustAlwaysScroll :boolean ;
99+
100+ @Input ( )
101+ public get mustScroll ( ) {
102+ return this . _mustScroll ;
103+ }
104+
105+ public set mustScroll ( mustScroll :boolean ) {
106+ this . _mustScroll = mustScroll ;
107+ // 'Cache' value in _mustAlwaysScroll so that if `true`, _mustScroll isn't ever auto-updated.
108+ this . _mustAlwaysScroll = mustScroll ;
109+ this . updateScroll ( ) ;
110+ }
111+
86112 public transitionController :TransitionController ;
87113
88114 // Transition to display modal with.
@@ -124,16 +150,21 @@ export class SuiModal<T, U> implements OnInit, AfterViewInit {
124150 }
125151
126152 public ngOnInit ( ) {
127- // Transition the modal to be visible.
128- this . transitionController . animate ( new Transition ( this . transition , this . transitionDuration , TransitionDirection . In ) ) ;
129153 // Use a slight delay as the `<sui-dimmer>` cancels the initial transition.
130- setTimeout ( ( ) => this . dimBackground = true ) ;
154+ setTimeout ( ( ) => {
155+ // Transition the modal to be visible.
156+ this . transitionController . animate ( new Transition ( this . transition , this . transitionDuration , TransitionDirection . In ) )
157+ this . dimBackground = true ;
158+ } ) ;
131159 }
132160
133161 public ngAfterViewInit ( ) {
134162 // Update margin offset to center modal correctly on-screen.
135163 const element = this . _modalElement . nativeElement as Element ;
136- this . _renderer . setStyle ( element , "margin-top" , `-${ element . clientHeight / 2 } px` ) ;
164+ setTimeout ( ( ) => {
165+ this . _renderer . setStyle ( element , "margin-top" , `-${ element . clientHeight / 2 } px` ) ;
166+ this . updateScroll ( ) ;
167+ } ) ;
137168 }
138169
139170 // Updates the modal with the specified configuration.
@@ -145,6 +176,8 @@ export class SuiModal<T, U> implements OnInit, AfterViewInit {
145176 this . isFullScreen = config . isFullScreen ;
146177 this . isBasic = config . isBasic ;
147178
179+ this . mustScroll = config . mustScroll ;
180+
148181 this . transition = config . transition ;
149182 this . transitionDuration = config . transitionDuration ;
150183 }
@@ -175,11 +208,31 @@ export class SuiModal<T, U> implements OnInit, AfterViewInit {
175208 }
176209 }
177210
211+ // Decides whether the modal needs to reposition to allow scrolling.
212+ private updateScroll ( ) {
213+ // Semantic UI modal margin is 3.5rem, which is relative to the global font size, so for compatibility:
214+ const fontSize = parseFloat ( window . getComputedStyle ( document . documentElement , null ) . getPropertyValue ( 'font-size' ) ) ;
215+ const margin = fontSize * 3.5 ;
216+
217+ // _mustAlwaysScroll works by stopping _mustScroll from being automatically updated, so it stays `true`.
218+ if ( ! this . _mustAlwaysScroll && this . _modalElement ) {
219+ const element = this . _modalElement . nativeElement as Element ;
220+
221+ // The modal must scroll if the window height is smaller than the modal height + both margins.
222+ this . _mustScroll = window . innerHeight < element . clientHeight + margin * 2 ;
223+ }
224+ }
225+
178226 @HostListener ( "document:keyup" , [ "$event" ] )
179- public onKeyup ( e :KeyboardEvent ) {
227+ public onDocumentKeyup ( e :KeyboardEvent ) {
180228 if ( e . keyCode == KeyCode . Escape ) {
181229 // Close automatically covers case of `!isClosable`, so check not needed.
182230 this . close ( ) ;
183231 }
184232 }
233+
234+ @HostListener ( "window:resize" )
235+ public onDocumentResize ( ) {
236+ this . updateScroll ( ) ;
237+ }
185238}
0 commit comments