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

Catalog cards #63

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

Catalog cards #63

wants to merge 19 commits into from

Conversation

max172-hqt
Copy link
Collaborator

@max172-hqt max172-hqt commented Jan 21, 2025

Description

Please include a summary of the changes and relevant context. List any dependencies that are required for this change.

Related issue: #62

Type of change

Delete options that are not relevant.

  • New feature (non-breaking change which adds functionality)

Instructions

Describe the steps required to verify that the changes are functioning as expected.

How Has This Been Tested?

Describe the tests that you ran to verify the changes. Provide instructions so we can reproduce. Please also list any relevant details for your test configuration.

  • Storybook for multiple use cases of CatalogCard and CatalogList
  • Component tests

Checklist:

  • I have read the CONTRIBUTING doc
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have updated Storybook with relevant examples
  • I have made corresponding changes to the documentation
  • I have added tests that prove my fix is effective or that the feature works
  • New and existing unit tests pass locally with my changes

Copy link
Collaborator

@JBurkinshaw JBurkinshaw 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 comments in the code.

General questions:

  • Should we be adding loading states for async data?
  • With MAX_LENGTH, does this need to be flexible? i.e. should we be passing it in as an optional property while keeping the default?
  • Will the cards require click handlers in the future?

export type IndicatorTag = "API" | "Catalog";

export interface BaseCatalog {
// eslint-disable-next-line react/no-unused-prop-types
Copy link
Collaborator

Choose a reason for hiding this comment

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

Can you think of a way to use id in here?
If not, would it make sense to make it optional?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is used in the Catalog component when rendering each Catalog card (set key), so we still expect the data to have id property. It's showing a warning because the file we're in doesn't use id. For the interfaces that are used in multiple places, should we move it to somewhere else?

I would love to do something like this since CatalogList (rename later) and CatalogCard are so closely related, but not sitting well with our structure.

  • components
    • Catalog (directory)
      • CatalogList.tsx
      • CatalogCard.tsx
      • ... others tsx
      • 1 file for typescript types if needed
      • css module
      • test
      • index.ts to export reusable components

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think that structure makes sense here and allows the interface to be in a different file too. The current flat directory structure is no very scaleable so moving to something more like this makes more sense to me.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I have done this change in my local. Should I push it now or should we discuss more about it, as it's gonna change the way we structure drastically? If doing this, we won't differentiate core / composite components anymore in the codebase, but still have component types on storybook.

import type { DateValue } from "react-aria";
import styles from "./CatalogCard.module.css";

export type TemporalExtent = [DateValue, DateValue?];
Copy link
Collaborator

Choose a reason for hiding this comment

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

Could we be more specific about DateValue null/undefined cases?
Maybe not, but I'm interested to know what happens if the 1st DateValue in the array is nullish.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Here we expect the library user to pass in one or two DateValue for TemporalExtent

So if user passes in null for the first item or anything that doesn't satisfy the type, the editor is gonna show an error. I think type checking with typescript is good enough. Wdyt?

Copy link
Collaborator

@JBurkinshaw JBurkinshaw Jan 21, 2025

Choose a reason for hiding this comment

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

Ok, I am happy with this approach in that case

Copy link
Collaborator

@JBurkinshaw JBurkinshaw Jan 22, 2025

Choose a reason for hiding this comment

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

I've been putting some more thought into this as I modify the DatePicker component.
I'm not convinced that passing in props which use react-aria types like DateValue is ideal. It introduces another dependency and requires the developer to understand the types in the library.
There are a few alternatives, but I'm leaning to passing in regular JS Date objects and converting them to a react-aria type like DateValue within the component. What do you think?

As an example, here's what I'm working on for the DatePicker: #66

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sounds good to me

Comment on lines 50 to 52
shouldTruncateDescription
? `${initialDescription.slice(0, MAX_LENGTH)}${isLongText ? "..." : ""}`
: initialDescription,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Consider moving this to a utility function. Something like this:

const truncateDescription = (text: string, maxLength: number) => {
    if (text.length <= maxLength) return text;
    return `${text.slice(0, maxLength)}...`;
};

There's actually a utils directory. The aim is to abstract useful utilities so we can use them without components in the future if required.

onPress={() =>
setShouldTruncateDescription(!shouldTruncateDescription)
}
aria-expanded={!shouldTruncateDescription}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Also add an aria-label property here for accessibility

Copy link

@alanjleonard alanjleonard left a comment

Choose a reason for hiding this comment

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

Re Catalog count:

  • I think we'll need something in place if the catalog count is in the hundreds+ Like if there's 3 digits in there.
  • Also 8px is too small. I would bump it up to at least 12px. @e-e-james thoughts on font size?

@alanjleonard
Copy link

Re: General questions @JBurkinshaw

  • Huy mentioned that the loading state would make more sense on the list of cards, as opposed to an individual card.
  • My fear with making the MAX_LENGTH optional is that it would break the card component if there was a really long description. I think we keep it in.
  • I'm not sure about a click handler right now for this component. If anything, cards in general could have a default action when clicked then secondary actions would be in an overflow menu. In this case it would be Browse. Let's leave it as is for now and we can revisit it if it comes up again for a more generic card component.

@max172-hqt
Copy link
Collaborator Author

  • I also think an empty state should be implemented.
  • We can have a prop maxDescriptionLength with default value of MAX_LENGTH, and let the user set another max length if needed.

@alanjleonard I'm working on this. We can remove fixed width and height, add some padding and aspect-ratio 1/1 so that the circle will grow as we have more digits. 4 digits or less look fine.

.catalogHeader span {
    ...
    padding: 4px;
    border-radius: 50%;
    aspect-ratio: 1/1;
    flex-shrink: 0; // not sure if this is needed, just to make sure it is not shrunk in a flex layout
    min-width: 16px;
}

@JBurkinshaw
Copy link
Collaborator

  • I also think an empty state should be implemented.
  • We can have a prop maxDescriptionLength with default value of MAX_LENGTH, and let the user set another max length if needed.

@alanjleonard I'm working on this. We can remove fixed width and height, add some padding and aspect-ratio 1/1 so that the circle will grow as we have more digits. 4 digits or less look fine.

.catalogHeader span {
    ...
    padding: 4px;
    border-radius: 50%;
    aspect-ratio: 1/1;
    flex-shrink: 0; // not sure if this is needed, just to make sure it is not shrunk in a flex layout
    min-width: 16px;
}

@max172-hqt maxDescriptionLength with a default set makes sense to me. It would be optional in the sense that if no value is passed, it will default to a sensible length e.g. 250

Comment on lines 31 to 36
border-radius: 50%;
display: inline-flex;
justify-content: center;
align-items: center;
color: #fff;
font-size: 10px;
Copy link
Collaborator

@JBurkinshaw JBurkinshaw Jan 22, 2025

Choose a reason for hiding this comment

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

@max172-hqt Another thought on this. Can you use CSS variables from src/components/styles/theme.css to set as many of these as possible please? Thinking in terms of color, font size, border radius and whatever else you can apply. In the work I'm doing on the datepicker I have added a new variable --border-radius: 4px; but we'll need some input from the design team to align on the approach we take here Edit: Forget this. Let's stay with the existing border-radius-* CSS vars

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

On this, I feel like we’re trying to figure out some default values / spacing in the theme.css file, which are very similar to defaults from TailwindCSS or similar libraries. A few things that made it work really well that I think we can adopt are:

  • consistent spacing. Everything is proportional to 1rem, which is the default browser / html font size (16px). So when user changes default font size, everything will scale correctly. Right now we override default font size to 14px, so it doesn’t make sense to use rem. Reference
  • have a normalize css rules. This is to solve browser inconsistencies and make working with semantic HTML tags easier (eg. remove margins from h1,h2…p tags). Looks like we’re mostly using div tags at the moment.
  • other than that, a lot of default colors, utility classes, easy to work with dark themes and responsive UIs

Copy link
Collaborator

Choose a reason for hiding this comment

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

For context, currently we're using the Vanilla CSS "starter kit" found here. It comes with css files for the base react-aria components, along with a theme.css file which we based our theme.css file in spk-components on.

  1. I am fine with using consistent spacing proportional to 1rem if we're all onboard.
  2. Normalize css is something I've thought about and I think it's a good idea. I think adding it should be tackled as a separate issue though.
  3. I think the default colours are deliberately minimal in our theme.css. It should handle dark/light themes too but we haven't focussed on that yet

@max172-hqt max172-hqt marked this pull request as ready for review January 22, 2025 20:37
@alanjleonard
Copy link

I think to keep inline with how we're going to render the description in the different detail sections, we can

Render the markdown. If the rendered markdown is longer than 300 characters. Add an x-overflow to the container.

Probably makes sense to do this in a different ticket, or after that card is complete. I'll make another placeholder ticket for it.

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.

3 participants