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
|
/*
* Copyright 2000-2016 Vaadin Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package com.vaadin.server;
import com.vaadin.shared.extension.responsive.ResponsiveState;
import com.vaadin.ui.Component;
/**
* An extension providing responsive layout capabilities to any Vaadin
* component. The Responsive extension allows specifying different CSS rules for
* different dimensions of extended components. This allows creating
* applications that provide an optimal viewing experience – easy reading and
* navigation with a minimum of resizing, panning, and scrolling – across a wide
* range of devices (from mobile phones to desktop computer monitors).
* <p>
* NOTE! You should always specify a relative (%) size for the extended
* component, doing otherwise will prevent the Responsive extension from
* working, as the component will not dynamically resize.
* </p>
* <p>
* All configuration of the visual breakpoints (ranges) for the component are
* done with CSS. Pixels (px) are the only supported unit. Fractional pixels are
* not supported.
* </p>
* <p>
* <i>Dynamic style injections (e.g. through
* <code>Page.getCurrent().getStyles().add(...)</code>) or any other style
* updates after the initial page load are not supported at the moment.</i>
* </p>
*
*
* <p>
* Example:
*
* <b>Java</b>
*
* <pre>
* CssLayout layout = new CssLayout();
* layout.setStyleName("responsive");
* layout.setSizeFull();
* Responsive.makeResponsive(layout);
* </pre>
*
* <b>SCSS</b>
*
* <pre>
* .v-csslayout.responsive {
* &[width-range~="0-300px"] {
* // Styles for the layout when its width is between 0 and 300 pixels
* }
* &[width-range~="301-500px"] {
* // Styles for the layout when its width is between 301 and 500 pixels
* }
* &[width-range~="501px-"] {
* // Styles for the layout when its width is over 500 pixels
* }
* &[height-range~="0-300px"] {
* // Styles for the layout when its height is between 0 and 300 pixels
* }
* &[height-range~="301-500px"] {
* // Styles for the layout when its height is between 301 and 500 pixels
* }
* &[height-range~="501-"] {
* // Styles for the layout when its height is over 500 pixels
* }
* }
* </pre>
*
* <b>CSS</b>
*
* <pre>
* .v-csslayout.responsive[width-range~="0-300px"] {
* // Styles for the layout when its width is between 0 and 300 pixels
* }
* .v-csslayout.responsive[width-range~="301-500px"] {
* // Styles for the layout when its width is between 301 and 500 pixels
* }
* .v-csslayout.responsive[width-range~="501-"] {
* // Styles for the layout when its width is over 500 pixels
* }
*
* .v-csslayout.responsive[height-range~="0-300px"] {
* // Styles for the layout when its height is between 0 and 300 pixels
* }
* .v-csslayout.responsive[height-range~="301-500px"] {
* // Styles for the layout when its height is between 301 and 500 pixels
* }
* .v-csslayout.responsive[height-range~="501px-"] {
* // Styles for the layout when its height is over 500 pixels
* }
* </pre>
*
* </p>
* <p>
* <b>Note:</b> <i>The defined ranges are applied on a global context, so even
* if you would write your CSS to target only a given context, the ranges would
* be applied to all other instances with the same style name.</i>
* </p>
* <p>
* E.g. this would affect all CssLayout instances in the application, even
* though the CSS implies it would only affect CssLayout instances inside a
* parent with a style name "foobar":
* </p>
*
* <pre>
* .foobar .v-csslayout[width-range~="0px-100px"] {
* // These properties will affect all responsive CssLayout instances
* }
* </pre>
*
* <p>
* To scope the ranges, use an additional style name for the target component,
* and add that to your CSS selector:
* </p>
*
* <pre>
* .v-csslayout.mystyle[width-range="0px-100px"] {
* // These properties will only affect responsive CssLayout instances with an additional style name of 'mystyle'
* }
* </pre>
*
* @author Vaadin Ltd
* @since 7.2
*/
public class Responsive extends AbstractExtension {
/**
* Creates a new instance, which can be used to extend a component.
*/
protected Responsive() {
}
/**
* Enable responsive width and height range styling for the target component
* or UI instance.
*
* @param target
* The component which should be able to respond to width and/or
* height changes.
*/
public static void makeResponsive(Component... components) {
for (Component c : components) {
if (c instanceof AbstractClientConnector) {
new Responsive().extend((AbstractClientConnector) c);
}
}
}
@Override
protected ResponsiveState getState() {
return (ResponsiveState) super.getState();
}
@Override
protected ResponsiveState getState(boolean markAsDirty) {
return (ResponsiveState) super.getState(markAsDirty);
}
}
|