From 72c4fd277983c9ebb25aeadcee25ba0e64d7d114 Mon Sep 17 00:00:00 2001 From: Dan Cormier Date: Mon, 23 Feb 2026 19:02:04 -0500 Subject: [PATCH 01/10] chore: remove cruft left over from removing components --- .../breadcrumbs/breadcrumbs.a11y.test.ts | 36 -- .../components/breadcrumbs/breadcrumbs.less | 41 --- .../breadcrumbs/breadcrumbs.visual.test.ts | 36 -- .../button-group/button-group.a11y.test.ts | 12 - .../components/button-group/button-group.less | 82 ----- .../button-group/button-group.test.setup.ts | 77 ---- .../button-group/button-group.visual.test.ts | 7 - .../expandable/expandable.a11y.test.ts | 26 -- .../lib/components/expandable/expandable.less | 119 ------ .../components/expandable/expandable.test.ts | 51 --- .../lib/components/expandable/expandable.ts | 238 ------------ .../expandable/expandable.visual.test.ts | 26 -- .../link-preview/link-preview.a11y.test.ts | 47 --- .../components/link-preview/link-preview.less | 140 ------- .../link-preview/link-preview.visual.test.ts | 52 --- .../page-title/page-title.a11y.test.ts | 28 -- .../lib/components/page-title/page-title.less | 51 --- .../page-title/page-title.visual.test.ts | 58 --- .../progress-bar/progress-bar.a11y.test.ts | 189 ---------- .../components/progress-bar/progress-bar.less | 292 --------------- .../progress-bar/progress-bar.visual.test.ts | 188 ---------- .../lib/components/uploader/uploader.less | 205 ----------- .../lib/components/uploader/uploader.ts | 207 ----------- packages/stacks-docs/.eleventy.js | 1 + .../_data/components/breadcrumbs.json | 23 -- .../_data/components/button-groups.json | 32 -- .../stacks-docs/_data/components/cards.json | 13 - .../_data/components/expandable.json | 18 - .../_data/components/link-previews.json | 81 ---- .../_data/components/page-titles.json | 32 -- .../_data/components/progress-bars.json | 120 ------ .../stacks-docs/_data/components/topbar.json | 78 ---- .../_data/components/uploader.json | 105 ------ .../stacks-docs/_data/site-navigation.json | 108 ++---- .../stacks-docs/_includes/layouts/page.html | 12 +- .../_includes/layouts/removed.html | 68 ++++ .../assets/less/stacks-documentation.less | 7 - .../product/components/breadcrumbs.html | 146 +------- .../product/components/button-groups.html | 223 +---------- .../stacks-docs/product/components/cards.html | 176 +-------- .../product/components/expandable.html | 170 +-------- .../product/components/link-previews.html | 221 +---------- .../product/components/page-titles.html | 118 +----- .../product/components/popovers.html | 8 +- .../product/components/progress-bars.html | 346 +----------------- .../product/components/tables.html | 128 +------ .../product/components/topbar.html | 198 +--------- .../product/components/uploader.html | 206 +---------- 48 files changed, 119 insertions(+), 4727 deletions(-) delete mode 100644 packages/stacks-classic/lib/components/breadcrumbs/breadcrumbs.a11y.test.ts delete mode 100644 packages/stacks-classic/lib/components/breadcrumbs/breadcrumbs.less delete mode 100644 packages/stacks-classic/lib/components/breadcrumbs/breadcrumbs.visual.test.ts delete mode 100644 packages/stacks-classic/lib/components/button-group/button-group.a11y.test.ts delete mode 100644 packages/stacks-classic/lib/components/button-group/button-group.less delete mode 100644 packages/stacks-classic/lib/components/button-group/button-group.test.setup.ts delete mode 100644 packages/stacks-classic/lib/components/button-group/button-group.visual.test.ts delete mode 100644 packages/stacks-classic/lib/components/expandable/expandable.a11y.test.ts delete mode 100644 packages/stacks-classic/lib/components/expandable/expandable.less delete mode 100644 packages/stacks-classic/lib/components/expandable/expandable.test.ts delete mode 100644 packages/stacks-classic/lib/components/expandable/expandable.ts delete mode 100644 packages/stacks-classic/lib/components/expandable/expandable.visual.test.ts delete mode 100644 packages/stacks-classic/lib/components/link-preview/link-preview.a11y.test.ts delete mode 100644 packages/stacks-classic/lib/components/link-preview/link-preview.less delete mode 100644 packages/stacks-classic/lib/components/link-preview/link-preview.visual.test.ts delete mode 100644 packages/stacks-classic/lib/components/page-title/page-title.a11y.test.ts delete mode 100644 packages/stacks-classic/lib/components/page-title/page-title.less delete mode 100644 packages/stacks-classic/lib/components/page-title/page-title.visual.test.ts delete mode 100644 packages/stacks-classic/lib/components/progress-bar/progress-bar.a11y.test.ts delete mode 100644 packages/stacks-classic/lib/components/progress-bar/progress-bar.less delete mode 100644 packages/stacks-classic/lib/components/progress-bar/progress-bar.visual.test.ts delete mode 100644 packages/stacks-classic/lib/components/uploader/uploader.less delete mode 100644 packages/stacks-classic/lib/components/uploader/uploader.ts delete mode 100644 packages/stacks-docs/_data/components/breadcrumbs.json delete mode 100644 packages/stacks-docs/_data/components/button-groups.json delete mode 100644 packages/stacks-docs/_data/components/cards.json delete mode 100644 packages/stacks-docs/_data/components/expandable.json delete mode 100644 packages/stacks-docs/_data/components/link-previews.json delete mode 100644 packages/stacks-docs/_data/components/page-titles.json delete mode 100644 packages/stacks-docs/_data/components/progress-bars.json delete mode 100644 packages/stacks-docs/_data/components/topbar.json delete mode 100644 packages/stacks-docs/_data/components/uploader.json create mode 100644 packages/stacks-docs/_includes/layouts/removed.html diff --git a/packages/stacks-classic/lib/components/breadcrumbs/breadcrumbs.a11y.test.ts b/packages/stacks-classic/lib/components/breadcrumbs/breadcrumbs.a11y.test.ts deleted file mode 100644 index e7b63b3b31..0000000000 --- a/packages/stacks-classic/lib/components/breadcrumbs/breadcrumbs.a11y.test.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { runA11yTests } from "../../test/a11y-test-utils"; -import { html } from "@open-wc/testing"; -import "../../index"; - -describe.skip("breadcrumbs", () => { - runA11yTests({ - baseClass: "s-breadcrumbs", - children: { - default: ` -
- Stacks - -
-
- Help center - -
-
- Icons -
- `, - }, - attributes: { - "aria-label": "Breadcrumb navigation", - }, - tag: "nav", - template: ({ component, testid }) => html` -
- ${component} -
- `, - }); -}); diff --git a/packages/stacks-classic/lib/components/breadcrumbs/breadcrumbs.less b/packages/stacks-classic/lib/components/breadcrumbs/breadcrumbs.less deleted file mode 100644 index 48c1f2bbb2..0000000000 --- a/packages/stacks-classic/lib/components/breadcrumbs/breadcrumbs.less +++ /dev/null @@ -1,41 +0,0 @@ -.s-breadcrumbs { - --_br-divider-px: var(--su4); - --_br-link-fc: var(--fc-light); - - // CONTEXTUAL STYLES - #stacks-internals #screen-sm({ - --_br-divider-px: var(--su2); - }); - - // CHILD ELEMENTS - & &--divider { - .highcontrast-mode({ - color: var(--fc-light); - }); - - margin-left: var(--_br-divider-px); - margin-right: var(--_br-divider-px); - } - - & &--item { - align-items: center; - display: flex; - flex-wrap: nowrap; - margin-bottom: var(--su2); - margin-top: var(--su2); - } - - & &--link { - color: var(--_br-link-fc); - - &:hover { - --_br-link-fc: var(--fc-medium); - } - } - - align-items: flex-start; - color: var(--black-300); - display: flex; - flex-wrap: wrap; - font-size: var(--fs-caption); -} diff --git a/packages/stacks-classic/lib/components/breadcrumbs/breadcrumbs.visual.test.ts b/packages/stacks-classic/lib/components/breadcrumbs/breadcrumbs.visual.test.ts deleted file mode 100644 index 00363a4f0a..0000000000 --- a/packages/stacks-classic/lib/components/breadcrumbs/breadcrumbs.visual.test.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { runVisualTests } from "../../test/visual-test-utils"; -import { html } from "@open-wc/testing"; -import "../../index"; - -describe.skip("breadcrumbs", () => { - runVisualTests({ - baseClass: "s-breadcrumbs", - children: { - default: ` -
- Stacks - -
-
- Help center - -
-
- Icons -
- `, - }, - attributes: { - "aria-label": "Breadcrumb navigation", - }, - tag: "nav", - template: ({ component, testid }) => html` -
- ${component} -
- `, - }); -}); diff --git a/packages/stacks-classic/lib/components/button-group/button-group.a11y.test.ts b/packages/stacks-classic/lib/components/button-group/button-group.a11y.test.ts deleted file mode 100644 index 9b1703204e..0000000000 --- a/packages/stacks-classic/lib/components/button-group/button-group.a11y.test.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { testArgs } from "./button-group.test.setup"; -import { runA11yTests } from "../../test/a11y-test-utils"; -import "../../index"; - -describe.skip("button group", () => { - runA11yTests({ - ...testArgs, - // TODO remove skipped tests once btn badge contrast issues are resolved - // see also https://github.com/StackExchange/Stacks/pull/1663 - skippedTestids: [/s-btn-group-(light|dark|highcontrast-light)-badge/], - }); -}); diff --git a/packages/stacks-classic/lib/components/button-group/button-group.less b/packages/stacks-classic/lib/components/button-group/button-group.less deleted file mode 100644 index 62e050bc87..0000000000 --- a/packages/stacks-classic/lib/components/button-group/button-group.less +++ /dev/null @@ -1,82 +0,0 @@ -.s-btn-group { - // CONTEXTUAL STYLES - #stacks-internals #screen-sm({ - .s-btn { - --_bu-px: 0.4em; - - &.s-btn__dropdown { - padding-right: 1.2em; - - &:after { - right: var(--_bu-px); - } - } - } - }, @force-selector: true); - - // CHILD ELEMENTS - form { - display: flex; - margin-right: var(--sun1); - } - - // --_bu-py values set below to ensure btn-group height matches same-sized button height - // See https://github.com/StackEng/StackOverflow/pull/18992#pullrequestreview-1947490680 - .s-btn { - --_bu-br: var(--br-md); - --_bu-bc-hover: transparent; - --_bu-px: calc(var(--su12) - var(--su1)); // 11px - --_bu-py: calc(var(--su6) + 0.65px); // 6.65px - - &.s-btn__xs { - --_bu-px: calc(var(--su8) - var(--su1)); // 7px - --_bu-py: calc(var(--su2) + 0.9px); // 2.9px - } - - &.s-btn__sm { - --_bu-px: calc(var(--su8) + var(--su1)); // 9px - --_bu-py: calc(var(--su4) + (var(--su2) - 0.15px)); // 5.85px - } - - &.s-btn__md { - --_bu-px: var(--su12); - --_bu-py: calc(var(--su8) + 0.15px); // 8.15px - } - - &.is-selected, - &--radio:checked + .s-btn { - font-weight: bold; - } - - .s-btn--badge { - // set negative margins so button height isn't affect by badge - margin-bottom: -100%; - margin-top: -100%; - font-weight: normal; - } - - & .s-btn--text { - &:before { - content: attr(data-text); - font-weight: bold; - height: 0; - pointer-events: none; - user-select: none; - visibility: hidden; - } - - display: inline-flex; - flex-direction: column; - } - - font-weight: 400; - white-space: nowrap; // When the buttons wrap, they get super tall and mess up the whole layout - } - - // STATIC COMPONENT STYLES - border: var(--su1) solid var(--black-300); - border-radius: var(--br-md); - display: inline-flex; - flex-wrap: wrap; - padding: var(--su3); -} diff --git a/packages/stacks-classic/lib/components/button-group/button-group.test.setup.ts b/packages/stacks-classic/lib/components/button-group/button-group.test.setup.ts deleted file mode 100644 index 698cfa078c..0000000000 --- a/packages/stacks-classic/lib/components/button-group/button-group.test.setup.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { html } from "@open-wc/testing"; -import type { TestVariationArgs } from "../../test/test-utils"; - -const btns = [ - { name: "Newest", isSelected: true }, - { name: "Frequent" }, - { name: "Active" }, -]; - -const getBtn = ({ - name = "", - isRadio, - isSelected, - hasBadge, -}: { - name: string; - isRadio?: boolean; - isSelected?: boolean; - hasBadge?: boolean; -}): string => { - const baseClasses = "s-btn s-btn__tonal"; - const btnChildren = ` - ${name} - ${ - hasBadge - ? `123` - : "" - } - `; - - return isRadio - ? ` - ` - : ``; -}; - -const getBtns = (ids: number[]): string => { - return ids.map((id) => getBtn(btns[id])).join(""); -}; - -const testArgs: TestVariationArgs = { - baseClass: "s-btn-group", - children: { - default: getBtns([0, 1, 2]), - single: getBtns([0]), - form: ` - ${getBtns([0])} -
- ${getBtn(btns[1])} -
- ${getBtns([2])} - `, - badge: btns.map((btn) => getBtn({ ...btn, hasBadge: true })).join(""), - radio: btns.map((btn) => getBtn({ ...btn, isRadio: true })).join(""), - }, - template: ({ component, testid }) => - html`
- ${component} -
`, -}; - -export { testArgs }; diff --git a/packages/stacks-classic/lib/components/button-group/button-group.visual.test.ts b/packages/stacks-classic/lib/components/button-group/button-group.visual.test.ts deleted file mode 100644 index 14262759bc..0000000000 --- a/packages/stacks-classic/lib/components/button-group/button-group.visual.test.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { testArgs } from "./button-group.test.setup"; -import { runVisualTests } from "../../test/visual-test-utils"; -import "../../index"; - -describe.skip("button group", () => { - runVisualTests(testArgs); -}); diff --git a/packages/stacks-classic/lib/components/expandable/expandable.a11y.test.ts b/packages/stacks-classic/lib/components/expandable/expandable.a11y.test.ts deleted file mode 100644 index 46aaa5f389..0000000000 --- a/packages/stacks-classic/lib/components/expandable/expandable.a11y.test.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { html } from "@open-wc/testing"; -import { runA11yTests } from "../../test/a11y-test-utils"; -import "../../index"; - -describe.skip("expandable", () => { - runA11yTests({ - baseClass: "s-expandable", - modifiers: { - global: ["is-expanded"], - }, - children: { - default: ` -
-

Expandable: Lorem ipsum dolor sit amet, ex iudicabit necessitatibus usu, cetero laboramus concludaturque mel no, facilisis posidonium cu cum. Pro ex senserit dissentiunt, imperdiet intellegam at sed, ex pri dicit eruditi convenire. Est harum movet gubergren ei, errem dictas evertitur ea sit, at mei oratio eligendi. Ad vis legere possit, vis ne ipsum democritum appellantur. Nullam ancillae iudicabit his ad.

-
- `, - }, - template: ({ component, testid }) => html` -
-

Before expandable content

- ${component} -

After expandable content

-
- `, - }); -}); diff --git a/packages/stacks-classic/lib/components/expandable/expandable.less b/packages/stacks-classic/lib/components/expandable/expandable.less deleted file mode 100644 index 10c77f5d40..0000000000 --- a/packages/stacks-classic/lib/components/expandable/expandable.less +++ /dev/null @@ -1,119 +0,0 @@ -.s-expandable { // [1] - // COMPONENT-SPECIFIC CONSTANTS - @ex-clip-path: polygon(-1000000px -1000000px, 1000000px -1000000px, 1000000px 1000000px, -1000000px 1000000px); - @ex-min-expected-height: 10px; - @ex-transition-duration: 100ms; - // COMPONENT-SPECIFIC CUSTOM PROPERTIES - --_ex-after-h: 10px; - --_ex-after-hmx: 0; - --_ex-after-transition: - height @ex-transition-duration linear, - max-height 0s @ex-transition-duration linear; - --_ex-content-hmx: 1000000px; - --_ex-content-mb: 0; - --_ex-content-o: unset; - --_ex-content-transform: unset; - --_ex-content-transition: - margin-bottom @ex-transition-duration cubic-bezier(0, 0, 0, 1), - transform @ex-transition-duration cubic-bezier(1, 0, 1, 1), - opacity @ex-transition-duration cubic-bezier(1, 0, 1, 1); - --_ex-content-v: unset; - - &:not(.is-expanded) { - --_ex-after-h: 0; - --_ex-after-hmx: @ex-min-expected-height; - --_ex-after-transition: height @ex-min-expected-height linear; - --_ex-content-hmx: 0; - --_ex-content-mb: -1500px; - --_ex-content-o: 0; - --_ex-content-transform: scaleY(0); - --_ex-content-transition: - margin-bottom @ex-transition-duration cubic-bezier(1, 0, 1, 1), - visibility 0s @ex-transition-duration, - max-height 0s @ex-transition-duration, - transform @ex-transition-duration cubic-bezier(0, 1, 1, 1), - opacity @ex-transition-duration cubic-bezier(0, 1, 1, 1); - --_ex-content-v: hidden; - - & .s-expandable--content { - @supports ((-webkit-clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%)) or (clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%))) { - --_ex-content-o: 0; - --_ex-content-transform: none; - } - } - - -webkit-clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%); - clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%); - overflow: hidden; - transition: none; - } - - &:after { - height: var(--_ex-after-h); - max-height: var(--_ex-after-hmx); - transition: var(--_ex-after-transition); - - -ms-flex-preferred-size: 0; - content: ''; - flex-basis: 0; - } - - & &--content { - max-height: var(--_ex-content-hmx); - margin-bottom: var(--_ex-content-mb); - opacity: var(--_ex-content-o); - -webkit-transform: var(--_ex-content-transform); - transform: var(--_ex-content-transform); - visibility: var(--_ex-content-v); - - -ms-flex-preferred-size: 100%; - flex-basis: 100%; - -webkit-transform-origin: 0 0; - transform-origin: 0 0; - transition: var(--_ex-content-transition); - } - - align-items: flex-start; // see comment above - display: flex; - -webkit-clip-path: @ex-clip-path; - clip-path: @ex-clip-path; - transition: clip-path 0s var(--_ex-transition-duration), -webkit-clip-path 0s var(--_ex-transition-duration); -} - -// [1] see http://stackoverflow.com/a/43965099 for how this works: - -// Notes on the clip-path stuff: What we would really like is overflow: hidden during the transition, -// but not when the element is expanded. Unfortunately, although the CSS spec provides for it, there's -// no browser support yet for transitioning non-interpolatable properties, and therefore we cannot say -// "change overflow to visible *after* the transition". -// -// So we use clip-path: polygon(0% 0%, 100% 0%, 100% 100%, 0% 100%), which is essentially the same -// as overflow: hidden, but unlike overflow, clip-path is interpolatable -- but only if the opposite state -// is also a polygon, and has the same vertice count. So our version of overflow: visible is a rectangle -// of 2x2 million pixels, which should be enough for everybody (TM). -// -// At the time of writing, clip-path works in Chrome, Firefox Beta, and Safari (with vendor prefix). -// -// In browsers that do not support this yet, we have to have another way to prevent the expandable content -// from being visible below the bottom edge during the transition, and the best I could come up with is -// transitioning to scaleY(0) with a timing function that's faster than the height-reducing transitions. -// This does kinda look like a deliberate effect, even more so if we also transition to transparency -// (which we therefore do), so I feel it's an okay fallback. -// -// We still set overflow to hidden in the collapsed state (which also applies to the collapsing transition), -// we just can't do that for the expanding transition. -// -// A major drawback of clip-path is that even though the content is clipped (not visible), it will still -// contribute to the document height. This caused a jumping around of the scrollbar (and possibly even -// of the viewport) when the expandable was at the bottom of the page, because once the negative bottom -// margin of the -expandable-group exceeds the actual height, any additional pixels were added on to the -// bottom. The fix is to set the -expandable-group's flex alignment to flex-start, which forces the -// (no longer visible) element itself to remain at the top, thereby forcing the excess pixels to be added -// above the top, not below the bottom. And because extending content above the document top will not do -// anything to the document height, there is no jumping during the transition. -// see "@ex-transition-duration" - -// Per the answer referenced above, the component can only guarantee smooth transitions if above a minimum -// height and can only guarantee the element will be hidden is below a maximimum height. -// The minimum height has been set at 10px because that's below the height of a single line of text in an s-description. -// see "@ex-min-expected-height" and "--_ex-content-mb" \ No newline at end of file diff --git a/packages/stacks-classic/lib/components/expandable/expandable.test.ts b/packages/stacks-classic/lib/components/expandable/expandable.test.ts deleted file mode 100644 index d3afa1e6b4..0000000000 --- a/packages/stacks-classic/lib/components/expandable/expandable.test.ts +++ /dev/null @@ -1,51 +0,0 @@ -import { html, fixture, expect } from "@open-wc/testing"; -import { screen } from "@testing-library/dom"; -import userEvent from "@testing-library/user-event"; -import "../../index"; - -const user = userEvent.setup(); - -describe.skip("expandable-control", () => { - it("should focus on expandable content only when expanded", async () => { - await fixture(html` - -
-
- -
-
- `); - - // expandable is not expanded - let expandableTrigger = screen.getByRole("button", { - name: "expandable trigger", - expanded: false, - }); - - expect( - screen.queryByRole("button", { - name: "inside expandable", - }) - ).to.be.null; - - await user.click(expandableTrigger); - - // expandable is now expanded - expandableTrigger = screen.getByRole("button", { - name: "expandable trigger", - expanded: true, - }); - - expect( - screen.getByRole("button", { - name: "inside expandable", - }) - ).to.be.visible; - }); -}); diff --git a/packages/stacks-classic/lib/components/expandable/expandable.ts b/packages/stacks-classic/lib/components/expandable/expandable.ts deleted file mode 100644 index 611fb19168..0000000000 --- a/packages/stacks-classic/lib/components/expandable/expandable.ts +++ /dev/null @@ -1,238 +0,0 @@ -import * as Stacks from "../../stacks"; - -// Radio buttons only trigger a change event when they're *checked*, but not when -// they're *unchecked*. Therefore, if we have an active `s-expandable-control` in -// the document, we listen for change events on *all* radio buttons and find any -// other radio buttons in the same `name` group, triggering a custom event on all -// of them so the controller can re-evaluate. -// -// We're keeping a count of how many of these controllers are connected to the DOM, -// so only have this global listener when we actually need it. -const RADIO_OFF_EVENT = "s-expandable-control:radio-off"; - -function globalChangeListener(e: UIEvent) { - const target = e.target; - if ( - !(target instanceof HTMLInputElement) || - target.nodeName !== "INPUT" || - target.type !== "radio" - ) { - return; - } - document - .querySelectorAll('input[type="radio"][name="' + target.name + '"]') - .forEach(function (other) { - if (other === e.target) { - return; - } - let customEvent; - try { - customEvent = new Event(RADIO_OFF_EVENT); - } catch { - // Internet Explorer - customEvent = document.createEvent("Event"); - customEvent.initEvent(RADIO_OFF_EVENT, true, true); - } - other.dispatchEvent(customEvent); - }); -} - -let refCount = 0; -function globalChangeListenerRequired(required: boolean) { - if (required) { - refCount++; - if (refCount === 1) { - document.body.addEventListener( - "change", - globalChangeListener as EventListener - ); - } - } else { - refCount--; - if (refCount === 0) { - document.body.removeEventListener( - "change", - globalChangeListener as EventListener - ); - } - } -} - -export class ExpandableController extends Stacks.StacksController { - private isCollapsed!: () => boolean; - private events!: string[]; - private isCheckable!: boolean; - private isRadio!: boolean; - private lastKeydownClickTimestamp = 0; - - initialize() { - if ( - this.element.nodeName === "INPUT" && - ["radio", "checkbox"].indexOf( - (this.element).type - ) >= 0 - ) { - this.isCollapsed = this._isCollapsedForCheckable.bind(this); - this.events = ["change", RADIO_OFF_EVENT]; - this.isCheckable = true; - this.isRadio = (this.element).type === "radio"; - } else { - this.isCollapsed = this._isCollapsedForClickable.bind(this); - this.events = ["click", "keydown"]; - } - this.listener = this.listener.bind(this); - } - - // for non-checkable elements, the initial source of truth is the collapsed/expanded - // state of the controlled element (unless the element doesn't exist) - _isCollapsedForClickable() { - const cc = this.controlledExpandables; - // the element is considered collapsed if *any* target element is collapsed - return cc.length > 0 - ? !cc.every((element) => element.classList.contains("is-expanded")) - : this.element.getAttribute("aria-expanded") === "false"; - } - - // for checkable elements, the initial source of truth is the checked state - _isCollapsedForCheckable() { - return !(this.element).checked; - } - - get controlledExpandables() { - const attr = this.element.getAttribute("aria-controls"); - if (!attr) { - throw `[aria-controls="targetId1 ... targetIdN"] attribute required`; - } - const result = attr - .split(/\s+/g) - .map((s) => document.getElementById(s)) - .filter((e): e is HTMLElement => !!e); - if (!result.length) { - throw "couldn't find controls"; - } - return result; - } - - _dispatchShowHideEvent(isShow: boolean) { - this.triggerEvent(isShow ? "show" : "hide"); - } - - _toggleClass(doAdd: boolean) { - if (!this.data.has("toggle-class")) { - return; - } - const cl = this.element.classList; - const toggleClass = this.data.get("toggle-class"); - if (!toggleClass) { - throw "couldn't find toggle class"; - } - toggleClass.split(/\s+/).forEach(function (cls) { - cl.toggle(cls, !!doAdd); - }); - } - - listener(e: Event) { - let newCollapsed; - if (this.isCheckable) { - newCollapsed = !(this.element).checked; - } else { - if ( - e.type == "keydown" && - e instanceof KeyboardEvent && - e.keyCode != 13 && - e.keyCode != 32 - ) { - return; - } - if ( - e.target !== e.currentTarget && - ["A", "BUTTON"].indexOf((e.target).nodeName) >= 0 - ) { - return; - } - - e.preventDefault(); - - // Prevent "click" events from toggling the expandable within 300ms of "keydown". - // e.preventDefault() should have done the same, but https://bugzilla.mozilla.org/show_bug.cgi?id=1487102 - // doesn't guarantee it. - if (e.type == "keydown") { - this.lastKeydownClickTimestamp = Date.now(); - } else if ( - e.type == "click" && - Date.now() - this.lastKeydownClickTimestamp < 300 - ) { - return; - } - newCollapsed = - this.element.getAttribute("aria-expanded") === "true"; - if (e.type === "click") { - (this.element).blur(); - } - } - this.element.setAttribute( - "aria-expanded", - newCollapsed ? "false" : "true" - ); - for (const controlledElement of this.controlledExpandables) { - controlledElement.classList.toggle("is-expanded", !newCollapsed); - } - this._dispatchShowHideEvent(!newCollapsed); - this._toggleClass(!newCollapsed); - } - - connect() { - this.events.forEach((e) => { - this.element.addEventListener(e, this.listener.bind(this)); - }, this); - - if (this.isRadio) { - globalChangeListenerRequired(true); - } - - // synchronize state -- in all cases, this means setting the correct `aria-expanded` - // attribute; for checkable controls this also means setting the `is-collapsed` class. - // Note: aria-expanded is currently an invalid attribute on radio elements - // Support for aria-expanded is being debated by the W3C https://github.com/w3c/aria/issues/1404 as recently as June 2022 - if (!this.isRadio) { - this.element.setAttribute( - "aria-expanded", - this.isCollapsed() ? "false" : "true" - ); - } - if (this.isCheckable) { - const cc = this.controlledExpandables; - if (cc.length) { - const expected = !this.isCollapsed(); - // if any element does not match the expected state, set them all to the expected state - if ( - cc.some( - (element) => - element.classList.contains("is-expanded") !== - expected - ) - ) { - for (const controlledElement of this - .controlledExpandables) { - controlledElement.classList.toggle( - "is-expanded", - expected - ); - } - this._dispatchShowHideEvent(expected); - this._toggleClass(expected); - } - } - } - } - - disconnect() { - this.events.forEach((e) => { - this.element.removeEventListener(e, this.listener.bind(this)); - }, this); - - if (this.isRadio) { - globalChangeListenerRequired(false); - } - } -} diff --git a/packages/stacks-classic/lib/components/expandable/expandable.visual.test.ts b/packages/stacks-classic/lib/components/expandable/expandable.visual.test.ts deleted file mode 100644 index 79b3fe5de8..0000000000 --- a/packages/stacks-classic/lib/components/expandable/expandable.visual.test.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { html } from "@open-wc/testing"; -import { runVisualTests } from "../../test/visual-test-utils"; -import "../../index"; - -describe.skip("expandable", () => { - runVisualTests({ - baseClass: "s-expandable", - modifiers: { - global: ["is-expanded"], - }, - children: { - default: ` -
-

Expandable: Lorem ipsum dolor sit amet, ex iudicabit necessitatibus usu, cetero laboramus concludaturque mel no, facilisis posidonium cu cum. Pro ex senserit dissentiunt, imperdiet intellegam at sed, ex pri dicit eruditi convenire. Est harum movet gubergren ei, errem dictas evertitur ea sit, at mei oratio eligendi. Ad vis legere possit, vis ne ipsum democritum appellantur. Nullam ancillae iudicabit his ad.

-
- `, - }, - template: ({ component, testid }) => html` -
-

Before expandable content

- ${component} -

After expandable content

-
- `, - }); -}); diff --git a/packages/stacks-classic/lib/components/link-preview/link-preview.a11y.test.ts b/packages/stacks-classic/lib/components/link-preview/link-preview.a11y.test.ts deleted file mode 100644 index bf18623070..0000000000 --- a/packages/stacks-classic/lib/components/link-preview/link-preview.a11y.test.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { runA11yTests } from "../../test/a11y-test-utils"; -import "../../index"; - -const getChild = (child?: string): string => { - return ` - - ${ - child - ? child - : ` - - ` - } - - `; -}; -describe.skip("link preview", () => { - runA11yTests({ - baseClass: "s-link-preview", - children: { - default: getChild(), - code: getChild(` - - `), - }, - }); -}); diff --git a/packages/stacks-classic/lib/components/link-preview/link-preview.less b/packages/stacks-classic/lib/components/link-preview/link-preview.less deleted file mode 100644 index 96204b9fd8..0000000000 --- a/packages/stacks-classic/lib/components/link-preview/link-preview.less +++ /dev/null @@ -1,140 +0,0 @@ -.s-link-preview { - --_lp-details-fc: var(--black-400); - --_lp-details-mt: var(--su2); - --_lp-footer-bg: var(--black-100); - --_lp-footer-fd: unset; - --_lp-header-bg: var(--black-100); - --_lp-misc-pl: var(--su4); - --_lp-misc-pt: unset; - - // CONTEXTUAL STYLES - #stacks-internals #screen-sm({ - --_lp-details-mt: var(--su4); - --_lp-footer-fd: column; - --_lp-misc-pl: 0; - --_lp-misc-pt: var(--su2); - }); - - .highcontrast-mode({ - --_lp-details-fc: var(--black-600); - --_lp-footer-bg: var(--black-050); - --_lp-header-bg: var(--black-050); - }); - - // CHILD ELEMENTS - & &--details, - & &--footer { - a { - &:hover, - &:active, - &:focus, - &:visited { - color: var(--black-500); - } - - color: var(--black-600); - cursor: pointer; - text-decoration: none; - } - } - - & &--body { - *:last-child { - margin-bottom: 0; - } - - font-size: var(--fs-body2); - padding: var(--su12); - } - - & &--code { - pre { - border-radius: 0 !important; - margin: 0; - max-height: 400px; - } - } - - & &--details { - color: var(--_lp-details-fc); - margin-top: var(--_lp-details-mt); - - font-size: var(--fs-caption); - } - - & &--footer { - background: var(--_lp-footer-bg); - flex-direction: var(--_lp-footer-fd); - - border-bottom-left-radius: var(--br-md); - border-bottom-right-radius: var(--br-md); - border-top: var(--su1) solid var(--bc-medium); - display: flex; - font-size: var(--fs-caption); - justify-content: space-between; - padding: var(--su12); - } - - & &--header { - background: var(--_lp-header-bg); - border-bottom: var(--su1) solid var(--bc-medium); - border-top-left-radius: var(--br-md); - border-top-right-radius: var(--br-md); - display: flex; - padding: var(--su12) var(--su8); - } - - & &--icon { - color: var(--black-600); // Set the default color of the integration's icon. Most likely this will be overridden by the integration icon's native colors. - margin-right: var(--su8); - } - - & &--misc { - padding-left: var(--_lp-misc-pl); - padding-top: var(--_lp-misc-pt); - - color: var(--black-400); - } - - & &--title { - color: var(--black-600); - font-size: var(--fs-body3); - font-weight: bold; - } - - & a&--title { - &:active, - &:hover { - .highcontrast-mode({ - text-decoration: underline; - }); - - color: var(--theme-link-color-hover, var(--theme-secondary-500)); - text-decoration: none; - } - - &:visited { - &:hover { - color: var(--theme-link-color, var(--purple-600)); - } - - color: var(--theme-link-color, var(--purple-500)); - } - - color: var(--theme-link-color, var(--theme-secondary)); - cursor: pointer; - text-decoration: none; - } - - & &--url { - max-width: 100%; - overflow: hidden; - text-overflow: ellipsis !important; - white-space: nowrap; - } - - border: var(--su1) solid var(--bc-medium); - border-radius: var(--br-md); - box-shadow: var(--bs-sm); - text-align: left; -} diff --git a/packages/stacks-classic/lib/components/link-preview/link-preview.visual.test.ts b/packages/stacks-classic/lib/components/link-preview/link-preview.visual.test.ts deleted file mode 100644 index 5f3e1f8bcd..0000000000 --- a/packages/stacks-classic/lib/components/link-preview/link-preview.visual.test.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { html } from "@open-wc/testing"; -import { runVisualTests } from "../../test/visual-test-utils"; -import "../../index"; - -const getChild = (child?: string): string => { - return ` - - ${ - child - ? child - : ` - - ` - } - - `; -}; - -describe.skip("link preview", () => { - runVisualTests({ - baseClass: "s-link-preview", - children: { - default: getChild(), - code: getChild(` - - `), - }, - template: ({ component, testid }) => html` -
${component}
- `, - }); -}); diff --git a/packages/stacks-classic/lib/components/page-title/page-title.a11y.test.ts b/packages/stacks-classic/lib/components/page-title/page-title.a11y.test.ts deleted file mode 100644 index e80fceda09..0000000000 --- a/packages/stacks-classic/lib/components/page-title/page-title.a11y.test.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { html } from "@open-wc/testing"; -import { runA11yTests } from "../../test/a11y-test-utils"; -import "../../index"; - -describe.skip("page title", () => { - runA11yTests({ - baseClass: "s-page-title", - children: { - default: ` -
- -

Page title

-

- Optional description de Finibus Bonorum et Malorum -

-
-
- -
- `, - }, - template: ({ component, testid }) => html` -
- ${component} -
- `, - }); -}); diff --git a/packages/stacks-classic/lib/components/page-title/page-title.less b/packages/stacks-classic/lib/components/page-title/page-title.less deleted file mode 100644 index 9ebd2a2dd5..0000000000 --- a/packages/stacks-classic/lib/components/page-title/page-title.less +++ /dev/null @@ -1,51 +0,0 @@ -.s-page-title { - --_pt-ai: flex-end; - --_pt-fd: row; - --_pt-actions-ml: var(--su8); - --_pt-actions-mt: unset; - --_pt-breadcrums-mb: var(--su8); - - // CONTEXTUAL STYLES - #stacks-internals #screen-sm({ - --_pt-breadcrums-mb: var(--su2); - }); - #stacks-internals #screen-md({ - --_pt-ai: flex-start; - --_pt-fd: column; - --_pt-actions-ml: 0; - --_pt-actions-mt: var(--su8); - }); - - // CHILD ELEMENTS - & &--actions { - margin-left: var(--_pt-actions-ml); - margin-top: var(--_pt-actions-mt); - flex-shrink: 0; - } - & &--description { - color: var(--fc-light); - font-size: var(--fs-body2); - margin-bottom: 0; - margin-top: var(--su4); - } - & &--header { - color: var(--fc-dark); - font-size: var(--fs-headline1); - font-weight: bold; - line-height: var(--lh-sm); - margin: 0; - margin-bottom: 0; // TODO: investigate why this exists. I assume it's so margin-bottom isn't overridden, but 🤷‍♂️ - } - .s-breadcrumbs { - margin-bottom: var(--_pt-breadcrums-mb); - } - - align-items: var(--_pt-ai); - flex-direction: var(--_pt-fd); - - border-bottom: var(--su1) solid var(--bc-medium); - display: flex; - justify-content: space-between; - padding-bottom: var(--su16); - width: 100%; -} diff --git a/packages/stacks-classic/lib/components/page-title/page-title.visual.test.ts b/packages/stacks-classic/lib/components/page-title/page-title.visual.test.ts deleted file mode 100644 index 91973a3c2b..0000000000 --- a/packages/stacks-classic/lib/components/page-title/page-title.visual.test.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { html } from "@open-wc/testing"; -import { runVisualTests } from "../../test/visual-test-utils"; -import "../../index"; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const postTitleTemplate = ({ component, testid }: any) => html` -
${component}
-`; - -const getChildren = ({ - showEverything = false, -}: { - showEverything: boolean; -}) => ` -
- ${ - showEverything - ? ` - - ` - : "" - } -

Page title

- ${ - showEverything - ? ` -

- Optional description de Finibus Bonorum et Malorum -

- ` - : "" - } -
- ${ - showEverything - ? ` -
- -
- ` - : "" - } -`; - -describe.skip("page title", () => { - runVisualTests({ - baseClass: "s-page-title", - children: { - default: getChildren({ showEverything: false }), - complete: getChildren({ showEverything: true }), - }, - template: postTitleTemplate, - }); -}); diff --git a/packages/stacks-classic/lib/components/progress-bar/progress-bar.a11y.test.ts b/packages/stacks-classic/lib/components/progress-bar/progress-bar.a11y.test.ts deleted file mode 100644 index 64185898f3..0000000000 --- a/packages/stacks-classic/lib/components/progress-bar/progress-bar.a11y.test.ts +++ /dev/null @@ -1,189 +0,0 @@ -import { html } from "@open-wc/testing"; -import { - IconAchievementsSm, - IconCheckmarkSm, -} from "@stackoverflow/stacks-icons-legacy/icons"; -import { runA11yTests } from "../../test/a11y-test-utils"; -import "../../index"; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const template = ({ component, testid }: any) => html` -
- ${component} -
-`; - -const steppedItems = [ - { - complete: true, - label: "Select plan", - }, - { - complete: true, - label: "Team name", - }, - { - active: true, - label: "Payment", - }, - { - label: "Create account", - }, -]; - -const getChildren = (type: string) => { - switch (type) { - case "badge": - return `
-
Electorate
-
-
`; - case "circular": - return ` - - - `; - case "privilege": - return ` -
- ${IconAchievementsSm} - Access Review Queues -
-
- `; - case "segmented": - return ` -
-
    -
  1. -
- `; - case "stepped": - return steppedItems - .map((step, i) => { - return ` -
- - ${step.complete ? IconCheckmarkSm : ""} - ${step.label} ${ - step.complete ? "complete" : "incomplete" - } - - ${ - i > 0 - ? '
' - : "" - } - - ${ - i < steppedItems.length - 1 - ? '
' - : "" - } - ${step.label} -
- `; - }) - .join(""); - default: - return `
`; - } -}; -describe.skip("progress-bar", () => { - // Base - runA11yTests({ - baseClass: "s-progress", - variants: ["brand", "info"], - children: { - default: getChildren(""), - }, - template, - }); - - // Badge - runA11yTests({ - baseClass: "s-progress", - variants: ["badge"], - modifiers: { - primary: ["gold", "silver", "bronze"], - }, - children: { - default: getChildren("badge"), - }, - template, - options: { - includeNullVariant: false, - includeNullModifier: false, - }, - }); - - // Circular - runA11yTests({ - baseClass: "s-progress", - variants: ["circular"], - modifiers: { - global: ["fc-green-400", "fc-theme-primary"], - }, - children: { - default: getChildren("circular"), - }, - template, - attributes: { - style: "--s-progress-value: .75", - }, - options: { - includeNullVariant: false, - includeNullModifier: false, - }, - }); - - // Privilege - runA11yTests({ - baseClass: "s-progress", - variants: ["privilege"], - children: { - default: getChildren("privilege"), - }, - template, - options: { - includeNullVariant: false, - }, - }); - - // Segmented - runA11yTests({ - baseClass: "s-progress", - variants: ["segmented"], - children: { - default: getChildren("segmented"), - }, - template, - options: { - includeNullVariant: false, - }, - }); - - // Stepped - runA11yTests({ - baseClass: "s-progress", - variants: ["stepped"], - children: { - default: getChildren("stepped"), - }, - template: ({ component, testid }) => html` -
- ${component} -
- `, - options: { - includeNullVariant: false, - }, - // TODO add skipped test ids - }); -}); diff --git a/packages/stacks-classic/lib/components/progress-bar/progress-bar.less b/packages/stacks-classic/lib/components/progress-bar/progress-bar.less deleted file mode 100644 index 091e50b173..0000000000 --- a/packages/stacks-classic/lib/components/progress-bar/progress-bar.less +++ /dev/null @@ -1,292 +0,0 @@ -.s-progress { - // COMPONENT-SPECIFIC CONSTANTS - @pr-circle-circumference: (2 * pi() * 14); // 2Ď€r, r = 14. - // COMPONENT-SPECIFIC CUSTOM PROPERTIES - --_pr-bar: var(--br-md); - --_pr-bg: var(--black-300); - --_pr-h: unset; - --_pr-size: unset; - --_pr-w: 100%; - --_pr-hmn: var(--su4); - --_pr-bar-bar: var(--br-md); - --_pr-bar-bg: var(--green-400); - --_pr-bar-hmn: var(--su4); - --_pr-label-ai: unset; - --_pr-label-bc: transparent; - --_pr-label-d: unset; - --_pr-label-g: unset; - --_pr-label-jc: unset; - --_pr-label-px: unset; - - // MODIFIERS - &&__brand { - --_pr-bar-bg: var(--orange-400); - } - - // TODO SPARK I've changed metallic colors here to use their new non-metallic equivalents - &&__bronze { - --_pr-bar-bg: var(--orange-100); - --_pr-label-bc: var(--orange-400); - } - - &&__gold { - --_pr-bar-bg: var(--yellow-100); - --_pr-label-bc: var(--yellow-400); - } - - &&__info { - --_pr-bar-bg: var(--blue-400); - } - - &&__silver { - --_pr-bar-bg: var(--blue-100); - --_pr-label-bc: var(--blue-400); - } - - // VARIANTS - &&__badge, - &&__privilege { - --_pr-bar: var(--br-md); - --_pr-bg: transparent; - --_pr-hmn: 2em; - --_pr-bar-bar: var(--br-md); - --_pr-bar-hmn: 2em; - --_pr-label-d: flex; - --_pr-label-g: var(--su4); - } - - &&__badge { - --_pr-label-ai: center; - --_pr-label-px: 1em; - - .s-progress--label { - .s-badge--label { - flex-grow: 1; - text-align: center; - } - } - } - - &&__circular { - --_pr-bg: transparent; - --_pr-size: var(--su32); - --s-progress-value: 0; - - &.s-progress { - &__sm { - --_pr-size: var(--su24); - } - - &__md { - --_pr-size: var(--su48); - } - - &__lg { - --_pr-size: var(--su64); - } - } - - // TODO: consider renaming to `.s-progress--bar` - .s-progress-bar { // It may necessitate wrapping element in a `&:not(&__circular)` - circle { - &:nth-of-type(1) { - opacity: 0.4; - stroke: currentColor; - } - &:nth-of-type(2) { - stroke: currentColor; - stroke-dasharray: @pr-circle-circumference; // [1] - stroke-dashoffset: calc(((1 - var(--s-progress-value)) * @pr-circle-circumference) * 1px); // Multiply everything by 1px since Safari and Firefox require these to be in pixels - } - - fill: none; - stroke-linecap: round; - stroke-width: var(--su4); - } - - transform: rotate(270deg); // Make everything originate from the top of the circle - } - } - - &&__privilege { - --_pr-bar-bg: var(--green-200); - --_pr-label-ai: center; - --_pr-label-bc: var(--green-400); - --_pr-label-jc: center; - - .highcontrast-mode({ --_pr-bar-bg: var(--green-300); }); - } - - // TODO move `.s-progress__stepped` to entirely separate component (or consider deprecating) - &&__stepped { // There's so little overlap with the base .s-progress that it doesn't make sense as a variant - background: transparent; - display: flex; - - .s-progress { - &--bar { - &.s-progress--bar { - &__left { - left: 0; - right: 50%; - } - - &__right { - left: 50%; - right: 0; - } - } - - background: var(--black-250); - border-radius: 0; - height: var(--su6); - position: absolute; - top: calc(var(--su8) + var(--su1)); - z-index: var(--zi-base); - } - - &--label { // Override a ton of properties - border: 0; - border-radius: 0; - color: var(--black-400); - display: block; - font-size: var(--fs-body1); - height: auto; - padding: var(--su12) var(--su6) 0 var(--su6); - position: static; - text-align: center; - width: auto; - z-index: var(--zi-base); - } - - &--step { - &.is-active { - .s-progress { - &--bar.s-progress--bar__left { - background: var(--theme-secondary); - } - - &--label { - color: var(--fc-dark); - } - - &--stop { - background: var(--theme-secondary); - box-shadow: 0 0 0 var(--su6) var(--translucent-secondary);// TODO SHINE revisit this value once theme colors are finalized - } - } - } - - &.is-complete { - .s-progress { - &--bar, - &--stop { - background: var(--theme-secondary); - } - - &--label { - color: var(--fc-dark); - } - } - } - - align-items: center; - display: flex; - flex-basis: 0; - flex-direction: column; - flex-grow: 1; - flex-shrink: 1; - position: relative; - } - - &--stop { - .highcontrast-mode({ - color: var(--white); - }); - - align-items: center; - background: var(--black-250); - border-radius: 100%; - color: var(--_white-static); - display: flex; - height: var(--su24); - justify-content: center; - position: relative; - width: var(--su24); - z-index: var(--zi-selected); - } - } - } - - // CHILD ELEMENTS - & &--bar { - background-color: var(--_pr-bar-bg); - border-radius: var(--_pr-bar); - min-height: var(--_pr-hmn); - - height: 100%; - min-width: var(--su6); - position: relative; - } - - & &--label { - align-items: var(--_pr-label-ai); - border: var(--su1) solid var(--_pr-label-bc); - display: var(--_pr-label-d); - gap: var(--_pr-label-g); - justify-content: var(--_pr-label-jc); - padding-left: var(--_pr-label-px); - padding-right: var(--_pr-label-px); - - border-radius: var(--br-md); - color: var(--fc-dark); - font-size: var(--fs-caption); - height: 100%; - line-height: var(--lh-xs); - position: absolute; - width: 100%; - z-index: calc(var(--zi-base) + 2); - } - - & &--segments { // DEPRECATED: AFAICT, this is unused in core (as well as it's intended parent variant class `.s-progress__segmented`) - li { - &:not(:first-child):not(:last-child):before { - background-color: var(--white); - content: ""; - display: block; - height: 100%; - left: var(--sun1); - position: absolute; - top: 0; - width: var(--su4); - } - - display: block; - padding-top: var(--su4); - position: relative; - text-align: center; - } - - display: flex; - height: 100%; - justify-content: space-between; - list-style: none; - margin: 0; - padding: 0; - position: absolute; - top: 0; - width: 100%; - } - - background-color: var(--_pr-bg); - border-radius: var(--_pr-bar); - height: var(--_pr-size, var(--_pr-h)); - min-height: var(--_pr-hmn); - - min-width: var(--su6); - position: relative; - width: var(--_pr-size, var(--_pr-w)); -} - -// [1] Multiply the circle circumference by an the opposite percentage of what we want to display -// For example 70%, represented as a decimal is 0.7 -// The opposite of that is 0.3 so ( 1 - 0.7 ) diff --git a/packages/stacks-classic/lib/components/progress-bar/progress-bar.visual.test.ts b/packages/stacks-classic/lib/components/progress-bar/progress-bar.visual.test.ts deleted file mode 100644 index 918f95ae1b..0000000000 --- a/packages/stacks-classic/lib/components/progress-bar/progress-bar.visual.test.ts +++ /dev/null @@ -1,188 +0,0 @@ -import { html } from "@open-wc/testing"; -import { - IconAchievementsSm, - IconCheckmarkSm, -} from "@stackoverflow/stacks-icons-legacy/icons"; -import { runVisualTests } from "../../test/visual-test-utils"; -import "../../index"; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const template = ({ component, testid }: any) => html` -
- ${component} -
-`; - -const steppedItems = [ - { - complete: true, - label: "Select plan", - }, - { - complete: true, - label: "Team name", - }, - { - active: true, - label: "Payment", - }, - { - label: "Create account", - }, -]; - -const getChildren = (type: string) => { - switch (type) { - case "badge": - return `
-
Electorate
-
-
`; - case "circular": - return ` - - - `; - case "privilege": - return ` -
- ${IconAchievementsSm} - Access Review Queues -
-
- `; - case "segmented": - return ` -
-
    -
  1. -
- `; - case "stepped": - return steppedItems - .map((step, i) => { - return ` -
- - ${step.complete ? IconCheckmarkSm : ""} - ${step.label} ${ - step.complete ? "complete" : "incomplete" - } - - ${ - i > 0 - ? '
' - : "" - } - - ${ - i < steppedItems.length - 1 - ? '
' - : "" - } - ${step.label} -
- `; - }) - .join(""); - default: - return `
`; - } -}; -describe.skip("progress-bar", () => { - // Base - runVisualTests({ - baseClass: "s-progress", - variants: ["brand", "info"], - children: { - default: getChildren(""), - }, - template, - }); - - // Badge - runVisualTests({ - baseClass: "s-progress", - variants: ["badge"], - modifiers: { - primary: ["gold", "silver", "bronze"], - }, - children: { - default: getChildren("badge"), - }, - template, - options: { - includeNullVariant: false, - includeNullModifier: false, - }, - }); - - // Circular - runVisualTests({ - baseClass: "s-progress", - variants: ["circular"], - modifiers: { - global: ["fc-green-400", "fc-theme-primary"], - }, - children: { - default: getChildren("circular"), - }, - template, - attributes: { - style: "--s-progress-value: .75", - }, - options: { - includeNullVariant: false, - includeNullModifier: false, - }, - }); - - // Privilege - runVisualTests({ - baseClass: "s-progress", - variants: ["privilege"], - children: { - default: getChildren("privilege"), - }, - template, - options: { - includeNullVariant: false, - }, - }); - - // Segmented - runVisualTests({ - baseClass: "s-progress", - variants: ["segmented"], - children: { - default: getChildren("segmented"), - }, - template, - options: { - includeNullVariant: false, - }, - }); - - // Stepped - runVisualTests({ - baseClass: "s-progress", - variants: ["stepped"], - children: { - default: getChildren("stepped"), - }, - template: ({ component, testid }) => html` -
- ${component} -
- `, - options: { - includeNullVariant: false, - }, - }); -}); diff --git a/packages/stacks-classic/lib/components/uploader/uploader.less b/packages/stacks-classic/lib/components/uploader/uploader.less deleted file mode 100644 index 96f8d32029..0000000000 --- a/packages/stacks-classic/lib/components/uploader/uploader.less +++ /dev/null @@ -1,205 +0,0 @@ -.s-uploader { - // COMPONENT-SPECIFIC CONSTANTS - --_up-bg-b-image: url("data:image/svg+xml;,%3csvg width='100%25' height='100%25' xmlns='http://www.w3.org/2000/svg'%3e%3crect width='100%25' height='100%25' fill='none' rx='5' ry='5' stroke='%23000000' stroke-width='8' stroke-dasharray='7%2c 22' stroke-dashoffset='0' stroke-linecap='square'/%3e%3c/svg%3e"); // Keeping this a custom property to save a few bytes - // COMPONENT-SPECIFIC CUSTOM PROPERTIES - --_up-bg: var(--black-100); - --_up-bg-focus: var(--black-150); - --_up-bg-bc: var(--black-250); - --_up-focus-ring-color: var(--focus-ring); - - // CONTEXTUAL STYLES - .highcontrast-mode({ - --_up-bg-bc-hc: var(--black-400); - &.has-error { - --_up-bg-bc-hc-state: var(--red-500); - } - &.has-success { - --_up-bg-bc-hc-state: var(--green-400); - } - &.has-warning { - --_up-bg-bc-hc-state: var(--yellow-500); - } - }); - - // STATES - &.has-error, - &.has-success, - &.has-warning { - .s-link { - color: var(--_up-link-fc); - } - } - - &.has-error { - --_up-bg: var(--red-100); - --_up-bg-focus: var(--red-200); - --_up-bg-bc: var(--red-300); - --_up-focus-ring-color: var(--focus-ring-error); - --_up-link-fc: var(--red-500); - } - - &.has-success { - --_up-bg: var(--green-100); - --_up-bg-focus: var(--green-200); - --_up-bg-bc: var(--green-300); - --_up-focus-ring-color: var(--focus-ring-success); - --_up-link-fc: var(--green-400); - } - - &.has-warning { - --_up-bg: var(--yellow-100); - --_up-bg-focus: var(--yellow-200); - --_up-bg-bc: var(--yellow-300); - --_up-focus-ring-color: var(--focus-ring-warning); - --_up-link-fc: var(--yellow-500); - } - - &.is-active { - --_up-bg: var(--black-150); - --_up-bg-bc: var(--black-300); - } - - &.is-disabled { - opacity: var(--_o-disabled-static); - } - - // CHILD ELEMENTS - & &--container { - &:before { // Add the dashed border as an SVG background mask - -webkit-mask-image: var(--_up-bg-b-image); - mask-image: var(--_up-bg-b-image); - background-color: var(--_up-bg-bc-hc-state, var(--_up-bg-bc-hc, var(--_up-bg-bc))); - border-radius: var(--br-md); - content: ''; - display: block; - inset: 0; - position: absolute; - } - - align-items: center; - background-color: var(--_up-bg); - border-radius: var(--br-md); - display: flex; - flex-direction: column; - justify-content: center; - min-height: var(--su128); - padding: var(--su8) var(--su16); - position: relative; - text-align: center; - } - - & &--input { - &:focus:focus-visible + .s-uploader--container { - .focus-styles(); - } - - &:focus:focus-visible + .s-uploader--container, - .s-uploader--container.focus { - background-color: var(--_up-bg-focus); - } - - cursor: pointer; - height: 100%; - inset: 0; - opacity: 0; - position: absolute; - width: 100%; - z-index: var(--zi-selected); - } - - & &--preview { - max-width: 100%; - pointer-events: none; - } - - & &--preview-thumbnail { - .highcontrast-mode({ - border: var(--su1) solid var(--black); - }); - - &:is(img) { - object-fit: scale-down; - object-position: center; - } - - &:not(img) { - padding: var(--su16); - } - - background-color: var(--white); - border-radius: var(--br-md); - box-shadow: var(--bs-md); - max-height: var(--su128); - max-width: 100%; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - & &--previews { - &.has-multiple { - display: block; - height: auto; - padding: var(--su8) var(--su2); - width: 100%; - - .s-uploader--preview { - &:after { - content: attr(data-filename); - display: block; - margin-left: var(--su12); - max-width: 100%; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - - align-items: center; - display: flex; - padding: var(--su6) 0; - width: 100%; - } - - .s-uploader--preview-thumbnail { - &:is(img) { - object-fit: cover; - } - &:not(img) { - background-image: url("data:image/svg+xml;,%3Csvg xmlns='http://www.w3.org/2000/svg' aria-hidden='true' fill='%23535A60' width='18' height='18' viewBox='0 0 18 18'%3E%3Cpath d='M3 3a2 2 0 012-2h6l4 4v10a2 2 0 01-2 2H5a2 2 0 01-2-2V3zm7-1.5V6h4.5L10 1.5z'%3E%3C/path%3E%3C/svg%3E"); - background-position: center; - background-repeat: no-repeat; - } - - color: transparent; - height: var(--su32); - flex-shrink: 0; - width: var(--su32); - } - } - - max-width: 100%; - text-align: left; - } - - & &--previews-heading { - color: var(--black-600); - font-size: var(--fs-body2); - font-weight: 700; - padding-bottom: var(--su8); - } - - & &--reset { - position: absolute; - right: var(--su8); - top: var(--su8); - z-index: var(--zi-active); - } - - // This is for safari shadow DOM - // see https://github.com/StackExchange/Stacks/pull/690#issuecomment-861028193 - input[type="file"]::file-selector-button { - cursor: pointer; - } - - position: relative; -} diff --git a/packages/stacks-classic/lib/components/uploader/uploader.ts b/packages/stacks-classic/lib/components/uploader/uploader.ts deleted file mode 100644 index 6ba2b6b68d..0000000000 --- a/packages/stacks-classic/lib/components/uploader/uploader.ts +++ /dev/null @@ -1,207 +0,0 @@ -import * as Stacks from "../../stacks"; - -interface FilePreview { - data?: string | ArrayBuffer; - name: string; - type: string; -} - -export class UploaderController extends Stacks.StacksController { - static targets = ["input", "previews", "uploader"]; - - declare readonly inputTarget: HTMLInputElement; - declare readonly previewsTarget: HTMLElement; - declare readonly uploaderTarget: HTMLElement; - - private boundDragEnter!: () => void; - private boundDragLeave!: () => void; - - private static readonly FILE_DISPLAY_LIMIT = 10; - private static readonly MAX_FILE_SIZE = 1024 * 1024 * 10; // 10 MB - - connect() { - super.connect(); - this.boundDragEnter = this.handleUploaderActive.bind(this, true); - this.boundDragLeave = this.handleUploaderActive.bind(this, false); - - this.inputTarget.addEventListener("dragenter", this.boundDragEnter); - this.inputTarget.addEventListener("dragleave", this.boundDragLeave); - } - - disconnect() { - this.inputTarget.removeEventListener("dragenter", this.boundDragEnter); - this.inputTarget.removeEventListener("dragleave", this.boundDragLeave); - super.disconnect(); - } - - /** - * Handles rendering the file preview state on input change - */ - handleInput() { - this.previewsTarget.innerHTML = ""; - - if (!this.inputTarget.files) { - return; - } - - const count = this.inputTarget.files.length; - this.getDataURLs( - this.inputTarget.files, - UploaderController.FILE_DISPLAY_LIMIT - ) - .then((res: FilePreview[]) => { - this.handleVisible(true); - const hasMultipleFiles = res.length > 1; - - if (hasMultipleFiles) { - const headingElement = document.createElement("div"); - headingElement.classList.add( - "s-uploader--previews-heading" - ); - headingElement.innerText = - res.length < count - ? `Showing ${res.length} of ${count} files` - : `${count} items`; - this.previewsTarget.appendChild(headingElement); - this.previewsTarget.classList.add("has-multiple"); - } else { - this.previewsTarget.classList.remove("has-multiple"); - } - res.forEach((file) => this.addFilePreview(file)); - this.handleUploaderActive(true); - }) - // TODO consider rendering an error message - .catch(() => null); - } - - /** - * Resets the Uploader to initial state - */ - reset() { - this.inputTarget.value = ""; - this.previewsTarget.innerHTML = ""; - this.handleVisible(false); - } - - /** - * Set hide/show and disabled state on elements depending on preview state - * @param {boolean} shouldPreview - Uploader is entering a preview state - */ - private handleVisible(shouldPreview: boolean) { - const { scope } = this.targets; - const hideElements = scope.findAllElements( - "[data-s-uploader-hide-on-input]" - ); - const showElements = scope.findAllElements( - "[data-s-uploader-show-on-input]" - ); - const enableElements = scope.findAllElements( - "[data-s-uploader-enable-on-input]" - ); - - if (shouldPreview) { - hideElements.forEach((el) => { - el.classList.add("d-none"); - }); - showElements.forEach((el) => { - el.classList.remove("d-none"); - }); - enableElements.forEach((el) => { - el.removeAttribute("disabled"); - }); - } else { - hideElements.forEach((el) => { - el.classList.remove("d-none"); - }); - showElements.forEach((el) => { - el.classList.add("d-none"); - }); - enableElements.forEach((el) => { - el.setAttribute("disabled", "true"); - }); - this.handleUploaderActive(false); - } - } - - /** - * Adds a DOM element to preview a selected file - * @param {FilePreview} file - */ - private addFilePreview(file: FilePreview) { - if (!file) { - return; - } - - const previewElement = document.createElement("div"); - let thumbElement; - - if (file.type.match("image/*") && file.data) { - thumbElement = document.createElement("img"); - - thumbElement.src = file.data.toString(); - thumbElement.alt = file.name; - } else { - thumbElement = document.createElement("div"); - thumbElement.innerText = file.name; - } - - thumbElement.classList.add("s-uploader--preview-thumbnail"); - previewElement.appendChild(thumbElement); - previewElement.classList.add("s-uploader--preview"); - previewElement.setAttribute("data-filename", file.name); - this.previewsTarget.appendChild(previewElement); - } - - /** - * Toggles display and disabled state for select elements on valid input - * @param {boolean} active - Uploader is in active state (typically on 'dragenter') - */ - private handleUploaderActive(active: boolean) { - this.uploaderTarget.classList.toggle("is-active", active); - } - - /** - * Converts the file data into a data URL - * @param {File} file - * @returns an object containing a FilePreview object - */ - private fileToDataURL(file: File): Promise { - const reader = new FileReader(); - const { name, size, type } = file; - - if ( - size < UploaderController.MAX_FILE_SIZE && - type.indexOf("image") > -1 - ) { - return new Promise((resolve, reject) => { - reader.onload = (evt) => { - const res = evt?.target?.result; - if (res) { - resolve({ data: res, name, type }); - } else { - reject(); - } - }; - reader.readAsDataURL(file); - }); - } else { - return Promise.resolve({ name, type }); - } - } - - /** - * Gets an array of FilePreviews from a FileList - * @param {FileList|[]} files - * @returns an array of FilePreview objects from a FileList - */ - private getDataURLs( - files: FileList, - limit: number - ): Promise { - const promises = Array.from(files) - .slice(0, Math.min(limit, files.length)) - .map((f) => this.fileToDataURL(f)); - - return Promise.all(promises); - } -} diff --git a/packages/stacks-docs/.eleventy.js b/packages/stacks-docs/.eleventy.js index d803890aaf..a58212c5d0 100644 --- a/packages/stacks-docs/.eleventy.js +++ b/packages/stacks-docs/.eleventy.js @@ -31,6 +31,7 @@ module.exports = function(eleventyConfig) { eleventyConfig.setQuietMode(true); // Reduce the console output eleventyConfig.addLayoutAlias('home', 'layouts/home.html'); eleventyConfig.addLayoutAlias('page', 'layouts/page.html'); + eleventyConfig.addLayoutAlias('removed', 'layouts/removed.html'); registerSubfolderData(eleventyConfig, 'atomic'); registerSubfolderData(eleventyConfig, 'components'); diff --git a/packages/stacks-docs/_data/components/breadcrumbs.json b/packages/stacks-docs/_data/components/breadcrumbs.json deleted file mode 100644 index 9b40c0c299..0000000000 --- a/packages/stacks-docs/_data/components/breadcrumbs.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "classes": [ - { - "code": ".s-breadcrumbs", - "description": "Base parent container for breadcrumbs" - }, - { - "code": ".s-breadcrumbs--item", - "parent": ".s-breadcrumbs", - "description": "Individual breadcrumb element containing a link and a divider" - }, - { - "code": ".s-breadcrumbs--link", - "parent": ".s-breadcrumbs--item", - "description": "Breadcrumb link element" - }, - { - "code": ".s-breadcrumbs--divider", - "parent": ".s-breadcrumbs--item", - "description": "Breadcrumb divider element" - } - ] -} \ No newline at end of file diff --git a/packages/stacks-docs/_data/components/button-groups.json b/packages/stacks-docs/_data/components/button-groups.json deleted file mode 100644 index fbdee95c75..0000000000 --- a/packages/stacks-docs/_data/components/button-groups.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "classes": [ - { - "code": ".s-btn-group", - "description": "Base button group style." - } - ], - "button-attributes": [ - { - "title": "Accessibility", - "description": "When used as navigation or a filter, button groups should include the aria-current attribute with the appropriate value.", - "attributes": [ - { - "attribute": "aria-current=\"[value]\"", - "applies": ".s-btn.is-selected", - "description": "When using a button group for navigation or filtering, include the aria-current attribute with the appropriate value to the selected button. Most commonly used values are page, step, and true." - } - ] - }, - { - "title": "Preventing layout shift", - "description": "Horizontal layout shift may occur when changing which button is selected within a button group. We recommend including the data-text attribute on each button text element with the value duplicating the text of the button to prevent the layout shift. See below for examples.", - "attributes": [ - { - "attribute": "data-text=\"[value]\"", - "applies": ".s-btn", - "description": "Prevents layout shift when changing selected button. Value should be the text of the button." - } - ] - } - ] -} \ No newline at end of file diff --git a/packages/stacks-docs/_data/components/cards.json b/packages/stacks-docs/_data/components/cards.json deleted file mode 100644 index fac8316d2a..0000000000 --- a/packages/stacks-docs/_data/components/cards.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "classes": [ - { - "code": ".s-card", - "description": "Base card style." - }, - { - "code": ".s-card__muted", - "applies": ".s-card", - "description": "Muted card style." - } - ] -} \ No newline at end of file diff --git a/packages/stacks-docs/_data/components/expandable.json b/packages/stacks-docs/_data/components/expandable.json deleted file mode 100644 index ddd1527443..0000000000 --- a/packages/stacks-docs/_data/components/expandable.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "classes": [ - { - "code": ".s-expandable", - "description": "Container for the expandable content. Include an id attribute to be referenced by the expandable control." - }, - { - "code": ".s-expandable--content", - "parent": ".s-expandable", - "description": "Class for the expandable content. This is the content that will be shown and hidden when the expandable is toggled." - }, - { - "code": ".is-expanded", - "applies": ".s-expandable", - "description": "Expanded state class." - } - ] -} \ No newline at end of file diff --git a/packages/stacks-docs/_data/components/link-previews.json b/packages/stacks-docs/_data/components/link-previews.json deleted file mode 100644 index a358bc60db..0000000000 --- a/packages/stacks-docs/_data/components/link-previews.json +++ /dev/null @@ -1,81 +0,0 @@ -{ - "classes": [ - { - "code": ".s-link-preview", - "description": "Base parent container for link previews" - }, - { - "code": ".s-link-preview--header", - "parent": ".s-link-preview", - "description": "Top section containing the title and details" - }, - { - "code": ".s-link-preview--body", - "parent": ".s-link-preview", - "description": "Middle section containing the body of the linked file whose expected content is rich text or markdown" - }, - { - "code": ".s-link-preview--code", - "parent": ".s-link-preview", - "description": "Middle section containing the body of the linked file whose expected content is code" - }, - { - "code": ".s-link-preview--footer", - "parent": ".s-link-preview", - "description": "Bottom section containing URL details" - }, - { - "code": ".s-link-preview--icon", - "parent": ".s-link-preview--header", - "description": "Logo of the third party link. Use the @Svg.Helper." - }, - { - "code": ".s-link-preview--title", - "parent": ".s-link-preview--header", - "description": "Title of the linked file." - }, - { - "code": ".s-link-preview--details", - "parent": ".s-link-preview--header", - "description": "Details and meta data of the linked file." - }, - { - "code": ".s-link-preview--url", - "parent": ".s-link-preview--footer", - "description": "URL of the linked file." - }, - { - "code": ".s-link-preview--misc", - "parent": ".s-link-preview--footer", - "description": "(optional) A small catch-all for anything you might need. This page contains a few use cases." - }, - { - "code": ".linenums", - "parent": ".s-link-preview--code", - "description": "Added to the pre of the preview block to properly display line numbers" - } - ], - "examples": { - "base": { - "title": "Using hooks for a simple fetch request and breaking the rules of hooks, unsure how?", - "description": "Use for links whose expected body is rich text or markdown like Jira issues or Slack messages. Wherever possible, it’s best practice to support basic markdown formatting (bold, italics, line breaks, lists, etc.)", - "details": "Issue submitted by Ricky Otero on Aug 12, 2019RESOLVED", - "body": [ - "I'm trying to create a simple fetch with hooks from an AWS database. At the moment it errors out and the only reason I can see is because it breaks the rules of hooks but I'm not sure how. It's at the top level of this functional component and it's not called inside an event handler.", - "The result of this call (an array of user data), needs to be exported as a function and called in another file.", - "If anyone can spot something I have missed and can highlighted how I'm breaking the rules of hooks I'd be grateful!", - "Thanks!" - ], - "url": "https://stackoverflow.atlassian.net/projects/SREREQ/queues/custom/1", - "misc": "Privacy notice" - }, - "code": { - "title": "Gruntfile.js", - "description": "Use for links whose expected body is code like code files or GitHub Gists. In these scenarios, replace s-link-preview--body class with s-link-preview--code.", - "details": "Located in StackExchange / Stacks", - "code": "use strict;\n\nmodule.exports = function(grunt) {\n grunt.initConfig({\n pkg: grunt.file.readJSON('package.json'),\n version: '<%= pkg.version %>',\n\n // Shell commands for use in Grunt tasks\n shell: {\n eleventyBuild: {\n command: 'npx @11ty/eleventy',\n options: {\n stderr: false,\n execOptions: {\n cwd: 'docs'\n }\n }\n }\n }\n });\n\n grunt.loadNpmTasks('grunt-contrib-uglify');\n\n grunt.registerTask('default', ['uglify']);\n};", - "url": "https://github.com/StackExchange/Stacks/blob/develop/Gruntfile.js", - "misc": "(truncated)" - } - } -} \ No newline at end of file diff --git a/packages/stacks-docs/_data/components/page-titles.json b/packages/stacks-docs/_data/components/page-titles.json deleted file mode 100644 index 3455997ee7..0000000000 --- a/packages/stacks-docs/_data/components/page-titles.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "classes": [ - { - "code": ".s-page-title", - "description": "Base class for the page title component." - }, - { - "code": ".s-page-title--actions", - "parent": ".s-page-title", - "description": "Contains the page actions." - }, - { - "code": ".s-page-title--text", - "parent": ".s-page-title", - "description": "Contains the page title and description." - }, - { - "code": ".s-page-title--description", - "parent": ".s-page-title--text", - "description": "Contains the page description." - }, - { - "code": ".s-page-title--header", - "parent": ".s-page-title--text", - "description": "Contains the page title." - } - ], - "example": { - "title": "Page title", - "description": "Optional description de Finibus Bonorum et Malorum with an optional link." - } -} \ No newline at end of file diff --git a/packages/stacks-docs/_data/components/progress-bars.json b/packages/stacks-docs/_data/components/progress-bars.json deleted file mode 100644 index e3fadca7d5..0000000000 --- a/packages/stacks-docs/_data/components/progress-bars.json +++ /dev/null @@ -1,120 +0,0 @@ -{ - "classes": [ - { - "code": ".s-progress", - "description": "The parent class for all progress bars." - }, - { - "code": ".s-progress--bar", - "parent": ".s-progress", - "description": "Shows the user’s current progress to accomplishing a goal with a background color." - }, - { - "code": ".s-progress--label", - "parent": ".s-progress", - "description": "Used to describe what progress bar is tracking." - }, - { - "code": ".s-progress--bar__left", - "parent": ".s-progress--step", - "description": "Draws a line on the left side of a step." - }, - { - "code": ".s-progress--bar__right", - "parent": ".s-progress--step", - "description": "Draws a line on the right side of a step." - }, - { - "code": ".s-progress--step", - "parent": ".s-progress--stepped", - "description": "Wrapper for each individual step." - }, - { - "code": ".s-progress__badge", - "applies": ".s-progress", - "description": "Styles the progress bar as a badge." - }, - { - "code": ".s-progress__brand", - "applies": ".s-progress", - "description": "Applies the brand color to the progress bar." - }, - { - "code": ".s-progress__circular", - "applies": ".s-progress", - "description": "Styles the progress bar as a circular progress bar." - }, - { - "code": ".s-progress__info", - "applies": ".s-progress", - "description": "Applies the info color to the progress bar." - }, - { - "code": ".s-progress__privilege", - "applies": ".s-progress", - "description": "Used to display a privilege progress bar." - }, - { - "code": ".s-progress__segmented", - "applies": ".s-progress", - "description": "Styles the progress bar as a segmented progress bar." - }, - { - "code": ".s-progress__stepped", - "applies": ".s-progress", - "description": "Styles the progress bar as a stepped progress bar." - }, - { - "code": ".s-progress__gold", - "applies": ".s-progress__badge", - "description": "Styles the progress bar as a gold badge." - }, - { - "code": ".s-progress__silver", - "applies": ".s-progress__badge", - "description": "Styles the progress bar as a silver badge." - }, - { - "code": ".s-progress__bronze", - "applies": ".s-progress__badge", - "description": "Styles the progress bar as a bronze badge." - }, - { - "code": ".is-active", - "applies": ".s-progress--step", - "description": "Styles the active step." - }, - { - "code": ".is-completed", - "applies": ".s-progress--step", - "description": "Styles the completed step." - } - ], - "parameters": [ - { - "code": "role=\"progressbar\"", - "applies": ".s-progress--bar", - "description": "This parameter communicates that element is displaying progress status that takes a long time or consists of several steps. (Source)" - }, - { - "code": "aria-valuemin", - "applies": ".s-progress--bar", - "description": "This parameter defines the minimum allowed value for the progress bar. (Source)" - }, - { - "code": "aria-valuemax", - "applies": ".s-progress--bar", - "description": "This parameter defines the maximum allowed value for the progress bar. (Source)" - }, - { - "code": "aria-valuenow", - "applies": ".s-progress--bar", - "description": "This parameter defines the current value for the progress bar. (Source)" - }, - { - "code": "style=\"width: [value]%\"", - "applies": ".s-progress--bar", - "description": "This parameter sets the width of the progress bar as a percentage. The value is the aria-valuenow value displayed as a percentage." - } - ] -} \ No newline at end of file diff --git a/packages/stacks-docs/_data/components/topbar.json b/packages/stacks-docs/_data/components/topbar.json deleted file mode 100644 index 291872153d..0000000000 --- a/packages/stacks-docs/_data/components/topbar.json +++ /dev/null @@ -1,78 +0,0 @@ -{ - "classes": [ - { - "code": ".s-topbar", - "description": "Base class" - }, - { - "code": ".s-topbar--container", - "parent": ".s-topbar", - "description": "Add atomic classes here to customize internal content width; defaults to `.wmx12`" - }, - { - "code": ".s-topbar--skip-link", - "parent": ".s-topbar", - "description": "Applied to an anchor tag for bypassing the top-level navigation links and jump to the main content on a page. See WCAG Technique G1" - }, - { - "code": ".s-topbar--logo", - "parent": ".s-topbar--container", - "description": "The logo. Can apply .is-selected to this" - }, - { - "code": ".s-topbar--menu-btn", - "parent": ".s-topbar--container", - "description": "Hamburger menu icon. Add .is-selected to turn it into an X" - }, - { - "code": ".s-topbar--navigation", - "parent": ".s-topbar--container", - "description": "Apply to nav to ensure proper layout." - }, - { - "code": ".s-topbar--notice", - "parent": ".s-topbar--container", - "description": "A badge-styled notice that stands out. Add .is-unread to make it stand out more." - }, - { - "code": ".s-topbar--searchbar", - "parent": ".s-topbar--container", - "description": "Contains a search input and an optional `.s-select`. Hides itself on mobile." - }, - { - "code": ".s-topbar--content", - "parent": ".s-topbar--navigation", - "description": "Contains li > .s-topbar--item elements that don’t look like anything in particular" - }, - { - "code": ".s-topbar--item", - "parent": ".s-topbar--content > li", - "description": "A topbar item element with hover, active and focused styling. Can add `.is-selected`" - }, - { - "code": ".s-topbar--searchbar--input-group", - "parent": ".s-topbar--searchbar", - "description": "Holds the search input + icon." - }, - { - "code": ".s-topbar--item__unset", - "applies": ".s-topbar--item", - "description": "This class excludes the .s-topbar--item from any automatic styling. This is useful for calls to action, e.g. buttons or log in links." - }, - { - "code": ".s-topbar--searchbar__open", - "applies": ".s-topbar--searchbar", - "description": "On mobile, this class shows the search input below the topbar. Toggle this class with a button." - }, - { - "code": ".s-topbar__light", - "applies": ".s-topbar", - "description": "Applies a forced light theme" - }, - { - "code": ".s-topbar__dark", - "applies": ".s-topbar", - "description": "Applies a forced dark theme" - } - ] -} diff --git a/packages/stacks-docs/_data/components/uploader.json b/packages/stacks-docs/_data/components/uploader.json deleted file mode 100644 index 17965b9b8f..0000000000 --- a/packages/stacks-docs/_data/components/uploader.json +++ /dev/null @@ -1,105 +0,0 @@ -{ - "classes": [ - { - "code": ".s-uploader", - "description": "Base uploader element" - }, - { - "code": ".s-uploader--container", - "parent": ".s-uploader", - "description": "Container for the visual elements of the uploader." - }, - { - "code": ".s-uploader--input", - "parent": ".s-uploader--container", - "description": "Adds proper styling to the uploader's file input. Visually hidden." - }, - { - "code": ".s-uploader--previews", - "parent": ".s-uploader--container", - "description": "Container for selected item(s) preview." - }, - { - "code": ".s-uploader--reset", - "parent": ".s-uploader--container", - "description": "Used to reset the uploader." - }, - { - "code": ".s-uploader--preview", - "parent": ".s-uploader--previews", - "description": "An image or string to preview a selected file." - }, - { - "code": ".is-active", - "applies": ".s-uploader", - "description": "Active styling for uploader element. Added on dragenter or when input has value." - }, - { - "code": ".is-disabled", - "applies": ".s-uploader", - "description": "Appropriately styles the uploader when it is disabled. Don’t forget to also add the disabled attribute on the input itself." - }, - { - "code": ".has-error", - "applies": ".s-uploader", - "description": "Adds error styling to the component." - }, - { - "code": ".has-success", - "applies": ".s-uploader", - "description": "Adds success styling to the component." - }, - { - "code": ".has-warning", - "applies": ".s-uploader", - "description": "Adds warning styling to the component." - } - ], - "attributes": [ - { - "code": "data-controller=\"s-uploader\"", - "secondaryContext": "Controller element", - "description": "Wires up the element to the uploader controller. This may be a .s-uploader element or a wrapper element." - }, - { - "code": "data-target=\"s-uploader.uploader\"", - "applies": ".s-uploader", - "description": "Wires up the element containing input, previews, and reset targets." - }, - { - "code": "data-s-uploader-target=\"input\"", - "applies": ".s-uploader--input", - "description": "Designates the file input element." - }, - { - "code": "data-target=\"s-uploader.previews\"", - "applies": ".s-uploader--previews", - "description": "Designates the element to act as a container to file preview(s)." - }, - { - "code": "data-action=\"input->s-uploader#handleInput\"", - "applies": "input[type=file]", - "description": "Wires up the element to provide files for preview on change." - }, - { - "code": "data-action=\"click->s-uploader#reset\"", - "secondaryContext": "Any child element", - "description": "Wires up the element to reset the uploader to its initial state." - }, - { - "code": "data-s-uploader-show-on-input", - "secondaryContext": "Any child element", - "description": "Toggles element visibility. Shows when input has value." - }, - { - "code": "data-s-uploader-hide-on-input", - "secondaryContext": "Any child element", - "description": "Toggles element visibility. Hides when input has value." - }, - { - "code": "data-s-uploader-enable-on-input", - "secondaryContext": "Any child element", - "description": "Toggles element disabled state. Disables when input has no value." - } - ] -} diff --git a/packages/stacks-docs/_data/site-navigation.json b/packages/stacks-docs/_data/site-navigation.json index f26014e237..666b189912 100644 --- a/packages/stacks-docs/_data/site-navigation.json +++ b/packages/stacks-docs/_data/site-navigation.json @@ -38,8 +38,7 @@ }, { "title": "Color palette", - "url": "/product/foundation/colors/", - "new": true + "url": "/product/foundation/colors/" }, { "title": "Theming", @@ -47,18 +46,15 @@ }, { "title": "Icons", - "url": "/product/foundation/icons/", - "new": true + "url": "/product/foundation/icons/" }, { "title": "Illustrations", - "url": "/product/foundation/spots/", - "new": true + "url": "/product/foundation/spots/" }, { "title": "Typography", - "url": "/product/foundation/typography/", - "new": true + "url": "/product/foundation/typography/" } ] }, @@ -67,8 +63,7 @@ "links": [ { "title": "Backgrounds", - "url": "/product/base/backgrounds/", - "new": true + "url": "/product/base/backgrounds/" }, { "title": "Borders", @@ -76,8 +71,7 @@ }, { "title": "Border radius", - "url": "/product/base/border-radius/", - "new": true + "url": "/product/base/border-radius/" }, { "title": "Box shadow", @@ -117,8 +111,7 @@ }, { "title": "Height", - "url": "/product/base/height/", - "new": true + "url": "/product/base/height/" }, { "title": "Interactivity", @@ -174,8 +167,7 @@ }, { "title": "Width", - "url": "/product/base/width/", - "new": true + "url": "/product/base/width/" }, { "title": "Z-index", @@ -188,33 +180,27 @@ "links": [ { "title": "Checkbox", - "url": "/product/components/checkbox/", - "new": true + "url": "/product/components/checkbox/" }, { "title": "Inputs", - "url": "/product/components/inputs/", - "new": true + "url": "/product/components/inputs/" }, { "title": "Labels", - "url": "/product/components/labels/", - "new": true + "url": "/product/components/labels/" }, { "title": "Radio", - "url": "/product/components/radio/", - "new": true + "url": "/product/components/radio/" }, { "title": "Select", - "url": "/product/components/select/", - "new": true + "url": "/product/components/select/" }, { "title": "Textarea", - "url": "/product/components/textarea/", - "new": true + "url": "/product/components/textarea/" } ] }, @@ -223,28 +209,23 @@ "links": [ { "title": "Activity indicator", - "url": "/product/components/activity-indicator/", - "new": true + "url": "/product/components/activity-indicator/" }, { "title": "Avatars", - "url": "/product/components/avatars/", - "new": true + "url": "/product/components/avatars/" }, { "title": "Badges", - "url": "/product/components/badges/", - "new": true + "url": "/product/components/badges/" }, { "title": "Banners", - "url": "/product/components/banners/", - "new": true + "url": "/product/components/banners/" }, { "title": "Bling", - "url": "/product/components/bling/", - "new": true + "url": "/product/components/bling/" }, { "title": "Breadcrumbs", @@ -252,8 +233,7 @@ }, { "title": "Buttons", - "url": "/product/components/buttons/", - "new": true + "url": "/product/components/buttons/" }, { "title": "Button groups", @@ -273,8 +253,7 @@ }, { "title": "Empty states", - "url": "/product/components/empty-states/", - "new": true + "url": "/product/components/empty-states/" }, { "title": "Expandable", @@ -282,8 +261,7 @@ }, { "title": "Links", - "url": "/product/components/links/", - "new": true + "url": "/product/components/links/" }, { "title": "Link previews", @@ -291,28 +269,23 @@ }, { "title": "Loader", - "url": "/product/components/loader/", - "new": true + "url": "/product/components/loader/" }, { "title": "Menus", - "url": "/product/components/menus/", - "new": true + "url": "/product/components/menus/" }, { "title": "Modals", - "url": "/product/components/modals/", - "new": true + "url": "/product/components/modals/" }, { "title": "Navigation", - "url": "/product/components/navigation/", - "new": true + "url": "/product/components/navigation/" }, { "title": "Notices", - "url": "/product/components/notices/", - "new": true + "url": "/product/components/notices/" }, { "title": "Page titles", @@ -320,18 +293,15 @@ }, { "title": "Pagination", - "url": "/product/components/pagination/", - "new": true + "url": "/product/components/pagination/" }, { "title": "Popovers", - "url": "/product/components/popovers/", - "new": true + "url": "/product/components/popovers/" }, { "title": "Post summary", - "url": "/product/components/post-summary/", - "new": true + "url": "/product/components/post-summary/" }, { "title": "Progress bars", @@ -339,13 +309,11 @@ }, { "title": "Prose", - "url": "/product/components/prose/", - "new": true + "url": "/product/components/prose/" }, { "title": "Sidebar widgets", - "url": "/product/components/sidebar-widgets/", - "new": true + "url": "/product/components/sidebar-widgets/" }, { "title": "Tables", @@ -353,13 +321,11 @@ }, { "title": "Tags", - "url": "/product/components/tags/", - "new": true + "url": "/product/components/tags/" }, { "title": "Toggle switch", - "url": "/product/components/toggle-switch/", - "new": true + "url": "/product/components/toggle-switch/" }, { "title": "Topbar", @@ -371,13 +337,11 @@ }, { "title": "User cards", - "url": "/product/components/user-cards/", - "new": true + "url": "/product/components/user-cards/" }, { "title": "Vote", - "url": "/product/components/vote/", - "new": true + "url": "/product/components/vote/" } ] } diff --git a/packages/stacks-docs/_includes/layouts/page.html b/packages/stacks-docs/_includes/layouts/page.html index ceec266951..d0c85b3a6c 100644 --- a/packages/stacks-docs/_includes/layouts/page.html +++ b/packages/stacks-docs/_includes/layouts/page.html @@ -86,18 +86,8 @@

{{ title }}

{% if description %}

{{ description }}

{% endif %} - - {% if removed %} -
- {% tip, "warning" %} - This component has been removed in Stacks v3. If using Stacks v2, please refer to the v2 documentation for more information. - {% endtip %} -
- {% endif %} - {% if removed != true %} -
{{ content }}
- {% endif %} +
{{ content }}
diff --git a/packages/stacks-docs/_includes/layouts/removed.html b/packages/stacks-docs/_includes/layouts/removed.html new file mode 100644 index 0000000000..d2ec06f8d9 --- /dev/null +++ b/packages/stacks-docs/_includes/layouts/removed.html @@ -0,0 +1,68 @@ + + +{% include 'head.html' %} + + + {% include 'theme.html' %} + {% include 'header.html' %} + +
+ + {% if site-navigation %} + {% for section in site-navigation.sections %} + {% assign slug = page.url | replace:'/',' ' | truncatewords: 2 | remove:'...' %} + {% assign url = section.url | replace:'/',' ' | truncatewords: 2 | remove:'...' %} + + {% if url == slug %} + {% if section.sections %} +
+ +
+ {% endif %} + {% endif %} + {% endfor %} + {% endif %} + + +
+
+

{{ title }}

+ +
+ {% tip, "warning" %} + This component has been removed in Stacks v3. If using Stacks v2, please refer to the v2 documentation for more information. + {% endtip %} +
+
+ +
+ Deploys by Netlify +
+
+
+ {% include 'scripts.html' %} + + diff --git a/packages/stacks-docs/assets/less/stacks-documentation.less b/packages/stacks-docs/assets/less/stacks-documentation.less index fe6a4d9602..2bd24d1382 100644 --- a/packages/stacks-docs/assets/less/stacks-documentation.less +++ b/packages/stacks-docs/assets/less/stacks-documentation.less @@ -3,15 +3,8 @@ // ---------------------------------------------------------------------------- @import (reference) "../../../stacks-classic/lib/stacks.less"; // These are actual styles used in SO projects // Deprecated components styles imports -@import "../../../stacks-classic/lib/components/breadcrumbs/breadcrumbs.less"; -@import "../../../stacks-classic/lib/components/button-group/button-group.less"; @import "../../../stacks-classic/lib/components/card/card.less"; -@import "../../../stacks-classic/lib/components/expandable/expandable.less"; -@import "../../../stacks-classic/lib/components/link-preview/link-preview.less"; -@import "../../../stacks-classic/lib/components/page-title/page-title.less"; -@import "../../../stacks-classic/lib/components/progress-bar/progress-bar.less"; @import "../../../stacks-classic/lib/components/topbar/topbar.less"; -@import "../../../stacks-classic/lib/components/uploader/uploader.less"; body { &.theme-custom { diff --git a/packages/stacks-docs/product/components/breadcrumbs.html b/packages/stacks-docs/product/components/breadcrumbs.html index 595468305f..45cbdb46f8 100644 --- a/packages/stacks-docs/product/components/breadcrumbs.html +++ b/packages/stacks-docs/product/components/breadcrumbs.html @@ -1,148 +1,4 @@ --- -layout: page +layout: removed title: Breadcrumbs -figma: https://svelte.stackoverflow.design/figma/breadcrumbs -description: Breadcrumbs are used to provide context for the currently-viewed page. -tags: components -removed: true --- - -
- {% header "h2", "Classes" %} - {% assign docsItems = breadcrumbs.classes %} - {% assign col1Classes = "s-table--cell4"%} - {% assign col2Classes = "s-table--cell3"%} - {% assign col3Heading = "" %} - {% include "docs-table.html" %} -
- -
- {% header "h2", "Examples" %} -

Breadcrumbs show users where they are within a site’s hierarchy. Breadcrumbs help orient the user and allow for navigation to previous page levels. It can be appropriate to use a breadcrumb when:

-
    -
  • The user is more than 2 levels of navigation deep
  • -
  • The current page does not have its own navigation
  • -
  • The user needs to quickly go back to the previous parent page
  • -
-

Breadcrumbs should be the first page element—placed directly above the page’s title. The page the user is on should not appear in the breadcrumb trail, since that indicator is satisfied by the title of the page itself. Additionally, the last .s-breadcrumb--item shouldn’t include the divider.

- -

It is not appropriate to use Breadcrumbs when:

-
    -
  • There is only one level of navigation.
  • -
  • There isn’t a clear navigation path or the page is orphaned.
  • -
- - {% header "h3", "Stack Overflow" %} -
-{% highlight html %} - -{% endhighlight %} -
- -

What types of questions should I avoid asking?

-
-
- - {% header "h3", "Stack Exchange" %} -
-{% highlight html %} - -{% endhighlight %} -
- -

Close votes

-
-
- - {% header "h3", "Team" %} -
-{% highlight html %} - -{% endhighlight %} -
- -

Payment Details

-
-
- - diff --git a/packages/stacks-docs/product/components/button-groups.html b/packages/stacks-docs/product/components/button-groups.html index d583c5a292..bf3257a681 100644 --- a/packages/stacks-docs/product/components/button-groups.html +++ b/packages/stacks-docs/product/components/button-groups.html @@ -1,225 +1,4 @@ --- -layout: page +layout: removed title: Button groups -figma: https://svelte.stackoverflow.design/figma/button-groups -description: Button groups are a collection of buttons. This component is used in our questions view, and is frequently used in conjunction with other form elements such as search fields and sorting dropdowns. If the content you’re interacting with is a simple paring down or filter of the current view, it’s appropriate to use the .s-btn-group component. Add the class .is-selected and the aria-current attribute with the appropriate value to show the currently selected button. -tags: components -removed: true --- - -
- {% header "h2", "Classes" %} - {% assign docsItems = button-groups.classes %} - {% assign col2Heading = "" %} - {% assign col3Heading = "" %} - {% include "docs-table.html" %} -
- -
- {% header "h2", "Button attributes" %} - - {% for item in button-groups.button-attributes %} - {% header "h3", item.title %} - -

{{item.description}}

- -
- - - - - - - - - - {% for attribute in item.attributes %} - - - - - - {% endfor %} - -
ItemApplied toDescription
{{ attribute.attribute }}{{ attribute.applies }}{{ attribute.description }}
-
- {% endfor %} -
- -
- {% header "h2", "Example" %} -
-{% highlight html %} -
- - - - - -
-{% endhighlight %} -
-
- - - - - -
-
-
-
- -
- {% header "h2", "Counts" %} -

- Counts are used to display a numerical count inside a button group. This is good for large data sets where it’s helpful to quickly know how many items are behind each filter. -

-
-{% highlight html %} -
- - - -
-{% endhighlight %} -
-
- - - -
-
-
-
- -
- {% header "h2", "Radio" %} -

- Button groups can be implemented using radio elements with the class .s-btn--radio on the radio input element. This class assumes all buttons are styled label elements. -

-
-{% highlight html %} -
- - - - - - -
-{% endhighlight %} -
-
- - - - - - -
-
-
-
- -
- {% header "h2", "Links" %} -

- In some cases items in the button groups let users navigate between related sections of content, displaying one section at a time. - In those cases an a tag should be prefferred over the button. -

-
-{% highlight html %} - -{% endhighlight %} -
- -
-
-
- - diff --git a/packages/stacks-docs/product/components/cards.html b/packages/stacks-docs/product/components/cards.html index d7422bd171..b8734ca980 100644 --- a/packages/stacks-docs/product/components/cards.html +++ b/packages/stacks-docs/product/components/cards.html @@ -1,178 +1,4 @@ --- -layout: page +layout: removed title: Cards -figma: https://svelte.stackoverflow.design/figma/cards -description: Cards are used to group similar concepts and tasks together to make information easier to scan, read, and act on. Cards should use a heading that sets clear expectations about the card’s purpose, paragraphs that put the most critical information first, and (optionally) calls to action on the bottom to direct user action. -tags: components -removed: true --- - -
- {% header "h2", "Classes" %} - {% assign docsItems = cards.classes %} - {% assign col2Heading = "" %} - {% include "docs-table.html" %} -
- -
- {% header "h2", "Base" %} -

The base card styling applies a border and padding to the card.

-

Cards can be any size and it’s ok to increase the body text size for larger cards.

-
-{% highlight html %} -
-

…

-

…

- -
-{% endhighlight %} -
-
-

Base card title

-

This is a description of the card’s content.

-
- - -
-
-
-

Base card title

-

This is a description of the card’s content. Sometimes the description is two or three sentences.

-
- - -
-
-
-
-
- -
- {% header "h2", "Box shadows" %} -

Applying a .bs-* class adds a box shadow to a card. Useful when giving users the impression they can interact with the card.

-
-{% highlight html %} -
…
-
…
-
…
-{% endhighlight %} -
-
-
-

Small box shadow

-

This adds a small box shadow.

-
-
-

Medium box shadow

-

This adds medium box shadow.

-
-
-

Large box shadow

-

This is the largest box shadow.

-
-
-
-
-
- -
- {% header "h2", "Linked cards" %} -

The .s-card class can be applied to an <a> tag for instances where a whole card should link somewhere. If possible, linked cards should visually indication that they’re interactive (ex. including an .s-btn or .s-link somewhere).

-

A :hover style for border color is automatically added to all linked cards. For linked cards with a box shadow (.bs-*), adding a .h:bs-* class will apply a hover style to the box shadow as well. Increasing the .bs- size by a factor of one is usually best.

- -
- -
- {% header "h2", "Muted" %} -

When a card is disabled or considered completed, apply the muted modifier to visually dim the card.

-
-{% highlight html %} -
-

…

-

…

-
-{% endhighlight %} -
-
-
-

Base card title

-

This is a description of the card’s content.

-
- -

Linked card title

-

This is a description of the card’s content.

-
-
-
-
-
- -
- {% header "h2", "Stacked" %} -

First introduced for our collections feature in Teams, cards can also be stacked to imply multiple sections or items. No need to overthink it, we can just nest our cards. Note: You’ll need to compensate for the 4px of nesting on that right edge to keep things equidistant.

-
-{% highlight html %} -
-
- … -
-
-{% endhighlight %} -
-
-
-
-

Community announcements

-

A collection of various announcements shared across the org.

-
-
-
-
-
-
diff --git a/packages/stacks-docs/product/components/expandable.html b/packages/stacks-docs/product/components/expandable.html index 7ae4c9c10e..c89eaf7658 100644 --- a/packages/stacks-docs/product/components/expandable.html +++ b/packages/stacks-docs/product/components/expandable.html @@ -1,172 +1,4 @@ --- -layout: page +layout: removed title: Expandable -js: true -description: An expandable, sometimes called an accordion, is an element that can be hidden / revealed with a sliding transition. -tags: components -removed: true --- - -
- {% header "h2", "Classes" %} - {% assign docsItems = expandable.classes %} - {% assign col1Classes = "s-table--cell3" %} - {% assign col2Classes = "s-table--cell3" %} - {% assign col3Classes = "s-table--cell3" %} - {% include "docs-table.html" %} -
- -
- {% header "h2", "Examples" %} - {% header "h3", "Basic" %} -

From a purely visual standpoint, all you need is a container of class s-expandable and a child of class s-expandable--content. Toggle the state class is-expanded on the container to collapse / expand the content. Care must be taken to keep the collapsing functionality accessible.

- - -
-{% highlight html %} -
- -
-
- … -
-
-
-{% endhighlight %} -
-
- -
-
-

Lorem ipsum dolor sit amet, ex iudicabit necessitatibus usu, cetero laboramus concludaturque mel no, facilisis posidonium cu cum. Pro ex senserit dissentiunt, imperdiet intellegam at sed, ex pri dicit eruditi convenire. Est harum movet gubergren ei, errem dictas evertitur ea sit, at mei oratio eligendi. Ad vis legere possit, vis ne ipsum democritum appellantur. Nullam ancillae iudicabit his ad.

-
-
-

Accusata reprimique interesset in sea, est graece dictas scriptorem ea. Consul facete mediocritatem quo et. Idque hendrerit theophrastus in vim, eum possit feugiat fastidii id. Idque invenire at quo, accusata salutandi sadipscing et qui. Eos doming adipiscing ea, eu pri debitis indoctum dissentiet. At libris labores adolescens eos, ex nec nobis aeterno.

-
-
-
- - {% header "h3", "Multiple" %} -

It’s also possible to control the state of multiple elements from a single s-expandable-control by listing all the ids for the controlled elements in the aria-controls attribute.

- -
-{% highlight html %} -
- -
-
- … -
-
- … -
-
- … -
-
-
-{% endhighlight %} -
-
- -
-
-

Lorem ipsum dolor sit amet, ex iudicabit necessitatibus usu, cetero laboramus concludaturque mel no, facilisis posidonium cu cum. Pro ex senserit dissentiunt, imperdiet intellegam at sed, ex pri dicit eruditi convenire. Est harum movet gubergren ei, errem dictas evertitur ea sit, at mei oratio eligendi. Ad vis legere possit, vis ne ipsum democritum appellantur. Nullam ancillae iudicabit his ad.

-
-
-

Accusata reprimique interesset in sea, est graece dictas scriptorem ea. Consul facete mediocritatem quo et. Idque hendrerit theophrastus in vim, eum possit feugiat fastidii id. Idque invenire at quo, accusata salutandi sadipscing et qui. Eos doming adipiscing ea, eu pri debitis indoctum dissentiet. At libris labores adolescens eos, ex nec nobis aeterno.

-
-
-

Aenean aliquet vitae erat sed luctus. Nullam elementum orci id leo lacinia fringilla. Quisque rutrum mauris at mi rhoncus, vel vulputate erat pellentesque. Sed blandit rhoncus sem at pulvinar. Curabitur maximus, metus a facilisis efficitur, ipsum eros faucibus quam, nec mollis lectus nunc ut diam.

-
-
-
-
-
-
-
- {% header "h2", "JavaScript" %} - -

In the usual case in which you have a button or other clickable element that toggles the expanded state, you can use the built-in s-expandable-control functionality. See the JavaScript introduction for general information on JS in Stacks.

- -
    -
  1. Give all desired s-expandable elements an id attribute.
  2. -
  3. Give your button an aria-controls attribute whose value is a space-separated list of all IDs in 1.
  4. -
  5. Give your button an aria-expanded attribute whose value is true or false depending on the initial state of your expandables.
  6. -
  7. Give your button a data-controller="s-expandable-control" attribute.
  8. -
  9. If your button is an element that is not focusable by default, be sure to make it keyboard-reachable with tabindex="0"
  10. -
  11. Give your button an aria-label attribute that makes it clear that this is a expanding/collapsing control, unless this is already clear from its text content
  12. -
- -

A common need is for one or more CSS classes to be applied to the expandable control whenever the state is toggled, e.g. to indicate a “selected” state. To achieve this, you can add the data-s-expandable-control-toggle-class attribute. The value should be a space-separated list of CSS classes. These classes will be added to the control whenever it expands the expandable, and removed whenever it collapses it.

- -

See the previous section for an example of all of this.

- -

If you are writing custom CSS to indicate the selected state of the expandable control, consider targetting [aria-controls="true"] instead of creating a new class.

- -

If your expandable control is a checkbox or radio button, then the visibility of the expandable will be synchronized with the radio / checkbox state:

- -
-{% highlight html %} -… -
- - -
-
-

@Svg.FaceSmile

-
-… -{% endhighlight %} -
-
- What is your mood? -
- - -
-
-

{% icon "FaceSmile", "", "64" %}

-
-
- - -
-
-

{% icon "FaceSad", "", "64" %}

-
-
-
-
- - {% header "h3", "Events" %} -

When an s-expandable-control collapses or expands an element, it will fire an event of type s-expandable-control:hide or s-expandable-control:show, respectively. This event is fired synchronously. The event’s target element is the s-expandable-control element, not the expandable itself.

-
diff --git a/packages/stacks-docs/product/components/link-previews.html b/packages/stacks-docs/product/components/link-previews.html index c97f2cfcba..4cc460707b 100644 --- a/packages/stacks-docs/product/components/link-previews.html +++ b/packages/stacks-docs/product/components/link-previews.html @@ -1,223 +1,4 @@ --- -layout: page +layout: removed title: Link previews -description: Link previews add rich previews to links included in questions and answers on Stack Overflow. They’re also known as oneboxes or link unfurls. -tags: components -removed: true --- -
- {% header "h2", "Classes" %} - {% assign docsItems = link-previews.classes %} - {% assign col1Classes = "s-table--cell4" %} - {% assign col2Classes = "s-table--cell4" %} - {% assign col3Heading = "" %} - {% assign col4Heading = "Description" %} - {% assign expandableClassesTable = true %} - {% include "docs-table.html" %} -
- -
- {% header "h2", "Examples" %} -

Link previews automatically appear when you pasting a link into a post, providing a glimpse of what’s been linked to. This approach has been popularized by Slack, Twitter, Facebook, etc. Link previews should be tailored to fit the content received from each third party. It might be appropriate to use atomic utility classes for further customization, but Stacks provides a few reusable patterns:

- {% header "h3", "Base style" %} -

Use for links whose expected body is rich text or markdown like Jira issues or Slack messages. Wherever possible, it’s best practice to support basic markdown formatting (bold, italics, line breaks, lists, etc.)

-
-{% highlight html %} - -{% endhighlight %} -
- {% assign baseExample = link-previews.examples.base %} - -
-
- - {% header "h3", "Code blocks" %} -

Use for links whose expected body is code like code files or GitHub Gists. In these scenarios, replace s-link-preview--body class with s-link-preview--code.

-

Add a s-code-block class to the <pre> tag if you’d like to apply highlight.js’s syntax highlighting on Stack Exchange sites with this option enabled.

-
-{% highlight html %} - -{% endhighlight %} -
- {% assign codeExample = link-previews.examples.code %} - -
-
- - {% header "h3", "Code blocks with line numbers" %} -

You can further configure highlight.js’s syntax highlighting to include line numbers by adding the class linenums to the prettified <pre> tag containing the code. See also Code blocks.

-
- - - - - - - - - - - - - - - - - -
ClassDescription
linenumsCount starts at line 1
linenums:<n>Count starts at line <n>
-
-
-{% highlight html %} - -{% endhighlight %} -
- -
-
-
diff --git a/packages/stacks-docs/product/components/page-titles.html b/packages/stacks-docs/product/components/page-titles.html index b3778e60a8..d2111558c2 100644 --- a/packages/stacks-docs/product/components/page-titles.html +++ b/packages/stacks-docs/product/components/page-titles.html @@ -1,120 +1,4 @@ --- -layout: page +layout: removed title: Page titles -description: Page titles create consistency in the layout of similar pages, specifically the placement and appearance of titles, descriptions, actions, and breadcrumbs. -tags: components -removed: true --- - -
- {% header "h2", "Classes" %} - {% assign docsItems = page-titles.classes %} - {% assign col1Classes = "s-table--cell4" %} - {% assign col2Classes = "s-table--cell3" %} - {% assign col3Heading = "" %} - {% include "docs-table.html" %} -
- -
- {% header "h2", "Examples" %} - {% header "h3", "Base example" %} -

The base style for pages that don’t need further description beyond the page title and don’t have any actions for filters.

- {% assign example = page-titles.example %} - -
-{% highlight html %} -
-

Page title

-
-{% endhighlight %} -
-
-

{{ example.title }}

-
-
-
- - {% header "h3", "Title with description" %} -

A summary of a page’s content. Helpful for large pages with multiple actions.

-
-{% highlight html %} -
-
-

Page title

-

…

-
-
-{% endhighlight %} -
-
-
-

{{ example.title }}

-

{{ example.description }}

-
-
-
-
- - {% header "h3", "Title with actions" %} -

When a page title includes actions, they are located at the far end of the component. This area is free-form, so we can include any markups we'd like, from single button to a d-flex of custom filters and text.

-
-{% highlight html %} -
-
-

Page title

-

…

-
-
…
-
-{% endhighlight %} -
-
-
-

{{ example.title }}

-

{{ example.description }}

-
-
-
- - -
-
-
-
-
- - {% header "h3", "Title with breadcrumbs" %} -

Breadcrumbs are used to provide context for the currently-viewed page and reduce the number of actions a website visitor needs to take in order to get to a higher-level page. Breadcrumbs should not be used for single-level sections that have no logical grouping.

-
-{% highlight html %} -
-
- -

Page title

-

…

-
-
-{% endhighlight %} -
-
-
- -

{{ example.title }}

-

Optional description de Finibus Bonorum et Malorum with an optional link.

-
-
-
-
-
diff --git a/packages/stacks-docs/product/components/popovers.html b/packages/stacks-docs/product/components/popovers.html index 09e2f22217..ec6d533394 100644 --- a/packages/stacks-docs/product/components/popovers.html +++ b/packages/stacks-docs/product/components/popovers.html @@ -226,11 +226,9 @@ {% endhighlight %}
-
-
-

Lorem ipsum

-
-
+
+

Lorem ipsum

+
- -
- {% header "h2", "Parameters" %} - {% assign tableId = "progress-bars-parameters-table" %} - {% assign docsItems = progress-bars.parameters %} - {% assign col1Classes = "s-table--cell4" %} - {% assign col2Heading = "" %} - {% assign col3Classes = "s-table--cell3" %} - {% assign col1Heading = "Parameter" %} - {% assign col3Heading = "Applies to" %} - {% include "docs-table.html" %} -
- - -
- {% header "h2", "Base style" %} -

Since most progress bars are used to show successful completion of a task, the default fill color is green.

-
-{% highlight html %} -
-
-
-{% endhighlight %} -
-
-
-
-
-
-
-
-
-
-
-
-
- -
- {% header "h2", "Fill alternates" %} -

In addition to the standard progress bar, there is also a brand (orange) and info (blue) progress bar color variation.

-
-{% highlight html %} - -
-
-
- - -
-
-
-{% endhighlight %} -
-
-
Brand
-
-
-
-
-
-
Info
-
-
-
-
-
-
-
- -
- {% header "h2", "Circular" %} -

In compact layouts, switching to a circular progress might be more appropriate. Our circular progress bar inherits the parent’s text color. You and your designer will need to choose an appropriate font color. You’ll also need to pass the --s-progress-value CSS variable a value percentage value in decimal form.

- -

By default, the circular progress bars are 32px. These dimensions can be modified by adding t-shirt sizing classes to .s-progress__circular: .s-progress__sm, .s-progress__md, and .s-progress__lg

- -
-{% highlight html %} -
- - - - -
-{% endhighlight %} -
-
-
- - - - -
- -
- - - - -
- -
- - - - -
- -
- - - - -
- -
- - - - -
-
-
-
-
- -
- {% header "h2", "Privileges" %} -

Taller progress bars used within Profiles to help users understand how close they are to achieving their next privilege.

-
-{% highlight html %} -
-
- @Svg.PromoteDemote - Access Review Queues -
-
-
-{% endhighlight %} -
-
-
-
- {% icon "PromoteDemote" %} - Access Review Queues -
-
-
-
-
- {% icon "AchievementsSm" %} - Trusted user -
-
-
-
-
- {% icon "PromoteDemote" %} - Protect questions -
-
-
-
-
-
-
- -
- {% header "h2", "Badges" %} -

Taller progress bars used within Profiles to help users understand how close they are to achieving their next gold, silver, or bonze badge.

-
-{% highlight html %} - -
-
- gold badge -
Electorate
-
-
-
- -
-
- silver badge -
Civic Duty - 162/300
-
-
-
- -
-
- bronze badge -
Proofreader - 16/100
-
-
-
-{% endhighlight %} -
-
-
-
- gold badge -
Electorate
-
-
-
-
-
- silver badge -
Civic Duty - 162/300
-
-
-
-
-
- bronze badge -
Proofreader - 16/100
-
-
-
-
-
-
-
- -
- {% header "h2", "Segmented" %} -

Stacks provides dividers to create segmented progress bars. The progess bar can be either independent of the dividers, or locked to them.

- - {% tip, "warning" %} - Note: The segmented variant has been deprecated. A similar layout can be achieved with several .s-progress-bar elements in a container. - {% endtip %} -
-{% highlight html %} -
-
-
    -
  1. -
  2. -
  3. -
  4. -
  5. -
  6. -
-
-{% endhighlight %} -
-
-
-
    -
  1. -
  2. -
  3. -
  4. -
  5. -
  6. -
-
-
-
-
- -
- {% header "h2", "Stepped" %} -

If your experience has a small number of discrete steps, it might be appropriate to use a stepped progress bar.

-
-{% highlight html %} -
- - - - -
-
-
-
-
…
-
- -
-
-
-
…
-
-
-{% endhighlight %} -
-
- - - - -
-
-
-
-
Payment
-
- -
-
-
-
Create account
-
-
-
-
-
diff --git a/packages/stacks-docs/product/components/tables.html b/packages/stacks-docs/product/components/tables.html index 0260f7153b..27ca4fdb11 100644 --- a/packages/stacks-docs/product/components/tables.html +++ b/packages/stacks-docs/product/components/tables.html @@ -822,133 +822,7 @@
-
- {% header "h2", "Bar graphs" %} -

To help users, you can add data visualizations into table cells. These are useful to help visualize the reported data and calling extra attention to the table cell. These graphs should always be paired with a number.

-
-{% highlight html %} -
- - … - - - - - - - - - - - - … - -
…………1,854 -
-
-
-
43 -
-
-
-
-
-{% endhighlight %} -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ListingStatusOwnerSourceViewsApplies
- Site Reliability Engineer, Generalist
- Sydney, Australia -
RunningSansa Starkstackoverflow.com - 1,854 - -
-
-
-
- 43 - -
-
-
-
- Senior Product Designer
- New York, NY, USA -
RunningRobert Baratheonlinkedin.com - 900 - -
-
-
-
- 15 - -
-
-
-
- Product Manager, Developer Products
- London, England -
RunningSansa Starkm.facebook.com - 3 - -
-
-
-
- 1 - -
-
-
-
-
-
-
-
+
{% header "h2", "Bulk actions" %}

Generally for a checkbox input that’s placed first in the table row for bulk actions.

diff --git a/packages/stacks-docs/product/components/topbar.html b/packages/stacks-docs/product/components/topbar.html index a387890720..04018ab047 100644 --- a/packages/stacks-docs/product/components/topbar.html +++ b/packages/stacks-docs/product/components/topbar.html @@ -1,200 +1,4 @@ --- -layout: page +layout: removed title: Topbar -description: The topbar component is a navigation bar that is placed at the top of the page. -tags: components -removed: true --- - -
- {% header "h2", "Classes" %} - {% assign docsItems = topbar.classes %} - {% assign col2Classes = "s-table--cell3" %} - {% assign expandableClassesTable = true %} - {% include "docs-table.html" %} -
- -
- {% header "h2", "Basic usage" %} -

At their most basic, our topbar component provides branding and context for the user. In this example, we have a scaled back version showing some global navigation, user settings & preferences, and notifications.

-
-{% highlight html %} -
- Skip to main content - -
-{% endhighlight %} -
- {% render 'topbar.html', hideNavigation: true, hideSearch: true, showMenu: true %} -
-
- - {% header "h3", "Skip Link" %} -

All topbars must include a skip link. - Usually a skip link should be the first focusable element of a page (with the expection of cookie consent dialogs). - Skip links are a mechanism to bypass blocks of content that are repeated on multiple web pages and comply with WCAG SC 2.4.1.

- - {% tip, "info" %} - Note: Skip links become visible only when focused via keyboard navigation and they are announced by screen readers. In the example below hit Tab on your keyboard to see it appearing when in focus. - {% endtip %} -
-{% highlight html %} -
- Skip to main content -
…
-
-{% endhighlight %} -
- {% render 'topbar.html', hideNavigation: true, hideSearch: true %} -
-
-
- -
- {% header "h2", "Advanced usage" %} -

Depending on the user's authentication levels, we may need to include lots of options and menus. The topbar can include new marketing notifications, marketing navigation, a search bar, user details, moderator tools, review queues, achievements, inbox, help, and various bits of navigation.

- - {% header "h3", "Theming" %} -

By default, the topbar automatically switches between light and dark modes as expected. In specific products like Teams, we choose to force a dark version to help the user differentiate between contexts. You can choose either light or dark by applying their respective classes to the main component.

-
-{% highlight html %} -
…
-
…
-
…
-{% endhighlight %} -
- {% assign variations = "s-topbar__auto,s-topbar__dark,s-topbar__light" | split: "," %} -
- {% for variation in variations %} -
-

{{ variation | split: "__" | last | capitalize }}

- {% render 'topbar.html', additionalClass: variation, isMod: true %} -
- {% endfor %} -
-
-
- - {% header "h3", "Search bar" %} -

The topbar can also include a search bar. Depending on the user’s products, it may be appropriate to add a select menu to choose the context for their search.

-
-{% highlight html %} -
- Skip to main content -
- - - - - -
-
-{% endhighlight %} -
-
-
-

With select

- {% render 'topbar.html', showNavigation: false, hideUserAvatar: true %} -
-
-

Input only

- {% render 'topbar.html', showNavigation: false, hideUserAvatar: true, hideSelect: true %} -
-
-
-
- - {% header "h3", "Navigation / Notices / CTAs" %} -

If a user is logged out, or is anonymous, we provide a container for various calls to actions. This is a less opinionated container that only provides layout without styling of the individual children.

-
-{% highlight html %} -
- Skip to main content -
- … - - - - New - - - - - -
-
-{% endhighlight %} -
- {% render 'topbar.html', showNotices: true, showFullNavigation: true, hideSearch: true, showCtas: true %} -
-
- - {% header "h3", "Variable content width" %} -

By default, the topbar has a container that is full width, up to our widest point as defined by our global variables. If you need to override this, you can apply any combination of atomic base classes to the container.

-
-{% highlight html %} -
- Skip to main content -
…
-
-{% endhighlight %} -
- {% render 'topbar.html', containerClass: "wmx75", hideUserAvatar: true %} -
-
-
- - diff --git a/packages/stacks-docs/product/components/uploader.html b/packages/stacks-docs/product/components/uploader.html index b5cdad5aff..168edd8d21 100644 --- a/packages/stacks-docs/product/components/uploader.html +++ b/packages/stacks-docs/product/components/uploader.html @@ -1,208 +1,4 @@ --- -layout: page +layout: removed title: Uploader -js: true -description: The Stacks uploader is a custom-styled file input with added functionality to preview the file or files the user is uploading. -tags: components -removed: true --- - -
- {% header "h2", "Classes" %} - {% assign tableId = "uploader-classes-table" %} - {% assign docsItems = uploader.classes %} - {% assign col2Classes = "s-table--cell3" %} - {% assign expandableClassesTable = true %} - {% include "docs-table.html" %} -
- -
- {% header "h2", "JavaScript" %} - - {% header "h3", "Attributes" %} - {% assign tableId = "uploader-attributes-table" %} - {% assign docsItems = uploader.attributes %} - {% assign col1Classes = "s-table--cell4" %} - {% assign col3Classes = "s-table--cell3" %} - {% assign col2Heading = "" %} - {% assign expandableClassesTable = true %} - {% assign expandableBtnText = "Show all attributes" %} - {% include "docs-table.html" %} -
- -
- {% header "h2", "Examples" %} -

Including a file input with the class s-uploader--input within s-uploader will provide the correct styling for an upload section.

- - {% header "h3", "Profile picture" %} -

In this example, we’re showing a single file input with an image as the example’s placeholder illustration.

-
-{% highlight html %} - -
-
- -
-
-
- -
- @Svg.Spot.Image.With("fc-medium mb8") -
Drag an image to upload
-
- Or choose your image -
-
-
-
-
- - -
-
-{% endhighlight %} -
- -
-
- -
-
-
- -
- {% spot "Image", "fc-medium mb8" %} -
Drag an image to upload
-
- Or choose your image -
-
-
-
-
- - -
-
-
-
- - {% header "h3", "Multiple files" %} -

In this example, this uploader accepts multiple documents so we’ve swapped @Svg.Spot.Image for @Svg.Spot.DocumentAlt and changed the input’s description and attributes to allow for multiples.

-
-{% highlight html %} - -
-
- -
-
-
- -
- @Svg.Spot.Image.With("fc-medium mb8") -
Drag some files to upload
-
- Or choose your files -
-
-
-
-
- - -
-
-{% endhighlight %} -
- -
-
- -
-
-
- -
- {% spot "DocumentAlt", "fc-medium mb8" %} -
Drag some files to upload
-
- Or choose your files -
-
-
-
-
- - -
-
-
-
-
From e827752fad08241f92f154b83daa83ba88bd3f02 Mon Sep 17 00:00:00 2001 From: Dan Cormier Date: Tue, 24 Feb 2026 16:18:00 -0500 Subject: [PATCH 02/10] remove s-card --- .../components/anchor/anchor.visual.test.ts | 6 +-- .../lib/components/card/card.a11y.test.ts | 12 ----- .../lib/components/card/card.less | 37 ------------- .../lib/components/card/card.visual.test.ts | 52 ------------------- .../stacks-docs/_includes/layouts/home.html | 2 +- .../assets/less/stacks-documentation.less | 8 ++- packages/stacks-docs/brand/colors.html | 14 ++--- .../stacks-docs/brand/data-visualization.html | 34 ++++++------ .../stacks-docs/email/components/tags.html | 4 +- .../guidelines/design-best-practices.html | 8 +-- .../email/guidelines/getting-started.html | 10 ++-- .../email/templates/major-announcements.html | 10 ++-- .../product/components/buttons.html | 4 +- .../stacks-docs/product/components/links.html | 2 +- .../stacks-docs/product/components/menus.html | 4 +- .../product/components/post-summary.html | 2 +- .../product/develop/conditional-classes.html | 16 +++--- .../product/develop/javascript.html | 8 +-- .../stacks-docs/product/foundation/icons.html | 2 +- .../stacks-docs/product/foundation/spots.html | 2 +- 20 files changed, 71 insertions(+), 166 deletions(-) delete mode 100644 packages/stacks-classic/lib/components/card/card.a11y.test.ts delete mode 100644 packages/stacks-classic/lib/components/card/card.less delete mode 100644 packages/stacks-classic/lib/components/card/card.visual.test.ts diff --git a/packages/stacks-classic/lib/components/anchor/anchor.visual.test.ts b/packages/stacks-classic/lib/components/anchor/anchor.visual.test.ts index f196842836..054e00f1ab 100644 --- a/packages/stacks-classic/lib/components/anchor/anchor.visual.test.ts +++ b/packages/stacks-classic/lib/components/anchor/anchor.visual.test.ts @@ -24,12 +24,12 @@ describe("anchors", () => { // children include nested anchors block to test for appropriate nested styling default: ` ${links} -
Danger: ${links}
-
Muted: ${links}
+
Danger: ${links}
+
Muted: ${links}
`, }, template: ({ component, testid }) => html` -
+
${testid}: ${component}
`, diff --git a/packages/stacks-classic/lib/components/card/card.a11y.test.ts b/packages/stacks-classic/lib/components/card/card.a11y.test.ts deleted file mode 100644 index 5577ae9ecb..0000000000 --- a/packages/stacks-classic/lib/components/card/card.a11y.test.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { runA11yTests } from "../../test/a11y-test-utils"; -import "../../index"; - -describe.skip("card", () => { - runA11yTests({ - baseClass: "s-card", - variants: ["muted"], - children: { - default: `

This is a description of the card’s content.

`, - }, - }); -}); diff --git a/packages/stacks-classic/lib/components/card/card.less b/packages/stacks-classic/lib/components/card/card.less deleted file mode 100644 index f28df139b0..0000000000 --- a/packages/stacks-classic/lib/components/card/card.less +++ /dev/null @@ -1,37 +0,0 @@ -.s-card { - --_ca-bc: var(--bc-medium); - - // CONTEXTUAL STYLES - a& { - text-decoration: none !important; - } - - // VARIANTS - &&__muted { - --_ca-bc: var(--bc-light); - - // Dim only the first child card content - > * { - opacity: 0.65; - - .dark-mode({ - opacity: 0.7; - }); - - .highcontrast-mode({ - opacity: 0.75; - }); - } - } - - // CHILD ELEMENTS - > :last-child { - margin-bottom: 0; - } - - border: var(--su1) solid var(--_ca-bc); - - background-color: var(--white); - border-radius: var(--br-md); - padding: var(--su12); -} diff --git a/packages/stacks-classic/lib/components/card/card.visual.test.ts b/packages/stacks-classic/lib/components/card/card.visual.test.ts deleted file mode 100644 index c915fa695e..0000000000 --- a/packages/stacks-classic/lib/components/card/card.visual.test.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { html } from "@open-wc/testing"; -import { runVisualTests } from "../../test/visual-test-utils"; -import "../../index"; - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -const cardTemplate = ({ component, testid }: any) => - html`
- ${component} -
`; - -const baseChild = ` -

Base card title

-

- This is a description of the card’s content. -

-
- - -
-`; - -describe.skip("card", () => { - runVisualTests({ - baseClass: "s-card", - variants: ["muted"], - children: { - default: baseChild, - }, - template: cardTemplate, - }); - - // Stacked - runVisualTests({ - baseClass: "s-card", - variants: ["stacked"], // dummy variant for testid differentiation - children: { - default: `
${baseChild}
`, - }, - attributes: { - class: "p0", - }, - template: cardTemplate, - options: { - includeNullVariant: false, - }, - }); -}); diff --git a/packages/stacks-docs/_includes/layouts/home.html b/packages/stacks-docs/_includes/layouts/home.html index 46351c20bc..2c6a4ee0bf 100644 --- a/packages/stacks-docs/_includes/layouts/home.html +++ b/packages/stacks-docs/_includes/layouts/home.html @@ -202,7 +202,7 @@

Stacks

{% endif %} -
    -
  1. - - {% icon "Glyph24" %} +
      +
    1. + + {% icon "Glyph24", "native" %}
    2. -
    3. - - {% icon "GitHub", "", "24" %} +
    4. + + {% icon "GitHub", "native", "24" %}
    5. -
    6. - - +
    7. + +
    -
diff --git a/packages/stacks-svelte/src/components/Toast/Toast.stories.svelte b/packages/stacks-svelte/src/components/Toast/Toast.stories.svelte index 7c92aedf06..6b6f1ce4d2 100644 --- a/packages/stacks-svelte/src/components/Toast/Toast.stories.svelte +++ b/packages/stacks-svelte/src/components/Toast/Toast.stories.svelte @@ -14,11 +14,8 @@ let toastId: string | number = $state(""); -
- Skip to main content -
- Sample Topbar -
+
+ Sample Topbar
From 17e1c9fa7866cd5497309c1ce617d40dc29d9ef9 Mon Sep 17 00:00:00 2001 From: Dan Cormier Date: Wed, 25 Feb 2026 17:55:47 -0500 Subject: [PATCH 09/10] Fix header icon colors --- packages/stacks-docs/_includes/header.html | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/stacks-docs/_includes/header.html b/packages/stacks-docs/_includes/header.html index 6e6f80dba8..642b7b0d49 100644 --- a/packages/stacks-docs/_includes/header.html +++ b/packages/stacks-docs/_includes/header.html @@ -4,7 +4,7 @@ {% if site-navigation %} @@ -30,17 +30,17 @@
  1. - {% icon "Glyph24", "native" %} + {% icon "Glyph24" %}
  2. - {% icon "GitHub", "native", "24" %} + {% icon "GitHub", "24" %}
  3. - +
@@ -69,7 +69,7 @@ data-s-popover-toggle-class="is-selected" data-s-popover-placement="bottom-end" title="Select a theme"> - {% icon "Theme", "native", "24" %} + {% icon "Theme", "24" %} From 960e058903c2428767e1297b6b17ff833bff310b Mon Sep 17 00:00:00 2001 From: Dan Cormier Date: Wed, 25 Feb 2026 18:50:34 -0500 Subject: [PATCH 10/10] Remove TOC on nav for removed component docs pages --- packages/stacks-docs/assets/js/global.navigation.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/stacks-docs/assets/js/global.navigation.js b/packages/stacks-docs/assets/js/global.navigation.js index ca6df65ff3..5284209464 100644 --- a/packages/stacks-docs/assets/js/global.navigation.js +++ b/packages/stacks-docs/assets/js/global.navigation.js @@ -78,9 +78,13 @@ $(document).ready(function() { $('#content').html(content) // Update the TOC from new content headings - var toc = $(html).find('.js-toc').html() - if (toc) { - $('.js-toc').html(toc) + var $newToc = $(html).find(".js-toc"); + var tocContent = $newToc.html(); + + if ($newToc.length > 0 && tocContent.trim() !== "") { + $(".js-toc").html(tocContent).show(); + } else { + $(".js-toc").html("").hide(); } // Scroll to the top of the page