Skip to content
This repository was archived by the owner on May 27, 2025. It is now read-only.
This repository was archived by the owner on May 27, 2025. It is now read-only.

[FEATURE] Using partials and conditionals for UI #88

Description

@raycharius

Is there an existing request for this?

  • I have searched for any related issues and avoided creating a duplicate issue.

Have you read our code of conduct?

  • I have read and agree to the code of conduct

Feature as a user story

I recently released an update to the slack-block-builder library that includes helper functions for inline conditionals, which can be helpful in a few places here, for example:

const { Modal, Blocks, Elements } = require('slack-block-builder');

module.exports = (prefilledTitle, currentUser) => {
  const textInput = (taskTitle) => {
    if (taskTitle) {
      return Elements.TextInput({
        placeholder: 'Do this thing',
        actionId: 'taskTitle',
        initialValue: taskTitle,
      });
    }
    return Elements.TextInput({
      placeholder: 'Do this thing',
      actionId: 'taskTitle',
    });
  };

  return Modal({ title: 'Create new task', submit: 'Create', callbackId: 'new-task-modal' })
    .blocks(
      Blocks.Input({ label: 'New task', blockId: 'taskTitle' }).element(
        textInput(prefilledTitle),
      ),
      Blocks.Input({ label: 'Assign user', blockId: 'taskAssignUser' }).element(
        Elements.UserSelect({
          actionId: 'taskAssignUser',
        }).initialUser(currentUser),
      ),
      Blocks.Input({ label: 'Due date', blockId: 'taskDueDate', optional: true }).element(
        Elements.DatePicker({
          actionId: 'taskDueDate',
        }),
      ),
      Blocks.Input({ label: 'Time', blockId: 'taskDueTime', optional: true }).element(
        Elements.TimePicker({
          actionId: 'taskDueTime',
        }),
      ),
    ).buildToJSON();
};

This can easily become the following:

const { Modal, Blocks, Elements, setIfTruthy } = require('slack-block-builder');

module.exports = (prefilledTitle, currentUser) => Modal({
  title: 'Create new task',
  submit: 'Create',
  callbackId: 'new-task-modal',
})
  .blocks(
    Blocks.Input({ label: 'New task', blockId: 'taskTitle' }).element(
      Elements.TextInput({
        placeholder: 'Do this thing',
        actionId: 'taskTitle',
        initialValue: setIfTruthy(prefilledTitle, prefilledTitle),
      })
    ),
    Blocks.Input({ label: 'Assign user', blockId: 'taskAssignUser' }).element(
      Elements.UserSelect({
        actionId: 'taskAssignUser',
      }).initialUser(currentUser),
    ),
    Blocks.Input({ label: 'Due date', blockId: 'taskDueDate', optional: true }).element(
      Elements.DatePicker({
        actionId: 'taskDueDate',
      }),
    ),
    Blocks.Input({ label: 'Time', blockId: 'taskDueTime', optional: true }).element(
      Elements.TimePicker({
        actionId: 'taskDueTime',
      }),
    ),
  ).buildToJSON();

It gets rid of the if, the duplicated copy, and keeps the view's code similar to the view itself. There are a few other similar places.

Another idea was to include partials, which was something we touched on during the talk around Tasks App at Frontiers:

  • Currently the navigation for the App Home is duplicated, they only differ in which button is primary. Could move those to a function that accepts a isOpenTasks: boolean parameter and returns the navigation with the correct button highlighted.
  • There is a general UI for empty task lists, that could be moved to a function that accepts a title and message.
  • I wonder if the open tasks checklist generation may also be moved to a partial to reduce the cognitive complexity of the view, where it could essentially be:
module.exports = (openTasks) => HomeTab({
  callbackId: 'tasks-home',
  privateMetaData: 'open',
}).blocks(
  partials.homeTabNavigation({ isOpenTasks: true }),
  openTasks.length === 0
    ? partials.emptyTaskListContent({
      title: 'No open tasks',
      message: 'Looks like you\'ve got nothing to do.',
    })
    : partials.openTaskListContent(openTasks),
).buildToJSON();

Let me know what you think – happy to send over a PR!

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions