Skip to content

Add OkThSlider component - #3048

Draft
atmgrifter00 with Copilot wants to merge 27 commits into
mainfrom
copilot/add-ok-component-for-fast-slider
Draft

atmgrifter00 with Copilot wants to merge 27 commits into
mainfrom
copilot/add-ok-component-for-fast-slider

Conversation

Copilot AI commented Aug 28, 2026

Copy link
Copy Markdown
Contributor

Pull Request

🤨 Rationale

Add a Nimble-styled OK slider backed by the FAST Foundation slider.

👩‍💻 Implementation

  • Added and registered ok-basic-slider under ok-components/src/basic.
  • Styled horizontal and vertical layouts using Nimble design tokens.
  • Covered hover, focus, active, readonly, and disabled states.
  • Added Storybook documentation and visual-state matrices.

🧪 Testing

  • Added construction and FAST template integration tests.

✅ Checklist

  • I have updated the project documentation to reflect my changes or determined no changes are needed.

Co-authored-by: atmgrifter00 <26874831+atmgrifter00@users.noreply.github.com>
@atmgrifter00

Copy link
Copy Markdown
Contributor

@copilot can we include the ok-react wrapper for this component as part of this PR?

Co-authored-by: atmgrifter00 <26874831+atmgrifter00@users.noreply.github.com>

Copilot AI commented Aug 28, 2026

Copy link
Copy Markdown
Contributor Author

@copilot can we include the ok-react wrapper for this component as part of this PR?

Added the OkBasicSlider wrapper with typed onChange support and package change metadata in b0cb180.

Comment thread change/@ni-ok-react-7f04b43d-439e-4848-b394-511e0909be4d.json
@rajsite

rajsite commented Aug 28, 2026

Copy link
Copy Markdown
Member

Approved the workflow runs

@atmgrifter00

Copy link
Copy Markdown
Contributor

@copilot When pressing the slider it looks like this:
image

I think we should adopt the same styling patterns seen in the switch control (see it's styling CSS file for reference: https://github.com/ni/nimble/blob/main/packages/nimble-components/src/switch/styles.ts.

Normal:
image

Hover:
image

Click:
image

The color of the track for the slider should also match that of the switch.

Co-authored-by: atmgrifter00 <26874831+atmgrifter00@users.noreply.github.com>
Co-authored-by: atmgrifter00 <26874831+atmgrifter00@users.noreply.github.com>

Copilot AI commented Aug 29, 2026

Copy link
Copy Markdown
Contributor Author

@copilot When pressing the slider it looks like this:
image

...

Updated the thumb to use the switch indicator’s normal, hover, focus, active-inner, and disabled patterns, and matched the track to the switch’s theme-specific colors in 3577776.

@atmgrifter00

Copy link
Copy Markdown
Contributor

@copilot we also need to provide visual feedback for what the actual value is as you are changing it (perhaps tooltip next to the . We can provide this configuration via an attribute API. Additionally it would be nice to provide a fill effect on the slider from the minimum up to the current value. Let's start with using the $ni-nimble-fill-selected-color token for the fill color.

Co-authored-by: atmgrifter00 <26874831+atmgrifter00@users.noreply.github.com>

Copilot AI commented Aug 29, 2026

Copy link
Copy Markdown
Contributor Author

@copilot we also need to provide visual feedback for what the actual value is as you are changing it (perhaps tooltip next to the . We can provide this configuration via an attribute API. Additionally...

Added value-visible for a live tooltip positioned beside and moving with the thumb, and changed the minimum-to-current fill to fillSelectedColor in ae9ad82.

@atmgrifter00

Copy link
Copy Markdown
Contributor

@copilot A few things to fix:
image

The thumb for the slider should not be showing the track behind it when in any mode (disabled or otherwise). The switch may have been able to get away with this because its track is the same size and color as the background of the thumb, but for the slider we can't do that, unless we can provide a mask image that removes the visuals behind the thumb. Let's also make the thumb size about 60% of its current size. We also should remove the visual box around the value. I would also like to see the min and max values to show up on the slider on hover.

Co-authored-by: atmgrifter00 <26874831+atmgrifter00@users.noreply.github.com>

Copilot AI commented Aug 29, 2026

Copy link
Copy Markdown
Contributor Author

@copilot A few things to fix:
image

...

Made the thumb opaque in every state, reduced it from 24px to 14px, removed the value box styling, and added hover-only min/max labels at the track ends in 8d2ec57.

Copilot AI commented Aug 30, 2026

Copy link
Copy Markdown
Contributor Author

@copilot While the fill is going in the right direction, the thumb is now positioned improperly for its value. In addition to the thumb being placed under its proper place, you can also see that the v...

Aligned the vertical thumb with the fill boundary by correcting its transform, and changed the matrix/test value to 4 so the non-middle position is verified. Addressed in 5e25b2a.

Comment thread packages/ok-components/src/th/slider/tests/th-slider.spec.ts
Comment on lines +38 to +43
const internals = this as unknown as FoundationSliderInternals;
const calculateFoundationValue = internals.calculateNewValue;
internals.calculateNewValue = rawValue => calculateFoundationValue(
this.orientation === Orientation.vertical
? this.trackMinHeight + this.trackHeight - rawValue
: rawValue

@rajsite rajsite Aug 30, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

(non-blocking) gonna guess llm is fighting with custom element restrictions on what you can do in a constructor. resulting in these weird access patterns. The usual way to handle this is to do things that require messing with the DOM in connectedCallback instead as described in that spec note:

In general, work should be deferred to connectedCallback as much as possible—especially work involving fetching resources or rendering. However, note that connectedCallback can be called more than once, so any initialization work that is truly one-time will need a guard to prevent it from running twice.

@rajsite rajsite Aug 30, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

(non-blocking) Oh actually, think I'm wrong, it's the llm trying to get access to private methods in the base class:

https://github.com/ni/fast/blob/02ccd24d9d3d3f53566e7c9c359888141474af4f/packages/web-components/fast-foundation/src/slider/slider.ts#L473

https://github.com/ni/fast/blob/02ccd24d9d3d3f53566e7c9c359888141474af4f/packages/web-components/fast-foundation/src/slider/slider.ts#L527

If actually really needed, dunno if a sane workaround, may be better to make a small PR to foundation to mark them /** @internal */ public instead. Or just merge as-is. Up to you

Comment thread packages/ok-components/src/th/slider/tests/slider.spec.ts Outdated
Comment thread packages/ok-components/src/th/slider/index.ts Outdated
Comment thread packages/ok-components/src/th/slider/index.ts Outdated
Comment thread packages/react-workspace/ok-react/src/th/slider/index.ts Outdated
Comment thread packages/storybook/src/ok/th/slider/th-slider-matrix.stories.ts
Comment thread packages/storybook/src/ok/th/slider/th-slider.mdx
Comment thread packages/storybook/src/ok/th/slider/th-slider.stories.ts
@rajsite rajsite changed the title Add OK basic slider component Add OkThSlider component Aug 30, 2026
${display('inline-block')}

:host {
width: 100%;

@rajsite rajsite Aug 30, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

(non-blocking) Form style controls (as opposed to block level paragraph or inline text style controls) generally have some reasonable arbitrary width by default as opposed to filling 100% of the parent. Could consider menuMinWidth (which is already a bit abused for that) or a value that feels right

width: 100%;
/* Three thumb widths allow three non-overlapping slider positions. */
min-width: 42px;
height: 32px;

@rajsite rajsite Aug 30, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

(non-blocking) This one we are more consistent on, controlHeight

Comment on lines +45 to +47
width: 32px;
min-width: 32px;
height: 100%;

@rajsite rajsite Aug 30, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

(non-blocking) similar considerations as above

Comment thread .github/CODEOWNERS
@@ -22,6 +22,8 @@
/**/Ts/** @jattasNI

@rajsite rajsite Aug 30, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Pretty much there. Question around accessing internal apis and gave some style feedback since was in the area but generally nimble owners won't be doing reviews of ok component content and focus on repo layout / infra.
Other repo layout considerations:

<Meta of={sliderStories} />
<Title of={sliderStories} />

A Nimble-styled TestHub slider based on the FAST Foundation slider.

@rajsite rajsite Aug 30, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

(non-blocking) The llm inferred what TH stood for :P Dunno if you want the term TestHub here or have it use ThSlider instead (same in the change file description).

@jattasNI jattasNI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Structure looks fine, all comments are because I can't stop myself from applying a higher bar to reviews, you don't have to address any of them for the ok level of quality

show-min-max="${x => x.showMinMax}"
></${thSliderTag}>
`),
argTypes: {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It'd be great to add description for all of these. Many can probably be copied from other controls like nimble number field.

Especially important to note the behavior of value: it's the initial value not the current value.

orientation === 'horizontal' ? `width: ${sliderSize};` : `height: ${sliderSize};`
);

const component = (

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Would be good to include the min/max/value visibility as states too

@@ -0,0 +1,7 @@
{

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Totally up to you whether these are in scope, but a few things I noticed that might be useful for others:

  1. label
  2. error state
  3. Angular wrappers
  4. Blazor wrappers

expect(document.createElement(thSliderTag)).toBeInstanceOf(ThSlider);
});

it('provides the FAST Foundation slider template', async () => {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Looks like we forked the template

Suggested change
it('provides the FAST Foundation slider template', async () => {
it('provides the expected slider template contents', async () => {

@atmgrifter00
atmgrifter00 marked this pull request as draft September 8, 2026 21:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants