Skip to main content

Are you looking for feedback on usability or design best practices for your Custom Block? As part of the ongoing Custom Blocks contest, we’re hosting a live Ask Me Anything (AMA) session in this thread on Wednesday (6/17) at 11am PT .



Jay Ransijn and Stephen Suen from our platform engineering team have designed and built countless blocks. They will be available to answer any design-related questions you have.



The top 3 upvoted questions (or solutions from the community!!) will win a $40 Amazon gift card. You can even start posting your questions now, and we’ll be answering questions live from 11am - 11:30am PT on Wednesday. See you there!

Hello Airtable team!



One design area I’ve been thinking a lot about since the last AMA is the concept of composable blocks that treat the bases themselves as the source of truth. There have been a few related threads about how best to go about this, where to store configuration data, and more.



My question for Jay and Stephen is: what do you find is the best way to store configuration info, or does it depend on the type of block? The user interface guidelines is a terrific read and provides a lot to think about. A few ideas come to mind about how to translate this to a block:





  • Have an onboarding screen that stores info in the global config


  • Have an onboarding screen that writes into to a “config” Table within the Base (could be easier for users to see/modify later)


  • Have a “settings” screen a user can visit whenever (populated with sensible defaults)




Obviously there’s a few ways to go about this. I’m trying to think of a use case where blocks are used by multiple users (so should be open to preference modification), but can be understood by people without a lot of coding experience.



Love to hear what you all have tried!


I noticed that the Blocks API Reference has multiple functions for permission checks. In particular, I noticed that there are different permission checks for operations on a single record versus batch operations for multiple records.



Is this an indication that you are looking into more granular permissions for batch operations in Airtable? Would these permissions for batch operations also apply to the Scripting API, the Standard REST API, and native UI?



Also, what do you think of having permissions that allow changes (create, delete, update) only through code (scripting block or custom blocks)? In this use case, a low-level user could still create, delete, and update data when using a custom block that enforces business logic, but wouldn’t be able to make changes to data directly that doesn’t have any code protecting business logic.


I like how the Buttons beta allows someone to launch a block with a specific record pre-loaded. For example, the Buttons beta lets someone launch Scripting block with a specific record pre-loaded. Is this possible with Custom Blocks? If so, how?



Currently, it looks like a Custom Block can useCursor to tell what the currently selected record is, and act on that record. However, it would be nice to be able to invoke a Custom Block with a record level button instead of having to open the Custom Block and then go back and select the desired record.


I like how the Buttons beta allows someone to launch a block with a specific record pre-loaded. For example, the Buttons beta lets someone launch Scripting block with a specific record pre-loaded. Is this possible with Custom Blocks? If so, how?



Currently, it looks like a Custom Block can useCursor to tell what the currently selected record is, and act on that record. However, it would be nice to be able to invoke a Custom Block with a record level button instead of having to open the Custom Block and then go back and select the desired record.




Already possible:


Will developers have access to UI elements not used in blocks? For instance, if our custom block included a calendar or a date picker, will we have access to the same calendar used for Calendar Views and the same date picker used in date fields?



Will other UI decisions which are determined by CSS classes be available to the blocks UI elements? For example, throughout Airtable’s interface, overflow text is hidden using the CSS class .truncate, could the Text/Heading block elements have a property to turn on or off the truncate class to match?


Hello Airtable team!



Could you answer these questions?





  1. I’m trying to implement image an Image annotation block from the list of possible use cases. Screenshot 2020-06-16 at 22.50.27|700x389





Could you suggest any ideas on how to implement this layout? I’ve managed to do it only by setting the fixed height for the wrapper block for now. Otherwise a scroll appears because of the overflow:auto property on body element in the iframe. Current code is here:



<Box width={'100%'} height={362} display='flex'>

<Box width={'70%'} height={'100%'} display={"flex"} flexDirection={"column"} justifyContent={"stretch"}>

<Box overflow={'auto'} border={'1px solid red'} flexGrow={1}>

