Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

feat(Demo Site): DS Demo Site: Pt. 2 #161

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open

feat(Demo Site): DS Demo Site: Pt. 2 #161

wants to merge 2 commits into from

Conversation

jmuzina
Copy link
Member

@jmuzina jmuzina commented Mar 20, 2025

Done

Depends on #160 , #177

Builds first major section of the DS demo site.

Includes:

  • Showcase configuration, controls (adjust styles for a showcase using a tooltip form)
  • Showcase CSS export (copy CSS variables from a showcase to the clipboard)
  • Showcase navigation, use prev/next buttons to move between showcases
  • Showcase state management - each showcase has its own configuration state

What's next (future PRs):

  1. PT3 - Form integration - consume form components from the forms package, dynamically generate setting controls
  2. PT4 - Applying styling to the typographic specimen example
  3. PT5 - SSR handling - integrating TanStack router with SSR

QA

  1. Open the Showcase
  2. Hover the "Configure" button and play around with settings. See that the example updates styles live.
  3. Use the "Copy" button to copy settings as CSS variables.
  4. Use "Prev" and "Next" buttons to switch between examples.

Open

PR readiness check

  • PR should have one of the following labels:
    • Feature 🎁, Breaking Change 💣, Bug 🐛, Documentation 📝, Maintenance 🔨.
  • PR title follows the Conventional Commits format.
  • All packages define the required scripts in package.json:
    • All packages: check, check:fix, and test.
    • Packages with a build step: build.

Copy link
Contributor

@advl advl left a comment

Choose a reason for hiding this comment

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

It looks very promising. A few comments so far :

  • I don't see ./routeTree.gen.js - How is it generated - what is its role ?
  • I wonder if this app would benefit from having a storybook as well ?
  • Curious about your approach to the shadow dom. We can ofc discuss it later today :)

@jmuzina
Copy link
Member Author

jmuzina commented Mar 25, 2025

This doesn't yet work with SSR - I suspect some changes will need to be made to follow Tanstack's SSR instructions:
https://tanstack.com/router/latest/docs/framework/react/guide/ssr

I see that as something that can be tackled in another PR.

@jmuzina
Copy link
Member Author

jmuzina commented Mar 25, 2025

* I don't see `./routeTree.gen.js` - How is it generated - what is its role ?

@advl

It is generated in the build stage using the Vite Tanstack Router plugin.

Per the TanStack router docs, it is imported by the application at runtime and used to instantiate the TanStack router.

* I wonder if this app would benefit from having a storybook as well ?

Good call, I've added a storybook.

* Curious about your approach to the shadow dom. We can ofc discuss it later today :)

As discussed yesterday, this is currently using react-shadow to wrap examples inside of the shadow DOM. All examples are isolated from the styles of the rest of the site.

As a potential improvement, we could do this natively with Web Components at a later date.

@jmuzina jmuzina changed the title wip: DS Demo Site: Pt. 1 feat(Demo Site): DS Demo Site: Pt. 1 Mar 25, 2025
@jmuzina jmuzina changed the title feat(Demo Site): DS Demo Site: Pt. 1 feat(Demo Site): DS Demo Site: Pt. 2 Mar 25, 2025
@jmuzina jmuzina force-pushed the ds-demo-site branch 4 times, most recently from 55a4cc1 to 4256d1f Compare March 25, 2025 19:04
@jmuzina jmuzina marked this pull request as ready for review March 25, 2025 19:09
@jmuzina jmuzina requested a review from advl March 25, 2025 19:26
Copy link
Contributor

@advl advl left a comment

Choose a reason for hiding this comment

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

Good :

  • Usage of the reducer
  • having not refactored too much your code - this helps with api flexibility and speed of development. We can refactor later
  • good API for the examples and type safety
  • Overall the architecture solves the problem and demonstrates you have a wide understanding of what needs to be solved, matching your ownership

Could be better :

  • File-based separation of concerns (see comments), in general having one file per function helps.
  • Folder structure and naming in some cases
  • Avoid usage of bem - use modern css instead ;)

Feel free to break this down into smaller chuks if it helps with the review.

Please keep notes of how you would split the next stages of implementation, and if there are some items you would like to look at later. This will help me understand your train of though as well, and ensure we have a future-proof view over quality.

Copy link
Contributor

Choose a reason for hiding this comment

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

