Skip to content

Commit

Permalink
feat(client): added full support for mobile responsiveness with adapt…
Browse files Browse the repository at this point in the history
…ed controls
  • Loading branch information
will-moss committed Jan 4, 2024
1 parent 6cea0ba commit eb1cc5b
Show file tree
Hide file tree
Showing 4 changed files with 189 additions and 14 deletions.
80 changes: 80 additions & 0 deletions app/client/assets/css/style.less
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
@import './colors.less';
@import './components.less';

@width-mobile: 960px;

* {
// outline: 1px dashed blue;
}
Expand Down Expand Up @@ -115,6 +117,10 @@ html {
.main {
height: 100%;
display: flex;

@media screen and (max-width: @width-mobile) {
flex-direction: column;
}
}

.footer {
Expand All @@ -137,6 +143,43 @@ html {
&:not(.is-active) {
display: none;
}

@media screen and (max-width: @width-mobile) {
display: none;
}
}

.mobile-controls {
align-items: center;
width: 100%;
height: 100%;
gap: 48px;
display: none;

@media screen and (max-width: @width-mobile) {
display: flex;
}

button {
width: 36px;
height: 100%;

&.has-icon {
display: flex;
justify-content: center;
align-items: center;

svg {
width: 100%;
height: 100%;
pointer-events: none;
}
}

&:not(.is-active) {
display: none;
}
}
}
}

Expand Down Expand Up @@ -183,6 +226,11 @@ html {
@width-left: 34%;
@width-right: 66%;

@media screen and (max-width: @width-mobile) {
padding-right: 6px;
row-gap: 24px;
}

.left,
.right {
// width: 50%;
Expand All @@ -199,6 +247,12 @@ html {
.left {
width: @width-left;
row-gap: 28px;

@media screen and (max-width: @width-mobile) {
width: 100%;
height: ~'calc(50% - 12px)';
}

.tab {
.tab-content {
height: 0; // Trick to make overflow:auto work without setting a defined height
Expand Down Expand Up @@ -231,6 +285,12 @@ html {
// Inspector part
.right {
width: @width-right;

@media screen and (max-width: @width-mobile) {
width: 100%;
height: ~'calc(50% - 12px)';
}

.tab {
.tab-content {
height: 0; // Trick to make overflow:auto work without setting a defined height
Expand Down Expand Up @@ -282,6 +342,13 @@ html {
}
}

@media screen and (max-width: @width-mobile) {
// Copied from data-layout='focus'
.left .tab:not(.is-current) {
display: none;
}
}

// States
&.is-loading {
.footer {
Expand Down Expand Up @@ -366,6 +433,19 @@ html {
&.for-message[data-category='authentication'] {
width: 435px;
}

@media screen and (max-width: @width-mobile) {
width: 90%;
&.for-message[data-category='authentication'],
&.for-tty,
&.for-prompt.for-login {
width: 90%;
}
}
}

@media screen and (max-width: @width-mobile) {
height: ~'calc(100% - 78px)';
}
}

Expand Down
51 changes: 50 additions & 1 deletion app/client/assets/js/isaiah.js
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,15 @@
*/
const hgetPromptInput = () => q('#prompt-input');

/**
* @returns {HTMLElement}
*/
const hgetMobileControl = (action) =>
q(`.mobile-controls button[data-action="${action}"]`);

const hgetMobileControls = (action) =>
qq(`.mobile-controls button[data-action]`);

// === Render-related methods

/**
Expand Down Expand Up @@ -876,6 +885,35 @@
).classList.add('is-active');
if (_state.isLoading)
hgetConnectionIndicator('loading').classList.add('is-active');

// 8. Reset mobile controls' visibility
hgetMobileControls().forEach((e) => {
e.classList.remove('is-active');
});

// 9. Update the mobile controls' visibility

// 9.1. Case when menuing
if (_state.isMenuIng) {
hgetMobileControl('reject').classList.add('is-active');
hgetMobileControl('confirm').classList.add('is-active');
}
// 9.2. Case when tty-ing / showing a message
else if (_state.popup === 'tty' || _state.popup === 'message') {
hgetMobileControl('_ttyQuit').classList.add('is-active');
}
// 9.3. Case when prompting
else if (_state.prompt.isEnabled || _state.prompt.input.isEnabled) {
hgetMobileControl('reject').classList.add('is-active');
hgetMobileControl('confirm').classList.add('is-active');
}
// 9.4. Every other case (default navigation)
else {
hgetMobileControl('previousTab').classList.add('is-active');
hgetMobileControl('nextTab').classList.add('is-active');
hgetMobileControl('menu').classList.add('is-active');
hgetMobileControl('bulk').classList.add('is-active');
}
};

// === Websocket-related methods
Expand Down Expand Up @@ -1458,6 +1496,17 @@
});
},

/**
* Public - Mobile-only - TTY-only - Quit the current TTY
*/
ttyQuit: function () {
state.tty.isEnabled = false;
state.tty.lines = [];
state.tty.history = [];
state.tty.historyCursor = [];
cmdRun(cmds._clearPopup);
},

/**
* Private - TTY-only - Quit and close the TTY session
*/
Expand Down Expand Up @@ -2431,7 +2480,7 @@
// 4.2. If menuing, and clicked outside the menu, dismiss it
else if (state.isMenuIng && target.classList.contains('popup-layer'))
cmdRun(cmds.reject);
// 4.3. If menuing, run the 3. scenario (assumption: we clicked a span inside a row)
// 4.3. If menuing, and clicked inside the menu, run the 3. scenario (assumption: we clicked a span inside a row)
else {
const tabContent = target.parentNode.parentNode;
const tabRow = target.parentNode;
Expand Down
60 changes: 49 additions & 11 deletions app/client/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,11 @@
<!-- HELPER -->
<div class="left">
<p class="help for-default">
← → ↑ ↓: navigate,
<button data-action="menu">x: menu</button>,
<button data-action="bulk">b: view bulk commands</button>,
<button data-action="quit">q: quit</button>,
<button data-action="help">?: help</button>
← → ↑ ↓: navigate,
<button data-action="menu">x: menu</button>,
<button data-action="bulk">b: view bulk commands</button>,
<button data-action="quit">q: quit</button>,
<button data-action="help">?: help</button>
</p>
<p class="help for-menu">
enter: execute, esc: close, ↑ ↓: navigate
Expand All @@ -55,6 +55,44 @@
<p class="help for-message">
n/esc/y/enter: ok
</p>

<div class="mobile-controls">
<button class="has-icon" data-action="previousTab">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="m11.25 9-3 3m0 0 3 3m-3-3h7.5M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>
</button>
<button class="has-icon" data-action="nextTab">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="m12.75 15 3-3m0 0-3-3m3 3h-7.5M21 12a9 9 0 1 1-18 0 9 9 0 0 1 18 0Z" />
</svg>
</button>
<button class="has-icon" data-action="menu">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
</svg>
</button>
<button class="has-icon" data-action="bulk">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M20.25 6.375c0 2.278-3.694 4.125-8.25 4.125S3.75 8.653 3.75 6.375m16.5 0c0-2.278-3.694-4.125-8.25-4.125S3.75 4.097 3.75 6.375m16.5 0v11.25c0 2.278-3.694 4.125-8.25 4.125s-8.25-1.847-8.25-4.125V6.375m16.5 0v3.75m-16.5-3.75v3.75m16.5 0v3.75C20.25 16.153 16.556 18 12 18s-8.25-1.847-8.25-4.125v-3.75m16.5 0c0 2.278-3.694 4.125-8.25 4.125s-8.25-1.847-8.25-4.125" />
</svg>
</button>
<button class="has-icon" data-action="reject">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
</svg>
</button>
<button class="has-icon" data-action="confirm">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="m4.5 12.75 6 6 9-13.5" />
</svg>
</button>
<button class="has-icon" data-action="_ttyQuit">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" class="w-6 h-6">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
</svg>
</button>
</div>
</div>

<!-- LOADING & CONNECTION INDICATOR -->
Expand Down Expand Up @@ -118,12 +156,12 @@
<div class="popup-layer"></div>

<!-- MOBILE BLOCKER -->
<div class="mobile-blocker">
<p>
As of now, Isaiah is not a responsive web application.<br /><br />
Please use a device with a display that is at least 920px wide.
</p>
</div>
<!-- <div class="mobile-blocker"> -->
<!-- <p> -->
<!-- As of now, Isaiah is not a responsive web application.<br /><br /> -->
<!-- Please use a device with a display that is at least 920px wide. -->
<!-- </p> -->
<!-- </div> -->
</div>
</body>
</html>
12 changes: 10 additions & 2 deletions app/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,10 @@ func main() {
}
server.Melody.Config.MaxMessageSize = _strconv.ParseInt(_os.GetEnv("SERVER_MAX_READ_SIZE"), 10, 64)

// Set up static file serving for the front-end with support for color-theming
// Load embed assets as a filesystem
serverRoot := _fs.Sub(clientAssets, "client")

// Set up static file serving for the CSS theming
http.HandleFunc("/assets/css/custom.css", func(w http.ResponseWriter, r *http.Request) {
if _, err := os.Stat("custom.css"); errors.Is(err, os.ErrNotExist) {
w.WriteHeader(200)
Expand All @@ -122,7 +124,13 @@ func main() {

http.ServeFile(w, r, "custom.css")
})
http.Handle("/", http.StripPrefix("/", http.FileServer(http.FS(serverRoot))))

if _os.GetEnv("DEV_ENABLED") != "TRUE" {
// Set up static file serving for all the front-end files
http.Handle("/", http.StripPrefix("/", http.FileServer(http.FS(serverRoot))))
} else {
http.Handle("/", http.FileServer(http.Dir("./client")))
}

// Set up an endpoint to handle Websocket connections with Melody
http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
Expand Down

0 comments on commit eb1cc5b

Please sign in to comment.