Skip to content

Commit

Permalink
feat: scope dist to index.ts file + add some demo code
Browse files Browse the repository at this point in the history
  • Loading branch information
essejmclean committed Oct 25, 2023
1 parent 5441e13 commit b8b007f
Show file tree
Hide file tree
Showing 6 changed files with 243 additions and 11 deletions.
24 changes: 14 additions & 10 deletions demo/src/app.tsx
Original file line number Diff line number Diff line change
@@ -1,23 +1,27 @@
import { Container } from "./container";
import { LayoutOverlay } from "./layout-overlay";

export function App() {
return (
<>
<div className="container">
<div className="w-10-cols bg-blue-500/10">
<p>Test</p>
<div className="w-5-cols bg-blue-500/10">
<main className="py-20">
<div className="container">
<div className="w-10-cols bg-blue-500/20">
<p>Test</p>
<div className="w-5-cols bg-blue-500/20">
<p>Test</p>
</div>
</div>
</div>
<div className="w-6-cols bg-blue-500/10">
<p>Test</p>
<div className="w-1/2-cols bg-blue-500/10">
<div className="w-6-cols bg-blue-500/20">
<p>Test</p>
<div className="w-1/2-cols bg-blue-500/20">
<p>Test</p>
</div>
</div>
<div className="breakout bg-blue-500/20">Breakout</div>
</div>
<div className="breakout bg-blue-500/10">Breakout</div>
</div>
<Container />
</main>
<LayoutOverlay />
</>
);
Expand Down
119 changes: 119 additions & 0 deletions demo/src/container.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
export function Container() {
return (
<div>
<div className="container prose max-w-none">
<h1>Container</h1>
<h2 id="description">Description</h2>
<p>
By default all components render across the full width of the
viewport. You can use the <code>.container</code> class to create a
contained layout. The container class uses the values set in{" "}
<code>outerGutters</code> and <code>containerWidths</code> in your{" "}
<code>tailwind.config.js</code> to create a responsive container.
</p>
<p>
Note that the default Tailwind container plugin will need to be
disabled.
</p>
<p>
Also includes a <code>.breakout</code> class to allow full 100vw
elements inside a container.
</p>
<ul>
<li>
<code>.container</code> makes a container that conforms to your{" "}
<code>theme.containerWidths</code> taking into account your{" "}
<code>theme.outerGutters</code>
</li>
<li>
<code>.breakout</code> breaks out of a <code>.container</code>, to
make your element <code>100vw</code> wide
</li>
<li>
<code>.container-reset</code> resets a <code>.container</code>
</li>
<li>
<code>.breakout-reset</code> resets a <code>.breakout</code>
</li>
</ul>

<h2 id="demo">Demo</h2>

<h3 id="container">Container</h3>

<p>
This site has its content wrapped in{" "}
<code>{`<div class="container">`}</code>. You'll see it is fluid with
outer margins set to the
<code>outerGutters</code> for each breakpoint. At then, when the
window is wider than 1536px wide (<code>theme.screens.2xl</code>) the
main column is a fixed width of 960px (
<code>theme.containerWidths.2xl</code>) and centered within the
window.
</p>

<h4 id="container-nesting">Container nesting</h4>

<div className="container bg-blue-600/20 mt-5 py-5">
<div className="container bg-blue-600/20 py-5">
<p>
<code>{`.container > .container > .container`}</code>
</p>
</div>
</div>

<div>
<figure>
<figcaption>document.html</figcaption>
<pre>
<code>
{`<div class="container">
<div class="container">
...
</div>
</div>
`}
</code>
</pre>
</figure>

<p>
Nesting of <code>.container</code> inside of <code>.breakout</code>,{" "}
<code>.breakout-reset</code> and <code>.container-reset</code>{" "}
should{" "}
<a href="./container-nesting-tests.html">all work as expected</a>.
</p>

<h3 id="container_reset">Container Reset</h3>

<p>
Instead of wrapping all your pages in <code>.container</code>,
perhaps you wrap each of your components, and then perhaps at some
breakpoint you want go full bleed. In which case{" "}
<code>.container-reset</code> will be useful. Here, at the{" "}
<code>lg</code> breakpoint, a <code>.container</code> resets to full
bleed:
</p>
</div>
</div>
<div className="container lg:container-reset mt-5 bg-blue-600/20 p-5">
<p>...</p>
</div>
<div className="container prose max-w-none">
<div>
<figure>
<figcaption>document.html</figcaption>
<pre>
<code>
{`<div class="container lg:container-reset">
...
</div>
`}
</code>
</pre>
</figure>
</div>
</div>
</div>
);
}
6 changes: 6 additions & 0 deletions demo/src/index.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

@layer base {
html {
overflow-x: hidden;
}
}
1 change: 1 addition & 0 deletions demo/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import "./index.css";
import "./scrollbar-visible-width";

import React from "react";
import ReactDOM from "react-dom/client";
Expand Down
102 changes: 102 additions & 0 deletions demo/src/scrollbar-visible-width.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/**
* This is an Immediately Invoked Function Expression (IIFE).
* It's a good way to isolate variables declarations.
* The JavaScript parser runs this function as soon as it encounters it in the script.
*/
(function () {
/**
* Type definition for a callback function.
* The function can accept any number of arguments of any type.
*/
type Callback = (...args: unknown[]) => void;

/**
* Creates a throttled version of a function that only invokes the provided function at most once every `limit` milliseconds.
*
* @param func - The function to throttle.
* @param limit - The number of milliseconds to wait before invoking the function again.
* @returns A new, throttled function.
*/
function throttle(func: Callback, limit: number): Callback {
// Store the ID of the timeout between function calls
let lastFunc: ReturnType<typeof setTimeout> | undefined;
// Store the timestamp of the last time the function was invoked
let lastRan: number | undefined;

// Return a new function that controls when `func` gets called
return (...args: unknown[]) => {
// If `func` hasn't been called yet, call it and record the call time
if (!lastRan) {
func(...args);
lastRan = Date.now();
} else {
// If `func` has been called before, clear the previous timeout and set a new one
if (lastFunc) clearTimeout(lastFunc);

lastFunc = setTimeout(() => {
// If the specified `limit` has passed since the last call to `func`, call `func` again and record the call time
if (Date.now() - (lastRan as number) >= limit) {
func(...args);
lastRan = Date.now();
}
}, limit - (Date.now() - (lastRan as number)));
}
};
}

/**
* Creates a div element, sets its overflow to scroll, appends it to the body,
* calculates the width of the scrollbar by subtracting the clientWidth from the offsetWidth of the div,
* removes the div from the body, and finally returns the calculated scrollbar width.
*
* @returns {number} The width of the scrollbar.
*/
function getScrollBarWidth(): number {
// Create a new div element
const scrollBox = document.createElement("div");
// Make it scrollable
scrollBox.style.overflow = "scroll";
// Add it to the body of the document
document.body.appendChild(scrollBox);
// Calculate the width of the scrollbar
const scrollBarWidth = scrollBox.offsetWidth - scrollBox.clientWidth;
// Remove the div from the body
document.body.removeChild(scrollBox);
// Return the width of the scrollbar
return scrollBarWidth;
}

/**
* Calculates the width of the scrollbar and sets it to a CSS variable.
* It also listens to the window's load and resize events to adjust the scrollbar width accordingly.
*
* @function setScrollBarVisible
* @returns {void}
*/
function setScrollBarVisible(): void {
// Get the width of the scrollbar
const scrollBarWidth = getScrollBarWidth();
// Check if the scrollbar is visible
const scrollBarVisible =
document.documentElement.scrollHeight >
document.documentElement.clientHeight;
// Check if the overflow-y property is set to scroll
const overflowYSet =
window
.getComputedStyle(document.documentElement, null)
.getPropertyValue("overflow-y") === "scroll";
// Set the CSS variable --scrollbar-visible-width to the width of the scrollbar if it's visible, or 0px if it's not
document.documentElement.style.setProperty(
"--scrollbar-visible-width",
`${scrollBarVisible || overflowYSet ? scrollBarWidth : 0}px`
);
}

// Throttled version of setScrollBarVisible
const throttledSetScrollBarVisible = throttle(setScrollBarVisible, 200);

// Call the setScrollBarVisible function when the window is loaded
window.addEventListener("load", throttledSetScrollBarVisible);
// Call the setScrollBarVisible function when the window is resized
window.addEventListener("resize", throttledSetScrollBarVisible);
})();
2 changes: 1 addition & 1 deletion plugin/tsup.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ export default defineConfig({
watch: env === "development",
target: "es2020",
outDir: "dist",
entry: ["src/**/*.ts"], //include all files under src
entry: ["src/index.ts"], //include all files under src
});

0 comments on commit b8b007f

Please sign in to comment.