is this a tanstack naming convention ? Is it possible to capture it somehow ?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, this comes from TanStack naming conventions.

Possibly we can reference this in ARCHITECTURE.md.

Copy link
Contributor

Choose a reason for hiding this comment

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

Could we possibly split the route declaration and the component ? What are the recommended patterns for that ?

Copy link
Member Author

Choose a reason for hiding this comment

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

The format you are seeing here is the recommended pattern: https://tanstack.com/router/latest/docs/framework/react/quick-start

I have adapted this slightly for the Showcase route, where the entire route content is encapsulated in a separate component (ref). This creates a better distinction between route and component and also allows me to test the entire page with Chromatic.

Copy link
Contributor

Choose a reason for hiding this comment

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

I would recommend to have two files, one for the route declaration, one for the Component, unless there are sizeable downsides to that

Copy link
Contributor

Choose a reason for hiding this comment

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

This file is where I have the most issues with in your code.

You should separate it into code units that are well differentiated :
helper functions in utils folder, for instanceutils/generateCssVariables.ts reexported in utils/index.ts
hooks in the hooksfolder
Context in Context.js
Provider in Provider.js

Look at the example from launchpad here, which is the best implementation of those patterns so far.

Copy link
Member Author

Choose a reason for hiding this comment

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

Good point - I've had a go at following that pattern, have a look and LMK what you think.

Copy link
Contributor

Choose a reason for hiding this comment

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

It's much better. There are a few things here and there I'll take a longer look tomorrow

(event: ChangeEvent<HTMLSelectElement>) => {
if (activeExampleName) {
dispatch({
type: "UPDATE_SETTING",
Copy link
Contributor

Choose a reason for hiding this comment

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

Would this be a good use case for an enum ?

Copy link
Member Author

Choose a reason for hiding this comment

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

Currently it is a strictly typed literal - it must be UPDATE_SETTING or RESET_EXAMPLE.

Do you think it would be more beneficial to use an enum?

Copy link
Contributor

Choose a reason for hiding this comment

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

I usually like them but the benefit here is not clear.

I think they reducers can be a good use case but it's mostly an opinion here

Copy link
Contributor

Choose a reason for hiding this comment

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

you will likely want to separate those types in the reducer-related types, that could live alongside it in the same folder, and the component related types. Also we are using TPrefixType for parameters - while it is ok, it is a different pattern from what is in use in the form, so we might want to discuss it together and find our future pattern

Copy link
Contributor

Choose a reason for hiding this comment

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

I will give a more in depth type review once I can see more clearly the domains they relate to - the file structure would help

Copy link
Member Author

Choose a reason for hiding this comment

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

I have separated reducer/context/provider and component-related types.

Regarding Type prefixes, I have a habit of using a T prefix myself (it dates back to college days) but will drop t for the sake of project consistency.

I think the domains should be more clear in the folder structure now.

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't mind the T if we're able to justify it as part of the future style guide. Happy to discuss it more later

Copy link
Contributor

@advl advl left a comment

Choose a reason for hiding this comment

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

A few more comments - not final, but to save time tomorrow

Copy link
Contributor

Choose a reason for hiding this comment

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

If the same of the project is "demo" then this should be "demo" as well. Otherwise you should rename the application folder name as well to be "ds-demo-site"

handleLineHeightChange,
}),
[
handleFontFamilyChange,
Copy link
Contributor

Choose a reason for hiding this comment

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

Dependencies can be simplified to activeExample or activeExampleName

@@ -0,0 +1,3 @@
export * from "./Controls/index.js";
export * from "./Renderer/index.js";
export * from "./examples/index.js";
Copy link
Contributor

Choose a reason for hiding this comment

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

If those have been moved to data then they can be removed from here

const setting = settings[settingName as keyof AllExampleSettings];
if (!setting || setting.disableFormats?.css || setting.value === undefined)
continue;
const cssVarName = `--${casing.toKebabCase(settingName)}`;
Copy link
Contributor

Choose a reason for hiding this comment

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

This somehow seems counterintuitive to me. I imagine it makes more sense to write css in css and, if necessary to transform it into js.


const Showcase = () => {
return (
<Example examples={SHOWCASE_EXAMPLES}>
Copy link
Contributor

Choose a reason for hiding this comment

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

I suggest to rename examples to "items" so when a map is required in a component we use a predictable name. Curious what you think here would be best

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants