+
+
+
+
+
+Styleguide Components.Callout
+*/
+@import url("_imports/tools/media-queries.css");
+@import url("_imports/tools/x-article-link.css");
+
+
+
+
+
+/* Layout */
+
+.c-callout {
+ display: grid;
+}
+.c-callout--has-figure {
+ /* See @media queries */
+}
+.c-callout:not(.c-callout--has-figure) {
+ grid-template-areas:
+ 'title'
+ 'desc';
+}
+.c-callout__figure { grid-area: figure; }
+.c-callout__title { grid-area: title; }
+.c-callout__desc { grid-area: desc; }
+
+@media only screen and (--narrow-and-above) {
+ .c-callout {
+ padding: 20px;
+ text-align: left;
+ }
+ .c-callout--has-figure {
+ grid-template-rows: auto 1fr;
+ grid-template-columns: auto 1fr;
+ grid-template-areas:
+ 'figure title'
+ 'figure desc';
+
+ column-gap: 40px;
+ }
+ .c-callout__figure { margin: 0; /* override Bootstrap */ }
+}
+
+@media only screen and (--narrow-and-below) {
+ .c-callout {
+ padding: 20px 40px;
+ text-align: center;
+ }
+ .c-callout--has-figure {
+ grid-template-areas:
+ 'figure'
+ 'title'
+ 'desc';
+
+ column-gap: 0px;
+ }
+ .c-callout__figure { margin: 0 0 20px; /* override Bootstrap */ }
+
+ /* To "disable" image resize */
+ .c-callout__figure[data-transform],
+ .c-callout__figure[data-transform] img {
+ height: unset !important; /* overwrite inline style tag (via JavaScript) */
+ }
+}
+
+/* To align figure to exact center */
+.c-callout__figure {
+ place-self: center;
+}
+/* To fit (expected) figure content to available horizontal space */
+.c-callout__figure img {
+ max-width: 100%;
+}
+
+/* To force wrap before full width (to match design) */
+/* NOTE: 1200px window, design has 15px but this was 7px (wraps the same) */
+/* FAQ: Differ from design so narrow screen wrap limit is not noticeable */
+.c-callout__desc { padding-right: 1%; }
+
+
+
+
+
+/* Style */
+
+.c-callout {
+ /* HELP: Should this color change if it is in a dark `o-section`? */
+ /* SEE: https://confluence.tacc.utexas.edu/x/DyUFDg */
+ background-color: var(--global-color-link-on-light--normal);
+}
+
+.c-callout__title {
+ padding-bottom: 12px;
+ margin-bottom: 12px;
+ border-bottom: 1px solid var(--global-color-primary--xx-light);
+
+ font-size: var(--global-font-size--x-large);
+ font-weight: var(--medium);
+ color: var(--global-color-primary--xx-light); /* override `html-elements` */
+}
+.c-callout__desc {
+ font-size: var(--global-font-size--large);
+ font-weight: var(--medium);
+ color: var(--global-color-primary--xx-light);
+}
+
+
+
+
+
+/* Link */
+
+.c-callout--is-link:hover {
+ text-decoration: none;
+}
+
+/* To expand link to cover its container */
+.c-callout--is-link::before { @extend %x-article-link-stretch; content: ''; }
+
+/* To give feedback on link hover and click */
+.c-callout--is-link:hover::before,
+.c-callout--is-link:active::before { outline-offset: 1rem; }
+.c-callout--is-link:hover::before { @extend %x-article-link-hover; }
+.c-callout--is-link:active::before { @extend %x-article-link-active; }
diff --git a/taccsite_cms/static/site_cms/css/src/_imports/tools/x-article-link.css b/taccsite_cms/static/site_cms/css/src/_imports/tools/x-article-link.css
index 85a1f2039..3720f2113 100644
--- a/taccsite_cms/static/site_cms/css/src/_imports/tools/x-article-link.css
+++ b/taccsite_cms/static/site_cms/css/src/_imports/tools/x-article-link.css
@@ -7,13 +7,14 @@ Styles that allow visible link hover for article lists.
%x-article-link-stretch--gapless - Make link box fix gapless layout
%x-article-link-hover - Give link a hover state
%x-article-link-hover--gapless - Make link hover state fix gapless layout
+%x-article-link-active - Give link an active (click, enter) state
Styleguide Tools.ExtendsAndMixins.ArticleLink
*/
/* WARNING: A link ancestor must have its `position` set (not to static) */
-/* Expand link to cover container */
+/* To expand link to cover container */
.x-article-link-stretch,
%x-article-link-stretch {
position: absolute;
@@ -33,7 +34,7 @@ Styleguide Tools.ExtendsAndMixins.ArticleLink
left: -15px;
}
-/* Give link state (pseudo-class) feedback */
+/* To give link state (pseudo-class) feedback */
.x-article-link-hover,
%x-article-link-hover {
outline: 1px solid var(--global-color-accent--normal);
@@ -44,3 +45,8 @@ Styleguide Tools.ExtendsAndMixins.ArticleLink
%x-article-link-hover--gapless {
outline-offset: 0;
}
+
+/* To give link active state feedback */
+%x-article-link-active {
+ outline: 1px dotted var(--global-color-accent--normal);
+}
diff --git a/taccsite_cms/static/site_cms/css/src/site.css b/taccsite_cms/static/site_cms/css/src/site.css
index 03103175e..c9318e035 100644
--- a/taccsite_cms/static/site_cms/css/src/site.css
+++ b/taccsite_cms/static/site_cms/css/src/site.css
@@ -27,6 +27,7 @@
/* COMPONENTS */
/* GH-302: HELP: How should all of these become individually built files? */
/* GH-302: FAQ: Individually built stylesheets could be loaded explicitely. */
+@import url("_imports/components/c-callout.css");
@import url("_imports/components/c-data-list.css");
@import url("_imports/components/c-footer.css");
@import url("_imports/components/c-see-all-link.css");
diff --git a/taccsite_cms/static/site_cms/js/modules/elementTransformer.js b/taccsite_cms/static/site_cms/js/modules/elementTransformer.js
new file mode 100644
index 000000000..c5897d094
--- /dev/null
+++ b/taccsite_cms/static/site_cms/js/modules/elementTransformer.js
@@ -0,0 +1,100 @@
+/**
+ * Transform elements (when CSS cannot)
+ *
+ * - Manipulates attributes within existing markup.
+ * - Transformations are NOT dynamically updated after initial load.
+ *
+ * This is a back-up solution. Try using CSS to solve the problem first.
+ * @module elementTransformer
+ */
+
+/** Resize first child element to match parent height (track state in markup) */
+export class SizeContentToFit {
+
+
+
+ // FAQ: Offers clarity of intent and consistency with state attr.
+ // NOTE: Could faciliate programmatic transforms (like as a plugin option)
+ /** A suggested selector to match the container */
+ static containerSelector = '[data-transform="size-content-to-fit"]';
+
+
+
+ /**
+ * Initialize and resize
+ * @param {HTMLElement} container - The direct parent of the content to resize
+ */
+ constructor (container) {
+ /** The `HTMLElement` containing the content to resize */
+ this.container = container;
+ /** The `HTMLElement` to resize */
+ this.content = container.querySelector(':scope > *');
+
+ // GH-320: Test whether `this.content` was in the DOM at runtime
+ // FAQ: Use `cloneNode` to NOT watch element reference that is updated later
+ // console.log({
+ // container: this.container.cloneNode(true),
+ // content: this.content.cloneNode(true)
+ // });
+
+ this.resizeContent();
+ }
+
+
+
+ /** Mark transformation as in the given state */
+ setState(state) {
+ this.container.dataset.transformState = state;
+ }
+
+ /** Mark transformation as NOT in the given state */
+ removeState(state) {
+ // NOTE: Multiple states are not supported, so there is no use for `state`
+ this.container.dataset.transformState = null;
+ }
+
+ /** Whether transformation is in the given state */
+ isState(state) {
+ return (this.container.dataset.transformState === state);
+ }
+
+ /** Whether to resize the content */
+ shouldResizeContent() {
+ if (this.container.getAttribute('hidden') !== null) {
+ this.content.style.offsetHeight = '0';
+ this.container.removeAttribute('hidden');
+ }
+ }
+
+
+ /** Resize the content */
+ resizeContent() {
+ /* To prevent natural height of content from increasing container height */
+ /* FAQ: Script will set wrong height if content is taller than is desired */
+ if (this.container.getAttribute('hidden') !== null) {
+ this.content.style.height = '0';
+ this.container.removeAttribute('hidden');
+ }
+
+ /* To inform observers that this transformation is active */
+ this.setState('resizing-content');
+
+ /* To make container (and its content) the same height as a root element */
+ /* FAQ: With tall content… container height = excessive content height */
+ /* FAQ: With hidden content… container height = desired content height */
+ this.container.style.height = '100%';
+ this.content.style.height = this.container.offsetHeight + 'px';
+ this.container.style.height = null;
+
+ /* To clean up mess (only if it appears to be the mess of this script) */
+ if (this.isState('resizing-content')) {
+ this.removeState('resizing-content');
+ if (this.container.getAttribute('style') === '') {
+ this.container.removeAttribute('style');
+ }
+ }
+
+ /* To inform observers that this module is done */
+ this.setState('complete');
+ }
+}