Skip to content

List view: improve appearance#8705

Draft
adoriandoran wants to merge 5 commits intomainfrom
feat/list-view-overhaul
Draft

List view: improve appearance#8705
adoriandoran wants to merge 5 commits intomainfrom
feat/list-view-overhaul

Conversation

@adoriandoran
Copy link
Member

No description provided.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @adoriandoran, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the visual appearance and structural integrity of the list view by introducing and integrating new, reusable Card and CardSection components. The changes provide a more consistent, organized, and interactive display for notes, improving the overall user experience and laying groundwork for future UI consistency.

Highlights

  • New Card Components Introduced: New Card and CardSection React components have been added, providing a standardized and reusable structure for UI elements. These components support nesting, action handling, and consistent styling.
  • List View Refactoring: The ListOrGridView has been refactored to utilize the newly introduced Card and CardSection components, replacing existing div structures for note cards and their sections. This change improves the visual hierarchy and maintainability of the list view.
  • Styling Enhancements: CSS styles have been updated to support the new card structure, including adjustments to the note expander's appearance, new flexbox layouts for note headers, and conditional display for empty note content previews. Custom CSS properties are used for consistent spacing and appearance.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • apps/client/src/widgets/collections/legacy/ListOrGridView.css
    • Removed position and top properties from .note-expander and added opacity.
    • Introduced new CSS variables and styles for .list-view-card.
    • Added flexbox styling for .note-list h5 elements, including icon and attribute alignment.
    • Implemented a rule to hide .note-content-preview when its content is empty.
  • apps/client/src/widgets/collections/legacy/ListOrGridView.tsx
    • Imported Card and CardSection components.
    • Wrapped the note-list-container with the new Card component.
    • Refactored ListNoteCard to use CardSection instead of a div for its main container.
    • Moved NoteContent and NoteChildren into the subSections prop of CardSection, conditionally rendering them based on expansion state.
    • Modified the onClick handler for the note expander to prevent event propagation.
  • apps/client/src/widgets/react/Card.css
    • Added new CSS file defining styles for .tn-card and .tn-card-section.
    • Defined custom CSS properties for card styling, including border-radius, padding, gap, and nested section indentation.
    • Included styles for nested card sections and hover effects for actionable sections.
  • apps/client/src/widgets/react/Card.tsx
    • Added new TypeScript file defining Card and CardSection React components.
    • Implemented Card as a simple container component.
    • Implemented CardSection to handle nested sections, conditional rendering of sub-sections, and click actions.
    • Created CardSectionContext to manage nesting levels for proper indentation.
Activity
  • No specific activity (comments, reviews, or progress updates) has been recorded for this pull request yet.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request improves the list view's appearance by refactoring it to use new, reusable Card and CardSection components. This is a positive architectural change that enhances modularity. The new components make good use of modern CSS features and React context for managing nested layouts. My review includes several suggestions for code simplification, adherence to best practices in React/Preact, and notes on the use of modern CSS features that might affect compatibility and maintainability.

Comment on lines +129 to +144
.tn-icon {
color: var(--left-pane-icon-color);
margin-inline-end: 8px;
font-size: 1.2em;
}

.note-book-title {
color: inherit;
}

.note-list-attributes {
flex-grow: 1;
text-align: right;
font-size: .75em;
opacity: .75;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This file uses CSS nesting syntax (e.g., .tn-icon nested inside .note-list h5) but has a .css extension. While modern browsers are starting to support this, it's not universal and can be confusing for developers who expect .css files to contain standard CSS.

If you are using a CSS preprocessor like Sass or Less, it's a best practice to rename the file to .scss or .less to make the dependency on a preprocessor explicit.

If you are relying on native CSS nesting, please ensure your target platforms (browsers, Electron version) have sufficient support.

Comment on lines +97 to +104
const children = <>
{isExpanded && <>
<CardSection className="note-content-preview">
<NoteContent note={note} highlightedTokens={highlightedTokens} noChildrenList includeArchivedNotes={includeArchived} />
</CardSection>
<NoteChildren note={note} parentNote={parentNote} highlightedTokens={highlightedTokens} currentLevel={currentLevel} expandDepth={expandDepth} includeArchived={includeArchived} />
</>}
</>
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The outer React.Fragment (<>...</>) and the object wrapper around the conditional rendering are unnecessary. You can simplify this by directly using the conditional rendering expression.

    const children = isExpanded && <>
        <CardSection className="note-content-preview">
            <NoteContent note={note} highlightedTokens={highlightedTokens} noChildrenList includeArchivedNotes={includeArchived} />
        </CardSection>
        <NoteChildren note={note} parentNote={parentNote} highlightedTokens={highlightedTokens} currentLevel={currentLevel} expandDepth={expandDepth} includeArchived={includeArchived} />
    </>;

data-note-id={note.noteId}
>
<h5 className="note-book-header">
<h5 className="">
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The className prop with an empty string is redundant and can be removed to simplify the code.

            <h5>

Comment on lines 116 to 119
<span
className={`note-expander ${isExpanded ? "bx bx-chevron-down" : "bx bx-chevron-right"}`}
onClick={() => setExpanded(!isExpanded)}
onClick={(e) => {setExpanded(!isExpanded); e.stopPropagation();}}
/>
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The onClick handler on this <span> is redundant. The parent <CardSection> already has an onAction prop that handles toggling the expansion state, and clicks on this span will bubble up to it. Removing this handler simplifies the code and avoids duplication of intent. The e.stopPropagation() is also not needed because other clickable elements like NoteLink already handle their own events and stop propagation.

                <span
                    className={`note-expander ${isExpanded ? "bx bx-chevron-down" : "bx bx-chevron-right"}`}
                />


&.tn-card-section-nested {
padding-left: calc(8px + (var(--card-nested-section-indent) * var(--tn-card-section-nesting-level)));
background-color: color-mix(in srgb, var(--card-background-color) calc(100% / (var(--tn-card-section-nesting-level) + 1)) , transparent);
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The color-mix() CSS function is a very recent addition to the CSS standard. Please verify that the target environments for this application (e.g., the specific version of Chromium used by Electron, supported browsers) provide support for it to avoid potential rendering issues.


export function CardSection(props: {children: ComponentChildren} & CardSectionProps) {
const parentContext = useContext(CardSectionContext);
const nestingLevel = (parentContext && parentContext.nestingLevel + 1) ?? 0;
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

This line can be written more concisely using optional chaining and the nullish coalescing operator.

Suggested change
const nestingLevel = (parentContext && parentContext.nestingLevel + 1) ?? 0;
const nestingLevel = (parentContext?.nestingLevel ?? -1) + 1;

Comment on lines +30 to +33
<section className={clsx(["tn-card-section", {
"tn-card-section-nested": nestingLevel > 0,
"tn-action": props?.hasAction}
], props.className)}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The clsx function can be called with multiple arguments, which is more idiomatic than passing an array as the first argument.

Suggested change
<section className={clsx(["tn-card-section", {
"tn-card-section-nested": nestingLevel > 0,
"tn-action": props?.hasAction}
], props.className)}
<section className={clsx("tn-card-section", {
"tn-card-section-nested": nestingLevel > 0,
"tn-action": props?.hasAction
}, props.className)}

Comment on lines +32 to +43
"tn-action": props?.hasAction}
], props.className)}
style={"--tn-card-section-nesting-level: " + nestingLevel}
onClick={() => {props.onAction?.()}}>
{props.children}
</section>

{props?.childrenVisible &&
<CardSectionContext.Provider value={{nestingLevel}}>
{props.subSections}
</CardSectionContext.Provider>
}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The optional chaining operator (?.) on props is unnecessary within this component, as props is a function argument and will always be defined. You can safely access its properties directly (e.g., props.hasAction).

"tn-card-section-nested": nestingLevel > 0,
"tn-action": props?.hasAction}
], props.className)}
style={"--tn-card-section-nesting-level: " + nestingLevel}
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

In Preact/React, it's a best practice to pass the style prop as an object rather than a string. This allows React to handle CSS properties more efficiently and safely.

Suggested change
style={"--tn-card-section-nesting-level: " + nestingLevel}
style={{ "--tn-card-section-nesting-level": nestingLevel }}

"tn-action": props?.hasAction}
], props.className)}
style={"--tn-card-section-nesting-level: " + nestingLevel}
onClick={() => {props.onAction?.()}}>
Copy link
Contributor

Choose a reason for hiding this comment

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

medium

The onClick handler can be simplified. Instead of wrapping props.onAction in another arrow function, you can pass it directly. This is more concise and avoids creating an extra function on each render.

Suggested change
onClick={() => {props.onAction?.()}}>
onClick={props.onAction}>

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.

1 participant