full screen visualization
we don't focus much on mobile data science, but maybe we should.
after testing accessible table visualizations on mobile i realize
there a huge opportunity to have a tactile experience with data.
there are some style and UX choices we can make to improve these outcome.
one challenge i've had it visualization moving while i am touching them.
i think a good solution for this challenge is the ability to full screen a visualization
and restrict the non-ground in the figure.
ultimately, the fullscreen transitions our visual and tactile landscape from fixed dimensions to fluid dimensions.
an secondary outcome of the fullscreen mode is that it reduces the visual cognitive accessibility of the content.
the dialog
technique sticks more strictly to the cognitive acessibility of the content.
both techniques are explored. these examples might lack keyboard accessibility with exiting fullscreen mode or dialogs.
the Esc should work.
javascript fullscreen api approach
import nbconvert_a11y.table
df = DataFrame ( index = numpy . arange ( 100 ) * numpy . pi / 180 * 10 )
table = df . assign ( x = df . index . map ( numpy . cos ), y = df . index . map ( numpy . sin )) . table ( options = dict ( max_rows = 100 ))
table . html . table . attrs . update ({ "class" : "xy" })
table . html . form . append (
DataFrame . table . new ( "button" , "fullscreen" , onclick = "event.preventDefault(); this.parentElement.parentElement.querySelector(`table`).requestFullscreen()" )
)
before = table . html . __copy__ ()
table
pandas dataframe with 100 rows, 2 columns with 1 index levels and 1 columns levels.
None
x
y
0.000
1.000
0.000
0.175
0.985
0.174
0.349
0.940
0.342
0.524
0.866
0.500
0.698
0.766
0.643
0.873
0.643
0.766
1.047
0.500
0.866
1.222
0.342
0.940
1.396
0.174
0.985
1.571
0.000
1.000
1.745
-0.174
0.985
1.920
-0.342
0.940
2.094
-0.500
0.866
2.269
-0.643
0.766
2.443
-0.766
0.643
2.618
-0.866
0.500
2.793
-0.940
0.342
2.967
-0.985
0.174
3.142
-1.000
0.000
3.316
-0.985
-0.174
3.491
-0.940
-0.342
3.665
-0.866
-0.500
3.840
-0.766
-0.643
4.014
-0.643
-0.766
4.189
-0.500
-0.866
4.363
-0.342
-0.940
4.538
-0.174
-0.985
4.712
-0.000
-1.000
4.887
0.174
-0.985
5.061
0.342
-0.940
5.236
0.500
-0.866
5.411
0.643
-0.766
5.585
0.766
-0.643
5.760
0.866
-0.500
5.934
0.940
-0.342
6.109
0.985
-0.174
6.283
1.000
-0.000
6.458
0.985
0.174
6.632
0.940
0.342
6.807
0.866
0.500
6.981
0.766
0.643
7.156
0.643
0.766
7.330
0.500
0.866
7.505
0.342
0.940
7.679
0.174
0.985
7.854
0.000
1.000
8.029
-0.174
0.985
8.203
-0.342
0.940
8.378
-0.500
0.866
8.552
-0.643
0.766
8.727
-0.766
0.643
8.901
-0.866
0.500
9.076
-0.940
0.342
9.250
-0.985
0.174
9.425
-1.000
0.000
9.599
-0.985
-0.174
9.774
-0.940
-0.342
9.948
-0.866
-0.500
10.123
-0.766
-0.643
10.297
-0.643
-0.766
10.472
-0.500
-0.866
10.647
-0.342
-0.940
10.821
-0.174
-0.985
10.996
-0.000
-1.000
11.170
0.174
-0.985
11.345
0.342
-0.940
11.519
0.500
-0.866
11.694
0.643
-0.766
11.868
0.766
-0.643
12.043
0.866
-0.500
12.217
0.940
-0.342
12.392
0.985
-0.174
12.566
1.000
-0.000
12.741
0.985
0.174
12.915
0.940
0.342
13.090
0.866
0.500
13.265
0.766
0.643
13.439
0.643
0.766
13.614
0.500
0.866
13.788
0.342
0.940
13.963
0.174
0.985
14.137
0.000
1.000
14.312
-0.174
0.985
14.486
-0.342
0.940
14.661
-0.500
0.866
14.835
-0.643
0.766
15.010
-0.766
0.643
15.184
-0.866
0.500
15.359
-0.940
0.342
15.533
-0.985
0.174
15.708
-1.000
0.000
15.882
-0.985
-0.174
16.057
-0.940
-0.342
16.232
-0.866
-0.500
16.406
-0.766
-0.643
16.581
-0.643
-0.766
16.755
-0.500
-0.866
16.930
-0.342
-0.940
17.104
-0.174
-0.985
17.279
0.000
-1.000
min
-1.000
-1.000
max
1.000
1.000
diff
2.000
2.000
%%
## dialog approach
the dialog approach reduces the axcessibility object model to the modal area only .
as a result , we reduce the palette of visual and nonvisual controls . this is good for focus .
new = before . __copy__ ()
new . append ( DataFrame . table . new ( "dialog" , before . figure . __copy__ (), ** { "class" : "xy" }))
new . table . decompose ()
new . form . insert_before ( new . dialog )
new . button . attrs . update ( onclick = "event.preventDefault(); this.parentElement.parentElement.querySelector(`dialog`).showModal()" )
HTML ( new )
pandas dataframe with 100 rows, 2 columns with 1 index levels and 1 columns levels. None x y 0.000 1.000 0.000 0.175 0.985 0.174 0.349 0.940 0.342 0.524 0.866 0.500 0.698 0.766 0.643 0.873 0.643 0.766 1.047 0.500 0.866 1.222 0.342 0.940 1.396 0.174 0.985 1.571 0.000 1.000 1.745 -0.174 0.985 1.920 -0.342 0.940 2.094 -0.500 0.866 2.269 -0.643 0.766 2.443 -0.766 0.643 2.618 -0.866 0.500 2.793 -0.940 0.342 2.967 -0.985 0.174 3.142 -1.000 0.000 3.316 -0.985 -0.174 3.491 -0.940 -0.342 3.665 -0.866 -0.500 3.840 -0.766 -0.643 4.014 -0.643 -0.766 4.189 -0.500 -0.866 4.363 -0.342 -0.940 4.538 -0.174 -0.985 4.712 -0.000 -1.000 4.887 0.174 -0.985 5.061 0.342 -0.940 5.236 0.500 -0.866 5.411 0.643 -0.766 5.585 0.766 -0.643 5.760 0.866 -0.500 5.934 0.940 -0.342 6.109 0.985 -0.174 6.283 1.000 -0.000 6.458 0.985 0.174 6.632 0.940 0.342 6.807 0.866 0.500 6.981 0.766 0.643 7.156 0.643 0.766 7.330 0.500 0.866 7.505 0.342 0.940 7.679 0.174 0.985 7.854 0.000 1.000 8.029 -0.174 0.985 8.203 -0.342 0.940 8.378 -0.500 0.866 8.552 -0.643 0.766 8.727 -0.766 0.643 8.901 -0.866 0.500 9.076 -0.940 0.342 9.250 -0.985 0.174 9.425 -1.000 0.000 9.599 -0.985 -0.174 9.774 -0.940 -0.342 9.948 -0.866 -0.500 10.123 -0.766 -0.643 10.297 -0.643 -0.766 10.472 -0.500 -0.866 10.647 -0.342 -0.940 10.821 -0.174 -0.985 10.996 -0.000 -1.000 11.170 0.174 -0.985 11.345 0.342 -0.940 11.519 0.500 -0.866 11.694 0.643 -0.766 11.868 0.766 -0.643 12.043 0.866 -0.500 12.217 0.940 -0.342 12.392 0.985 -0.174 12.566 1.000 -0.000 12.741 0.985 0.174 12.915 0.940 0.342 13.090 0.866 0.500 13.265 0.766 0.643 13.439 0.643 0.766 13.614 0.500 0.866 13.788 0.342 0.940 13.963 0.174 0.985 14.137 0.000 1.000 14.312 -0.174 0.985 14.486 -0.342 0.940 14.661 -0.500 0.866 14.835 -0.643 0.766 15.010 -0.766 0.643 15.184 -0.866 0.500 15.359 -0.940 0.342 15.533 -0.985 0.174 15.708 -1.000 0.000 15.882 -0.985 -0.174 16.057 -0.940 -0.342 16.232 -0.866 -0.500 16.406 -0.766 -0.643 16.581 -0.643 -0.766 16.755 -0.500 -0.866 16.930 -0.342 -0.940 17.104 -0.174 -0.985 17.279 0.000 -1.000 min -1.000 -1.000 max 1.000 1.000 diff 2.000 2.000
dialog approach
the dialog approach reduces the axcessibility object model to the modal area only.
as a result, we reduce the palette of visual and nonvisual controls. this is good for focus.
new = before.__copy__()
new.append(DataFrame.table.new("dialog", before.figure.__copy__(), **{"class": "xy"}))
new.table.decompose()
new.form.insert_before(new.dialog)
new.button.attrs.update(onclick="event.preventDefault(); this.parentElement.parentElement.querySelector(`dialog`).showModal()")
HTML(new)
marginalia
i'll have to test this with the mobile emulator
need to think about landscape and portrait mode.
this approach might overlap with email too because you design for 600px, uses inline css instead
https://css-tricks.com/html-email-accessibility/
%%
## css
``` css
: root {
-- w : 600 px ; -- h : 400 px ;}
table : fullscreen , dialog . xy [ open ] {
-- w : 100 vw ; -- h : 100 vh ;
overflow : auto ;
}
table . xy {
box - sizing : border - box ;
height : var ( -- h ); width : var ( -- w );
display : block ; position : relative ;
tbody {
height : var ( -- h ); width : var ( -- w );
display : block ;
tr {
-- x : calc (( var ( -- 0 ) - var ( -- 0 - min )) / var ( -- 0 - diff ) * var ( -- w ));
-- y : calc (( var ( -- 1 ) - var ( -- 1 - min )) / var ( -- 1 - diff ) * var ( -- h ));
display : block ; position : absolute ;
top : var ( -- y ); left : var ( -- x );
transform : translate ( - 50 % , - 50 % );
}
}
}
dialog . xy {
display : contents ;
& amp ;[ open ] { height : 100 vh ; width : 100 vw ;}
}
. xy thead ,
. xy tfoot ,
. xy caption ,
. nv {
clip : rect ( 0 0 0 0 );
clip - path : inset ( 50 % );
height : 1 px ;
overflow : hidden ;
position : absolute ;
white - space : nowrap ;
width : 1 px ;
}
```
css
:root {
--w : 600 px ; --h : 400 px ;}
table :fullscreen , dialog .xy [ open ] {
--w : 100 vw ; --h : 100 vh ;
overflow : auto ;
}
table .xy {
box-sizing : border-box ;
height : var (--h ); width : var (--w );
display : block ; position : relative ;
tbody {
height : var (--h ); width : var (--w );
display : block ;
tr {
--x : calc (( var (--0 ) - var (--0 -min )) / var (--0 -diff ) * var (--w ));
--y : calc (( var (--1 ) - var (--1 -min )) / var (--1 -diff ) * var (--h ));
display : block ; position : absolute ;
top : var (--y ); left : var (--x );
transform : translate (-50 % , -50 % );
}
}
}
dialog .xy {
display : contents;
&[open] { height : 100 vh ; width : 100 vw ;}
}
.xy thead ,
.xy tfoot ,
.xy caption ,
.nv {
clip : rect (0 0 0 0 );
clip-path : inset (50 % );
height : 1 px ;
overflow : hidden ;
position : absolute ;
white-space : nowrap ;
width : 1 px ;
}