<Text size={"xlarge"}>Big images are possible here. This block should be with overflow: auto</Text>

{/*<ImageFromRecord*/}

{/* activeTable={activeTable} selectedRecordId={selectedRecordId} selectedFieldId={selectedFieldId}*/}

{/* annotations={getAnnotationsShapes()}*/}

{/* onAnnotationAdding={handleAnnotationAdding}*/}

{/*/>*/}

</Box>

<Box border={'1px solid blue'}>

<Text size={"xlarge"}>Annotation form here.</Text>

{/*<AnnotationForm onSubmit={handleAnnotationSubmit} onChange={handleAnnotationFormChange}/>*/}

</Box>

</Box>

<Box as={'aside'} width={'30%'} border={'1px solid green'}>

<Text size={"xlarge"}>List of annotations here</Text>

{/*<AnnotationsList annotations={annotations}/>*/}

</Box>

</Box>



I can set height for the wrapper based on window.innerHeight and add change it on resize. But maybe you can give me an advice on better solution?





  1. The second question is about UX. Does it make sense to make the image annotation block available only in FullScreen mode?



Hi Airtable Team, I’ve been trying to install the Airtable Blocks command line tool by pasting npm install -g @airtable/blocks-cli then hitting the enter key. However, it kept resulting into an error. Any advice?


Hi Airtable Team, I’ve been trying to install the Airtable Blocks command line tool by pasting npm install -g @airtable/blocks-cli then hitting the enter key. However, it kept resulting into an error. Any advice?


You have to run npm install as an administrator. Try:


sudo npm install -g @airtable/blocks-cli


You’ll be asked to type in your computer’s password, then it should install.


For the purposes of the contest, can a block submitted to the contest use the button beta, or do entries need to use only released features (other than custom blocks itself)?



For example, I wrote a block that is invoked by a button field (thanks Kamille!), because I prefer that workflow. If I want to submit my block for the contest, should I re-write it to have a different method of launching?


Can you tell us a little more about the decision to host this contest on devpost.com versus how you hosted the contests for scripting block?



Is it possible to submit one block as part of a team, and another block as a solo entry? How would one go about that?



If I have a set of blocks that are meant to be used together in a workflow, would that be two separate entries? Or would they each be independent entries? Each block would have its own repository, and each block could be used independently. However the value of the two blocks is enhanced when they are used in conjunction with each other.



If I use a module from npm with an “MIT” license, is that fair game for the contest? Do I need to do anything for the purposes of the contest to document that I use the module? The module won’t appear in the git repository by default. By default, it will simply be listed in package.json. Is that enough?


Can you tell us a little more about the decision to host this contest on devpost.com versus how you hosted the contests for scripting block?



Is it possible to submit one block as part of a team, and another block as a solo entry? How would one go about that?



If I have a set of blocks that are meant to be used together in a workflow, would that be two separate entries? Or would they each be independent entries? Each block would have its own repository, and each block could be used independently. However the value of the two blocks is enhanced when they are used in conjunction with each other.



If I use a module from npm with an “MIT” license, is that fair game for the contest? Do I need to do anything for the purposes of the contest to document that I use the module? The module won’t appear in the git repository by default. By default, it will simply be listed in package.json. Is that enough?


Kind of building off of a part of @kuovonne’s latest question





I’ve written some Custom Block-specific helper functions to do some common operations like batch operations. These live in a helpers.js file in the same directory as my custom block. If however, I have an idea for how multiple blocks can operate together, moving the helpers.js file to a common parent directory the blocks will not find the code. Say I have a parent blocks directory, inside of which I have block_1 and block_2 directories with the code for my two custom blocks. Importing the helper file (two dirs up in the tree, hence ../../) results in an error message like the following:



Updating bundle...

Bundle Error: Cannot find module '../../helpers' from '~/blocks/block_1/build/development/transpiled/user/frontend'



Is/will importing local modules be supported by custom blocks? Would it make more sense to package-ify my helper files, or is there another solution so I don’t have to copy/paste the file to each block after I make changes?




In the future, could you please convert this to a random drawing? Picking the top upvoted questions (as indicated by “likes”) actually provides a dis-incentive for people to like other developer’s posts. Upvoting someone else’s question or solution automatically reduces one’s own chance of winning.


Will developers have access to UI elements not used in blocks? For instance, if our custom block included a calendar or a date picker, will we have access to the same calendar used for Calendar Views and the same date picker used in date fields?



Will other UI decisions which are determined by CSS classes be available to the blocks UI elements? For example, throughout Airtable’s interface, overflow text is hidden using the CSS class .truncate, could the Text/Heading block elements have a property to turn on or off the truncate class to match?




The date picker provided in the INPUT component works quite well. It doesn’t look the same as the date picture in the native interface, but it provides the functionality.



 <Input type="date" />

<Input type="datetime-local" />


Will developers have access to UI elements not used in blocks? For instance, if our custom block included a calendar or a date picker, will we have access to the same calendar used for Calendar Views and the same date picker used in date fields?



Will other UI decisions which are determined by CSS classes be available to the blocks UI elements? For example, throughout Airtable’s interface, overflow text is hidden using the CSS class .truncate, could the Text/Heading block elements have a property to turn on or off the truncate class to match?




I’ve had trouble setting CSS that isn’t listed in the API reference. I wasn’t able to set visibility to hidden. I had to resort to setting opacity to 0 instead.


Hi Airtable Team,



Many thanks to Kamille! Inserting sudo worked.



I just wanted to follow up with another question - I’ve been working on the “Hello World” tutorial, but I’ve been encountering issues with the command “block run.” It seems that this command doesn’t exist for me, and as a result, I’m unable to find the block url. Any advice?


👋 We’re now live! We’ll be answering your questions over the next half hour — keep asking your questions!


Hi Airtable Team,



Many thanks to Kamille! Inserting sudo worked.



I just wanted to follow up with another question - I’ve been working on the “Hello World” tutorial, but I’ve been encountering issues with the command “block run.” It seems that this command doesn’t exist for me, and as a result, I’m unable to find the block url. Any advice?


The hello_world is, in this case, the name of the block.



The first step, which you do, is change into that directory (the cd hello_world). Once you’re in the block’s directory, you can just execute block run (no hello_world at the beginning needed)!


The hello_world is, in this case, the name of the block.



The first step, which you do, is change into that directory (the cd hello_world). Once you’re in the block’s directory, you can just execute block run (no hello_world at the beginning needed)!


Awesome, thank you Matthew! It worked!


It looks like Stephen and Jay are typing, but I’m not seeing any posts from them. Does anyone else see posts from them?


Hello Airtable team!



One design area I’ve been thinking a lot about since the last AMA is the concept of composable blocks that treat the bases themselves as the source of truth. There have been a few related threads about how best to go about this, where to store configuration data, and more.



My question for Jay and Stephen is: what do you find is the best way to store configuration info, or does it depend on the type of block? The user interface guidelines is a terrific read and provides a lot to think about. A few ideas come to mind about how to translate this to a block:





  • Have an onboarding screen that stores info in the global config


  • Have an onboarding screen that writes into to a “config” Table within the Base (could be easier for users to see/modify later)


  • Have a “settings” screen a user can visit whenever (populated with sensible defaults)




Obviously there’s a few ways to go about this. I’m trying to think of a use case where blocks are used by multiple users (so should be open to preference modification), but can be understood by people without a lot of coding experience.



Love to hear what you all have tried!




What do you find is the best way to store configuration info, or does it depend on the type of block?





You almost always want to store shared configuration in global config, since global config is scoped to a specific block installation. Writing config to a table might clutter the base with additional information that users don’t need to see most of the time, and runs the risk of accidental modification/deletion. It’s also important to consider the scenario where a base has multiple instances of the same block installed — in that situation, you’d have to create separate tables for each installation, which could quickly get out of hand. For user-specific configuration, you can also use local storage.



In terms of UI, it depends on the type of block you’re building. Generally speaking, the recommended pattern is to have a dedicated settings screen (accessed with the useSettingsButton hook) that can be visited whenever. For visualization blocks, consider displaying the settings in a sidebar so that users can tweak settings and see the changes in real-time without switching back and forth between two screens. For wizard blocks where the settings may not change too often, this settings screen might simply be the first screen rendered by the block.




What do you find is the best way to store configuration info, or does it depend on the type of block?





You almost always want to store shared configuration in global config, since global config is scoped to a specific block installation. Writing config to a table might clutter the base with additional information that users don’t need to see most of the time, and runs the risk of accidental modification/deletion. It’s also important to consider the scenario where a base has multiple instances of the same block installed — in that situation, you’d have to create separate tables for each installation, which could quickly get out of hand. For user-specific configuration, you can also use local storage.



In terms of UI, it depends on the type of block you’re building. Generally speaking, the recommended pattern is to have a dedicated settings screen (accessed with the useSettingsButton hook) that can be visited whenever. For visualization blocks, consider displaying the settings in a sidebar so that users can tweak settings and see the changes in real-time without switching back and forth between two screens. For wizard blocks where the settings may not change too often, this settings screen might simply be the first screen rendered by the block.




Could you expand a bit more on local storage? Is it unique to the specific user and block? Can it be accessed outside the block? Is it suitable for storing sensitive information such as API keys or passwords? Does it persist after the block is closed? Does it persist after Airtable is closed? Does it persist after the computer is restarted?


Will developers have access to UI elements not used in blocks? For instance, if our custom block included a calendar or a date picker, will we have access to the same calendar used for Calendar Views and the same date picker used in date fields?



Will other UI decisions which are determined by CSS classes be available to the blocks UI elements? For example, throughout Airtable’s interface, overflow text is hidden using the CSS class .truncate, could the Text/Heading block elements have a property to turn on or off the truncate class to match?


Hey Kamille, thanks for your question. I will try to unpack your questions a bit:





Will developers have access to UI elements not used in blocks?





The UI kit we provide for the Blocks SDK is separate from our core product UI for several reasons. We build new components for the Blocks UI kit optimized for the Blocks SDK and developer experience. We prioritize new components based on the needs from the Blocks developer community, and our own needs as well.





For instance, if our custom block included a calendar or a date picker, will we have access to the same calendar used for Calendar Views and the same date picker used in date fields?





More specifically your question about the date picker, we have got some signal on the need for this component and it’s a component on our radar! For now I would recommend using something like http://react-day-picker.js.org/ (which our own core date picker is based on).





Will other UI decisions which are determined by CSS classes be available to the blocks UI elements?





How we deal with CSS and styling is different in our core product than in the Blocks SDK, so we will never be sharing or importing CSS from the core product. We do aim to add new component props or utilities to solve for common pain points!





For example, throughout Airtable’s interface, overflow text is hidden using the CSS class .truncate , could the Text/Heading block elements have a property to turn on or off the truncate class to match?





I will create a note for the team to look into truncating! Thanks for bringing this to our attention. In the mean time you could use a style prop on your component with the following properties:



style={{

overflow: 'hidden',

textOverflow: 'ellipsis',

whiteSpace: 'nowrap',

}}


Hi Airtable Team, I’m following the tutorial for “Hello World” and seems to be getting an error after “block run.” However, I was able to successfully obtain the block url through terminal. Does anyone know how to resolve the error? Thank you in advance!


Hi Airtable Team, I’m following the tutorial for “Hello World” and seems to be getting an error after “block run.” However, I was able to successfully obtain the block url through terminal. Does anyone know how to resolve the error? Thank you in advance!


For that error, make sure you are only trying to run the custom block from the Base you originally set it up in, and on the same computer.


What will happen to questions in this thread that aren’t answered before time runs out?


Reply