Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use SheafDisplay fr composed sheaf view in discuss #136

Draft
wants to merge 23 commits into
base: feat/discussion/sheaf-creation-modal
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
81cb5be
Use SheafDisplay fr composed sheaf view in discuss
rtshkmr Nov 19, 2024
5023450
Follow telegram ui for mark_quote in mark_content
rtshkmr Nov 20, 2024
a4d9dcc
Attempt to use hsla for colors
rtshkmr Nov 20, 2024
e719c1a
Fix functionality in TextareaAutoResize
rtshkmr Nov 20, 2024
998bee6
Fix Control Panel interference bug
rtshkmr Nov 20, 2024
98b1475
Use action_toggle_button for text-based buttons
rtshkmr Nov 20, 2024
78e07ae
Use action toggle button for marks edit
rtshkmr Nov 20, 2024
45587f4
Shift the edit buttongroups for marks inwards
rtshkmr Nov 20, 2024
b21fb63
Display clickable quote region for marks w/o quote
rtshkmr Nov 20, 2024
ea7beae
Rely on a fn for selector for pseudoform
rtshkmr Nov 21, 2024
fe4c134
Prettify indent guides, support tap to collapse
rtshkmr Nov 21, 2024
17a404f
Prevent zoom-out beyond 1x scale on mobile
rtshkmr Nov 21, 2024
8cdf697
Improve sheaf modal styling
rtshkmr Nov 29, 2024
3e0bcd1
Style SheafCreationForm's replyto_context_display
rtshkmr Dec 6, 2024
16697e2
Minor changes
rtshkmr Dec 6, 2024
8dac303
Fix issue in make_reply for root sheaf creation
rtshkmr Dec 7, 2024
e74a947
Fix sheaf::publish on discussions mode
rtshkmr Dec 7, 2024
80fa60c
Wire up 2 out of 4 of the alternative action btns
rtshkmr Dec 7, 2024
0e1cd6c
Add action btn to create new thread @ discuss mode
rtshkmr Dec 8, 2024
7950455
Fix the re-introduced scrolling bug
rtshkmr Dec 8, 2024
a3eeac3
Merge branch 'feat/discussion/sheaf-creation-modal' into feat/discuss…
rtshkmr Dec 8, 2024
f4ac084
Wire clear_reply_to, improve sheaf::publish
rtshkmr Dec 9, 2024
8ac06d3
Use push_js_cmd to dispatch js actions fm srv
rtshkmr Dec 10, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions assets/colors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* Convenience js module that defines the site-wide colours
*/

// Define individual HSLA colors as constants
const chiliRed = "hsla(5, 100%, 55%, 1)"; // #e83a21
const pearl = "hsla(39, 40%, 90%, 1)"; // #e3dabe
const black = "hsla(0, 0%, 3%, 1)"; // #070302
const dun = "hsla(39, 20%, 80%, 1)"; // #deb587
const bloodRed = "hsla(0, 100%, 20%, 1)"; // #5b1208

const whiteAlabaster = "hsla(40, 20%, 95%, 1)"; // #f3efe3
const linen = "hsla(40, 30%, 97%, 1)"; // #faf1e6

const aerospaceOrange = "hsla(30, 100%, 50%, 1)"; // #fd4f00
const coralOrange = "hsla(15, 100%, 60%, 1)"; // #ff8349
const atomicTangerine = "hsla(15, 100%, 70%, 1)"; // #ff9b6d

const brown = "hsla(15, 80%, 30%, 1)"; // #922e00
const sienna = "hsla(10, 80%, 25%, 1)"; // #7f2800
const rust = "hsla(0, 85%, 40%, 1)"; // #ae3700

// Define color variables using the constants without the 'color' prefix
const colors = {
aerospaceOrange: "hsla(30, 100%, 50%, 1)",
brand: aerospaceOrange,
brandLight: atomicTangerine,
brandExtraLight: linen,
brandAccent: aerospaceOrange,
brandAccentLight: atomicTangerine,

brandDark: brown,
brandExtraDark: sienna,

primary: chiliRed,
primaryAccent: chiliRed,
primaryBackground: whiteAlabaster,
secondary: bloodRed,
secondaryBackground: dun,
text: black,
};

export default colors;
42 changes: 26 additions & 16 deletions assets/css/app.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,21 @@
**/
@layer base {
:root {
--chili-red: #e83a21ff;
--pearl: #e3dabeff;
--black: #070302ff;
--dun: #deb587;
--blood-red: #5b1208ff;

--white-alabaster: #f3efe3;
--linen: #faf1e6;
--deep-saffron: #ff9933;
--coral-orange: #FF8349;
--atomic-tangerine: #FF9B6D;


--brown: #922e00;
--sienna: #7f2800;
--rust: #ae3700;
--chili-red: hsla(5, 100%, 55%, 1); /* #e83a21 */
--pearl: hsla(39, 40%, 90%, 1); /* #e3dabe */
--black: hsla(0, 0%, 3%, 1); /* #070302 */
--dun: hsla(39, 20%, 80%, 1); /* #deb587 */
--blood-red: hsla(0, 100%, 20%, 1); /* #5b1208 */

--white-alabaster: hsla(40, 20%, 95%, 1); /* #f3efe3 */
--linen: hsla(40, 30%, 97%, 1); /* #faf1e6 */
--deep-saffron: hsla(30, 100%, 60%, 1); /* #ff9933 */
--aerospace-orange: hsla(30, 100%, 50%, 1); /* #fd4f00 */
--coral-orange: hsla(15, 100%, 60%, 1); /* #ff8349 */
--atomic-tangerine: hsla(15, 100%, 70%, 1); /* #ff9b6d */
--brown: hsla(15, 80%, 30%, 1); /* #922e00 */
--sienna: hsla(10, 80%, 25%, 1); /* #7f2800 */
--rust: hsla(0, 85%, 40%, 1); /* #ae3700 */

--color-brand: var(--deep-saffron);
--color-brand-light: var(--atomic-tangerine);
Expand Down Expand Up @@ -162,3 +161,14 @@
vertical-align: baseline;
position: relative;
}
textarea {
/* Remove default outline on focus */
outline: none;
border: none; /* Ensure no default border */
}

textarea:focus {
/* Change border color on focus */
border-color: #ff6347; /* Change this to your desired focus color */
box-shadow: 0 0 5px rgba(255, 99, 71, 0.5); /* Optional shadow effect */
}
128 changes: 118 additions & 10 deletions assets/js/app.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,17 +41,17 @@ let liveSocket = new LiveSocket("/live", Socket, {

function fetchSession() {
try {
sess = JSON.parse(localStorage.getItem("session"))
if(sess && sess.id && typeof sess.id == 'string' ) return sess
new_sess = {id: genAnonId()}
localStorage.setItem("session", JSON.stringify(new_sess))
return new_sess;
sess = JSON.parse(localStorage.getItem("session"));
if (sess && sess.id && typeof sess.id == "string") return sess;
new_sess = { id: genAnonId() };
localStorage.setItem("session", JSON.stringify(new_sess));
return new_sess;
} catch (error) {
new_sess = {id: genAnonId()}
localStorage.setItem("session", JSON.stringify(new_sess))
return new_sess
new_sess = { id: genAnonId() };
localStorage.setItem("session", JSON.stringify(new_sess));
return new_sess;
}
};
}

function genAnonId(length = 18) {
try {
Expand All @@ -67,13 +67,121 @@ function genAnonId(length = 18) {

return base64String;
} catch (error) {
console.error('Error generating random Base64 string:', error);
console.error("Error generating random Base64 string:", error);
throw error;
}
}

let Focus = {
focusMain() {
let target =
document.querySelector("main h1") || document.querySelector("main");
if (target) {
let origTabIndex = target.tabIndex;
target.tabIndex = -1;
target.focus();
target.tabIndex = origTabIndex;
}
},
// Subject to the W3C Software License at https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
isFocusable(el) {
if (
el.tabIndex > 0 ||
(el.tabIndex === 0 && el.getAttribute("tabIndex") !== null)
) {
return true;
}
if (el.disabled) {
return false;
}

switch (el.nodeName) {
case "A":
return !!el.href && el.rel !== "ignore";
case "INPUT":
return el.type != "hidden" && el.type !== "file";
case "BUTTON":
case "SELECT":
case "TEXTAREA":
return true;
default:
return false;
}
},
// Subject to the W3C Software License at https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
attemptFocus(el) {
if (!el) {
return;
}
if (!this.isFocusable(el)) {
return false;
}
try {
el.focus();
} catch (e) {}

return document.activeElement === el;
},
// Subject to the W3C Software License at https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
focusFirstDescendant(el) {
for (let i = 0; i < el.childNodes.length; i++) {
let child = el.childNodes[i];
if (this.attemptFocus(child) || this.focusFirstDescendant(child)) {
return true;
}
}
return false;
},
// Subject to the W3C Software License at https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document
focusLastDescendant(element) {
for (let i = element.childNodes.length - 1; i >= 0; i--) {
let child = element.childNodes[i];
if (this.attemptFocus(child) || this.focusLastDescendant(child)) {
return true;
}
}
return false;
},
};

// Acessible routing -- effecting frontend changes from server-side events:
// refs:
// 1. fly.io blog post: https://fly.io/phoenix-files/server-triggered-js/
// 2. livebeats as an example: https://github.com/fly-apps/live_beats/blob/ac9780472e7019af274110a1cf71250a8d40c986/assets/js/app.js#L307
window.addEventListener("phx:js:exec", (e) => {
liveSocket.execJS(liveSocket.main.el, e.detail.cmd);
});

window.addEventListener("js:call", (e) =>
e.target[e.detail.call](...e.detail.args),
);
window.addEventListener("js:focus", (e) => {
let parent = document.querySelector(e.detail.parent);
if (parent && isVisible(parent)) {
e.target.focus();
}
});
window.addEventListener("js:focus-closest", (e) => {
let el = e.target;
let sibling = el.nextElementSibling;
while (sibling) {
if (isVisible(sibling) && Focus.attemptFocus(sibling)) {
return;
}
sibling = sibling.nextElementSibling;
}
sibling = el.previousElementSibling;
while (sibling) {
if (isVisible(sibling) && Focus.attemptFocus(sibling)) {
return;
}
sibling = sibling.previousElementSibling;
}
Focus.attemptFocus(el.parent) || Focus.focusMain();
});
window.addEventListener("phx:remove-el", (e) =>
document.getElementById(e.detail.id).remove(),
);

// Show progress bar on live navigation and form submits
topbar.config({ barColors: { 0: "#29d" }, shadowColor: "rgba(0, 0, 0, .3)" });
Expand Down
2 changes: 2 additions & 0 deletions assets/js/hooks/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import Scrolling from "./scrolling.js";
import ButtonClickRelayer from "./button_click_relayer.js";
import SessionBox from "./session_box.js";
import TextareaAutoResize from "./textarea_auto_resize.js";
import TextareaFocus from "./textarea_focus.js";
import PseudoForm from "./pseudo_form.js";

let Hooks = {
Expand All @@ -29,6 +30,7 @@ let Hooks = {
ButtonClickRelayer,
SessionBox,
TextareaAutoResize,
TextareaFocus,
PseudoForm,
};

Expand Down
67 changes: 65 additions & 2 deletions assets/js/hooks/textarea_auto_resize.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,75 @@
* textarea height (bound by max height, if already defined).
* */

const targetEvents = ["input", "focus", "click"];

export default TextareaAutoResize = {
mounted() {
console.log("!!! mounted TextareaAutoResize");
this.handleInput();

// Bind handleInput to maintain context
this.handleInputBound = this.handleInput.bind(this);

// Add event listeners correctly
targetEvents.forEach((e) =>
this.el.addEventListener(e, this.handleInputBound),
);

// watches for visibility changes:
this.observer = new IntersectionObserver((entries) => {
entries.forEach((entry) => {
const isTextAreaVisibleInViewport = entry.isIntersecting;
if (isTextAreaVisibleInViewport) {
this.handleInput(); // Call handleInput when textarea becomes visible
}
});
});

// watches for mutations on the element
this.mutationObserver = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
const isDisabledAttrMutated =
mutation.type === "attributes" &&
mutation.attributeName === "disabled";
if (isDisabledAttrMutated) {
this.handleInput();
}
});
});

// Start observing:
this.observer.observe(this.el);
this.mutationObserver.observe(this.el, { attributes: true });
},

destroyed() {
console.log("!!! destroyed TextareaAutoResize");

// Prevent memory leaks by removing event listeners
targetEvents.forEach((e) =>
this.el.removeEventListener(e, this.handleInputBound),
);

// Disconnect observers:
if (this.observer) {
this.observer.disconnect();
}

if (this.mutationObserver) {
this.mutationObserver.disconnect();
}
},

/**
* Adjusts the height of the textarea on input.
*/
handleInput() {
this.el.style.height = "auto"; // Resets height to auto to shrink if needed
this.el.style.height = `${this.el.scrollHeight}px`; // Sets height based on scrollHeight
this.el.style.height = "auto"; // Reset height
this.el.style.height = `${this.el.scrollHeight}px`; // Set height based on scrollHeight
console.log("!!! Handling input", {
elem: this.el,
pxScrollHeight: this.el.scrollHeight,
});
},
};
9 changes: 9 additions & 0 deletions assets/js/hooks/textarea_focus.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/**
* Autofocuses on the textarea that the hook is applied to.
* Just a client-side shortcut.
* */
export default TextareaFocus = {
mounted() {
this.el.focus();
},
};
7 changes: 6 additions & 1 deletion assets/tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
const plugin = require("tailwindcss/plugin");
const fs = require("fs");
const path = require("path");
// const colors = require("./colors"); // QQ: @ks0m1c_dharma any idea why if i uncomment this, the tailwind plugin config gets broken?
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FIXME odd tailwind config issue:

So after the annoyance about using css variables to define other css variables and how even after doing the hsl syntax, when using them in tailwind utility classes, it wasn’t possible to add opacity classes to it,
here’s a related gh comment for it

I decided to try using an external colors.js so that I can make my best friend, JS, do the magic.

Turns out this breaks the tailwindconfig file and some other import doesn’t get its name resolved. I have no idea why, let me know if you know this.

    Rebuilding...
    Error: Cannot find module 'tailwindcss/plugin'
    Require stack:
    - /Users/rtshkmr/Projects/vyasa/assets/tailwind.config.js
        at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
        at Function._resolveFilename (pkg/prelude/bootstrap.js:1955:46)
        at Function.resolve (node:internal/modules/cjs/helpers:108:19)
        at _resolve (/snapshot/tailwindcss/node_modules/jiti/dist/jiti.js:1:241025)
        at jiti (/snapshot/tailwindcss/node_modules/jiti/dist/jiti.js:1:243309)
        at /Users/rtshkmr/Projects/vyasa/assets/tailwind.config.js:4:16
        at jiti (/snapshot/tailwindcss/node_modules/jiti/dist/jiti.js:1:245784)
        at /snapshot/tailwindcss/lib/lib/load-config.js:37:30
        at loadConfig (/snapshot/tailwindcss/lib/lib/load-config.js:39:6)
        at Object.loadConfig (/snapshot/tailwindcss/lib/cli/build/plugin.js:135:49) {
      code: 'MODULE_NOT_FOUND',
      requireStack: [ '/Users/rtshkmr/Projects/vyasa/assets/tailwind.config.js' ]
    }

Using JS might be more convenient.
perhaps this functional fetching of colors might make work as seen here?
I’m going to side-step this for now.


module.exports = {
content: [
Expand Down Expand Up @@ -49,19 +50,23 @@ module.exports = {
xs: "0.65rem",
},
colors: {
aerospaceOrange: "hsla(30, 100%, 50%, 1)",
primary: "var(--color-primary)",
ink: "#1E1024",
primaryAccent: "var(--color-primary-accent)",
secondary: "var(--color-secondary)",
primaryBackground: "var(--color-primary-background)",
secondary: "var(--color-secondary)",
secondaryBackground: "var(--color-secondary-background)",
brand: "var(--color-brand)",
brandLight: "var(--color-brand-light)",
brandExtraLight: "var(--color-brand-extra-light)",
brandAccent: "var(--color-brand-accent)",
brandAccentLight: "var(--color-brand-accent-light)",
brandDark: "var(--color-brand-dark)",
brandExtraDark: "var(--color-brand-extra-dark)",
// Additional colors from your palette
dun: "var(--dun)",
bloodRed: "var(--blood-red)",
},
},
},
Expand Down
3 changes: 3 additions & 0 deletions assets/vendor/customicons/icon-game-icons-portal.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading